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