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_find_reg_addr(uint32_t pin)90 static uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
91 {
92 uintptr_t reg_addr = 0U;
93 struct mt_pin_info gpio_info;
94
95 gpio_info = mt8192_pin_infos[pin];
96
97 switch (gpio_info.base & 0x0f) {
98 case 0:
99 reg_addr = IOCFG_RM_BASE;
100 break;
101 case 1:
102 reg_addr = IOCFG_BM_BASE;
103 break;
104 case 2:
105 reg_addr = IOCFG_BL_BASE;
106 break;
107 case 3:
108 reg_addr = IOCFG_BR_BASE;
109 break;
110 case 4:
111 reg_addr = IOCFG_LM_BASE;
112 break;
113 case 5:
114 reg_addr = IOCFG_LB_BASE;
115 break;
116 case 6:
117 reg_addr = IOCFG_RT_BASE;
118 break;
119 case 7:
120 reg_addr = IOCFG_LT_BASE;
121 break;
122 case 8:
123 reg_addr = IOCFG_TL_BASE;
124 break;
125 default:
126 break;
127 }
128
129 return reg_addr;
130 }
131
mt_gpio_set_spec_pull_pupd(uint32_t pin,int enable,int select)132 static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
133 int select)
134 {
135 uintptr_t reg1;
136 uintptr_t reg2;
137 struct mt_pin_info gpio_info;
138
139 gpio_info = mt8192_pin_infos[pin];
140 uint32_t bit = gpio_info.bit;
141
142 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
143 reg2 = reg1 + (gpio_info.base & 0xf0);
144 if (enable == MT_GPIO_PULL_ENABLE) {
145 mmio_write_32(reg2 + SET, (1U << bit));
146 if (select == MT_GPIO_PULL_DOWN) {
147 mmio_write_32(reg1 + SET, (1U << bit));
148 } else {
149 mmio_write_32(reg1 + CLR, (1U << bit));
150 }
151 } else {
152 mmio_write_32(reg2 + CLR, (1U << bit));
153 mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
154 }
155 }
156
mt_gpio_set_pull_pu_pd(uint32_t pin,int enable,int select)157 static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
158 int select)
159 {
160 uintptr_t reg1;
161 uintptr_t reg2;
162 struct mt_pin_info gpio_info;
163
164 gpio_info = mt8192_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 if (enable == MT_GPIO_PULL_ENABLE) {
171 if (select == MT_GPIO_PULL_DOWN) {
172 mmio_write_32(reg1 + CLR, (1U << bit));
173 mmio_write_32(reg2 + SET, (1U << bit));
174 } else {
175 mmio_write_32(reg2 + CLR, (1U << bit));
176 mmio_write_32(reg1 + SET, (1U << bit));
177 }
178 } else {
179 mmio_write_32(reg1 + CLR, (1U << bit));
180 mmio_write_32(reg2 + CLR, (1U << bit));
181 }
182 }
183
mt_gpio_set_pull_chip(uint32_t pin,int enable,int select)184 static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
185 int select)
186 {
187 struct mt_pin_info gpio_info;
188
189 gpio_info = mt8192_pin_infos[pin];
190 if (gpio_info.flag) {
191 mt_gpio_set_spec_pull_pupd(pin, enable, select);
192 } else {
193 mt_gpio_set_pull_pu_pd(pin, enable, select);
194 }
195 }
196
mt_gpio_get_spec_pull_pupd(uint32_t pin)197 static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
198 {
199 uintptr_t reg1;
200 uintptr_t reg2;
201 uint32_t r0;
202 uint32_t r1;
203
204 struct mt_pin_info gpio_info;
205
206 gpio_info = mt8192_pin_infos[pin];
207 uint32_t bit = gpio_info.bit;
208
209 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
210 reg2 = reg1 + (gpio_info.base & 0xf0);
211
212 r0 = (mmio_read_32(reg2) >> bit) & 1U;
213 r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
214 if (r0 == 0U && r1 == 0U) {
215 return MT_GPIO_PULL_NONE;
216 } else {
217 if (mmio_read_32(reg1) & (1U << bit)) {
218 return MT_GPIO_PULL_DOWN;
219 } else {
220 return MT_GPIO_PULL_UP;
221 }
222 }
223 }
224
mt_gpio_get_pull_pu_pd(uint32_t pin)225 static int mt_gpio_get_pull_pu_pd(uint32_t pin)
226 {
227 uintptr_t reg1;
228 uintptr_t reg2;
229 uint32_t pu;
230 uint32_t pd;
231
232 struct mt_pin_info gpio_info;
233
234 gpio_info = mt8192_pin_infos[pin];
235 uint32_t bit = gpio_info.bit;
236
237 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
238 reg2 = reg1 - (gpio_info.base & 0xf0);
239 pu = (mmio_read_32(reg1) >> bit) & 1U;
240 pd = (mmio_read_32(reg2) >> bit) & 1U;
241 if (pu == 1U) {
242 return MT_GPIO_PULL_UP;
243 } else if (pd == 1U) {
244 return MT_GPIO_PULL_DOWN;
245 } else {
246 return MT_GPIO_PULL_NONE;
247 }
248 }
249
mt_gpio_get_pull_chip(uint32_t pin)250 static int mt_gpio_get_pull_chip(uint32_t pin)
251 {
252 struct mt_pin_info gpio_info;
253
254 gpio_info = mt8192_pin_infos[pin];
255 if (gpio_info.flag) {
256 return mt_gpio_get_spec_pull_pupd(pin);
257 } else {
258 return mt_gpio_get_pull_pu_pd(pin);
259 }
260 }
261
mt_set_gpio_pull_select_chip(uint32_t pin,int sel)262 static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
263 {
264 assert(pin < MAX_GPIO_PIN);
265
266 if (sel == MT_GPIO_PULL_NONE) {
267 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
268 } else if (sel == MT_GPIO_PULL_UP) {
269 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
270 } else if (sel == MT_GPIO_PULL_DOWN) {
271 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
272 }
273 }
274
275 /* get pull-up or pull-down, regardless of resistor value */
mt_get_gpio_pull_select_chip(uint32_t pin)276 static int mt_get_gpio_pull_select_chip(uint32_t pin)
277 {
278 assert(pin < MAX_GPIO_PIN);
279
280 return mt_gpio_get_pull_chip(pin);
281 }
282
mt_set_gpio_dir(int gpio,int direction)283 static void mt_set_gpio_dir(int gpio, int direction)
284 {
285 mt_set_gpio_dir_chip((uint32_t)gpio, direction);
286 }
287
mt_get_gpio_dir(int gpio)288 static int mt_get_gpio_dir(int gpio)
289 {
290 uint32_t pin;
291
292 pin = (uint32_t)gpio;
293 return mt_get_gpio_dir_chip(pin);
294 }
295
mt_set_gpio_pull(int gpio,int pull)296 static void mt_set_gpio_pull(int gpio, int pull)
297 {
298 uint32_t pin;
299
300 pin = (uint32_t)gpio;
301 mt_set_gpio_pull_select_chip(pin, pull);
302 }
303
mt_get_gpio_pull(int gpio)304 static int mt_get_gpio_pull(int gpio)
305 {
306 uint32_t pin;
307
308 pin = (uint32_t)gpio;
309 return mt_get_gpio_pull_select_chip(pin);
310 }
311
mt_set_gpio_out(int gpio,int value)312 static void mt_set_gpio_out(int gpio, int value)
313 {
314 uint32_t pin;
315
316 pin = (uint32_t)gpio;
317 mt_set_gpio_out_chip(pin, value);
318 }
319
mt_get_gpio_in(int gpio)320 static int mt_get_gpio_in(int gpio)
321 {
322 uint32_t pin;
323
324 pin = (uint32_t)gpio;
325 return mt_get_gpio_in_chip(pin);
326 }
327
328 const gpio_ops_t mtgpio_ops = {
329 .get_direction = mt_get_gpio_dir,
330 .set_direction = mt_set_gpio_dir,
331 .get_value = mt_get_gpio_in,
332 .set_value = mt_set_gpio_out,
333 .set_pull = mt_set_gpio_pull,
334 .get_pull = mt_get_gpio_pull,
335 };
336
plat_mt8192_gpio_init(void)337 void plat_mt8192_gpio_init(void)
338 {
339 gpio_init(&mtgpio_ops);
340 }
341