xref: /rk3399_ARM-atf/plat/mediatek/mt8183/drivers/gpio/mtgpio.c (revision 76eac18647f3bb81e029309ea61f8c4c5336ca27)
1*50cd9522Skenny liang /*
2*50cd9522Skenny liang  * Copyright (c) 2019, MediaTek Inc. All rights reserved.
3*50cd9522Skenny liang  *
4*50cd9522Skenny liang  * SPDX-License-Identifier: BSD-3-Clause
5*50cd9522Skenny liang  */
6*50cd9522Skenny liang 
7*50cd9522Skenny liang #include <assert.h>
8*50cd9522Skenny liang #include <common/debug.h>
9*50cd9522Skenny liang #include <drivers/delay_timer.h>
10*50cd9522Skenny liang #include <gpio/mtgpio.h>
11*50cd9522Skenny liang #include <gpio/mtgpio_cfg.h>
12*50cd9522Skenny liang #include <drivers/gpio.h>
13*50cd9522Skenny liang #include <mcucfg.h>
14*50cd9522Skenny liang #include <lib/mmio.h>
15*50cd9522Skenny liang #include <platform_def.h>
16*50cd9522Skenny liang #include <spm.h>
17*50cd9522Skenny liang #include <stdbool.h>
18*50cd9522Skenny liang 
19*50cd9522Skenny liang /******************************************************************************
20*50cd9522Skenny liang  *Macro Definition
21*50cd9522Skenny liang  ******************************************************************************/
22*50cd9522Skenny liang #define GPIO_MODE_BITS		4
23*50cd9522Skenny liang #define MAX_GPIO_MODE_PER_REG	8
24*50cd9522Skenny liang #define MAX_GPIO_REG_BITS	32
25*50cd9522Skenny liang #define DIR_BASE		(GPIO_BASE + 0x000)
26*50cd9522Skenny liang #define DOUT_BASE		(GPIO_BASE + 0x100)
27*50cd9522Skenny liang #define DIN_BASE		(GPIO_BASE + 0x200)
28*50cd9522Skenny liang #define MODE_BASE		(GPIO_BASE + 0x300)
29*50cd9522Skenny liang #define SET			0x4
30*50cd9522Skenny liang #define CLR			0x8
31*50cd9522Skenny liang #define PULLEN_ADDR_OFFSET	0x060
32*50cd9522Skenny liang #define PULLSEL_ADDR_OFFSET	0x080
33*50cd9522Skenny liang 
mt_set_gpio_dir_chip(uint32_t pin,int dir)34*50cd9522Skenny liang void mt_set_gpio_dir_chip(uint32_t pin, int dir)
35*50cd9522Skenny liang {
36*50cd9522Skenny liang 	uint32_t pos, bit;
37*50cd9522Skenny liang 
38*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
39*50cd9522Skenny liang 	assert(dir < GPIO_DIR_MAX);
40*50cd9522Skenny liang 
41*50cd9522Skenny liang 	pos = pin / MAX_GPIO_REG_BITS;
42*50cd9522Skenny liang 	bit = pin % MAX_GPIO_REG_BITS;
43*50cd9522Skenny liang 
44*50cd9522Skenny liang 	if (dir == GPIO_DIR_IN)
45*50cd9522Skenny liang 		mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit);
46*50cd9522Skenny liang 	else
47*50cd9522Skenny liang 		mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit);
48*50cd9522Skenny liang }
49*50cd9522Skenny liang 
mt_get_gpio_dir_chip(uint32_t pin)50*50cd9522Skenny liang int mt_get_gpio_dir_chip(uint32_t pin)
51*50cd9522Skenny liang {
52*50cd9522Skenny liang 	uint32_t pos, bit;
53*50cd9522Skenny liang 	uint32_t reg;
54*50cd9522Skenny liang 
55*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
56*50cd9522Skenny liang 
57*50cd9522Skenny liang 	pos = pin / MAX_GPIO_REG_BITS;
58*50cd9522Skenny liang 	bit = pin % MAX_GPIO_REG_BITS;
59*50cd9522Skenny liang 
60*50cd9522Skenny liang 	reg = mmio_read_32(DIR_BASE + 0x10 * pos);
61*50cd9522Skenny liang 	return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN);
62*50cd9522Skenny liang }
63*50cd9522Skenny liang 
mt_set_gpio_out_chip(uint32_t pin,int output)64*50cd9522Skenny liang void mt_set_gpio_out_chip(uint32_t pin, int output)
65*50cd9522Skenny liang {
66*50cd9522Skenny liang 	uint32_t pos, bit;
67*50cd9522Skenny liang 
68*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
69*50cd9522Skenny liang 	assert(output < GPIO_OUT_MAX);
70*50cd9522Skenny liang 
71*50cd9522Skenny liang 	pos = pin / MAX_GPIO_REG_BITS;
72*50cd9522Skenny liang 	bit = pin % MAX_GPIO_REG_BITS;
73*50cd9522Skenny liang 
74*50cd9522Skenny liang 	if (output == GPIO_OUT_ZERO)
75*50cd9522Skenny liang 		mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit);
76*50cd9522Skenny liang 	else
77*50cd9522Skenny liang 		mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit);
78*50cd9522Skenny liang }
79*50cd9522Skenny liang 
mt_get_gpio_out_chip(uint32_t pin)80*50cd9522Skenny liang int mt_get_gpio_out_chip(uint32_t pin)
81*50cd9522Skenny liang {
82*50cd9522Skenny liang 	uint32_t pos, bit;
83*50cd9522Skenny liang 	uint32_t reg;
84*50cd9522Skenny liang 
85*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
86*50cd9522Skenny liang 
87*50cd9522Skenny liang 	pos = pin / MAX_GPIO_REG_BITS;
88*50cd9522Skenny liang 	bit = pin % MAX_GPIO_REG_BITS;
89*50cd9522Skenny liang 
90*50cd9522Skenny liang 	reg = mmio_read_32(DOUT_BASE + 0x10 * pos);
91*50cd9522Skenny liang 	return (((reg & (1U << bit)) != 0) ? 1 : 0);
92*50cd9522Skenny liang }
93*50cd9522Skenny liang 
mt_get_gpio_in_chip(uint32_t pin)94*50cd9522Skenny liang int mt_get_gpio_in_chip(uint32_t pin)
95*50cd9522Skenny liang {
96*50cd9522Skenny liang 	uint32_t pos, bit;
97*50cd9522Skenny liang 	uint32_t reg;
98*50cd9522Skenny liang 
99*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
100*50cd9522Skenny liang 
101*50cd9522Skenny liang 	pos = pin / MAX_GPIO_REG_BITS;
102*50cd9522Skenny liang 	bit = pin % MAX_GPIO_REG_BITS;
103*50cd9522Skenny liang 
104*50cd9522Skenny liang 	reg = mmio_read_32(DIN_BASE + 0x10 * pos);
105*50cd9522Skenny liang 	return (((reg & (1U << bit)) != 0) ? 1 : 0);
106*50cd9522Skenny liang }
107*50cd9522Skenny liang 
mt_set_gpio_mode_chip(uint32_t pin,int mode)108*50cd9522Skenny liang void mt_set_gpio_mode_chip(uint32_t pin, int mode)
109*50cd9522Skenny liang {
110*50cd9522Skenny liang 	uint32_t pos, bit;
111*50cd9522Skenny liang 	uint32_t data;
112*50cd9522Skenny liang 	uint32_t mask;
113*50cd9522Skenny liang 
114*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
115*50cd9522Skenny liang 	assert(mode < GPIO_MODE_MAX);
116*50cd9522Skenny liang 
117*50cd9522Skenny liang 	mask = (1U << GPIO_MODE_BITS) - 1;
118*50cd9522Skenny liang 
119*50cd9522Skenny liang 	mode = mode & mask;
120*50cd9522Skenny liang 	pos = pin / MAX_GPIO_MODE_PER_REG;
121*50cd9522Skenny liang 	bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
122*50cd9522Skenny liang 
123*50cd9522Skenny liang 	data = mmio_read_32(MODE_BASE + 0x10 * pos);
124*50cd9522Skenny liang 	data &= (~(mask << bit));
125*50cd9522Skenny liang 	data |= (mode << bit);
126*50cd9522Skenny liang 	mmio_write_32(MODE_BASE + 0x10 * pos, data);
127*50cd9522Skenny liang }
128*50cd9522Skenny liang 
mt_get_gpio_mode_chip(uint32_t pin)129*50cd9522Skenny liang int mt_get_gpio_mode_chip(uint32_t pin)
130*50cd9522Skenny liang {
131*50cd9522Skenny liang 	uint32_t pos, bit;
132*50cd9522Skenny liang 	uint32_t data;
133*50cd9522Skenny liang 	uint32_t mask;
134*50cd9522Skenny liang 
135*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
136*50cd9522Skenny liang 
137*50cd9522Skenny liang 	mask = (1U << GPIO_MODE_BITS) - 1;
138*50cd9522Skenny liang 
139*50cd9522Skenny liang 	pos = pin / MAX_GPIO_MODE_PER_REG;
140*50cd9522Skenny liang 	bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
141*50cd9522Skenny liang 
142*50cd9522Skenny liang 	data = mmio_read_32(MODE_BASE + 0x10 * pos);
143*50cd9522Skenny liang 	return (data >> bit) & mask;
144*50cd9522Skenny liang }
145*50cd9522Skenny liang 
gpio_get_pull_iocfg(uint32_t pin)146*50cd9522Skenny liang int32_t gpio_get_pull_iocfg(uint32_t pin)
147*50cd9522Skenny liang {
148*50cd9522Skenny liang 	switch (pin) {
149*50cd9522Skenny liang 	case 0 ... 10:
150*50cd9522Skenny liang 		return IOCFG_5_BASE;
151*50cd9522Skenny liang 	case 11 ... 12:
152*50cd9522Skenny liang 		return IOCFG_0_BASE;
153*50cd9522Skenny liang 	case 13 ... 28:
154*50cd9522Skenny liang 		return IOCFG_1_BASE;
155*50cd9522Skenny liang 	case 43 ... 49:
156*50cd9522Skenny liang 		return IOCFG_2_BASE;
157*50cd9522Skenny liang 	case 50 ... 60:
158*50cd9522Skenny liang 		return IOCFG_3_BASE;
159*50cd9522Skenny liang 	case 61 ... 88:
160*50cd9522Skenny liang 		return IOCFG_4_BASE;
161*50cd9522Skenny liang 	case 89 ... 90:
162*50cd9522Skenny liang 		return IOCFG_5_BASE;
163*50cd9522Skenny liang 	case 95 ... 106:
164*50cd9522Skenny liang 		return IOCFG_5_BASE;
165*50cd9522Skenny liang 	case 107 ... 121:
166*50cd9522Skenny liang 		return IOCFG_6_BASE;
167*50cd9522Skenny liang 	case 134 ... 160:
168*50cd9522Skenny liang 		return IOCFG_0_BASE;
169*50cd9522Skenny liang 	case 161 ... 166:
170*50cd9522Skenny liang 		return IOCFG_1_BASE;
171*50cd9522Skenny liang 	case 167 ... 176:
172*50cd9522Skenny liang 		return IOCFG_3_BASE;
173*50cd9522Skenny liang 	case 177 ... 179:
174*50cd9522Skenny liang 		return IOCFG_5_BASE;
175*50cd9522Skenny liang 	default:
176*50cd9522Skenny liang 		return -1;
177*50cd9522Skenny liang 	}
178*50cd9522Skenny liang }
179*50cd9522Skenny liang 
gpio_get_pupd_iocfg(uint32_t pin)180*50cd9522Skenny liang int32_t gpio_get_pupd_iocfg(uint32_t pin)
181*50cd9522Skenny liang {
182*50cd9522Skenny liang 	const int32_t offset = 0x0c0;
183*50cd9522Skenny liang 
184*50cd9522Skenny liang 	switch (pin) {
185*50cd9522Skenny liang 	case 29 ... 34:
186*50cd9522Skenny liang 		return IOCFG_1_BASE + offset;
187*50cd9522Skenny liang 	case 35 ... 42:
188*50cd9522Skenny liang 		return IOCFG_2_BASE + offset;
189*50cd9522Skenny liang 	case 91 ... 94:
190*50cd9522Skenny liang 		return IOCFG_5_BASE + offset;
191*50cd9522Skenny liang 	case 122 ... 133:
192*50cd9522Skenny liang 		return IOCFG_7_BASE + offset;
193*50cd9522Skenny liang 	default:
194*50cd9522Skenny liang 		return -1;
195*50cd9522Skenny liang 	}
196*50cd9522Skenny liang }
197*50cd9522Skenny liang 
gpio_get_pupd_offset(uint32_t pin)198*50cd9522Skenny liang int gpio_get_pupd_offset(uint32_t pin)
199*50cd9522Skenny liang {
200*50cd9522Skenny liang 	switch (pin) {
201*50cd9522Skenny liang 	case 29 ... 34:
202*50cd9522Skenny liang 		return (pin - 29) * 4 % 32;
203*50cd9522Skenny liang 	case 35 ... 42:
204*50cd9522Skenny liang 		return (pin - 35) * 4 % 32;
205*50cd9522Skenny liang 	case 91 ... 94:
206*50cd9522Skenny liang 		return (pin - 91) * 4 % 32;
207*50cd9522Skenny liang 	case 122 ... 129:
208*50cd9522Skenny liang 		return (pin - 122) * 4 % 32;
209*50cd9522Skenny liang 	case 130 ... 133:
210*50cd9522Skenny liang 		return (pin - 130) * 4 % 32;
211*50cd9522Skenny liang 	default:
212*50cd9522Skenny liang 		return -1;
213*50cd9522Skenny liang 	}
214*50cd9522Skenny liang }
215*50cd9522Skenny liang 
mt_set_gpio_pull_enable_chip(uint32_t pin,int en)216*50cd9522Skenny liang void mt_set_gpio_pull_enable_chip(uint32_t pin, int en)
217*50cd9522Skenny liang {
218*50cd9522Skenny liang 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
219*50cd9522Skenny liang 	int pupd_addr = gpio_get_pupd_iocfg(pin);
220*50cd9522Skenny liang 	int pupd_offset = gpio_get_pupd_offset(pin);
221*50cd9522Skenny liang 
222*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
223*50cd9522Skenny liang 
224*50cd9522Skenny liang 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
225*50cd9522Skenny liang 		(pupd_offset == (int8_t)-1)));
226*50cd9522Skenny liang 
227*50cd9522Skenny liang 	if (en == GPIO_PULL_DISABLE) {
228*50cd9522Skenny liang 		if (PULL_offset[pin].offset == (int8_t)-1)
229*50cd9522Skenny liang 			mmio_clrbits_32(pupd_addr, 3U << pupd_offset);
230*50cd9522Skenny liang 		else
231*50cd9522Skenny liang 			mmio_clrbits_32(pullen_addr,
232*50cd9522Skenny liang 					1U << PULL_offset[pin].offset);
233*50cd9522Skenny liang 	} else if (en == GPIO_PULL_ENABLE) {
234*50cd9522Skenny liang 		if (PULL_offset[pin].offset == (int8_t)-1) {
235*50cd9522Skenny liang 			/* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable
236*50cd9522Skenny liang 			 * does not know
237*50cd9522Skenny liang 			 * which one between PU and PD shall be enabled.
238*50cd9522Skenny liang 			 * Use R0 to guarantee at one resistor is set when lk
239*50cd9522Skenny liang 			 * apply default setting
240*50cd9522Skenny liang 			 */
241*50cd9522Skenny liang 			mmio_setbits_32(pupd_addr, 1U << pupd_offset);
242*50cd9522Skenny liang 			mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
243*50cd9522Skenny liang 		} else {
244*50cd9522Skenny liang 			/* For PULLEN + PULLSEL Type */
245*50cd9522Skenny liang 			mmio_setbits_32(pullen_addr,
246*50cd9522Skenny liang 					1U << PULL_offset[pin].offset);
247*50cd9522Skenny liang 		}
248*50cd9522Skenny liang 	} else if (en == GPIO_PULL_ENABLE_R0) {
249*50cd9522Skenny liang 		assert(!(pupd_offset == (int8_t)-1));
250*50cd9522Skenny liang 		mmio_setbits_32(pupd_addr, 1U << pupd_offset);
251*50cd9522Skenny liang 		mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
252*50cd9522Skenny liang 	} else if (en == GPIO_PULL_ENABLE_R1) {
253*50cd9522Skenny liang 		assert(!(pupd_offset == (int8_t)-1));
254*50cd9522Skenny liang 
255*50cd9522Skenny liang 		mmio_clrbits_32(pupd_addr, 1U << pupd_offset);
256*50cd9522Skenny liang 		mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1));
257*50cd9522Skenny liang 	} else if (en == GPIO_PULL_ENABLE_R0R1) {
258*50cd9522Skenny liang 		assert(!(pupd_offset == (int8_t)-1));
259*50cd9522Skenny liang 		mmio_setbits_32(pupd_addr, 3U << pupd_offset);
260*50cd9522Skenny liang 	}
261*50cd9522Skenny liang }
262*50cd9522Skenny liang 
mt_get_gpio_pull_enable_chip(uint32_t pin)263*50cd9522Skenny liang int mt_get_gpio_pull_enable_chip(uint32_t pin)
264*50cd9522Skenny liang {
265*50cd9522Skenny liang 	uint32_t reg;
266*50cd9522Skenny liang 
267*50cd9522Skenny liang 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
268*50cd9522Skenny liang 	int pupd_addr = gpio_get_pupd_iocfg(pin);
269*50cd9522Skenny liang 	int pupd_offset = gpio_get_pupd_offset(pin);
270*50cd9522Skenny liang 
271*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
272*50cd9522Skenny liang 
273*50cd9522Skenny liang 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
274*50cd9522Skenny liang 		(pupd_offset == (int8_t)-1)));
275*50cd9522Skenny liang 
276*50cd9522Skenny liang 	if (PULL_offset[pin].offset == (int8_t)-1) {
277*50cd9522Skenny liang 		reg = mmio_read_32(pupd_addr);
278*50cd9522Skenny liang 		return ((reg & (3U << pupd_offset)) ? 1 : 0);
279*50cd9522Skenny liang 	} else if (pupd_offset == (int8_t)-1) {
280*50cd9522Skenny liang 		reg = mmio_read_32(pullen_addr);
281*50cd9522Skenny liang 		return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0);
282*50cd9522Skenny liang 	}
283*50cd9522Skenny liang 
284*50cd9522Skenny liang 	return -ERINVAL;
285*50cd9522Skenny liang }
286*50cd9522Skenny liang 
mt_set_gpio_pull_select_chip(uint32_t pin,int sel)287*50cd9522Skenny liang void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
288*50cd9522Skenny liang {
289*50cd9522Skenny liang 	int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
290*50cd9522Skenny liang 	int pupd_addr = gpio_get_pupd_iocfg(pin);
291*50cd9522Skenny liang 	int pupd_offset = gpio_get_pupd_offset(pin);
292*50cd9522Skenny liang 
293*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
294*50cd9522Skenny liang 
295*50cd9522Skenny liang 	assert(!((PULL_offset[pin].offset == (int8_t) -1) &&
296*50cd9522Skenny liang 		(pupd_offset == (int8_t)-1)));
297*50cd9522Skenny liang 
298*50cd9522Skenny liang 	if (sel == GPIO_PULL_NONE) {
299*50cd9522Skenny liang 		/*  Regard No PULL as PULL disable + pull down */
300*50cd9522Skenny liang 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE);
301*50cd9522Skenny liang 		if (PULL_offset[pin].offset == (int8_t)-1)
302*50cd9522Skenny liang 			mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
303*50cd9522Skenny liang 		else
304*50cd9522Skenny liang 			mmio_clrbits_32(pullsel_addr,
305*50cd9522Skenny liang 					1U << PULL_offset[pin].offset);
306*50cd9522Skenny liang 	} else if (sel == GPIO_PULL_UP) {
307*50cd9522Skenny liang 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
308*50cd9522Skenny liang 		if (PULL_offset[pin].offset == (int8_t)-1)
309*50cd9522Skenny liang 			mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2));
310*50cd9522Skenny liang 		else
311*50cd9522Skenny liang 			mmio_setbits_32(pullsel_addr,
312*50cd9522Skenny liang 					1U << PULL_offset[pin].offset);
313*50cd9522Skenny liang 	} else if (sel == GPIO_PULL_DOWN) {
314*50cd9522Skenny liang 		mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
315*50cd9522Skenny liang 		if (PULL_offset[pin].offset == -1)
316*50cd9522Skenny liang 			mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
317*50cd9522Skenny liang 		else
318*50cd9522Skenny liang 			mmio_clrbits_32(pullsel_addr,
319*50cd9522Skenny liang 					1U << PULL_offset[pin].offset);
320*50cd9522Skenny liang 	}
321*50cd9522Skenny liang }
322*50cd9522Skenny liang 
323*50cd9522Skenny liang /* get pull-up or pull-down, regardless of resistor value */
mt_get_gpio_pull_select_chip(uint32_t pin)324*50cd9522Skenny liang int mt_get_gpio_pull_select_chip(uint32_t pin)
325*50cd9522Skenny liang {
326*50cd9522Skenny liang 	uint32_t reg;
327*50cd9522Skenny liang 
328*50cd9522Skenny liang 	int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
329*50cd9522Skenny liang 	int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
330*50cd9522Skenny liang 	int pupd_addr = gpio_get_pupd_iocfg(pin);
331*50cd9522Skenny liang 	int pupd_offset = gpio_get_pupd_offset(pin);
332*50cd9522Skenny liang 
333*50cd9522Skenny liang 	assert(pin < MAX_GPIO_PIN);
334*50cd9522Skenny liang 
335*50cd9522Skenny liang 	assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
336*50cd9522Skenny liang 		(pupd_offset == (int8_t)-1)));
337*50cd9522Skenny liang 
338*50cd9522Skenny liang 	if (PULL_offset[pin].offset == (int8_t)-1) {
339*50cd9522Skenny liang 		reg = mmio_read_32(pupd_addr);
340*50cd9522Skenny liang 		if (reg & (3U << pupd_offset)) {
341*50cd9522Skenny liang 			reg = mmio_read_32(pupd_addr);
342*50cd9522Skenny liang 			/* Reg value: 0 for PU, 1 for PD -->
343*50cd9522Skenny liang 			 * reverse return value */
344*50cd9522Skenny liang 			return ((reg & (1U << (pupd_offset + 2))) ?
345*50cd9522Skenny liang 					GPIO_PULL_DOWN : GPIO_PULL_UP);
346*50cd9522Skenny liang 		} else {
347*50cd9522Skenny liang 			return GPIO_PULL_NONE;
348*50cd9522Skenny liang 		}
349*50cd9522Skenny liang 	} else if (pupd_offset == (int8_t)-1) {
350*50cd9522Skenny liang 		reg = mmio_read_32(pullen_addr);
351*50cd9522Skenny liang 		if ((reg & (1U << PULL_offset[pin].offset))) {
352*50cd9522Skenny liang 			reg = mmio_read_32(pullsel_addr);
353*50cd9522Skenny liang 			return ((reg & (1U << PULL_offset[pin].offset)) ?
354*50cd9522Skenny liang 					GPIO_PULL_UP : GPIO_PULL_DOWN);
355*50cd9522Skenny liang 		} else {
356*50cd9522Skenny liang 			return GPIO_PULL_NONE;
357*50cd9522Skenny liang 		}
358*50cd9522Skenny liang 	}
359*50cd9522Skenny liang 
360*50cd9522Skenny liang 	return -ERINVAL;
361*50cd9522Skenny liang }
362*50cd9522Skenny liang 
mt_set_gpio_dir(int gpio,int direction)363*50cd9522Skenny liang void mt_set_gpio_dir(int gpio, int direction)
364*50cd9522Skenny liang {
365*50cd9522Skenny liang 	mt_set_gpio_dir_chip((uint32_t)gpio, direction);
366*50cd9522Skenny liang }
367*50cd9522Skenny liang 
mt_get_gpio_dir(int gpio)368*50cd9522Skenny liang int mt_get_gpio_dir(int gpio)
369*50cd9522Skenny liang {
370*50cd9522Skenny liang 	uint32_t pin;
371*50cd9522Skenny liang 
372*50cd9522Skenny liang 	pin = (uint32_t)gpio;
373*50cd9522Skenny liang 	return mt_get_gpio_dir_chip(pin);
374*50cd9522Skenny liang }
375*50cd9522Skenny liang 
mt_set_gpio_pull(int gpio,int pull)376*50cd9522Skenny liang void mt_set_gpio_pull(int gpio, int pull)
377*50cd9522Skenny liang {
378*50cd9522Skenny liang 	uint32_t pin;
379*50cd9522Skenny liang 
380*50cd9522Skenny liang 	pin = (uint32_t)gpio;
381*50cd9522Skenny liang 	mt_set_gpio_pull_select_chip(pin, pull);
382*50cd9522Skenny liang }
383*50cd9522Skenny liang 
mt_get_gpio_pull(int gpio)384*50cd9522Skenny liang int mt_get_gpio_pull(int gpio)
385*50cd9522Skenny liang {
386*50cd9522Skenny liang 	uint32_t pin;
387*50cd9522Skenny liang 
388*50cd9522Skenny liang 	pin = (uint32_t)gpio;
389*50cd9522Skenny liang 	return mt_get_gpio_pull_select_chip(pin);
390*50cd9522Skenny liang }
391*50cd9522Skenny liang 
mt_set_gpio_out(int gpio,int value)392*50cd9522Skenny liang void mt_set_gpio_out(int gpio, int value)
393*50cd9522Skenny liang {
394*50cd9522Skenny liang 	uint32_t pin;
395*50cd9522Skenny liang 
396*50cd9522Skenny liang 	pin = (uint32_t)gpio;
397*50cd9522Skenny liang 	mt_set_gpio_out_chip(pin, value);
398*50cd9522Skenny liang }
399*50cd9522Skenny liang 
mt_get_gpio_out(int gpio)400*50cd9522Skenny liang int mt_get_gpio_out(int gpio)
401*50cd9522Skenny liang {
402*50cd9522Skenny liang 	uint32_t pin;
403*50cd9522Skenny liang 
404*50cd9522Skenny liang 	pin = (uint32_t)gpio;
405*50cd9522Skenny liang 	return mt_get_gpio_out_chip(pin);
406*50cd9522Skenny liang }
407*50cd9522Skenny liang 
mt_get_gpio_in(int gpio)408*50cd9522Skenny liang int mt_get_gpio_in(int gpio)
409*50cd9522Skenny liang {
410*50cd9522Skenny liang 	uint32_t pin;
411*50cd9522Skenny liang 
412*50cd9522Skenny liang 	pin = (uint32_t)gpio;
413*50cd9522Skenny liang 	return mt_get_gpio_in_chip(pin);
414*50cd9522Skenny liang }
415*50cd9522Skenny liang 
mt_set_gpio_mode(int gpio,int mode)416*50cd9522Skenny liang void mt_set_gpio_mode(int gpio, int mode)
417*50cd9522Skenny liang {
418*50cd9522Skenny liang 	uint32_t pin;
419*50cd9522Skenny liang 
420*50cd9522Skenny liang 	pin = (uint32_t)gpio;
421*50cd9522Skenny liang 	mt_set_gpio_mode_chip(pin, mode);
422*50cd9522Skenny liang }
423*50cd9522Skenny liang 
mt_get_gpio_mode(int gpio)424*50cd9522Skenny liang int mt_get_gpio_mode(int gpio)
425*50cd9522Skenny liang {
426*50cd9522Skenny liang 	uint32_t pin;
427*50cd9522Skenny liang 
428*50cd9522Skenny liang 	pin = (uint32_t)gpio;
429*50cd9522Skenny liang 	return mt_get_gpio_mode_chip(pin);
430*50cd9522Skenny liang }
431*50cd9522Skenny liang 
432*50cd9522Skenny liang const gpio_ops_t mtgpio_ops = {
433*50cd9522Skenny liang 	 .get_direction = mt_get_gpio_dir,
434*50cd9522Skenny liang 	 .set_direction = mt_set_gpio_dir,
435*50cd9522Skenny liang 	 .get_value = mt_get_gpio_in,
436*50cd9522Skenny liang 	 .set_value = mt_set_gpio_out,
437*50cd9522Skenny liang 	 .set_pull = mt_set_gpio_pull,
438*50cd9522Skenny liang 	 .get_pull = mt_get_gpio_pull,
439*50cd9522Skenny liang };
440