blob: 61aaeefbc591243ef6e434d3b81ede195709465d [file] [log] [blame]
developerb7ba14b2019-05-02 20:24:50 +08001/*
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
34void 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
50int 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
64void 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
80int 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
94int 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
108void 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
129int 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
146int32_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
180int32_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
198int 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
216void 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
263int 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
287void 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 */
324int 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
363void mt_set_gpio_dir(int gpio, int direction)
364{
365 mt_set_gpio_dir_chip((uint32_t)gpio, direction);
366}
367
368int 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
376void 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
384int 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
392void 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
400int 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
408int 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
416void 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
424int 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
432const 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};