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