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