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