1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2002-2021 Xilinx, Inc. All rights reserved.
4 * Copyright (c) 2022 Foundries.io Ltd. (jorge@foundries.io)
5 * Copyright (c) 2024-2025, Advanced Micro Devices, Inc. All rights reserved.
6 *
7 */
8
9 #include <assert.h>
10 #include <drivers/gpio.h>
11 #include <io.h>
12 #include <kernel/dt.h>
13 #include <kernel/panic.h>
14 #include <libfdt.h>
15 #include <malloc.h>
16 #include <mm/core_mmu.h>
17 #include <stdbool.h>
18 #include <stdint.h>
19 #include <trace.h>
20 #include <util.h>
21
22 #include "gpio_private.h"
23
24 static struct amd_gbank_data ps_bank = {
25 .label = "ps_gpio",
26 .ngpio = 58,
27 .max_bank = PS_BANK_MAX,
28 .bank_min[0] = 0,
29 .bank_max[0] = 25,
30 .bank_min[3] = 26,
31 .bank_max[3] = 57,
32 };
33
34 /* Standard GPIO Operations */
ps_gpio_get_value(struct gpio_chip * chip,unsigned int gpio_pin)35 static enum gpio_level ps_gpio_get_value(struct gpio_chip *chip,
36 unsigned int gpio_pin)
37 {
38 uint32_t bank = 0;
39 uint32_t pin = 0;
40 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
41 chip);
42
43 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
44
45 if (io_read32(ps->vbase + DATA_RO_OFFSET(bank)) & BIT(pin))
46 return GPIO_LEVEL_HIGH;
47
48 return GPIO_LEVEL_LOW;
49 }
50
ps_gpio_set_value(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_level level)51 static void ps_gpio_set_value(struct gpio_chip *chip,
52 unsigned int gpio_pin,
53 enum gpio_level level)
54 {
55 uint32_t bank = 0;
56 uint32_t pin = 0;
57 uint32_t offset = 0;
58 uint32_t lvl = 0;
59 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
60 chip);
61
62 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
63
64 if (pin < GPIO_NUM_MAX) {
65 offset = DATA_LSW_OFFSET(bank);
66 } else {
67 pin -= GPIO_NUM_MAX;
68 offset = DATA_MSW_OFFSET(bank);
69 }
70
71 /* Explicitly compare the enum value */
72 if (level == GPIO_LEVEL_HIGH)
73 lvl = 1;
74 else
75 lvl = 0;
76
77 lvl = ~BIT32(pin + GPIO_NUM_MAX) &
78 (SHIFT_U32(lvl, pin) | GPIO_UPPER_MASK);
79
80 io_write32(ps->vbase + offset, lvl);
81 }
82
ps_gpio_get_dir(struct gpio_chip * chip,unsigned int gpio_pin)83 static enum gpio_dir ps_gpio_get_dir(struct gpio_chip *chip,
84 unsigned int gpio_pin)
85 {
86 uint32_t bank = 0;
87 uint32_t pin = 0;
88 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
89 chip);
90
91 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
92
93 if (io_read32(ps->vbase + DIRM_OFFSET(bank)) & BIT(pin))
94 return GPIO_DIR_OUT;
95
96 return GPIO_DIR_IN;
97 }
98
ps_gpio_set_dir(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_dir direction)99 static void ps_gpio_set_dir(struct gpio_chip *chip,
100 unsigned int gpio_pin,
101 enum gpio_dir direction)
102 {
103 uint32_t bank = 0;
104 uint32_t pin = 0;
105 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
106 chip);
107
108 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
109
110 if (direction == GPIO_DIR_OUT) {
111 /* set the GPIO pin as output */
112 io_setbits32(ps->vbase + DIRM_OFFSET(bank), BIT(pin));
113
114 /* configure the output enable reg for the pin */
115 io_setbits32(ps->vbase + OUTEN_OFFSET(bank), BIT(pin));
116
117 /* set the state of the pin */
118 ps_gpio_set_value(chip, gpio_pin, GPIO_LEVEL_LOW);
119 } else {
120 /* Set the GPIO pin as input */
121 io_clrbits32(ps->vbase + DIRM_OFFSET(bank), BIT(pin));
122 }
123 }
124
ps_gpio_get_intr(struct gpio_chip * chip,unsigned int gpio_pin)125 static enum gpio_interrupt ps_gpio_get_intr(struct gpio_chip *chip,
126 unsigned int gpio_pin)
127 {
128 uint32_t bank = 0;
129 uint32_t pin = 0;
130 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
131 chip);
132
133 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
134
135 if ((io_read32(ps->vbase + INTMASK_OFFSET(bank)) & BIT(pin)))
136 return GPIO_INTERRUPT_DISABLE;
137
138 return GPIO_INTERRUPT_ENABLE;
139 }
140
ps_gpio_set_intr(struct gpio_chip * chip,unsigned int gpio_pin,enum gpio_interrupt interrupt)141 static void ps_gpio_set_intr(struct gpio_chip *chip,
142 unsigned int gpio_pin,
143 enum gpio_interrupt interrupt)
144 {
145 uint32_t bank = 0;
146 uint32_t pin = 0;
147 uint32_t offset = 0;
148 uint32_t mask = 0;
149 struct amd_gpio_info *ps = container_of(chip, struct amd_gpio_info,
150 chip);
151
152 amd_gpio_get_bank_and_pin(ps->bdata, gpio_pin, &bank, &pin);
153
154 mask = io_read32(ps->vbase + INTMASK_OFFSET(bank)) & BIT(pin);
155
156 /*
157 * mask = 1 --> Interrupt is masked/disabled.
158 * mask = 0 --> Interrupt is un-masked/enabled.
159 */
160 if (mask && interrupt == GPIO_INTERRUPT_ENABLE) {
161 offset = INTEN_OFFSET(bank);
162 } else if (!mask && interrupt == GPIO_INTERRUPT_DISABLE) {
163 offset = INTDIS_OFFSET(bank);
164 } else {
165 DMSG("No change, interrupt already %s",
166 interrupt ? "Enabled" : "Disabled");
167 return;
168 }
169
170 io_setbits32(ps->vbase + offset, BIT(pin));
171 }
172
173 static const struct gpio_ops ps_gpio_ops = {
174 .get_direction = ps_gpio_get_dir,
175 .set_direction = ps_gpio_set_dir,
176 .get_value = ps_gpio_get_value,
177 .set_value = ps_gpio_set_value,
178 .get_interrupt = ps_gpio_get_intr,
179 .set_interrupt = ps_gpio_set_intr,
180 };
181
amd_ps_gpio_probe(const void * fdt,int node,const void * compat_data __unused)182 static TEE_Result amd_ps_gpio_probe(const void *fdt, int node,
183 const void *compat_data __unused)
184 {
185 TEE_Result res = TEE_ERROR_GENERIC;
186 int status = DT_STATUS_DISABLED;
187 struct amd_gpio_info *ps_gpio = NULL;
188 paddr_t base = 0;
189 size_t len = 0;
190
191 /* Status Check */
192 status = fdt_get_status(fdt, node);
193
194 /* PS GPIO Controller to be in Non Secure World */
195 if (status & DT_STATUS_OK_NSEC) {
196 DMSG("PS GPIO controller configured for NS world");
197 return TEE_SUCCESS;
198 }
199
200 /* PS GPIO Controller is disabled for Secure World as well */
201 if (!(status & DT_STATUS_OK_SEC)) {
202 DMSG("PS GPIO Controller is disabled");
203 return TEE_SUCCESS;
204 }
205
206 ps_gpio = calloc(1, sizeof(*ps_gpio));
207 if (!ps_gpio) {
208 EMSG("Failed to allocate memory for ps_gpio");
209 return TEE_ERROR_OUT_OF_MEMORY;
210 }
211
212 if (fdt_reg_info(fdt, node, &base, &len) != 0) {
213 EMSG("Failed to get Register Base and Size");
214 free(ps_gpio);
215 return TEE_ERROR_GENERIC;
216 }
217
218 /* Populate GPIO ops */
219 ps_gpio->chip.ops = &ps_gpio_ops;
220 /* Populate Bank information */
221 ps_gpio->bdata = &ps_bank;
222
223 /* Validate node entries */
224 assert(base);
225 assert(len);
226
227 ps_gpio->vbase = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, base,
228 len);
229 if (!ps_gpio->vbase) {
230 EMSG("AMD PS GPIO initialization Failed");
231 free(ps_gpio);
232 return TEE_ERROR_GENERIC;
233 }
234
235 res = gpio_register_provider(fdt, node, amd_gpio_get_dt, ps_gpio);
236 if (res) {
237 EMSG("Failed to register PS GPIO Provider");
238 /* Ignoring return value */
239 core_mmu_remove_mapping(MEM_AREA_IO_SEC,
240 (void *)ps_gpio->vbase, len);
241 free(ps_gpio);
242 return res;
243 }
244
245 DMSG("AMD PS GPIO initialized");
246
247 return TEE_SUCCESS;
248 }
249
250 GPIO_DT_DECLARE(amd_ps_gpio, "xlnx,versal-gpio-1.0", amd_ps_gpio_probe);
251