xref: /optee_os/core/drivers/versal_gpio.c (revision cd495a5a47721f32aae86944ec172f13241bd32a)
1*cd495a5aSJorge Ramirez-Ortiz // SPDX-License-Identifier: MIT
2*cd495a5aSJorge Ramirez-Ortiz /*
3*cd495a5aSJorge Ramirez-Ortiz  * Copyright (C) 2002 - 2021 Xilinx, Inc.  All rights reserved.
4*cd495a5aSJorge Ramirez-Ortiz  * Copyright (c) 2022 Foundries.io Ltd. (jorge@foundries.io)
5*cd495a5aSJorge Ramirez-Ortiz  */
6*cd495a5aSJorge Ramirez-Ortiz #include <arm.h>
7*cd495a5aSJorge Ramirez-Ortiz #include <assert.h>
8*cd495a5aSJorge Ramirez-Ortiz #include <crypto/crypto.h>
9*cd495a5aSJorge Ramirez-Ortiz #include <initcall.h>
10*cd495a5aSJorge Ramirez-Ortiz #include <io.h>
11*cd495a5aSJorge Ramirez-Ortiz #include <kernel/panic.h>
12*cd495a5aSJorge Ramirez-Ortiz #include <mm/core_mmu.h>
13*cd495a5aSJorge Ramirez-Ortiz #include <platform_config.h>
14*cd495a5aSJorge Ramirez-Ortiz #include <stdlib.h>
15*cd495a5aSJorge Ramirez-Ortiz #include <string.h>
16*cd495a5aSJorge Ramirez-Ortiz #include <tee/tee_cryp_utl.h>
17*cd495a5aSJorge Ramirez-Ortiz 
18*cd495a5aSJorge Ramirez-Ortiz #include "drivers/versal_gpio.h"
19*cd495a5aSJorge Ramirez-Ortiz 
20*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_LEN  0x10000
21*cd495a5aSJorge Ramirez-Ortiz 
22*cd495a5aSJorge Ramirez-Ortiz #define DATA_LSW_OFFSET(__bank)	(0x000 + 0x08 * (__bank))
23*cd495a5aSJorge Ramirez-Ortiz #define DATA_MSW_OFFSET(__bank)	(0x004 + 0x08 * (__bank))
24*cd495a5aSJorge Ramirez-Ortiz #define DATA_RO_OFFSET(__bank)	(0x060 + 0x04 * (__bank))
25*cd495a5aSJorge Ramirez-Ortiz #define DIRM_OFFSET(__bank)	(0x204 + 0x40 * (__bank))
26*cd495a5aSJorge Ramirez-Ortiz #define OUTEN_OFFSET(__bank)	(0x208 + 0x40 * (__bank))
27*cd495a5aSJorge Ramirez-Ortiz 
28*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_MID_PIN		16
29*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_UPPER_MASK		0xFFFF0000
30*cd495a5aSJorge Ramirez-Ortiz 
31*cd495a5aSJorge Ramirez-Ortiz /* Max pins in the PMC_GPIO devices
32*cd495a5aSJorge Ramirez-Ortiz  * 00  - 025,  Bank 0
33*cd495a5aSJorge Ramirez-Ortiz  * 26 -  051,  Bank 1
34*cd495a5aSJorge Ramirez-Ortiz  * 52 -  083,  Bank 3
35*cd495a5aSJorge Ramirez-Ortiz  * 84 -  115,  Bank 4
36*cd495a5aSJorge Ramirez-Ortiz  */
37*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_BASE		0xf1020000
38*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_NR_GPIOS	116
39*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PMC_MAX_BANK	5
40*cd495a5aSJorge Ramirez-Ortiz 
41*cd495a5aSJorge Ramirez-Ortiz static const struct versal_gpio_platform_data versal_gpio_pmc_def = {
42*cd495a5aSJorge Ramirez-Ortiz 	.max_bank = VERSAL_GPIO_PMC_MAX_BANK,
43*cd495a5aSJorge Ramirez-Ortiz 	.ngpio = VERSAL_GPIO_PMC_NR_GPIOS,
44*cd495a5aSJorge Ramirez-Ortiz 	.label = "versal_pmc_gpio",
45*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[0] = 0,
46*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[0] = 25,
47*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[1] = 26,
48*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[1] = 51,
49*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[3] = 52,
50*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[3] = 83,
51*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[4] = 84,
52*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[4] = 115,
53*cd495a5aSJorge Ramirez-Ortiz };
54*cd495a5aSJorge Ramirez-Ortiz 
55*cd495a5aSJorge Ramirez-Ortiz /* Max pins in the PS_GPIO devices
56*cd495a5aSJorge Ramirez-Ortiz  *  00 - 25, Bank 0
57*cd495a5aSJorge Ramirez-Ortiz  *  26 - 57, Bank 3
58*cd495a5aSJorge Ramirez-Ortiz  */
59*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_BASE		0xff0b0000
60*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_NR_GPIOS		58
61*cd495a5aSJorge Ramirez-Ortiz #define VERSAL_GPIO_PS_MAX_BANK		4
62*cd495a5aSJorge Ramirez-Ortiz 
63*cd495a5aSJorge Ramirez-Ortiz static const struct versal_gpio_platform_data versal_gpio_ps_def = {
64*cd495a5aSJorge Ramirez-Ortiz 	.max_bank = VERSAL_GPIO_PS_MAX_BANK,
65*cd495a5aSJorge Ramirez-Ortiz 	.ngpio = VERSAL_GPIO_PS_NR_GPIOS,
66*cd495a5aSJorge Ramirez-Ortiz 	.label = "versal_ps_gpio",
67*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[0] = 0,
68*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[0] = 25,
69*cd495a5aSJorge Ramirez-Ortiz 	.bank_min[3] = 26,
70*cd495a5aSJorge Ramirez-Ortiz 	.bank_max[3] = 57,
71*cd495a5aSJorge Ramirez-Ortiz };
72*cd495a5aSJorge Ramirez-Ortiz 
73*cd495a5aSJorge Ramirez-Ortiz static void versal_gpio_get_pin(struct versal_gpio_chip *chip, uint32_t gpio,
74*cd495a5aSJorge Ramirez-Ortiz 				uint32_t *bank, uint32_t *pin)
75*cd495a5aSJorge Ramirez-Ortiz {
76*cd495a5aSJorge Ramirez-Ortiz 	struct versal_gpio_platdata *platdata = &chip->plat;
77*cd495a5aSJorge Ramirez-Ortiz 	uint32_t bnk = 0;
78*cd495a5aSJorge Ramirez-Ortiz 
79*cd495a5aSJorge Ramirez-Ortiz 	assert(gpio < platdata->p_data->ngpio);
80*cd495a5aSJorge Ramirez-Ortiz 
81*cd495a5aSJorge Ramirez-Ortiz 	for (bnk = 0; bnk < platdata->p_data->max_bank; bnk++) {
82*cd495a5aSJorge Ramirez-Ortiz 		if (gpio < platdata->p_data->bank_min[bnk])
83*cd495a5aSJorge Ramirez-Ortiz 			continue;
84*cd495a5aSJorge Ramirez-Ortiz 
85*cd495a5aSJorge Ramirez-Ortiz 		if (gpio > platdata->p_data->bank_max[bnk])
86*cd495a5aSJorge Ramirez-Ortiz 			continue;
87*cd495a5aSJorge Ramirez-Ortiz 
88*cd495a5aSJorge Ramirez-Ortiz 		*bank = bnk;
89*cd495a5aSJorge Ramirez-Ortiz 		*pin = gpio - platdata->p_data->bank_min[bnk];
90*cd495a5aSJorge Ramirez-Ortiz 
91*cd495a5aSJorge Ramirez-Ortiz 		return;
92*cd495a5aSJorge Ramirez-Ortiz 	}
93*cd495a5aSJorge Ramirez-Ortiz 
94*cd495a5aSJorge Ramirez-Ortiz 	EMSG("GPIO_%d not found", gpio);
95*cd495a5aSJorge Ramirez-Ortiz 	panic();
96*cd495a5aSJorge Ramirez-Ortiz }
97*cd495a5aSJorge Ramirez-Ortiz 
98*cd495a5aSJorge Ramirez-Ortiz static enum gpio_level gpio_get_value(struct versal_gpio_chip *chip,
99*cd495a5aSJorge Ramirez-Ortiz 				      uint32_t gpio)
100*cd495a5aSJorge Ramirez-Ortiz {
101*cd495a5aSJorge Ramirez-Ortiz 	uint32_t bank = 0;
102*cd495a5aSJorge Ramirez-Ortiz 	uint32_t pin = 0;
103*cd495a5aSJorge Ramirez-Ortiz 
104*cd495a5aSJorge Ramirez-Ortiz 	versal_gpio_get_pin(chip, gpio, &bank, &pin);
105*cd495a5aSJorge Ramirez-Ortiz 
106*cd495a5aSJorge Ramirez-Ortiz 	return (io_read32(chip->base + DATA_RO_OFFSET(bank)) >> pin) & 1;
107*cd495a5aSJorge Ramirez-Ortiz }
108*cd495a5aSJorge Ramirez-Ortiz 
109*cd495a5aSJorge Ramirez-Ortiz static void gpio_set_value(struct versal_gpio_chip *chip, uint32_t gpio,
110*cd495a5aSJorge Ramirez-Ortiz 			   enum gpio_level val)
111*cd495a5aSJorge Ramirez-Ortiz {
112*cd495a5aSJorge Ramirez-Ortiz 	uint32_t bank = 0;
113*cd495a5aSJorge Ramirez-Ortiz 	uint32_t off = 0;
114*cd495a5aSJorge Ramirez-Ortiz 	uint32_t pin = 0;
115*cd495a5aSJorge Ramirez-Ortiz 
116*cd495a5aSJorge Ramirez-Ortiz 	versal_gpio_get_pin(chip, gpio, &bank, &pin);
117*cd495a5aSJorge Ramirez-Ortiz 
118*cd495a5aSJorge Ramirez-Ortiz 	if (bank >= VERSAL_GPIO_MID_PIN) {
119*cd495a5aSJorge Ramirez-Ortiz 		bank -= VERSAL_GPIO_MID_PIN;
120*cd495a5aSJorge Ramirez-Ortiz 		off = DATA_MSW_OFFSET(bank);
121*cd495a5aSJorge Ramirez-Ortiz 	} else {
122*cd495a5aSJorge Ramirez-Ortiz 		off = DATA_LSW_OFFSET(bank);
123*cd495a5aSJorge Ramirez-Ortiz 	}
124*cd495a5aSJorge Ramirez-Ortiz 
125*cd495a5aSJorge Ramirez-Ortiz 	/*
126*cd495a5aSJorge Ramirez-Ortiz 	 * get the 32 bit value to be written to the mask/data register where
127*cd495a5aSJorge Ramirez-Ortiz 	 * the upper 16 bits is the mask and lower 16 bits is the data
128*cd495a5aSJorge Ramirez-Ortiz 	 */
129*cd495a5aSJorge Ramirez-Ortiz 	val = !!val;
130*cd495a5aSJorge Ramirez-Ortiz 	val = ~BIT32(pin + VERSAL_GPIO_MID_PIN) &
131*cd495a5aSJorge Ramirez-Ortiz 	      (SHIFT_U32(val, pin) | VERSAL_GPIO_UPPER_MASK);
132*cd495a5aSJorge Ramirez-Ortiz 
133*cd495a5aSJorge Ramirez-Ortiz 	io_write32(chip->base + off, val);
134*cd495a5aSJorge Ramirez-Ortiz }
135*cd495a5aSJorge Ramirez-Ortiz 
136*cd495a5aSJorge Ramirez-Ortiz static void gpio_set_direction(struct versal_gpio_chip *chip, uint32_t gpio,
137*cd495a5aSJorge Ramirez-Ortiz 			       enum gpio_dir direction)
138*cd495a5aSJorge Ramirez-Ortiz {
139*cd495a5aSJorge Ramirez-Ortiz 	uint32_t bank = 0;
140*cd495a5aSJorge Ramirez-Ortiz 	uint32_t reg = 0;
141*cd495a5aSJorge Ramirez-Ortiz 	uint32_t pin = 0;
142*cd495a5aSJorge Ramirez-Ortiz 
143*cd495a5aSJorge Ramirez-Ortiz 	versal_gpio_get_pin(chip, gpio, &bank, &pin);
144*cd495a5aSJorge Ramirez-Ortiz 
145*cd495a5aSJorge Ramirez-Ortiz 	if (direction == GPIO_DIR_OUT) {
146*cd495a5aSJorge Ramirez-Ortiz 		/* set the GPIO pin as output */
147*cd495a5aSJorge Ramirez-Ortiz 		reg = io_read32(chip->base + DIRM_OFFSET(bank));
148*cd495a5aSJorge Ramirez-Ortiz 		reg |= BIT(pin);
149*cd495a5aSJorge Ramirez-Ortiz 		io_write32(chip->base + DIRM_OFFSET(bank), reg);
150*cd495a5aSJorge Ramirez-Ortiz 
151*cd495a5aSJorge Ramirez-Ortiz 		/* configure the output enable reg for the pin */
152*cd495a5aSJorge Ramirez-Ortiz 		reg = io_read32(chip->base + OUTEN_OFFSET(bank));
153*cd495a5aSJorge Ramirez-Ortiz 
154*cd495a5aSJorge Ramirez-Ortiz 		reg |= BIT(pin);
155*cd495a5aSJorge Ramirez-Ortiz 		io_write32(chip->base + OUTEN_OFFSET(bank), reg);
156*cd495a5aSJorge Ramirez-Ortiz 
157*cd495a5aSJorge Ramirez-Ortiz 		/* set the state of the pin */
158*cd495a5aSJorge Ramirez-Ortiz 		gpio_set_value(chip, gpio, GPIO_LEVEL_LOW);
159*cd495a5aSJorge Ramirez-Ortiz 	} else {
160*cd495a5aSJorge Ramirez-Ortiz 		/* bnk 0 pins 7 and 8 cannot be used as inputs */
161*cd495a5aSJorge Ramirez-Ortiz 		assert(!(bank == 0 && (pin == 7 || pin == 8)));
162*cd495a5aSJorge Ramirez-Ortiz 
163*cd495a5aSJorge Ramirez-Ortiz 		reg = io_read32(chip->base + DIRM_OFFSET(bank));
164*cd495a5aSJorge Ramirez-Ortiz 		reg &= ~BIT(pin);
165*cd495a5aSJorge Ramirez-Ortiz 		io_write32(chip->base + DIRM_OFFSET(bank), reg);
166*cd495a5aSJorge Ramirez-Ortiz 	}
167*cd495a5aSJorge Ramirez-Ortiz }
168*cd495a5aSJorge Ramirez-Ortiz 
169*cd495a5aSJorge Ramirez-Ortiz static enum gpio_dir gpio_get_direction(struct versal_gpio_chip *chip,
170*cd495a5aSJorge Ramirez-Ortiz 					uint32_t gpio)
171*cd495a5aSJorge Ramirez-Ortiz {
172*cd495a5aSJorge Ramirez-Ortiz 	uint32_t pin = 0;
173*cd495a5aSJorge Ramirez-Ortiz 	uint32_t bank = 0;
174*cd495a5aSJorge Ramirez-Ortiz 
175*cd495a5aSJorge Ramirez-Ortiz 	versal_gpio_get_pin(chip, gpio, &bank, &pin);
176*cd495a5aSJorge Ramirez-Ortiz 
177*cd495a5aSJorge Ramirez-Ortiz 	if (io_read32(chip->base + DIRM_OFFSET(bank)) & BIT(pin))
178*cd495a5aSJorge Ramirez-Ortiz 		return GPIO_DIR_OUT;
179*cd495a5aSJorge Ramirez-Ortiz 
180*cd495a5aSJorge Ramirez-Ortiz 	return GPIO_DIR_IN;
181*cd495a5aSJorge Ramirez-Ortiz }
182*cd495a5aSJorge Ramirez-Ortiz 
183*cd495a5aSJorge Ramirez-Ortiz static enum gpio_level do_get_value(struct gpio_chip *chip, uint32_t gpio)
184*cd495a5aSJorge Ramirez-Ortiz {
185*cd495a5aSJorge Ramirez-Ortiz 	struct versal_gpio_chip *p = container_of(chip,
186*cd495a5aSJorge Ramirez-Ortiz 						struct versal_gpio_chip, chip);
187*cd495a5aSJorge Ramirez-Ortiz 	return gpio_get_value(p, gpio);
188*cd495a5aSJorge Ramirez-Ortiz }
189*cd495a5aSJorge Ramirez-Ortiz 
190*cd495a5aSJorge Ramirez-Ortiz static void do_set_value(struct gpio_chip *chip, uint32_t gpio,
191*cd495a5aSJorge Ramirez-Ortiz 			 enum gpio_level val)
192*cd495a5aSJorge Ramirez-Ortiz {
193*cd495a5aSJorge Ramirez-Ortiz 	struct versal_gpio_chip *p = container_of(chip,
194*cd495a5aSJorge Ramirez-Ortiz 						struct versal_gpio_chip, chip);
195*cd495a5aSJorge Ramirez-Ortiz 	return gpio_set_value(p, gpio, val);
196*cd495a5aSJorge Ramirez-Ortiz }
197*cd495a5aSJorge Ramirez-Ortiz 
198*cd495a5aSJorge Ramirez-Ortiz static void do_set_dir(struct gpio_chip *chip, uint32_t gpio,
199*cd495a5aSJorge Ramirez-Ortiz 		       enum gpio_dir direction)
200*cd495a5aSJorge Ramirez-Ortiz {
201*cd495a5aSJorge Ramirez-Ortiz 	struct versal_gpio_chip *p = container_of(chip,
202*cd495a5aSJorge Ramirez-Ortiz 						struct versal_gpio_chip, chip);
203*cd495a5aSJorge Ramirez-Ortiz 	return gpio_set_direction(p, gpio, direction);
204*cd495a5aSJorge Ramirez-Ortiz }
205*cd495a5aSJorge Ramirez-Ortiz 
206*cd495a5aSJorge Ramirez-Ortiz static enum gpio_dir do_get_dir(struct gpio_chip *chip, uint32_t gpio)
207*cd495a5aSJorge Ramirez-Ortiz {
208*cd495a5aSJorge Ramirez-Ortiz 	struct versal_gpio_chip *p = container_of(chip,
209*cd495a5aSJorge Ramirez-Ortiz 						struct versal_gpio_chip, chip);
210*cd495a5aSJorge Ramirez-Ortiz 	return gpio_get_direction(p, gpio);
211*cd495a5aSJorge Ramirez-Ortiz }
212*cd495a5aSJorge Ramirez-Ortiz 
213*cd495a5aSJorge Ramirez-Ortiz static const struct gpio_ops versal_gpio_ops = {
214*cd495a5aSJorge Ramirez-Ortiz 	.get_direction = do_get_dir,
215*cd495a5aSJorge Ramirez-Ortiz 	.set_direction = do_set_dir,
216*cd495a5aSJorge Ramirez-Ortiz 	.get_value = do_get_value,
217*cd495a5aSJorge Ramirez-Ortiz 	.set_value = do_set_value,
218*cd495a5aSJorge Ramirez-Ortiz 	.get_interrupt = NULL,
219*cd495a5aSJorge Ramirez-Ortiz 	.set_interrupt = NULL,
220*cd495a5aSJorge Ramirez-Ortiz };
221*cd495a5aSJorge Ramirez-Ortiz 
222*cd495a5aSJorge Ramirez-Ortiz TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip)
223*cd495a5aSJorge Ramirez-Ortiz {
224*cd495a5aSJorge Ramirez-Ortiz 	if (chip->base)
225*cd495a5aSJorge Ramirez-Ortiz 		return TEE_SUCCESS;
226*cd495a5aSJorge Ramirez-Ortiz 
227*cd495a5aSJorge Ramirez-Ortiz 	chip->plat.p_data = &versal_gpio_pmc_def;
228*cd495a5aSJorge Ramirez-Ortiz 	chip->plat.base = VERSAL_GPIO_PMC_BASE;
229*cd495a5aSJorge Ramirez-Ortiz 	chip->chip.ops = &versal_gpio_ops;
230*cd495a5aSJorge Ramirez-Ortiz 
231*cd495a5aSJorge Ramirez-Ortiz 	chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
232*cd495a5aSJorge Ramirez-Ortiz 						   VERSAL_GPIO_PMC_BASE,
233*cd495a5aSJorge Ramirez-Ortiz 						   VERSAL_GPIO_LEN);
234*cd495a5aSJorge Ramirez-Ortiz 	if (!chip->base) {
235*cd495a5aSJorge Ramirez-Ortiz 		EMSG("Failed to map gpio");
236*cd495a5aSJorge Ramirez-Ortiz 		chip->chip.ops = NULL;
237*cd495a5aSJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
238*cd495a5aSJorge Ramirez-Ortiz 	}
239*cd495a5aSJorge Ramirez-Ortiz 
240*cd495a5aSJorge Ramirez-Ortiz 	return TEE_SUCCESS;
241*cd495a5aSJorge Ramirez-Ortiz }
242*cd495a5aSJorge Ramirez-Ortiz 
243*cd495a5aSJorge Ramirez-Ortiz TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip)
244*cd495a5aSJorge Ramirez-Ortiz {
245*cd495a5aSJorge Ramirez-Ortiz 	if (chip->base)
246*cd495a5aSJorge Ramirez-Ortiz 		return TEE_SUCCESS;
247*cd495a5aSJorge Ramirez-Ortiz 
248*cd495a5aSJorge Ramirez-Ortiz 	chip->plat.p_data = &versal_gpio_ps_def;
249*cd495a5aSJorge Ramirez-Ortiz 	chip->plat.base = VERSAL_GPIO_PS_BASE;
250*cd495a5aSJorge Ramirez-Ortiz 	chip->chip.ops = &versal_gpio_ops;
251*cd495a5aSJorge Ramirez-Ortiz 
252*cd495a5aSJorge Ramirez-Ortiz 	chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
253*cd495a5aSJorge Ramirez-Ortiz 						   VERSAL_GPIO_PS_BASE,
254*cd495a5aSJorge Ramirez-Ortiz 						   VERSAL_GPIO_LEN);
255*cd495a5aSJorge Ramirez-Ortiz 	if (!chip->base) {
256*cd495a5aSJorge Ramirez-Ortiz 		EMSG("Failed to map gpio");
257*cd495a5aSJorge Ramirez-Ortiz 		chip->chip.ops = NULL;
258*cd495a5aSJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
259*cd495a5aSJorge Ramirez-Ortiz 	}
260*cd495a5aSJorge Ramirez-Ortiz 
261*cd495a5aSJorge Ramirez-Ortiz 	return TEE_SUCCESS;
262*cd495a5aSJorge Ramirez-Ortiz }
263