• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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