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