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