1 /*
2 * Copyright (c) 2020-2022, 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 <lib/mtk_init/mtk_init.h>
13 #include <mtgpio.h>
14 #include <platform_def.h>
15
16 /******************************************************************************
17 *Macro Definition
18 ******************************************************************************/
19 #define GPIO_MODE_BITS 4
20 #define MAX_GPIO_MODE_PER_REG 8
21 #define MAX_GPIO_REG_BITS 32
22 #define DIR_BASE (GPIO_BASE + 0x000)
23 #define DOUT_BASE (GPIO_BASE + 0x100)
24 #define DIN_BASE (GPIO_BASE + 0x200)
25 #define MODE_BASE (GPIO_BASE + 0x300)
26 #define SET 0x4
27 #define CLR 0x8
28
mt_set_gpio_dir_chip(uint32_t pin,int dir)29 static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
30 {
31 uint32_t pos, bit;
32
33 assert(pin < MAX_GPIO_PIN);
34 assert(dir < MT_GPIO_DIR_MAX);
35
36 pos = pin / MAX_GPIO_REG_BITS;
37 bit = pin % MAX_GPIO_REG_BITS;
38
39 if (dir == MT_GPIO_DIR_IN) {
40 mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
41 } else {
42 mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
43 }
44 }
45
mt_get_gpio_dir_chip(uint32_t pin)46 static int mt_get_gpio_dir_chip(uint32_t pin)
47 {
48 uint32_t pos, bit;
49 uint32_t reg;
50
51 assert(pin < MAX_GPIO_PIN);
52
53 pos = pin / MAX_GPIO_REG_BITS;
54 bit = pin % MAX_GPIO_REG_BITS;
55
56 reg = mmio_read_32(DIR_BASE + 0x10U * pos);
57 return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
58 }
59
mt_set_gpio_out_chip(uint32_t pin,int output)60 static void mt_set_gpio_out_chip(uint32_t pin, int output)
61 {
62 uint32_t pos, bit;
63
64 assert(pin < MAX_GPIO_PIN);
65 assert(output < MT_GPIO_OUT_MAX);
66
67 pos = pin / MAX_GPIO_REG_BITS;
68 bit = pin % MAX_GPIO_REG_BITS;
69
70 if (output == MT_GPIO_OUT_ZERO) {
71 mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
72 } else {
73 mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
74 }
75 }
76
mt_get_gpio_in_chip(uint32_t pin)77 static int mt_get_gpio_in_chip(uint32_t pin)
78 {
79 uint32_t pos, bit;
80 uint32_t reg;
81
82 assert(pin < MAX_GPIO_PIN);
83
84 pos = pin / MAX_GPIO_REG_BITS;
85 bit = pin % MAX_GPIO_REG_BITS;
86
87 reg = mmio_read_32(DIN_BASE + 0x10U * pos);
88 return (((reg & (1U << bit)) != 0U) ? 1 : 0);
89 }
90
mt_gpio_set_spec_pull_pupd(uint32_t pin,int enable,int select)91 static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
92 int select)
93 {
94 uintptr_t reg1;
95 uintptr_t reg2;
96 struct mt_pin_info gpio_info;
97
98 gpio_info = mt_pin_infos[pin];
99 uint32_t bit = gpio_info.bit;
100
101 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
102 reg2 = reg1 + (gpio_info.base & 0xf0);
103 if (enable == MT_GPIO_PULL_ENABLE) {
104 mmio_write_32(reg2 + SET, (1U << bit));
105 if (select == MT_GPIO_PULL_DOWN) {
106 mmio_write_32(reg1 + SET, (1U << bit));
107 } else {
108 mmio_write_32(reg1 + CLR, (1U << bit));
109 }
110 } else {
111 mmio_write_32(reg2 + CLR, (1U << bit));
112 mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
113 }
114 }
115
mt_gpio_set_pull_pu_pd(uint32_t pin,int enable,int select)116 static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
117 int select)
118 {
119 uintptr_t reg1;
120 uintptr_t reg2;
121 struct mt_pin_info gpio_info;
122
123 gpio_info = mt_pin_infos[pin];
124 uint32_t bit = gpio_info.bit;
125
126 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
127 reg2 = reg1 - (gpio_info.base & 0xf0);
128
129 if (enable == MT_GPIO_PULL_ENABLE) {
130 if (select == MT_GPIO_PULL_DOWN) {
131 mmio_write_32(reg1 + CLR, (1U << bit));
132 mmio_write_32(reg2 + SET, (1U << bit));
133 } else {
134 mmio_write_32(reg2 + CLR, (1U << bit));
135 mmio_write_32(reg1 + SET, (1U << bit));
136 }
137 } else {
138 mmio_write_32(reg1 + CLR, (1U << bit));
139 mmio_write_32(reg2 + CLR, (1U << bit));
140 }
141 }
142
mt_gpio_set_pull_chip(uint32_t pin,int enable,int select)143 static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
144 int select)
145 {
146 struct mt_pin_info gpio_info;
147
148 gpio_info = mt_pin_infos[pin];
149 if (gpio_info.flag) {
150 mt_gpio_set_spec_pull_pupd(pin, enable, select);
151 } else {
152 mt_gpio_set_pull_pu_pd(pin, enable, select);
153 }
154 }
155
mt_gpio_get_spec_pull_pupd(uint32_t pin)156 static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
157 {
158 uintptr_t reg1;
159 uintptr_t reg2;
160 uint32_t r0;
161 uint32_t r1;
162
163 struct mt_pin_info gpio_info;
164
165 gpio_info = mt_pin_infos[pin];
166 uint32_t bit = gpio_info.bit;
167
168 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
169 reg2 = reg1 + (gpio_info.base & 0xf0);
170
171 r0 = (mmio_read_32(reg2) >> bit) & 1U;
172 r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
173 if (r0 == 0U && r1 == 0U) {
174 return MT_GPIO_PULL_NONE;
175 } else {
176 if (mmio_read_32(reg1) & (1U << bit)) {
177 return MT_GPIO_PULL_DOWN;
178 } else {
179 return MT_GPIO_PULL_UP;
180 }
181 }
182 }
183
mt_gpio_get_pull_pu_pd(uint32_t pin)184 static int mt_gpio_get_pull_pu_pd(uint32_t pin)
185 {
186 uintptr_t reg1;
187 uintptr_t reg2;
188 uint32_t pu;
189 uint32_t pd;
190
191 struct mt_pin_info gpio_info;
192
193 gpio_info = mt_pin_infos[pin];
194 uint32_t bit = gpio_info.bit;
195
196 reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
197 reg2 = reg1 - (gpio_info.base & 0xf0);
198 pu = (mmio_read_32(reg1) >> bit) & 1U;
199 pd = (mmio_read_32(reg2) >> bit) & 1U;
200 if (pu == 1U) {
201 return MT_GPIO_PULL_UP;
202 } else if (pd == 1U) {
203 return MT_GPIO_PULL_DOWN;
204 } else {
205 return MT_GPIO_PULL_NONE;
206 }
207 }
208
mt_gpio_get_pull_chip(uint32_t pin)209 static int mt_gpio_get_pull_chip(uint32_t pin)
210 {
211 struct mt_pin_info gpio_info;
212
213 gpio_info = mt_pin_infos[pin];
214 if (gpio_info.flag) {
215 return mt_gpio_get_spec_pull_pupd(pin);
216 } else {
217 return mt_gpio_get_pull_pu_pd(pin);
218 }
219 }
220
mt_set_gpio_pull_select_chip(uint32_t pin,int sel)221 static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
222 {
223 assert(pin < MAX_GPIO_PIN);
224
225 if (sel == MT_GPIO_PULL_NONE) {
226 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
227 } else if (sel == MT_GPIO_PULL_UP) {
228 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
229 } else if (sel == MT_GPIO_PULL_DOWN) {
230 mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
231 }
232 }
233
234 /* get pull-up or pull-down, regardless of resistor value */
mt_get_gpio_pull_select_chip(uint32_t pin)235 static int mt_get_gpio_pull_select_chip(uint32_t pin)
236 {
237 assert(pin < MAX_GPIO_PIN);
238
239 return mt_gpio_get_pull_chip(pin);
240 }
241
mt_set_gpio_dir(int gpio,int direction)242 static void mt_set_gpio_dir(int gpio, int direction)
243 {
244 mt_set_gpio_dir_chip((uint32_t)gpio, direction);
245 }
246
mt_get_gpio_dir(int gpio)247 static int mt_get_gpio_dir(int gpio)
248 {
249 uint32_t pin;
250
251 pin = (uint32_t)gpio;
252 return mt_get_gpio_dir_chip(pin);
253 }
254
mt_set_gpio_pull(int gpio,int pull)255 static void mt_set_gpio_pull(int gpio, int pull)
256 {
257 uint32_t pin;
258
259 pin = (uint32_t)gpio;
260 mt_set_gpio_pull_select_chip(pin, pull);
261 }
262
mt_get_gpio_pull(int gpio)263 static int mt_get_gpio_pull(int gpio)
264 {
265 uint32_t pin;
266
267 pin = (uint32_t)gpio;
268 return mt_get_gpio_pull_select_chip(pin);
269 }
270
mt_set_gpio_out(int gpio,int value)271 static void mt_set_gpio_out(int gpio, int value)
272 {
273 uint32_t pin;
274
275 pin = (uint32_t)gpio;
276 mt_set_gpio_out_chip(pin, value);
277 }
278
mt_get_gpio_in(int gpio)279 static int mt_get_gpio_in(int gpio)
280 {
281 uint32_t pin;
282
283 pin = (uint32_t)gpio;
284 return mt_get_gpio_in_chip(pin);
285 }
286
287 const gpio_ops_t mtgpio_ops = {
288 .get_direction = mt_get_gpio_dir,
289 .set_direction = mt_set_gpio_dir,
290 .get_value = mt_get_gpio_in,
291 .set_value = mt_set_gpio_out,
292 .set_pull = mt_set_gpio_pull,
293 .get_pull = mt_get_gpio_pull,
294 };
295
mt_gpio_init(void)296 int mt_gpio_init(void)
297 {
298 gpio_init(&mtgpio_ops);
299
300 return 0;
301 }
302 MTK_PLAT_SETUP_0_INIT(mt_gpio_init);
303