xref: /optee_os/core/drivers/amd/ps_gpio_driver.c (revision 82a84a88ae5cc840ad50ef088beaa416b1e86a2c)
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 */
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 
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 
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 
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 
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 
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 
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