1 /*
2  * Copyright (c) 2020, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <common/debug.h>
9 #include <drivers/delay_timer.h>
10 #include <drivers/gpio.h>
11 #include <lib/mmio.h>
12 #include <mtgpio.h>
13 #include <platform_def.h>
14 
15 /******************************************************************************
16  *Macro Definition
17  ******************************************************************************/
18 #define GPIO_MODE_BITS		4
19 #define MAX_GPIO_MODE_PER_REG	8
20 #define MAX_GPIO_REG_BITS	32
21 #define DIR_BASE		(GPIO_BASE + 0x000)
22 #define DOUT_BASE		(GPIO_BASE + 0x100)
23 #define DIN_BASE		(GPIO_BASE + 0x200)
24 #define MODE_BASE		(GPIO_BASE + 0x300)
25 #define SET			0x4
26 #define CLR			0x8
27 
mt_set_gpio_dir_chip(uint32_t pin,int dir)28 static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
29 {
30 	uint32_t pos, bit;
31 
32 	assert(pin < MAX_GPIO_PIN);
33 	assert(dir < MT_GPIO_DIR_MAX);
34 
35 	pos = pin / MAX_GPIO_REG_BITS;
36 	bit = pin % MAX_GPIO_REG_BITS;
37 
38 	if (dir == MT_GPIO_DIR_IN) {
39 		mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
40 	} else {
41 		mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
42 	}
43 }
44 
mt_get_gpio_dir_chip(uint32_t pin)45 static int mt_get_gpio_dir_chip(uint32_t pin)
46 {
47 	uint32_t pos, bit;
48 	uint32_t reg;
49 
50 	assert(pin < MAX_GPIO_PIN);
51 
52 	pos = pin / MAX_GPIO_REG_BITS;
53 	bit = pin % MAX_GPIO_REG_BITS;
54 
55 	reg = mmio_read_32(DIR_BASE + 0x10U * pos);
56 	return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
57 }
58 
mt_set_gpio_out_chip(uint32_t pin,int output)59 static void mt_set_gpio_out_chip(uint32_t pin, int output)
60 {
61 	uint32_t pos, bit;
62 
63 	assert(pin < MAX_GPIO_PIN);
64 	assert(output < MT_GPIO_OUT_MAX);
65 
66 	pos = pin / MAX_GPIO_REG_BITS;
67 	bit = pin % MAX_GPIO_REG_BITS;
68 
69 	if (output == MT_GPIO_OUT_ZERO) {
70 		mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
71 	} else {
72 		mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
73 	}
74 }
75 
mt_get_gpio_in_chip(uint32_t pin)76 static int mt_get_gpio_in_chip(uint32_t pin)
77 {
78 	uint32_t pos, bit;
79 	uint32_t reg;
80 
81 	assert(pin < MAX_GPIO_PIN);
82 
83 	pos = pin / MAX_GPIO_REG_BITS;
84 	bit = pin % MAX_GPIO_REG_BITS;
85 
86 	reg = mmio_read_32(DIN_BASE + 0x10U * pos);
87 	return (((reg & (1U << bit)) != 0U) ? 1 : 0);
88 }
89 
mt_gpio_set_spec_pull_pupd(uint32_t pin,int enable,int select)90 static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
91 			       int select)
92 {
93 	uintptr_t reg1;
94 	uintptr_t reg2;
95 	struct mt_pin_info gpio_info;
96 
97 	gpio_info = mt_pin_infos[pin];
98 	uint32_t bit = gpio_info.bit;
99 
100 	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
101 	reg2 = reg1 + (gpio_info.base & 0xf0);
102 	if (enable == MT_GPIO_PULL_ENABLE) {
103 		mmio_write_32(reg2 + SET, (1U << bit));
104 		if (select == MT_GPIO_PULL_DOWN) {
105 			mmio_write_32(reg1 + SET, (1U << bit));
106 		} else {
107 			mmio_write_32(reg1 + CLR, (1U << bit));
108 		}
109 	} else {
110 		mmio_write_32(reg2 + CLR, (1U << bit));
111 		mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
112 	}
113 }
114 
mt_gpio_set_pull_pu_pd(uint32_t pin,int enable,int select)115 static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
116 				 int select)
117 {
118 	uintptr_t reg1;
119 	uintptr_t reg2;
120 	struct mt_pin_info gpio_info;
121 
122 	gpio_info = mt_pin_infos[pin];
123 	uint32_t bit = gpio_info.bit;
124 
125 	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
126 	reg2 = reg1 - (gpio_info.base & 0xf0);
127 
128 	if (enable == MT_GPIO_PULL_ENABLE) {
129 		if (select == MT_GPIO_PULL_DOWN) {
130 			mmio_write_32(reg1 + CLR, (1U << bit));
131 			mmio_write_32(reg2 + SET, (1U << bit));
132 		} else {
133 			mmio_write_32(reg2 + CLR, (1U << bit));
134 			mmio_write_32(reg1 + SET, (1U << bit));
135 		}
136 	} else {
137 		mmio_write_32(reg1 + CLR, (1U << bit));
138 		mmio_write_32(reg2 + CLR, (1U << bit));
139 	}
140 }
141 
mt_gpio_set_pull_chip(uint32_t pin,int enable,int select)142 static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
143 		   int select)
144 {
145 	struct mt_pin_info gpio_info;
146 
147 	gpio_info = mt_pin_infos[pin];
148 	if (gpio_info.flag) {
149 		mt_gpio_set_spec_pull_pupd(pin, enable, select);
150 	} else {
151 		mt_gpio_set_pull_pu_pd(pin, enable, select);
152 	}
153 }
154 
mt_gpio_get_spec_pull_pupd(uint32_t pin)155 static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
156 {
157 	uintptr_t reg1;
158 	uintptr_t reg2;
159 	uint32_t r0;
160 	uint32_t r1;
161 
162 	struct mt_pin_info gpio_info;
163 
164 	gpio_info = mt_pin_infos[pin];
165 	uint32_t bit = gpio_info.bit;
166 
167 	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
168 	reg2 = reg1 + (gpio_info.base & 0xf0);
169 
170 	r0 = (mmio_read_32(reg2) >> bit) & 1U;
171 	r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
172 	if (r0 == 0U && r1 == 0U) {
173 		return MT_GPIO_PULL_NONE;
174 	} else {
175 		if (mmio_read_32(reg1) & (1U << bit)) {
176 			return MT_GPIO_PULL_DOWN;
177 		} else {
178 			return MT_GPIO_PULL_UP;
179 		}
180 	}
181 }
182 
mt_gpio_get_pull_pu_pd(uint32_t pin)183 static int mt_gpio_get_pull_pu_pd(uint32_t pin)
184 {
185 	uintptr_t reg1;
186 	uintptr_t reg2;
187 	uint32_t pu;
188 	uint32_t pd;
189 
190 	struct mt_pin_info gpio_info;
191 
192 	gpio_info = mt_pin_infos[pin];
193 	uint32_t bit = gpio_info.bit;
194 
195 	reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
196 	reg2 = reg1 - (gpio_info.base & 0xf0);
197 	pu = (mmio_read_32(reg1) >> bit) & 1U;
198 	pd = (mmio_read_32(reg2) >> bit) & 1U;
199 	if (pu == 1U) {
200 		return MT_GPIO_PULL_UP;
201 	} else if (pd == 1U) {
202 		return MT_GPIO_PULL_DOWN;
203 	} else {
204 		return MT_GPIO_PULL_NONE;
205 	}
206 }
207 
mt_gpio_get_pull_chip(uint32_t pin)208 static int mt_gpio_get_pull_chip(uint32_t pin)
209 {
210 	struct mt_pin_info gpio_info;
211 
212 	gpio_info = mt_pin_infos[pin];
213 	if (gpio_info.flag) {
214 		return mt_gpio_get_spec_pull_pupd(pin);
215 	} else {
216 		return mt_gpio_get_pull_pu_pd(pin);
217 	}
218 }
219 
mt_set_gpio_pull_select_chip(uint32_t pin,int sel)220 static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
221 {
222 	assert(pin < MAX_GPIO_PIN);
223 
224 	if (sel == MT_GPIO_PULL_NONE) {
225 		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
226 	} else if (sel == MT_GPIO_PULL_UP) {
227 		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
228 	} else if (sel == MT_GPIO_PULL_DOWN) {
229 		mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
230 	}
231 }
232 
233 /* get pull-up or pull-down, regardless of resistor value */
mt_get_gpio_pull_select_chip(uint32_t pin)234 static int mt_get_gpio_pull_select_chip(uint32_t pin)
235 {
236 	assert(pin < MAX_GPIO_PIN);
237 
238 	return mt_gpio_get_pull_chip(pin);
239 }
240 
mt_set_gpio_dir(int gpio,int direction)241 static void mt_set_gpio_dir(int gpio, int direction)
242 {
243 	mt_set_gpio_dir_chip((uint32_t)gpio, direction);
244 }
245 
mt_get_gpio_dir(int gpio)246 static int mt_get_gpio_dir(int gpio)
247 {
248 	uint32_t pin;
249 
250 	pin = (uint32_t)gpio;
251 	return mt_get_gpio_dir_chip(pin);
252 }
253 
mt_set_gpio_pull(int gpio,int pull)254 static void mt_set_gpio_pull(int gpio, int pull)
255 {
256 	uint32_t pin;
257 
258 	pin = (uint32_t)gpio;
259 	mt_set_gpio_pull_select_chip(pin, pull);
260 }
261 
mt_get_gpio_pull(int gpio)262 static int mt_get_gpio_pull(int gpio)
263 {
264 	uint32_t pin;
265 
266 	pin = (uint32_t)gpio;
267 	return mt_get_gpio_pull_select_chip(pin);
268 }
269 
mt_set_gpio_out(int gpio,int value)270 static void mt_set_gpio_out(int gpio, int value)
271 {
272 	uint32_t pin;
273 
274 	pin = (uint32_t)gpio;
275 	mt_set_gpio_out_chip(pin, value);
276 }
277 
mt_get_gpio_in(int gpio)278 static int mt_get_gpio_in(int gpio)
279 {
280 	uint32_t pin;
281 
282 	pin = (uint32_t)gpio;
283 	return mt_get_gpio_in_chip(pin);
284 }
285 
286 const gpio_ops_t mtgpio_ops = {
287 	 .get_direction = mt_get_gpio_dir,
288 	 .set_direction = mt_set_gpio_dir,
289 	 .get_value = mt_get_gpio_in,
290 	 .set_value = mt_set_gpio_out,
291 	 .set_pull = mt_set_gpio_pull,
292 	 .get_pull = mt_get_gpio_pull,
293 };
294 
mt_gpio_init(void)295 void mt_gpio_init(void)
296 {
297 	gpio_init(&mtgpio_ops);
298 }
299