xref: /aosp_15_r20/external/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2019, Linaro Limited
3*54fd6939SJiyong Park  * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) <[email protected]>
4*54fd6939SJiyong Park  *
5*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
6*54fd6939SJiyong Park  */
7*54fd6939SJiyong Park 
8*54fd6939SJiyong Park #include <string.h>
9*54fd6939SJiyong Park #include <assert.h>
10*54fd6939SJiyong Park #include <lib/mmio.h>
11*54fd6939SJiyong Park #include <drivers/delay_timer.h>
12*54fd6939SJiyong Park #include <drivers/rpi3/gpio/rpi3_gpio.h>
13*54fd6939SJiyong Park 
14*54fd6939SJiyong Park static uintptr_t reg_base;
15*54fd6939SJiyong Park 
16*54fd6939SJiyong Park static int rpi3_gpio_get_direction(int gpio);
17*54fd6939SJiyong Park static void rpi3_gpio_set_direction(int gpio, int direction);
18*54fd6939SJiyong Park static int rpi3_gpio_get_value(int gpio);
19*54fd6939SJiyong Park static void rpi3_gpio_set_value(int gpio, int value);
20*54fd6939SJiyong Park static void rpi3_gpio_set_pull(int gpio, int pull);
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park static const gpio_ops_t rpi3_gpio_ops = {
23*54fd6939SJiyong Park 	.get_direction  = rpi3_gpio_get_direction,
24*54fd6939SJiyong Park 	.set_direction  = rpi3_gpio_set_direction,
25*54fd6939SJiyong Park 	.get_value      = rpi3_gpio_get_value,
26*54fd6939SJiyong Park 	.set_value      = rpi3_gpio_set_value,
27*54fd6939SJiyong Park 	.set_pull       = rpi3_gpio_set_pull,
28*54fd6939SJiyong Park };
29*54fd6939SJiyong Park 
30*54fd6939SJiyong Park /**
31*54fd6939SJiyong Park  * Get selection of GPIO pinmux settings.
32*54fd6939SJiyong Park  *
33*54fd6939SJiyong Park  * @param gpio The pin number of GPIO. From 0 to 53.
34*54fd6939SJiyong Park  * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
35*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_OUTPUT: output,
36*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT0: alt-0,
37*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT1: alt-1,
38*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT2: alt-2,
39*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT3: alt-3,
40*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT4: alt-4,
41*54fd6939SJiyong Park  *                                  RPI3_GPIO_FUNC_ALT5: alt-5
42*54fd6939SJiyong Park  */
rpi3_gpio_get_select(int gpio)43*54fd6939SJiyong Park int rpi3_gpio_get_select(int gpio)
44*54fd6939SJiyong Park {
45*54fd6939SJiyong Park 	int ret;
46*54fd6939SJiyong Park 	int regN = gpio / 10;
47*54fd6939SJiyong Park 	int shift = 3 * (gpio % 10);
48*54fd6939SJiyong Park 	uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
49*54fd6939SJiyong Park 	uint32_t sel = mmio_read_32(reg_sel);
50*54fd6939SJiyong Park 
51*54fd6939SJiyong Park 	ret = (sel >> shift) & 0x07;
52*54fd6939SJiyong Park 
53*54fd6939SJiyong Park 	return ret;
54*54fd6939SJiyong Park }
55*54fd6939SJiyong Park 
56*54fd6939SJiyong Park /**
57*54fd6939SJiyong Park  * Set selection of GPIO pinmux settings.
58*54fd6939SJiyong Park  *
59*54fd6939SJiyong Park  * @param gpio The pin number of GPIO. From 0 to 53.
60*54fd6939SJiyong Park  * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input,
61*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_OUTPUT: output,
62*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT0: alt-0,
63*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT1: alt-1,
64*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT2: alt-2,
65*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT3: alt-3,
66*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT4: alt-4,
67*54fd6939SJiyong Park  *                                      RPI3_GPIO_FUNC_ALT5: alt-5
68*54fd6939SJiyong Park  */
rpi3_gpio_set_select(int gpio,int fsel)69*54fd6939SJiyong Park void rpi3_gpio_set_select(int gpio, int fsel)
70*54fd6939SJiyong Park {
71*54fd6939SJiyong Park 	int regN = gpio / 10;
72*54fd6939SJiyong Park 	int shift = 3 * (gpio % 10);
73*54fd6939SJiyong Park 	uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN);
74*54fd6939SJiyong Park 	uint32_t sel = mmio_read_32(reg_sel);
75*54fd6939SJiyong Park 	uint32_t mask = U(0x07) << shift;
76*54fd6939SJiyong Park 
77*54fd6939SJiyong Park 	sel = (sel & (~mask)) | ((fsel << shift) & mask);
78*54fd6939SJiyong Park 	mmio_write_32(reg_sel, sel);
79*54fd6939SJiyong Park }
80*54fd6939SJiyong Park 
rpi3_gpio_get_direction(int gpio)81*54fd6939SJiyong Park static int rpi3_gpio_get_direction(int gpio)
82*54fd6939SJiyong Park {
83*54fd6939SJiyong Park 	int result = rpi3_gpio_get_select(gpio);
84*54fd6939SJiyong Park 
85*54fd6939SJiyong Park 	if (result == RPI3_GPIO_FUNC_INPUT)
86*54fd6939SJiyong Park 		return GPIO_DIR_IN;
87*54fd6939SJiyong Park 	else if (result == RPI3_GPIO_FUNC_OUTPUT)
88*54fd6939SJiyong Park 		return GPIO_DIR_OUT;
89*54fd6939SJiyong Park 
90*54fd6939SJiyong Park 	return GPIO_DIR_IN;
91*54fd6939SJiyong Park }
92*54fd6939SJiyong Park 
rpi3_gpio_set_direction(int gpio,int direction)93*54fd6939SJiyong Park static void rpi3_gpio_set_direction(int gpio, int direction)
94*54fd6939SJiyong Park {
95*54fd6939SJiyong Park 	switch (direction) {
96*54fd6939SJiyong Park 	case GPIO_DIR_IN:
97*54fd6939SJiyong Park 		rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT);
98*54fd6939SJiyong Park 		break;
99*54fd6939SJiyong Park 	case GPIO_DIR_OUT:
100*54fd6939SJiyong Park 		rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT);
101*54fd6939SJiyong Park 		break;
102*54fd6939SJiyong Park 	}
103*54fd6939SJiyong Park }
104*54fd6939SJiyong Park 
rpi3_gpio_get_value(int gpio)105*54fd6939SJiyong Park static int rpi3_gpio_get_value(int gpio)
106*54fd6939SJiyong Park {
107*54fd6939SJiyong Park 	int regN = gpio / 32;
108*54fd6939SJiyong Park 	int shift = gpio % 32;
109*54fd6939SJiyong Park 	uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN);
110*54fd6939SJiyong Park 	uint32_t value = mmio_read_32(reg_lev);
111*54fd6939SJiyong Park 
112*54fd6939SJiyong Park 	if ((value >> shift) & 0x01)
113*54fd6939SJiyong Park 		return GPIO_LEVEL_HIGH;
114*54fd6939SJiyong Park 	return GPIO_LEVEL_LOW;
115*54fd6939SJiyong Park }
116*54fd6939SJiyong Park 
rpi3_gpio_set_value(int gpio,int value)117*54fd6939SJiyong Park static void rpi3_gpio_set_value(int gpio, int value)
118*54fd6939SJiyong Park {
119*54fd6939SJiyong Park 	int regN = gpio / 32;
120*54fd6939SJiyong Park 	int shift = gpio % 32;
121*54fd6939SJiyong Park 	uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN);
122*54fd6939SJiyong Park 	uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN);
123*54fd6939SJiyong Park 
124*54fd6939SJiyong Park 	switch (value) {
125*54fd6939SJiyong Park 	case GPIO_LEVEL_LOW:
126*54fd6939SJiyong Park 		mmio_write_32(reg_clr, U(1) << shift);
127*54fd6939SJiyong Park 		break;
128*54fd6939SJiyong Park 	case GPIO_LEVEL_HIGH:
129*54fd6939SJiyong Park 		mmio_write_32(reg_set, U(1) << shift);
130*54fd6939SJiyong Park 		break;
131*54fd6939SJiyong Park 	}
132*54fd6939SJiyong Park }
133*54fd6939SJiyong Park 
rpi3_gpio_set_pull(int gpio,int pull)134*54fd6939SJiyong Park static void rpi3_gpio_set_pull(int gpio, int pull)
135*54fd6939SJiyong Park {
136*54fd6939SJiyong Park 	int regN = gpio / 32;
137*54fd6939SJiyong Park 	int shift = gpio % 32;
138*54fd6939SJiyong Park 	uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD;
139*54fd6939SJiyong Park 	uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN);
140*54fd6939SJiyong Park 
141*54fd6939SJiyong Park 	switch (pull) {
142*54fd6939SJiyong Park 	case GPIO_PULL_NONE:
143*54fd6939SJiyong Park 		mmio_write_32(reg_pud, 0x0);
144*54fd6939SJiyong Park 		break;
145*54fd6939SJiyong Park 	case GPIO_PULL_UP:
146*54fd6939SJiyong Park 		mmio_write_32(reg_pud, 0x2);
147*54fd6939SJiyong Park 		break;
148*54fd6939SJiyong Park 	case GPIO_PULL_DOWN:
149*54fd6939SJiyong Park 		mmio_write_32(reg_pud, 0x1);
150*54fd6939SJiyong Park 		break;
151*54fd6939SJiyong Park 	}
152*54fd6939SJiyong Park 	mdelay(150);
153*54fd6939SJiyong Park 	mmio_write_32(reg_clk, U(1) << shift);
154*54fd6939SJiyong Park 	mdelay(150);
155*54fd6939SJiyong Park 	mmio_write_32(reg_clk, 0x0);
156*54fd6939SJiyong Park 	mmio_write_32(reg_pud, 0x0);
157*54fd6939SJiyong Park }
158*54fd6939SJiyong Park 
rpi3_gpio_init(void)159*54fd6939SJiyong Park void rpi3_gpio_init(void)
160*54fd6939SJiyong Park {
161*54fd6939SJiyong Park 	reg_base = RPI3_GPIO_BASE;
162*54fd6939SJiyong Park 	gpio_init(&rpi3_gpio_ops);
163*54fd6939SJiyong Park }
164