blob: e07b75a4766169f323d962cf505326296850554a [file] [log] [blame]
developer404e08b2020-09-18 09:32:31 +08001/*
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
28static 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
45static 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
59static 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
76static 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
90static 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
132static 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
157static 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
184static 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
197static 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
225static 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
250static 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
262static 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 */
276static 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
283static void mt_set_gpio_dir(int gpio, int direction)
284{
285 mt_set_gpio_dir_chip((uint32_t)gpio, direction);
286}
287
288static 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
296static 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
304static 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
312static 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
320static 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
328const 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
337void plat_mt8192_gpio_init(void)
338{
339 gpio_init(&mtgpio_ops);
340}