xref: /optee_os/core/drivers/ls_gpio.c (revision 16c13b4d7043d48a117ce13f818b43bbff208f08)
1*16c13b4dSManish Tomar // SPDX-License-Identifier: BSD-2-Clause
2*16c13b4dSManish Tomar /*
3*16c13b4dSManish Tomar  * Copyright 2021 NXP
4*16c13b4dSManish Tomar  *
5*16c13b4dSManish Tomar  * Driver for GPIO Controller
6*16c13b4dSManish Tomar  *
7*16c13b4dSManish Tomar  */
8*16c13b4dSManish Tomar 
9*16c13b4dSManish Tomar #include <assert.h>
10*16c13b4dSManish Tomar #include <drivers/ls_gpio.h>
11*16c13b4dSManish Tomar #include <io.h>
12*16c13b4dSManish Tomar #include <kernel/boot.h>
13*16c13b4dSManish Tomar #include <kernel/dt.h>
14*16c13b4dSManish Tomar #include <libfdt.h>
15*16c13b4dSManish Tomar #include <mm/core_memprot.h>
16*16c13b4dSManish Tomar 
17*16c13b4dSManish Tomar static const char * const gpio_controller_map[] = {
18*16c13b4dSManish Tomar 	 "/soc/gpio@2300000",
19*16c13b4dSManish Tomar 	 "/soc/gpio@2310000",
20*16c13b4dSManish Tomar 	 "/soc/gpio@2320000",
21*16c13b4dSManish Tomar 	 "/soc/gpio@2330000"
22*16c13b4dSManish Tomar };
23*16c13b4dSManish Tomar 
24*16c13b4dSManish Tomar /*
25*16c13b4dSManish Tomar  * Get value from GPIO controller
26*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
27*16c13b4dSManish Tomar  * gpio_pin:    pin from which value needs to be read
28*16c13b4dSManish Tomar  */
29*16c13b4dSManish Tomar static enum gpio_level gpio_get_value(struct gpio_chip *chip,
30*16c13b4dSManish Tomar 				      unsigned int gpio_pin)
31*16c13b4dSManish Tomar {
32*16c13b4dSManish Tomar 	vaddr_t gpio_data_addr = 0;
33*16c13b4dSManish Tomar 	uint32_t data = 0;
34*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
35*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
36*16c13b4dSManish Tomar 						      chip);
37*16c13b4dSManish Tomar 
38*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
39*16c13b4dSManish Tomar 
40*16c13b4dSManish Tomar 	gpio_data_addr = gc_data->gpio_base + GPIODAT;
41*16c13b4dSManish Tomar 	data = io_read32(gpio_data_addr);
42*16c13b4dSManish Tomar 
43*16c13b4dSManish Tomar 	if (data & PIN_SHIFT(gpio_pin))
44*16c13b4dSManish Tomar 		return GPIO_LEVEL_HIGH;
45*16c13b4dSManish Tomar 	else
46*16c13b4dSManish Tomar 		return GPIO_LEVEL_LOW;
47*16c13b4dSManish Tomar }
48*16c13b4dSManish Tomar 
49*16c13b4dSManish Tomar /*
50*16c13b4dSManish Tomar  * Set value for GPIO controller
51*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
52*16c13b4dSManish Tomar  * gpio_pin:    pin to which value needs to be write
53*16c13b4dSManish Tomar  * value:       value needs to be written to the pin
54*16c13b4dSManish Tomar  */
55*16c13b4dSManish Tomar static void gpio_set_value(struct gpio_chip *chip, unsigned int gpio_pin,
56*16c13b4dSManish Tomar 			   enum gpio_level value)
57*16c13b4dSManish Tomar {
58*16c13b4dSManish Tomar 	vaddr_t gpio_data_addr = 0;
59*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
60*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
61*16c13b4dSManish Tomar 						      chip);
62*16c13b4dSManish Tomar 
63*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
64*16c13b4dSManish Tomar 
65*16c13b4dSManish Tomar 	gpio_data_addr = gc_data->gpio_base + GPIODAT;
66*16c13b4dSManish Tomar 
67*16c13b4dSManish Tomar 	if (value == GPIO_LEVEL_HIGH)
68*16c13b4dSManish Tomar 		/* if value is high then set pin value */
69*16c13b4dSManish Tomar 		io_setbits32(gpio_data_addr, PIN_SHIFT(gpio_pin));
70*16c13b4dSManish Tomar 	else
71*16c13b4dSManish Tomar 		/* if value is low then clear pin value */
72*16c13b4dSManish Tomar 		io_clrbits32(gpio_data_addr, PIN_SHIFT(gpio_pin));
73*16c13b4dSManish Tomar }
74*16c13b4dSManish Tomar 
75*16c13b4dSManish Tomar /*
76*16c13b4dSManish Tomar  * Get direction from GPIO controller
77*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
78*16c13b4dSManish Tomar  * gpio_pin:    pin from which direction needs to be read
79*16c13b4dSManish Tomar  */
80*16c13b4dSManish Tomar static enum gpio_dir gpio_get_direction(struct gpio_chip *chip,
81*16c13b4dSManish Tomar 					unsigned int gpio_pin)
82*16c13b4dSManish Tomar {
83*16c13b4dSManish Tomar 	vaddr_t gpio_dir_addr = 0;
84*16c13b4dSManish Tomar 	uint32_t data = 0;
85*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
86*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
87*16c13b4dSManish Tomar 						      chip);
88*16c13b4dSManish Tomar 
89*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
90*16c13b4dSManish Tomar 
91*16c13b4dSManish Tomar 	gpio_dir_addr = gc_data->gpio_base + GPIODIR;
92*16c13b4dSManish Tomar 	data = io_read32(gpio_dir_addr);
93*16c13b4dSManish Tomar 
94*16c13b4dSManish Tomar 	if (data & PIN_SHIFT(gpio_pin))
95*16c13b4dSManish Tomar 		return GPIO_DIR_OUT;
96*16c13b4dSManish Tomar 	else
97*16c13b4dSManish Tomar 		return GPIO_DIR_IN;
98*16c13b4dSManish Tomar }
99*16c13b4dSManish Tomar 
100*16c13b4dSManish Tomar /*
101*16c13b4dSManish Tomar  * Set direction for GPIO controller
102*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
103*16c13b4dSManish Tomar  * gpio_pin:    pin on which direction needs to be set
104*16c13b4dSManish Tomar  * direction:   direction which needs to be set on pin
105*16c13b4dSManish Tomar  */
106*16c13b4dSManish Tomar static void gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin,
107*16c13b4dSManish Tomar 			       enum gpio_dir direction)
108*16c13b4dSManish Tomar {
109*16c13b4dSManish Tomar 	vaddr_t gpio_dir_addr = 0;
110*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
111*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
112*16c13b4dSManish Tomar 						      chip);
113*16c13b4dSManish Tomar 
114*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
115*16c13b4dSManish Tomar 
116*16c13b4dSManish Tomar 	gpio_dir_addr = gc_data->gpio_base + GPIODIR;
117*16c13b4dSManish Tomar 
118*16c13b4dSManish Tomar 	if (direction == GPIO_DIR_OUT)
119*16c13b4dSManish Tomar 		io_setbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin));
120*16c13b4dSManish Tomar 	else
121*16c13b4dSManish Tomar 		io_clrbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin));
122*16c13b4dSManish Tomar }
123*16c13b4dSManish Tomar 
124*16c13b4dSManish Tomar /*
125*16c13b4dSManish Tomar  * Get interrupt from GPIO controller
126*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
127*16c13b4dSManish Tomar  * gpio_pin:    pin from which interrupt value needs to be read
128*16c13b4dSManish Tomar  */
129*16c13b4dSManish Tomar static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip,
130*16c13b4dSManish Tomar 					      unsigned int gpio_pin)
131*16c13b4dSManish Tomar {
132*16c13b4dSManish Tomar 	vaddr_t gpio_ier_addr = 0;
133*16c13b4dSManish Tomar 	uint32_t data = 0;
134*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
135*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
136*16c13b4dSManish Tomar 						      chip);
137*16c13b4dSManish Tomar 
138*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
139*16c13b4dSManish Tomar 
140*16c13b4dSManish Tomar 	gpio_ier_addr = gc_data->gpio_base + GPIOIER;
141*16c13b4dSManish Tomar 	data = io_read32(gpio_ier_addr);
142*16c13b4dSManish Tomar 
143*16c13b4dSManish Tomar 	if (data & PIN_SHIFT(gpio_pin))
144*16c13b4dSManish Tomar 		return GPIO_INTERRUPT_ENABLE;
145*16c13b4dSManish Tomar 	else
146*16c13b4dSManish Tomar 		return GPIO_INTERRUPT_DISABLE;
147*16c13b4dSManish Tomar }
148*16c13b4dSManish Tomar 
149*16c13b4dSManish Tomar /*
150*16c13b4dSManish Tomar  * Set interrupt event for GPIO controller
151*16c13b4dSManish Tomar  * chip:        pointer to GPIO controller chip instance
152*16c13b4dSManish Tomar  * gpio_pin:    pin on which interrupt value needs to be set
153*16c13b4dSManish Tomar  * interrupt:   interrupt valie which needs to be set on pin
154*16c13b4dSManish Tomar  */
155*16c13b4dSManish Tomar static void gpio_set_interrupt(struct gpio_chip *chip, unsigned int gpio_pin,
156*16c13b4dSManish Tomar 			       enum gpio_interrupt interrupt)
157*16c13b4dSManish Tomar {
158*16c13b4dSManish Tomar 	vaddr_t gpio_ier_addr = 0;
159*16c13b4dSManish Tomar 	struct ls_gpio_chip_data *gc_data = container_of(chip,
160*16c13b4dSManish Tomar 						      struct ls_gpio_chip_data,
161*16c13b4dSManish Tomar 						      chip);
162*16c13b4dSManish Tomar 
163*16c13b4dSManish Tomar 	assert(gpio_pin <= MAX_GPIO_PINS);
164*16c13b4dSManish Tomar 
165*16c13b4dSManish Tomar 	gpio_ier_addr = gc_data->gpio_base + GPIOIER;
166*16c13b4dSManish Tomar 
167*16c13b4dSManish Tomar 	if (interrupt == GPIO_INTERRUPT_ENABLE)
168*16c13b4dSManish Tomar 		io_setbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin));
169*16c13b4dSManish Tomar 	else
170*16c13b4dSManish Tomar 		io_clrbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin));
171*16c13b4dSManish Tomar }
172*16c13b4dSManish Tomar 
173*16c13b4dSManish Tomar /*
174*16c13b4dSManish Tomar  * Extract information for GPIO Controller from the DTB
175*16c13b4dSManish Tomar  * gpio_data:	GPIO controller chip instance
176*16c13b4dSManish Tomar  */
177*16c13b4dSManish Tomar static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data)
178*16c13b4dSManish Tomar {
179*16c13b4dSManish Tomar 	size_t size = 0;
180*16c13b4dSManish Tomar 	int node = 0;
181*16c13b4dSManish Tomar 	vaddr_t ctrl_base = 0;
182*16c13b4dSManish Tomar 	void *fdt = NULL;
183*16c13b4dSManish Tomar 
184*16c13b4dSManish Tomar 	/*
185*16c13b4dSManish Tomar 	 * First get the GPIO Controller base address from the DTB
186*16c13b4dSManish Tomar 	 * if DTB present and if the GPIO Controller defined in it.
187*16c13b4dSManish Tomar 	 */
188*16c13b4dSManish Tomar 	fdt = get_embedded_dt();
189*16c13b4dSManish Tomar 	if (!fdt) {
190*16c13b4dSManish Tomar 		EMSG("Unable to get the Embedded DTB, GPIO init failed\n");
191*16c13b4dSManish Tomar 		return TEE_ERROR_GENERIC;
192*16c13b4dSManish Tomar 	}
193*16c13b4dSManish Tomar 
194*16c13b4dSManish Tomar 	node = fdt_path_offset(fdt, gpio_controller_map
195*16c13b4dSManish Tomar 			       [gpio_data->gpio_controller]);
196*16c13b4dSManish Tomar 	if (node > 0) {
197*16c13b4dSManish Tomar 		if (dt_map_dev(fdt, node, &ctrl_base, &size) < 0) {
198*16c13b4dSManish Tomar 			EMSG("Unable to get virtual address");
199*16c13b4dSManish Tomar 			return TEE_ERROR_GENERIC;
200*16c13b4dSManish Tomar 		}
201*16c13b4dSManish Tomar 	} else {
202*16c13b4dSManish Tomar 		EMSG("Unable to get gpio offset node");
203*16c13b4dSManish Tomar 		return TEE_ERROR_ITEM_NOT_FOUND;
204*16c13b4dSManish Tomar 	}
205*16c13b4dSManish Tomar 
206*16c13b4dSManish Tomar 	gpio_data->gpio_base = ctrl_base;
207*16c13b4dSManish Tomar 
208*16c13b4dSManish Tomar 	return TEE_SUCCESS;
209*16c13b4dSManish Tomar }
210*16c13b4dSManish Tomar 
211*16c13b4dSManish Tomar static const struct gpio_ops ls_gpio_ops = {
212*16c13b4dSManish Tomar 	.get_direction = gpio_get_direction,
213*16c13b4dSManish Tomar 	.set_direction = gpio_set_direction,
214*16c13b4dSManish Tomar 	.get_value = gpio_get_value,
215*16c13b4dSManish Tomar 	.set_value = gpio_set_value,
216*16c13b4dSManish Tomar 	.get_interrupt = gpio_get_interrupt,
217*16c13b4dSManish Tomar 	.set_interrupt = gpio_set_interrupt,
218*16c13b4dSManish Tomar };
219*16c13b4dSManish Tomar DECLARE_KEEP_PAGER(ls_gpio_ops);
220*16c13b4dSManish Tomar 
221*16c13b4dSManish Tomar TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data)
222*16c13b4dSManish Tomar {
223*16c13b4dSManish Tomar 	TEE_Result status = TEE_ERROR_GENERIC;
224*16c13b4dSManish Tomar 
225*16c13b4dSManish Tomar 	/*
226*16c13b4dSManish Tomar 	 * First get the GPIO Controller base address from the DTB,
227*16c13b4dSManish Tomar 	 * if DTB present and if the GPIO Controller defined in it.
228*16c13b4dSManish Tomar 	 */
229*16c13b4dSManish Tomar 	status = get_info_from_device_tree(gpio_data);
230*16c13b4dSManish Tomar 	if (status == TEE_SUCCESS) {
231*16c13b4dSManish Tomar 		/* set GPIO Input Buffer Enable register */
232*16c13b4dSManish Tomar 		io_setbits32(gpio_data->gpio_base + GPIOIBE, UINT32_MAX);
233*16c13b4dSManish Tomar 
234*16c13b4dSManish Tomar 		/* generic GPIO chip handle */
235*16c13b4dSManish Tomar 		gpio_data->chip.ops = &ls_gpio_ops;
236*16c13b4dSManish Tomar 	} else {
237*16c13b4dSManish Tomar 		EMSG("Unable to get info from device tree");
238*16c13b4dSManish Tomar 	}
239*16c13b4dSManish Tomar 
240*16c13b4dSManish Tomar 	return status;
241*16c13b4dSManish Tomar }
242