xref: /rk3399_rockchip-uboot/drivers/pinctrl/rockchip/pinctrl-rk3562.c (revision c9641f3a1b879414b5e599135d66fdb023167156)
1*c9641f3aSSteven Liu // SPDX-License-Identifier: GPL-2.0+
2*c9641f3aSSteven Liu /*
3*c9641f3aSSteven Liu  * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4*c9641f3aSSteven Liu  */
5*c9641f3aSSteven Liu 
6*c9641f3aSSteven Liu #include <common.h>
7*c9641f3aSSteven Liu #include <dm.h>
8*c9641f3aSSteven Liu #include <dm/pinctrl.h>
9*c9641f3aSSteven Liu #include <regmap.h>
10*c9641f3aSSteven Liu #include <syscon.h>
11*c9641f3aSSteven Liu 
12*c9641f3aSSteven Liu #include "pinctrl-rockchip.h"
13*c9641f3aSSteven Liu 
rk3562_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)14*c9641f3aSSteven Liu static int rk3562_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
15*c9641f3aSSteven Liu {
16*c9641f3aSSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
17*c9641f3aSSteven Liu 	int iomux_num = (pin / 8);
18*c9641f3aSSteven Liu 	struct regmap *regmap;
19*c9641f3aSSteven Liu 	int reg, ret, mask;
20*c9641f3aSSteven Liu 	u8 bit;
21*c9641f3aSSteven Liu 	u32 data;
22*c9641f3aSSteven Liu 
23*c9641f3aSSteven Liu 	debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
24*c9641f3aSSteven Liu 
25*c9641f3aSSteven Liu 	regmap = priv->regmap_base;
26*c9641f3aSSteven Liu 	reg = bank->iomux[iomux_num].offset;
27*c9641f3aSSteven Liu 	if ((pin % 8) >= 4)
28*c9641f3aSSteven Liu 		reg += 0x4;
29*c9641f3aSSteven Liu 	bit = (pin % 4) * 4;
30*c9641f3aSSteven Liu 	mask = 0xf;
31*c9641f3aSSteven Liu 
32*c9641f3aSSteven Liu 	data = (mask << (bit + 16));
33*c9641f3aSSteven Liu 	data |= (mux & mask) << bit;
34*c9641f3aSSteven Liu 
35*c9641f3aSSteven Liu 	/* force jtag m1 */
36*c9641f3aSSteven Liu 	if (bank->bank_num == 1) {
37*c9641f3aSSteven Liu 		if ((pin == 13) || (pin == 14)) {
38*c9641f3aSSteven Liu 			if (mux == 1) {
39*c9641f3aSSteven Liu 				regmap_write(regmap, 0x504, 0x10001);
40*c9641f3aSSteven Liu 			} else {
41*c9641f3aSSteven Liu 				regmap_write(regmap, 0x504, 0x10000);
42*c9641f3aSSteven Liu 			}
43*c9641f3aSSteven Liu 		}
44*c9641f3aSSteven Liu 	}
45*c9641f3aSSteven Liu 
46*c9641f3aSSteven Liu 	debug("iomux write reg = %x data = %x\n", reg, data);
47*c9641f3aSSteven Liu 
48*c9641f3aSSteven Liu 	ret = regmap_write(regmap, reg, data);
49*c9641f3aSSteven Liu 
50*c9641f3aSSteven Liu 	return ret;
51*c9641f3aSSteven Liu }
52*c9641f3aSSteven Liu 
53*c9641f3aSSteven Liu #define RK3562_DRV_BITS_PER_PIN		8
54*c9641f3aSSteven Liu #define RK3562_DRV_PINS_PER_REG		2
55*c9641f3aSSteven Liu #define RK3562_DRV_GPIO0_OFFSET		0x20070
56*c9641f3aSSteven Liu #define RK3562_DRV_GPIO1_OFFSET		0x200
57*c9641f3aSSteven Liu #define RK3562_DRV_GPIO2_OFFSET		0x240
58*c9641f3aSSteven Liu #define RK3562_DRV_GPIO3_OFFSET		0x10280
59*c9641f3aSSteven Liu #define RK3562_DRV_GPIO4_OFFSET		0x102C0
60*c9641f3aSSteven Liu 
rk3562_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)61*c9641f3aSSteven Liu static void rk3562_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
62*c9641f3aSSteven Liu 					int pin_num, struct regmap **regmap,
63*c9641f3aSSteven Liu 					int *reg, u8 *bit)
64*c9641f3aSSteven Liu {
65*c9641f3aSSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
66*c9641f3aSSteven Liu 
67*c9641f3aSSteven Liu 	*regmap = priv->regmap_base;
68*c9641f3aSSteven Liu 	switch (bank->bank_num) {
69*c9641f3aSSteven Liu 	case 0:
70*c9641f3aSSteven Liu 		*reg = RK3562_DRV_GPIO0_OFFSET;
71*c9641f3aSSteven Liu 		break;
72*c9641f3aSSteven Liu 
73*c9641f3aSSteven Liu 	case 1:
74*c9641f3aSSteven Liu 		*reg = RK3562_DRV_GPIO1_OFFSET;
75*c9641f3aSSteven Liu 		break;
76*c9641f3aSSteven Liu 
77*c9641f3aSSteven Liu 	case 2:
78*c9641f3aSSteven Liu 		*reg = RK3562_DRV_GPIO2_OFFSET;
79*c9641f3aSSteven Liu 		break;
80*c9641f3aSSteven Liu 
81*c9641f3aSSteven Liu 	case 3:
82*c9641f3aSSteven Liu 		*reg = RK3562_DRV_GPIO3_OFFSET;
83*c9641f3aSSteven Liu 		break;
84*c9641f3aSSteven Liu 
85*c9641f3aSSteven Liu 	case 4:
86*c9641f3aSSteven Liu 		*reg = RK3562_DRV_GPIO4_OFFSET;
87*c9641f3aSSteven Liu 		break;
88*c9641f3aSSteven Liu 
89*c9641f3aSSteven Liu 	default:
90*c9641f3aSSteven Liu 		*reg = 0;
91*c9641f3aSSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
92*c9641f3aSSteven Liu 		break;
93*c9641f3aSSteven Liu 	}
94*c9641f3aSSteven Liu 
95*c9641f3aSSteven Liu 	*reg += ((pin_num / RK3562_DRV_PINS_PER_REG) * 4);
96*c9641f3aSSteven Liu 	*bit = pin_num % RK3562_DRV_PINS_PER_REG;
97*c9641f3aSSteven Liu 	*bit *= RK3562_DRV_BITS_PER_PIN;
98*c9641f3aSSteven Liu }
99*c9641f3aSSteven Liu 
rk3562_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)100*c9641f3aSSteven Liu static int rk3562_set_drive(struct rockchip_pin_bank *bank,
101*c9641f3aSSteven Liu 			    int pin_num, int strength)
102*c9641f3aSSteven Liu {
103*c9641f3aSSteven Liu 	struct regmap *regmap;
104*c9641f3aSSteven Liu 	int reg, ret;
105*c9641f3aSSteven Liu 	u32 data;
106*c9641f3aSSteven Liu 	u8 bit;
107*c9641f3aSSteven Liu 	int drv = (1 << (strength + 1)) - 1;
108*c9641f3aSSteven Liu 
109*c9641f3aSSteven Liu 	rk3562_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
110*c9641f3aSSteven Liu 
111*c9641f3aSSteven Liu 	/* enable the write to the equivalent lower bits */
112*c9641f3aSSteven Liu 	data = ((1 << RK3562_DRV_BITS_PER_PIN) - 1) << (bit + 16);
113*c9641f3aSSteven Liu 	data |= (drv << bit);
114*c9641f3aSSteven Liu 	ret = regmap_write(regmap, reg, data);
115*c9641f3aSSteven Liu 
116*c9641f3aSSteven Liu 	return ret;
117*c9641f3aSSteven Liu }
118*c9641f3aSSteven Liu 
119*c9641f3aSSteven Liu #define RK3562_PULL_BITS_PER_PIN		2
120*c9641f3aSSteven Liu #define RK3562_PULL_PINS_PER_REG		8
121*c9641f3aSSteven Liu #define RK3562_PULL_GPIO0_OFFSET		0x20020
122*c9641f3aSSteven Liu #define RK3562_PULL_GPIO1_OFFSET		0x80
123*c9641f3aSSteven Liu #define RK3562_PULL_GPIO2_OFFSET		0x90
124*c9641f3aSSteven Liu #define RK3562_PULL_GPIO3_OFFSET		0x100A0
125*c9641f3aSSteven Liu #define RK3562_PULL_GPIO4_OFFSET		0x100B0
126*c9641f3aSSteven Liu 
rk3562_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)127*c9641f3aSSteven Liu static void rk3562_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
128*c9641f3aSSteven Liu 					 int pin_num, struct regmap **regmap,
129*c9641f3aSSteven Liu 					 int *reg, u8 *bit)
130*c9641f3aSSteven Liu {
131*c9641f3aSSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
132*c9641f3aSSteven Liu 
133*c9641f3aSSteven Liu 	*regmap = priv->regmap_base;
134*c9641f3aSSteven Liu 	switch (bank->bank_num) {
135*c9641f3aSSteven Liu 	case 0:
136*c9641f3aSSteven Liu 		*reg = RK3562_PULL_GPIO0_OFFSET;
137*c9641f3aSSteven Liu 		break;
138*c9641f3aSSteven Liu 
139*c9641f3aSSteven Liu 	case 1:
140*c9641f3aSSteven Liu 		*reg = RK3562_PULL_GPIO1_OFFSET;
141*c9641f3aSSteven Liu 		break;
142*c9641f3aSSteven Liu 
143*c9641f3aSSteven Liu 	case 2:
144*c9641f3aSSteven Liu 		*reg = RK3562_PULL_GPIO2_OFFSET;
145*c9641f3aSSteven Liu 		break;
146*c9641f3aSSteven Liu 
147*c9641f3aSSteven Liu 	case 3:
148*c9641f3aSSteven Liu 		*reg = RK3562_PULL_GPIO3_OFFSET;
149*c9641f3aSSteven Liu 		break;
150*c9641f3aSSteven Liu 
151*c9641f3aSSteven Liu 	case 4:
152*c9641f3aSSteven Liu 		*reg = RK3562_PULL_GPIO4_OFFSET;
153*c9641f3aSSteven Liu 		break;
154*c9641f3aSSteven Liu 
155*c9641f3aSSteven Liu 	default:
156*c9641f3aSSteven Liu 		*reg = 0;
157*c9641f3aSSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
158*c9641f3aSSteven Liu 		break;
159*c9641f3aSSteven Liu 	}
160*c9641f3aSSteven Liu 
161*c9641f3aSSteven Liu 	*reg += ((pin_num / RK3562_PULL_PINS_PER_REG) * 4);
162*c9641f3aSSteven Liu 	*bit = pin_num % RK3562_PULL_PINS_PER_REG;
163*c9641f3aSSteven Liu 	*bit *= RK3562_PULL_BITS_PER_PIN;
164*c9641f3aSSteven Liu }
165*c9641f3aSSteven Liu 
rk3562_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)166*c9641f3aSSteven Liu static int rk3562_set_pull(struct rockchip_pin_bank *bank,
167*c9641f3aSSteven Liu 			   int pin_num, int pull)
168*c9641f3aSSteven Liu {
169*c9641f3aSSteven Liu 	struct regmap *regmap;
170*c9641f3aSSteven Liu 	int reg, ret;
171*c9641f3aSSteven Liu 	u8 bit, type;
172*c9641f3aSSteven Liu 	u32 data;
173*c9641f3aSSteven Liu 
174*c9641f3aSSteven Liu 	if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
175*c9641f3aSSteven Liu 		return -ENOTSUPP;
176*c9641f3aSSteven Liu 
177*c9641f3aSSteven Liu 	rk3562_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
178*c9641f3aSSteven Liu 	type = bank->pull_type[pin_num / 8];
179*c9641f3aSSteven Liu 	ret = rockchip_translate_pull_value(type, pull);
180*c9641f3aSSteven Liu 	if (ret < 0) {
181*c9641f3aSSteven Liu 		debug("unsupported pull setting %d\n", pull);
182*c9641f3aSSteven Liu 		return ret;
183*c9641f3aSSteven Liu 	}
184*c9641f3aSSteven Liu 
185*c9641f3aSSteven Liu 	/* enable the write to the equivalent lower bits */
186*c9641f3aSSteven Liu 	data = ((1 << RK3562_PULL_BITS_PER_PIN) - 1) << (bit + 16);
187*c9641f3aSSteven Liu 
188*c9641f3aSSteven Liu 	data |= (ret << bit);
189*c9641f3aSSteven Liu 	ret = regmap_write(regmap, reg, data);
190*c9641f3aSSteven Liu 
191*c9641f3aSSteven Liu 	return ret;
192*c9641f3aSSteven Liu }
193*c9641f3aSSteven Liu 
194*c9641f3aSSteven Liu #define RK3562_SMT_BITS_PER_PIN		2
195*c9641f3aSSteven Liu #define RK3562_SMT_PINS_PER_REG		8
196*c9641f3aSSteven Liu #define RK3562_SMT_GPIO0_OFFSET		0x20030
197*c9641f3aSSteven Liu #define RK3562_SMT_GPIO1_OFFSET		0xC0
198*c9641f3aSSteven Liu #define RK3562_SMT_GPIO2_OFFSET		0xD0
199*c9641f3aSSteven Liu #define RK3562_SMT_GPIO3_OFFSET		0x100E0
200*c9641f3aSSteven Liu #define RK3562_SMT_GPIO4_OFFSET		0x100F0
201*c9641f3aSSteven Liu 
rk3562_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)202*c9641f3aSSteven Liu static int rk3562_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
203*c9641f3aSSteven Liu 					   int pin_num,
204*c9641f3aSSteven Liu 					   struct regmap **regmap,
205*c9641f3aSSteven Liu 					   int *reg, u8 *bit)
206*c9641f3aSSteven Liu {
207*c9641f3aSSteven Liu 	struct rockchip_pinctrl_priv *priv = bank->priv;
208*c9641f3aSSteven Liu 
209*c9641f3aSSteven Liu 	*regmap = priv->regmap_base;
210*c9641f3aSSteven Liu 	switch (bank->bank_num) {
211*c9641f3aSSteven Liu 	case 0:
212*c9641f3aSSteven Liu 		*reg = RK3562_SMT_GPIO0_OFFSET;
213*c9641f3aSSteven Liu 		break;
214*c9641f3aSSteven Liu 
215*c9641f3aSSteven Liu 	case 1:
216*c9641f3aSSteven Liu 		*reg = RK3562_SMT_GPIO1_OFFSET;
217*c9641f3aSSteven Liu 		break;
218*c9641f3aSSteven Liu 
219*c9641f3aSSteven Liu 	case 2:
220*c9641f3aSSteven Liu 		*reg = RK3562_SMT_GPIO2_OFFSET;
221*c9641f3aSSteven Liu 		break;
222*c9641f3aSSteven Liu 
223*c9641f3aSSteven Liu 	case 3:
224*c9641f3aSSteven Liu 		*reg = RK3562_SMT_GPIO3_OFFSET;
225*c9641f3aSSteven Liu 		break;
226*c9641f3aSSteven Liu 
227*c9641f3aSSteven Liu 	case 4:
228*c9641f3aSSteven Liu 		*reg = RK3562_SMT_GPIO4_OFFSET;
229*c9641f3aSSteven Liu 		break;
230*c9641f3aSSteven Liu 
231*c9641f3aSSteven Liu 	default:
232*c9641f3aSSteven Liu 		*reg = 0;
233*c9641f3aSSteven Liu 		dev_err(priv->dev, "unsupported bank_num %d\n", bank->bank_num);
234*c9641f3aSSteven Liu 		break;
235*c9641f3aSSteven Liu 	}
236*c9641f3aSSteven Liu 
237*c9641f3aSSteven Liu 	*reg += ((pin_num / RK3562_SMT_PINS_PER_REG) * 4);
238*c9641f3aSSteven Liu 	*bit = pin_num % RK3562_SMT_PINS_PER_REG;
239*c9641f3aSSteven Liu 	*bit *= RK3562_SMT_BITS_PER_PIN;
240*c9641f3aSSteven Liu 
241*c9641f3aSSteven Liu 	return 0;
242*c9641f3aSSteven Liu }
243*c9641f3aSSteven Liu 
rk3562_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)244*c9641f3aSSteven Liu static int rk3562_set_schmitt(struct rockchip_pin_bank *bank,
245*c9641f3aSSteven Liu 			      int pin_num, int enable)
246*c9641f3aSSteven Liu {
247*c9641f3aSSteven Liu 	struct regmap *regmap;
248*c9641f3aSSteven Liu 	int reg, ret;
249*c9641f3aSSteven Liu 	u32 data;
250*c9641f3aSSteven Liu 	u8 bit;
251*c9641f3aSSteven Liu 
252*c9641f3aSSteven Liu 	rk3562_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
253*c9641f3aSSteven Liu 
254*c9641f3aSSteven Liu 	/* enable the write to the equivalent lower bits */
255*c9641f3aSSteven Liu 	data = ((1 << RK3562_SMT_BITS_PER_PIN) - 1) << (bit + 16);
256*c9641f3aSSteven Liu 	data |= (enable << bit);
257*c9641f3aSSteven Liu 	ret = regmap_write(regmap, reg, data);
258*c9641f3aSSteven Liu 
259*c9641f3aSSteven Liu 	return ret;
260*c9641f3aSSteven Liu }
261*c9641f3aSSteven Liu 
262*c9641f3aSSteven Liu static struct rockchip_pin_bank rk3562_pin_banks[] = {
263*c9641f3aSSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
264*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
265*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
266*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
267*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
268*c9641f3aSSteven Liu 				    0x20000, 0x20008, 0x20010, 0x20018),
269*c9641f3aSSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
270*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
271*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
272*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
273*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
274*c9641f3aSSteven Liu 				    0, 0x08, 0x10, 0x18),
275*c9641f3aSSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
276*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
277*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
278*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
279*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
280*c9641f3aSSteven Liu 				    0x20, 0, 0, 0),
281*c9641f3aSSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
282*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
283*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
284*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
285*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
286*c9641f3aSSteven Liu 				    0x10040, 0x10048, 0x10050, 0x10058),
287*c9641f3aSSteven Liu 	PIN_BANK_IOMUX_FLAGS_OFFSET(4, 16, "gpio4",
288*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
289*c9641f3aSSteven Liu 				    IOMUX_WIDTH_4BIT,
290*c9641f3aSSteven Liu 				    0,
291*c9641f3aSSteven Liu 				    0,
292*c9641f3aSSteven Liu 				    0x10060, 0x10068, 0, 0),
293*c9641f3aSSteven Liu };
294*c9641f3aSSteven Liu 
295*c9641f3aSSteven Liu static const struct rockchip_pin_ctrl rk3562_pin_ctrl = {
296*c9641f3aSSteven Liu 	.pin_banks		= rk3562_pin_banks,
297*c9641f3aSSteven Liu 	.nr_banks		= ARRAY_SIZE(rk3562_pin_banks),
298*c9641f3aSSteven Liu 	.nr_pins		= 144,
299*c9641f3aSSteven Liu 	.grf_mux_offset		= 0x0,
300*c9641f3aSSteven Liu 	.set_mux		= rk3562_set_mux,
301*c9641f3aSSteven Liu 	.set_pull		= rk3562_set_pull,
302*c9641f3aSSteven Liu 	.set_drive		= rk3562_set_drive,
303*c9641f3aSSteven Liu 	.set_schmitt		= rk3562_set_schmitt,
304*c9641f3aSSteven Liu };
305*c9641f3aSSteven Liu 
306*c9641f3aSSteven Liu static const struct udevice_id rk3562_pinctrl_ids[] = {
307*c9641f3aSSteven Liu 	{
308*c9641f3aSSteven Liu 		.compatible = "rockchip,rk3562-pinctrl",
309*c9641f3aSSteven Liu 		.data = (ulong)&rk3562_pin_ctrl
310*c9641f3aSSteven Liu 	},
311*c9641f3aSSteven Liu 	{ }
312*c9641f3aSSteven Liu };
313*c9641f3aSSteven Liu 
314*c9641f3aSSteven Liu U_BOOT_DRIVER(pinctrl_rk3562) = {
315*c9641f3aSSteven Liu 	.name		= "rockchip_rk3562_pinctrl",
316*c9641f3aSSteven Liu 	.id		= UCLASS_PINCTRL,
317*c9641f3aSSteven Liu 	.of_match	= rk3562_pinctrl_ids,
318*c9641f3aSSteven Liu 	.priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
319*c9641f3aSSteven Liu 	.ops		= &rockchip_pinctrl_ops,
320*c9641f3aSSteven Liu #if !CONFIG_IS_ENABLED(OF_PLATDATA)
321*c9641f3aSSteven Liu 	.bind		= dm_scan_fdt_dev,
322*c9641f3aSSteven Liu #endif
323*c9641f3aSSteven Liu 	.probe		= rockchip_pinctrl_probe,
324*c9641f3aSSteven Liu };
325