1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "low_level_access.h"
9 #include "synquacer_mmap.h"
10 
11 #include <sysdef_option.h>
12 
13 #include <internal/gpio.h>
14 
15 #include <mod_synquacer_system.h>
16 
17 #include <fwk_log.h>
18 #include <fwk_macros.h>
19 
20 #include <inttypes.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 static const uint8_t prmux_pingrp[] = CONFIG_SCB_PRMUX_PINGRP;
25 static const uint8_t gpio_direction[] = CONFIG_SCB_GPIO_DIRECTION;
26 static const uint8_t gpio_function[] = CONFIG_SCB_GPIO_FUNCTION;
27 
prmux_set_pingrp(void * prmux_base_addr,uint32_t idx,uint32_t pingrp)28 void prmux_set_pingrp(void *prmux_base_addr, uint32_t idx, uint32_t pingrp)
29 {
30     if (idx > PRMUX_MAX_IDX) {
31         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
32         return;
33     }
34 
35     writel((uint32_t)prmux_base_addr + (idx << 2), pingrp);
36 }
37 
gpio_set_data(void * gpio_base_addr,uint32_t idx,uint8_t value)38 void gpio_set_data(void *gpio_base_addr, uint32_t idx, uint8_t value)
39 {
40     if (idx > GPIO_MAX_IDX) {
41         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
42         return;
43     }
44 
45     writel((uint32_t)gpio_base_addr + (idx << 2), value);
46 }
47 
gpio_get_data(void * gpio_base_addr,uint32_t idx)48 uint8_t gpio_get_data(void *gpio_base_addr, uint32_t idx)
49 {
50     if (idx > GPIO_MAX_IDX) {
51         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
52         return 0;
53     }
54 
55     return readl((uint32_t)gpio_base_addr + (idx << 2));
56 }
57 
gpio_set_direction(void * gpio_base_addr,uint32_t idx,uint8_t value)58 void gpio_set_direction(void *gpio_base_addr, uint32_t idx, uint8_t value)
59 {
60     if (idx > GPIO_MAX_IDX) {
61         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
62         return;
63     }
64 
65     writel((uint32_t)gpio_base_addr + 0x10 + (idx << 2), value);
66 }
67 
gpio_get_direction(void * gpio_base_addr,uint32_t idx)68 uint8_t gpio_get_direction(void *gpio_base_addr, uint32_t idx)
69 {
70     if (idx > GPIO_MAX_IDX) {
71         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
72         return 0;
73     }
74 
75     return readl((uint32_t)gpio_base_addr + 0x10 + (idx << 2));
76 }
77 
gpio_set_function(void * gpio_base_addr,uint32_t idx,uint8_t value)78 void gpio_set_function(void *gpio_base_addr, uint32_t idx, uint8_t value)
79 {
80     if (idx > GPIO_MAX_IDX) {
81         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
82         return;
83     }
84 
85     writel((uint32_t)gpio_base_addr + 0x20 + (idx << 2), value);
86 }
87 
gpio_get_function(void * gpio_base_addr,uint32_t idx)88 uint8_t gpio_get_function(void *gpio_base_addr, uint32_t idx)
89 {
90     if (idx > GPIO_MAX_IDX) {
91         FWK_LOG_ERR("Error@%s idx(%" PRIu32 ") too big", __func__, idx);
92         return 0;
93     }
94 
95     return readl((uint32_t)gpio_base_addr + 0x20 + (idx << 2));
96 }
97 
fw_gpio_init(void)98 void fw_gpio_init(void)
99 {
100     size_t i;
101     uint32_t gpio_initial_values;
102 
103     uint32_t gpio_desc_num;
104     const struct sysdef_option_gpio_desc *gpio_desc_p;
105 
106     FWK_LOG_INFO("[SYSTEM] Setting up PRMUX");
107     for (i = 0; i < FWK_ARRAY_SIZE(prmux_pingrp); i++) {
108         prmux_set_pingrp(
109             (void *)CONFIG_SOC_PRMUX_BASE_ADDR, i, prmux_pingrp[i]);
110     }
111     FWK_LOG_INFO("[SYSTEM] Finished setting up PRMUX");
112 
113     FWK_LOG_INFO("[SYSTEM] Setting up GPIO");
114     for (i = 0; i < FWK_ARRAY_SIZE(gpio_function); i++)
115         gpio_set_function((void *)CONFIG_SOC_AP_GPIO_BASE, i, gpio_function[i]);
116 
117     for (i = 0; i < FWK_ARRAY_SIZE(gpio_direction); i++)
118         gpio_set_direction(
119             (void *)CONFIG_SOC_AP_GPIO_BASE, i, gpio_direction[i]);
120 
121     FWK_LOG_INFO("[SYSTEM] Finished setting up GPIO");
122 
123     gpio_initial_values =
124         (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 3) << 24) |
125         (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 2) << 16) |
126         (gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 1) << 8) |
127         gpio_get_data((void *)CONFIG_SOC_AP_GPIO_BASE, 0);
128 
129     FWK_LOG_INFO(
130         "[SYSTEM] Initial GPIO input values = 0x%08" PRIx32 ": ",
131         gpio_initial_values);
132 
133     gpio_desc_num = sysdef_option_get_gpio_desc(&gpio_desc_p);
134     for (i = 0; i < gpio_desc_num; i++) {
135         if (((gpio_initial_values >> gpio_desc_p->pin_no) & 0x1) ==
136             (gpio_desc_p->inv ? 1 : 0)) {
137             /* prepend "!" if the target signal is not asserted */
138             FWK_LOG_INFO("!");
139         }
140         FWK_LOG_INFO("%s ", gpio_desc_p->str);
141     }
142 }
143