• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019, 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 <gpio/mtgpio.h>
11 #include <gpio/mtgpio_cfg.h>
12 #include <drivers/gpio.h>
13 #include <mcucfg.h>
14 #include <lib/mmio.h>
15 #include <platform_def.h>
16 #include <spm.h>
17 #include <stdbool.h>
18 
19 /******************************************************************************
20  *Macro Definition
21  ******************************************************************************/
22 #define GPIO_MODE_BITS		4
23 #define MAX_GPIO_MODE_PER_REG	8
24 #define MAX_GPIO_REG_BITS	32
25 #define DIR_BASE		(GPIO_BASE + 0x000)
26 #define DOUT_BASE		(GPIO_BASE + 0x100)
27 #define DIN_BASE		(GPIO_BASE + 0x200)
28 #define MODE_BASE		(GPIO_BASE + 0x300)
29 #define SET			0x4
30 #define CLR			0x8
31 #define PULLEN_ADDR_OFFSET	0x060
32 #define PULLSEL_ADDR_OFFSET	0x080
33 
mt_set_gpio_dir_chip(uint32_t pin,int dir)34 void mt_set_gpio_dir_chip(uint32_t pin, int dir)
35 {
36 	uint32_t pos, bit;
37 
38 	assert(pin < MAX_GPIO_PIN);
39 	assert(dir < GPIO_DIR_MAX);
40 
41 	pos = pin / MAX_GPIO_REG_BITS;
42 	bit = pin % MAX_GPIO_REG_BITS;
43 
44 	if (dir == GPIO_DIR_IN)
45 		mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit);
46 	else
47 		mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit);
48 }
49 
mt_get_gpio_dir_chip(uint32_t pin)50 int mt_get_gpio_dir_chip(uint32_t pin)
51 {
52 	uint32_t pos, bit;
53 	uint32_t reg;
54 
55 	assert(pin < MAX_GPIO_PIN);
56 
57 	pos = pin / MAX_GPIO_REG_BITS;
58 	bit = pin % MAX_GPIO_REG_BITS;
59 
60 	reg = mmio_read_32(DIR_BASE + 0x10 * pos);
61 	return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN);
62 }
63 
mt_set_gpio_out_chip(uint32_t pin,int output)64 void mt_set_gpio_out_chip(uint32_t pin, int output)
65 {
66 	uint32_t pos, bit;
67 
68 	assert(pin < MAX_GPIO_PIN);
69 	assert(output < GPIO_OUT_MAX);
70 
71 	pos = pin / MAX_GPIO_REG_BITS;
72 	bit = pin % MAX_GPIO_REG_BITS;
73 
74 	if (output == GPIO_OUT_ZERO)
75 		mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit);
76 	else
77 		mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit);
78 }
79 
mt_get_gpio_out_chip(uint32_t pin)80 int mt_get_gpio_out_chip(uint32_t pin)
81 {
82 	uint32_t pos, bit;
83 	uint32_t reg;
84 
85 	assert(pin < MAX_GPIO_PIN);
86 
87 	pos = pin / MAX_GPIO_REG_BITS;
88 	bit = pin % MAX_GPIO_REG_BITS;
89 
90 	reg = mmio_read_32(DOUT_BASE + 0x10 * pos);
91 	return (((reg & (1U << bit)) != 0) ? 1 : 0);
92 }
93 
mt_get_gpio_in_chip(uint32_t pin)94 int mt_get_gpio_in_chip(uint32_t pin)
95 {
96 	uint32_t pos, bit;
97 	uint32_t reg;
98 
99 	assert(pin < MAX_GPIO_PIN);
100 
101 	pos = pin / MAX_GPIO_REG_BITS;
102 	bit = pin % MAX_GPIO_REG_BITS;
103 
104 	reg = mmio_read_32(DIN_BASE + 0x10 * pos);
105 	return (((reg & (1U << bit)) != 0) ? 1 : 0);
106 }
107 
mt_set_gpio_mode_chip(uint32_t pin,int mode)108 void mt_set_gpio_mode_chip(uint32_t pin, int mode)
109 {
110 	uint32_t pos, bit;
111 	uint32_t data;
112 	uint32_t mask;
113 
114 	assert(pin < MAX_GPIO_PIN);
115 	assert(mode < GPIO_MODE_MAX);
116 
117 	mask = (1U << GPIO_MODE_BITS) - 1;
118 
119 	mode = mode & mask;
120 	pos = pin / MAX_GPIO_MODE_PER_REG;
121 	bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
122 
123 	data = mmio_read_32(MODE_BASE + 0x10 * pos);
124 	data &= (~(mask << bit));
125 	data |= (mode << bit);
126 	mmio_write_32(MODE_BASE + 0x10 * pos, data);
127 }
128 
mt_get_gpio_mode_chip(uint32_t pin)129 int mt_get_gpio_mode_chip(uint32_t pin)
130 {
131 	uint32_t pos, bit;
132 	uint32_t data;
133 	uint32_t mask;
134 
135 	assert(pin < MAX_GPIO_PIN);
136 
137 	mask = (1U << GPIO_MODE_BITS) - 1;
138 
139 	pos = pin / MAX_GPIO_MODE_PER_REG;
140 	bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
141 
142 	data = mmio_read_32(MODE_BASE + 0x10 * pos);
143 	return (data >> bit) & mask;
144 }
145 
gpio_get_pull_iocfg(uint32_t pin)146 int32_t gpio_get_pull_iocfg(uint32_t pin)
147 {
148 	switch (pin) {
149 	case 0 ... 10:
150 		return IOCFG_5_BASE;
151 	case 11 ... 12:
152 		return IOCFG_0_BASE;
153 	case 13 ... 28:
154 		return IOCFG_1_BASE;
155 	case 43 ... 49:
156 		return IOCFG_2_BASE;
157 	case 50 ... 60:
158 		return IOCFG_3_BASE;
159 	case 61 ... 88:
160 		return IOCFG_4_BASE;
161 	case 89 ... 90:
162 		return IOCFG_5_BASE;
163 	case 95 ... 106:
164 		return IOCFG_5_BASE;
165 	case 107 ... 121:
166 		return IOCFG_6_BASE;
167 	case 134 ... 160:
168 		return IOCFG_0_BASE;
169 	case 161 ... 166:
170 		return IOCFG_1_BASE;
171 	case 167 ... 176:
172 		return IOCFG_3_BASE;
173 	case 177 ... 179:
174 		return IOCFG_5_BASE;
175 	default:
176 		return -1;
177 	}
178 }
179 
gpio_get_pupd_iocfg(uint32_t pin)180 int32_t gpio_get_pupd_iocfg(uint32_t pin)
181 {
182 	const int32_t offset = 0x0c0;
183 
184 	switch (pin) {
185 	case 29 ... 34:
186 		return IOCFG_1_BASE + offset;
187 	case 35 ... 42:
188 		return IOCFG_2_BASE + offset;
189 	case 91 ... 94:
190 		return IOCFG_5_BASE + offset;
191 	case 122 ... 133:
192 		return IOCFG_7_BASE + offset;
193 	default:
194 		return -1;
195 	}
196 }
197 
gpio_get_pupd_offset(uint32_t pin)198 int gpio_get_pupd_offset(uint32_t pin)
199 {
200 	switch (pin) {
201 	case 29 ... 34:
202 		return (pin - 29) * 4 % 32;
203 	case 35 ... 42:
204 		return (pin - 35) * 4 % 32;
205 	case 91 ... 94:
206 		return (pin - 91) * 4 % 32;
207 	case 122 ... 129:
208 		return (pin - 122) * 4 % 32;
209 	case 130 ... 133:
210 		return (pin - 130) * 4 % 32;
211 	default:
212 		return -1;
213 	}
214 }
215 
mt_set_gpio_pull_enable_chip(uint32_t pin,int en)216 void mt_set_gpio_pull_enable_chip(uint32_t pin, int en)
217 {
218 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
219 	int pupd_addr = gpio_get_pupd_iocfg(pin);
220 	int pupd_offset = gpio_get_pupd_offset(pin);
221 
222 	assert(pin < MAX_GPIO_PIN);
223 
224 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
225 		(pupd_offset == (int8_t)-1)));
226 
227 	if (en == GPIO_PULL_DISABLE) {
228 		if (PULL_offset[pin].offset == (int8_t)-1)
229 			mmio_clrbits_32(pupd_addr, 3U << pupd_offset);
230 		else
231 			mmio_clrbits_32(pullen_addr,
232 					1U << PULL_offset[pin].offset);
233 	} else if (en == GPIO_PULL_ENABLE) {
234 		if (PULL_offset[pin].offset == (int8_t)-1) {
235 			/* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable
236 			 * does not know
237 			 * which one between PU and PD shall be enabled.
238 			 * Use R0 to guarantee at one resistor is set when lk
239 			 * apply default setting
240 			 */
241 			mmio_setbits_32(pupd_addr, 1U << pupd_offset);
242 			mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
243 		} else {
244 			/* For PULLEN + PULLSEL Type */
245 			mmio_setbits_32(pullen_addr,
246 					1U << PULL_offset[pin].offset);
247 		}
248 	} else if (en == GPIO_PULL_ENABLE_R0) {
249 		assert(!(pupd_offset == (int8_t)-1));
250 		mmio_setbits_32(pupd_addr, 1U << pupd_offset);
251 		mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
252 	} else if (en == GPIO_PULL_ENABLE_R1) {
253 		assert(!(pupd_offset == (int8_t)-1));
254 
255 		mmio_clrbits_32(pupd_addr, 1U << pupd_offset);
256 		mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1));
257 	} else if (en == GPIO_PULL_ENABLE_R0R1) {
258 		assert(!(pupd_offset == (int8_t)-1));
259 		mmio_setbits_32(pupd_addr, 3U << pupd_offset);
260 	}
261 }
262 
mt_get_gpio_pull_enable_chip(uint32_t pin)263 int mt_get_gpio_pull_enable_chip(uint32_t pin)
264 {
265 	uint32_t reg;
266 
267 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
268 	int pupd_addr = gpio_get_pupd_iocfg(pin);
269 	int pupd_offset = gpio_get_pupd_offset(pin);
270 
271 	assert(pin < MAX_GPIO_PIN);
272 
273 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
274 		(pupd_offset == (int8_t)-1)));
275 
276 	if (PULL_offset[pin].offset == (int8_t)-1) {
277 		reg = mmio_read_32(pupd_addr);
278 		return ((reg & (3U << pupd_offset)) ? 1 : 0);
279 	} else if (pupd_offset == (int8_t)-1) {
280 		reg = mmio_read_32(pullen_addr);
281 		return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0);
282 	}
283 
284 	return -ERINVAL;
285 }
286 
mt_set_gpio_pull_select_chip(uint32_t pin,int sel)287 void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
288 {
289 	int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
290 	int pupd_addr = gpio_get_pupd_iocfg(pin);
291 	int pupd_offset = gpio_get_pupd_offset(pin);
292 
293 	assert(pin < MAX_GPIO_PIN);
294 
295 	assert(!((PULL_offset[pin].offset == (int8_t) -1) &&
296 		(pupd_offset == (int8_t)-1)));
297 
298 	if (sel == GPIO_PULL_NONE) {
299 		/*  Regard No PULL as PULL disable + pull down */
300 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE);
301 		if (PULL_offset[pin].offset == (int8_t)-1)
302 			mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
303 		else
304 			mmio_clrbits_32(pullsel_addr,
305 					1U << PULL_offset[pin].offset);
306 	} else if (sel == GPIO_PULL_UP) {
307 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
308 		if (PULL_offset[pin].offset == (int8_t)-1)
309 			mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2));
310 		else
311 			mmio_setbits_32(pullsel_addr,
312 					1U << PULL_offset[pin].offset);
313 	} else if (sel == GPIO_PULL_DOWN) {
314 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
315 		if (PULL_offset[pin].offset == -1)
316 			mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
317 		else
318 			mmio_clrbits_32(pullsel_addr,
319 					1U << PULL_offset[pin].offset);
320 	}
321 }
322 
323 /* get pull-up or pull-down, regardless of resistor value */
mt_get_gpio_pull_select_chip(uint32_t pin)324 int mt_get_gpio_pull_select_chip(uint32_t pin)
325 {
326 	uint32_t reg;
327 
328 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
329 	int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
330 	int pupd_addr = gpio_get_pupd_iocfg(pin);
331 	int pupd_offset = gpio_get_pupd_offset(pin);
332 
333 	assert(pin < MAX_GPIO_PIN);
334 
335 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
336 		(pupd_offset == (int8_t)-1)));
337 
338 	if (PULL_offset[pin].offset == (int8_t)-1) {
339 		reg = mmio_read_32(pupd_addr);
340 		if (reg & (3U << pupd_offset)) {
341 			reg = mmio_read_32(pupd_addr);
342 			/* Reg value: 0 for PU, 1 for PD -->
343 			 * reverse return value */
344 			return ((reg & (1U << (pupd_offset + 2))) ?
345 					GPIO_PULL_DOWN : GPIO_PULL_UP);
346 		} else {
347 			return GPIO_PULL_NONE;
348 		}
349 	} else if (pupd_offset == (int8_t)-1) {
350 		reg = mmio_read_32(pullen_addr);
351 		if ((reg & (1U << PULL_offset[pin].offset))) {
352 			reg = mmio_read_32(pullsel_addr);
353 			return ((reg & (1U << PULL_offset[pin].offset)) ?
354 					GPIO_PULL_UP : GPIO_PULL_DOWN);
355 		} else {
356 			return GPIO_PULL_NONE;
357 		}
358 	}
359 
360 	return -ERINVAL;
361 }
362 
mt_set_gpio_dir(int gpio,int direction)363 void mt_set_gpio_dir(int gpio, int direction)
364 {
365 	mt_set_gpio_dir_chip((uint32_t)gpio, direction);
366 }
367 
mt_get_gpio_dir(int gpio)368 int mt_get_gpio_dir(int gpio)
369 {
370 	uint32_t pin;
371 
372 	pin = (uint32_t)gpio;
373 	return mt_get_gpio_dir_chip(pin);
374 }
375 
mt_set_gpio_pull(int gpio,int pull)376 void mt_set_gpio_pull(int gpio, int pull)
377 {
378 	uint32_t pin;
379 
380 	pin = (uint32_t)gpio;
381 	mt_set_gpio_pull_select_chip(pin, pull);
382 }
383 
mt_get_gpio_pull(int gpio)384 int mt_get_gpio_pull(int gpio)
385 {
386 	uint32_t pin;
387 
388 	pin = (uint32_t)gpio;
389 	return mt_get_gpio_pull_select_chip(pin);
390 }
391 
mt_set_gpio_out(int gpio,int value)392 void mt_set_gpio_out(int gpio, int value)
393 {
394 	uint32_t pin;
395 
396 	pin = (uint32_t)gpio;
397 	mt_set_gpio_out_chip(pin, value);
398 }
399 
mt_get_gpio_out(int gpio)400 int mt_get_gpio_out(int gpio)
401 {
402 	uint32_t pin;
403 
404 	pin = (uint32_t)gpio;
405 	return mt_get_gpio_out_chip(pin);
406 }
407 
mt_get_gpio_in(int gpio)408 int mt_get_gpio_in(int gpio)
409 {
410 	uint32_t pin;
411 
412 	pin = (uint32_t)gpio;
413 	return mt_get_gpio_in_chip(pin);
414 }
415 
mt_set_gpio_mode(int gpio,int mode)416 void mt_set_gpio_mode(int gpio, int mode)
417 {
418 	uint32_t pin;
419 
420 	pin = (uint32_t)gpio;
421 	mt_set_gpio_mode_chip(pin, mode);
422 }
423 
mt_get_gpio_mode(int gpio)424 int mt_get_gpio_mode(int gpio)
425 {
426 	uint32_t pin;
427 
428 	pin = (uint32_t)gpio;
429 	return mt_get_gpio_mode_chip(pin);
430 }
431 
432 const gpio_ops_t mtgpio_ops = {
433 	 .get_direction = mt_get_gpio_dir,
434 	 .set_direction = mt_set_gpio_dir,
435 	 .get_value = mt_get_gpio_in,
436 	 .set_value = mt_set_gpio_out,
437 	 .set_pull = mt_set_gpio_pull,
438 	 .get_pull = mt_get_gpio_pull,
439 };
440