xref: /OK3568_Linux_fs/kernel/drivers/misc/rk628/rk628_pinctrl.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Wyon Bi <bivvy.bi@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "rk628.h"
9*4882a593Smuzhiyun 
rk628_calc_mux_offset(struct rk628 * rk628,int mux,int reg,int offset)10*4882a593Smuzhiyun static int rk628_calc_mux_offset(struct rk628 *rk628, int mux, int reg, int offset)
11*4882a593Smuzhiyun {
12*4882a593Smuzhiyun 	int val = 0, orig;
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun 	switch (reg) {
15*4882a593Smuzhiyun 	case GRF_SYSTEM_CON3:
16*4882a593Smuzhiyun 		rk628_i2c_read(rk628, reg, &orig);
17*4882a593Smuzhiyun 		if (mux)
18*4882a593Smuzhiyun 			val = BIT(offset) | orig;
19*4882a593Smuzhiyun 		else
20*4882a593Smuzhiyun 			val = ~BIT(offset) & orig;
21*4882a593Smuzhiyun 		break;
22*4882a593Smuzhiyun 	case GRF_GPIO0AB_SEL_CON:
23*4882a593Smuzhiyun 		if (offset >= 4 && offset < 8) {
24*4882a593Smuzhiyun 			offset += offset - 4;
25*4882a593Smuzhiyun 			val = 0x3 << (offset + 16) | (mux << offset);
26*4882a593Smuzhiyun 		} else if (offset > 7) {
27*4882a593Smuzhiyun 			offset += 4;
28*4882a593Smuzhiyun 			val = BIT(offset + 16) | (mux << offset);
29*4882a593Smuzhiyun 		} else {
30*4882a593Smuzhiyun 			val = BIT(offset + 16) | (mux << offset);
31*4882a593Smuzhiyun 		}
32*4882a593Smuzhiyun 		break;
33*4882a593Smuzhiyun 	case GRF_GPIO1AB_SEL_CON:
34*4882a593Smuzhiyun 		if (offset == 13)
35*4882a593Smuzhiyun 			offset++;
36*4882a593Smuzhiyun 		if (offset > 11)
37*4882a593Smuzhiyun 			val = 0x3 << (offset + 16) | (mux << offset);
38*4882a593Smuzhiyun 		else
39*4882a593Smuzhiyun 			val = BIT(offset + 16) | (mux << offset);
40*4882a593Smuzhiyun 		break;
41*4882a593Smuzhiyun 	case GRF_GPIO2AB_SEL_CON:
42*4882a593Smuzhiyun 		val = BIT(offset + 16) | (mux << offset);
43*4882a593Smuzhiyun 		break;
44*4882a593Smuzhiyun 	case GRF_GPIO2C_SEL_CON:
45*4882a593Smuzhiyun 		offset -= 16;
46*4882a593Smuzhiyun 		val = 0x3 << ((offset*2) + 16) | (mux << (offset*2));
47*4882a593Smuzhiyun 		break;
48*4882a593Smuzhiyun 	case GRF_GPIO3AB_SEL_CON:
49*4882a593Smuzhiyun 		if (offset > 11)
50*4882a593Smuzhiyun 			val = 0x3 << (offset + 16) | (mux << offset);
51*4882a593Smuzhiyun 		else
52*4882a593Smuzhiyun 			val = BIT(offset + 16) | (mux << offset);
53*4882a593Smuzhiyun 		break;
54*4882a593Smuzhiyun 	default:
55*4882a593Smuzhiyun 		break;
56*4882a593Smuzhiyun 	}
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	return val;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
rk628_misc_pinctrl_set_mux(struct rk628 * rk628,int gpio,int mux)61*4882a593Smuzhiyun int rk628_misc_pinctrl_set_mux(struct rk628 *rk628, int gpio, int mux)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	int i, iomux_base, offset, val;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	mux &= 0x3;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
68*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins == gpio) {
69*4882a593Smuzhiyun 			iomux_base = rk628_pin_iomux_groups[i].iomux_base;
70*4882a593Smuzhiyun 			offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
71*4882a593Smuzhiyun 			break;
72*4882a593Smuzhiyun 		}
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!iomux_base)) {
76*4882a593Smuzhiyun 		pr_info("%s invalid gpio or iomux_base\n", __func__);
77*4882a593Smuzhiyun 		return -1;
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	val = rk628_calc_mux_offset(rk628, mux, iomux_base, offset);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	rk628_i2c_write(rk628, iomux_base, val);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return 0;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* generic gpio chip */
rk628_misc_gpio_get_value(struct rk628 * rk628,int gpio)90*4882a593Smuzhiyun int rk628_misc_gpio_get_value(struct rk628 *rk628, int gpio)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	int i, data_reg, offset, val;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
95*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins == gpio) {
96*4882a593Smuzhiyun 			data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_EXT_PORT;
97*4882a593Smuzhiyun 			offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
98*4882a593Smuzhiyun 			break;
99*4882a593Smuzhiyun 		}
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!data_reg)) {
103*4882a593Smuzhiyun 		pr_info("%s invalid gpio or data_reg\n", __func__);
104*4882a593Smuzhiyun 		return -1;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	rk628_i2c_read(rk628, data_reg, &val);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	val >>= offset;
110*4882a593Smuzhiyun 	val &= 1;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return val;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
rk628_misc_gpio_set_value(struct rk628 * rk628,int gpio,int value)115*4882a593Smuzhiyun int rk628_misc_gpio_set_value(struct rk628 *rk628, int gpio, int value)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	int i, data_reg, offset, val;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
120*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins == gpio) {
121*4882a593Smuzhiyun 			offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
122*4882a593Smuzhiyun 			if (offset >= 16) {
123*4882a593Smuzhiyun 				data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DR_H;
124*4882a593Smuzhiyun 				offset -= 16;
125*4882a593Smuzhiyun 			} else {
126*4882a593Smuzhiyun 				data_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DR_L;
127*4882a593Smuzhiyun 			}
128*4882a593Smuzhiyun 			break;
129*4882a593Smuzhiyun 		}
130*4882a593Smuzhiyun 	}
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!data_reg)) {
133*4882a593Smuzhiyun 		pr_info("%s invalid gpio or data_reg\n", __func__);
134*4882a593Smuzhiyun 		return -1;
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	if (value)
138*4882a593Smuzhiyun 		val = BIT(offset + 16) | BIT(offset);
139*4882a593Smuzhiyun 	else
140*4882a593Smuzhiyun 		val = BIT(offset + 16) | (0xffff & ~BIT(offset));
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	rk628_i2c_write(rk628, data_reg, val);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	return 0;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 
rk628_misc_gpio_set_direction(struct rk628 * rk628,int gpio,int direction)149*4882a593Smuzhiyun int rk628_misc_gpio_set_direction(struct rk628 *rk628, int gpio, int direction)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	int i, dir_reg, offset, val;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
154*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins == gpio) {
155*4882a593Smuzhiyun 			offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
156*4882a593Smuzhiyun 			if (offset >= 16) {
157*4882a593Smuzhiyun 				dir_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DDR_H;
158*4882a593Smuzhiyun 				offset -= 16;
159*4882a593Smuzhiyun 			} else {
160*4882a593Smuzhiyun 				dir_reg = rk628_pin_iomux_groups[i].gpio_base + GPIO_SWPORT_DDR_L;
161*4882a593Smuzhiyun 			}
162*4882a593Smuzhiyun 			break;
163*4882a593Smuzhiyun 		}
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if ((i == ARRAY_SIZE(rk628_pin_iomux_groups)) || (!dir_reg)) {
167*4882a593Smuzhiyun 		pr_info("%s invalid gpio or dir_reg\n", __func__);
168*4882a593Smuzhiyun 		return -1;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	if (!direction)
172*4882a593Smuzhiyun 		val = BIT(offset + 16) | (0xffff & ~BIT(offset));
173*4882a593Smuzhiyun 	else
174*4882a593Smuzhiyun 		val = BIT(offset + 16) | BIT(offset);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	rk628_i2c_write(rk628, dir_reg, val);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	return 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 
rk628_misc_iomux_init(struct rk628 * rk628)182*4882a593Smuzhiyun int rk628_misc_iomux_init(struct rk628 *rk628)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	int i, iomux_base, offset, val, mux;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
187*4882a593Smuzhiyun 		mux = rk628_pin_iomux_groups[i].mux;
188*4882a593Smuzhiyun 		iomux_base = rk628_pin_iomux_groups[i].iomux_base;
189*4882a593Smuzhiyun 		offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
190*4882a593Smuzhiyun 		if (iomux_base) {
191*4882a593Smuzhiyun 			val = rk628_calc_mux_offset(rk628, mux, iomux_base, offset);
192*4882a593Smuzhiyun 			rk628_i2c_write(rk628, iomux_base, val);
193*4882a593Smuzhiyun 		}
194*4882a593Smuzhiyun 	}
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	return 0;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 
rk628_misc_gpio_direction_input(struct rk628 * rk628,int gpio)200*4882a593Smuzhiyun int rk628_misc_gpio_direction_input(struct rk628 *rk628, int gpio)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	rk628_misc_pinctrl_set_mux(rk628, gpio, GPIO_FUNC);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	rk628_misc_gpio_set_direction(rk628, gpio, GPIO_DIRECTION_IN);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return 0;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 
rk628_misc_gpio_direction_output(struct rk628 * rk628,int gpio,int value)210*4882a593Smuzhiyun int rk628_misc_gpio_direction_output(struct rk628 *rk628, int gpio, int value)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	rk628_misc_pinctrl_set_mux(rk628, gpio, GPIO_FUNC);
214*4882a593Smuzhiyun 	rk628_misc_gpio_set_value(rk628, gpio, value);
215*4882a593Smuzhiyun 	rk628_misc_gpio_set_direction(rk628, gpio, GPIO_DIRECTION_OUT);
216*4882a593Smuzhiyun 	return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 
rk628_misc_gpio_set_pull_highz_up_down(struct rk628 * rk628,int gpio,int pull)220*4882a593Smuzhiyun int rk628_misc_gpio_set_pull_highz_up_down(struct rk628 *rk628, int gpio, int pull)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	int i, bank, pull_reg = 0, offset, val = 0;
223*4882a593Smuzhiyun 	int valid_pinnum[] = { 8, 8, 24, 13 };
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
226*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins == gpio) {
227*4882a593Smuzhiyun 			bank = rk628_pin_iomux_groups[i].bank;
228*4882a593Smuzhiyun 			pull_reg = rk628_pin_iomux_groups[i].pull_reg;
229*4882a593Smuzhiyun 			offset = rk628_pin_iomux_groups[i].pins % BANK_OFFSET;
230*4882a593Smuzhiyun 			break;
231*4882a593Smuzhiyun 		}
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if ((i == ARRAY_SIZE(rk628_pin_iomux_groups))  || (!pull_reg)) {
235*4882a593Smuzhiyun 		pr_info("rk628_gpio_pull_highz_up_down invalid gpio or pull_reg\n");
236*4882a593Smuzhiyun 		return -1;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	switch (bank) {
240*4882a593Smuzhiyun 	case GPIO_BANK0:
241*4882a593Smuzhiyun 		if (pull == GPIO_PULL_UP)
242*4882a593Smuzhiyun 			return -1;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 		if (offset == 2)
245*4882a593Smuzhiyun 			return -1;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 		if (offset < valid_pinnum[bank])
248*4882a593Smuzhiyun 			val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
249*4882a593Smuzhiyun 		break;
250*4882a593Smuzhiyun 	case GPIO_BANK1:
251*4882a593Smuzhiyun 		if (pull == GPIO_PULL_UP)
252*4882a593Smuzhiyun 			return -1;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 		if (offset == 2)
255*4882a593Smuzhiyun 			return -1;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 		if (offset < valid_pinnum[bank])
258*4882a593Smuzhiyun 			val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
259*4882a593Smuzhiyun 		break;
260*4882a593Smuzhiyun 	case GPIO_BANK2:
261*4882a593Smuzhiyun 		if (pull == GPIO_PULL_UP)
262*4882a593Smuzhiyun 			pull = GPIO_PULL_DOWN;
263*4882a593Smuzhiyun 		else if (pull == GPIO_PULL_DOWN)
264*4882a593Smuzhiyun 			pull = GPIO_PULL_UP;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 		if (offset < valid_pinnum[bank]) {
267*4882a593Smuzhiyun 			offset = offset % 8;
268*4882a593Smuzhiyun 			val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
269*4882a593Smuzhiyun 		}
270*4882a593Smuzhiyun 		break;
271*4882a593Smuzhiyun 	case GPIO_BANK3:
272*4882a593Smuzhiyun 		if (pull == GPIO_PULL_UP && (offset == 2 || offset == 11 || offset == 12))
273*4882a593Smuzhiyun 			return -1;
274*4882a593Smuzhiyun 		else if (pull == GPIO_PULL_DOWN && (offset == 9 || offset == 10))
275*4882a593Smuzhiyun 			return -1;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 		if (offset == 0 || offset == 1 || offset == 3 || offset == 8) {
278*4882a593Smuzhiyun 			if (pull == GPIO_PULL_UP)
279*4882a593Smuzhiyun 				pull = GPIO_PULL_DOWN;
280*4882a593Smuzhiyun 			else if (pull == GPIO_PULL_DOWN)
281*4882a593Smuzhiyun 				pull = GPIO_PULL_UP;
282*4882a593Smuzhiyun 		}
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 		if ((offset > 7 && offset < valid_pinnum[bank]) || offset < 4) {
285*4882a593Smuzhiyun 			offset = offset % 8;
286*4882a593Smuzhiyun 			val = 0x3 << (2 * offset + 16) | pull << (2 * offset);
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 		break;
289*4882a593Smuzhiyun 	default:
290*4882a593Smuzhiyun 		break;
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	rk628_i2c_write(rk628, pull_reg, val);
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	return 0;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 
rk628_misc_gpio_test_all(struct rk628 * rk628)300*4882a593Smuzhiyun int rk628_misc_gpio_test_all(struct rk628 *rk628)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	int i;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
305*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins && (rk628_pin_iomux_groups[i].pins != GPIO1_A1)
306*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C0)
307*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C1)
308*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C2)
309*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C3)
310*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C4))
311*4882a593Smuzhiyun 			rk628_misc_gpio_direction_output(rk628, rk628_pin_iomux_groups[i].pins, 1);
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(rk628_pin_iomux_groups); i++) {
315*4882a593Smuzhiyun 		if (rk628_pin_iomux_groups[i].pins && (rk628_pin_iomux_groups[i].pins != GPIO1_A1)
316*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C0)
317*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C1)
318*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C2)
319*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C3)
320*4882a593Smuzhiyun 		    && (rk628_pin_iomux_groups[i].pins != GPIO2_C4))
321*4882a593Smuzhiyun 			rk628_misc_gpio_direction_output(rk628, rk628_pin_iomux_groups[i].pins, 0);
322*4882a593Smuzhiyun 	}
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	return 0;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun 
327