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, ®map, ®, &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, ®map, ®, &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, ®map, ®, &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