1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * (C) Copyright 2020 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <dm/pinctrl.h>
9*4882a593Smuzhiyun #include <regmap.h>
10*4882a593Smuzhiyun #include <syscon.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "pinctrl-rockchip.h"
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun static struct rockchip_mux_route_data rk1808_mux_route_data[] = {
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun /* i2c2m0_sda */
17*4882a593Smuzhiyun .bank_num = 3,
18*4882a593Smuzhiyun .pin = 12,
19*4882a593Smuzhiyun .func = 2,
20*4882a593Smuzhiyun .route_offset = 0x190,
21*4882a593Smuzhiyun .route_val = BIT(16 + 3),
22*4882a593Smuzhiyun }, {
23*4882a593Smuzhiyun /* i2c2m1_sda */
24*4882a593Smuzhiyun .bank_num = 1,
25*4882a593Smuzhiyun .pin = 13,
26*4882a593Smuzhiyun .func = 2,
27*4882a593Smuzhiyun .route_offset = 0x190,
28*4882a593Smuzhiyun .route_val = BIT(16 + 3) | BIT(3),
29*4882a593Smuzhiyun }, {
30*4882a593Smuzhiyun /* uart2_rxm0 */
31*4882a593Smuzhiyun .bank_num = 4,
32*4882a593Smuzhiyun .pin = 3,
33*4882a593Smuzhiyun .func = 2,
34*4882a593Smuzhiyun .route_offset = 0x190,
35*4882a593Smuzhiyun .route_val = BIT(16 + 14) | BIT(16 + 15),
36*4882a593Smuzhiyun }, {
37*4882a593Smuzhiyun /* uart2_rxm1 */
38*4882a593Smuzhiyun .bank_num = 2,
39*4882a593Smuzhiyun .pin = 25,
40*4882a593Smuzhiyun .func = 2,
41*4882a593Smuzhiyun .route_offset = 0x190,
42*4882a593Smuzhiyun .route_val = BIT(16 + 14) | BIT(14) | BIT(16 + 15),
43*4882a593Smuzhiyun }, {
44*4882a593Smuzhiyun /* uart2_rxm2 */
45*4882a593Smuzhiyun .bank_num = 3,
46*4882a593Smuzhiyun .pin = 4,
47*4882a593Smuzhiyun .func = 2,
48*4882a593Smuzhiyun .route_offset = 0x190,
49*4882a593Smuzhiyun .route_val = BIT(16 + 14) | BIT(16 + 15) | BIT(15),
50*4882a593Smuzhiyun },
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
rk1808_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)53*4882a593Smuzhiyun static int rk1808_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun struct rockchip_pinctrl_priv *priv = bank->priv;
56*4882a593Smuzhiyun int iomux_num = (pin / 8);
57*4882a593Smuzhiyun struct regmap *regmap;
58*4882a593Smuzhiyun int reg, ret, mask, mux_type;
59*4882a593Smuzhiyun u8 bit;
60*4882a593Smuzhiyun u32 data;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
65*4882a593Smuzhiyun regmap = priv->regmap_pmu;
66*4882a593Smuzhiyun else if (bank->iomux[iomux_num].type & IOMUX_L_SOURCE_PMU)
67*4882a593Smuzhiyun regmap = (pin % 8 < 4) ? priv->regmap_pmu : priv->regmap_base;
68*4882a593Smuzhiyun else
69*4882a593Smuzhiyun regmap = priv->regmap_base;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* get basic quadrupel of mux registers and the correct reg inside */
72*4882a593Smuzhiyun mux_type = bank->iomux[iomux_num].type;
73*4882a593Smuzhiyun reg = bank->iomux[iomux_num].offset;
74*4882a593Smuzhiyun if (mux_type & IOMUX_WIDTH_4BIT) {
75*4882a593Smuzhiyun if ((pin % 8) >= 4)
76*4882a593Smuzhiyun reg += 0x4;
77*4882a593Smuzhiyun bit = (pin % 4) * 4;
78*4882a593Smuzhiyun mask = 0xf;
79*4882a593Smuzhiyun } else {
80*4882a593Smuzhiyun bit = (pin % 8) * 2;
81*4882a593Smuzhiyun mask = 0x3;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun if (bank->recalced_mask & BIT(pin))
85*4882a593Smuzhiyun rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun data = (mask << (bit + 16));
88*4882a593Smuzhiyun data |= (mux & mask) << bit;
89*4882a593Smuzhiyun ret = regmap_write(regmap, reg, data);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun return ret;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun #define RK1808_PULL_PMU_OFFSET 0x10
95*4882a593Smuzhiyun #define RK1808_PULL_GRF_OFFSET 0x80
96*4882a593Smuzhiyun #define RK1808_PULL_PINS_PER_REG 8
97*4882a593Smuzhiyun #define RK1808_PULL_BITS_PER_PIN 2
98*4882a593Smuzhiyun #define RK1808_PULL_BANK_STRIDE 16
99*4882a593Smuzhiyun
rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)100*4882a593Smuzhiyun static void rk1808_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
101*4882a593Smuzhiyun int pin_num,
102*4882a593Smuzhiyun struct regmap **regmap,
103*4882a593Smuzhiyun int *reg, u8 *bit)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct rockchip_pinctrl_priv *priv = bank->priv;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun if (bank->bank_num == 0) {
108*4882a593Smuzhiyun *regmap = priv->regmap_pmu;
109*4882a593Smuzhiyun *reg = RK1808_PULL_PMU_OFFSET;
110*4882a593Smuzhiyun } else {
111*4882a593Smuzhiyun *reg = RK1808_PULL_GRF_OFFSET;
112*4882a593Smuzhiyun *regmap = priv->regmap_base;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun *reg += ((pin_num / RK1808_PULL_PINS_PER_REG) * 4);
116*4882a593Smuzhiyun *bit = (pin_num % RK1808_PULL_PINS_PER_REG);
117*4882a593Smuzhiyun *bit *= RK1808_PULL_BITS_PER_PIN;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun #define RK1808_DRV_PMU_OFFSET 0x20
121*4882a593Smuzhiyun #define RK1808_DRV_GRF_OFFSET 0x140
122*4882a593Smuzhiyun #define RK1808_DRV_BITS_PER_PIN 2
123*4882a593Smuzhiyun #define RK1808_DRV_PINS_PER_REG 8
124*4882a593Smuzhiyun #define RK1808_DRV_BANK_STRIDE 16
125*4882a593Smuzhiyun
rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)126*4882a593Smuzhiyun static void rk1808_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
127*4882a593Smuzhiyun int pin_num,
128*4882a593Smuzhiyun struct regmap **regmap,
129*4882a593Smuzhiyun int *reg, u8 *bit)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct rockchip_pinctrl_priv *priv = bank->priv;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (bank->bank_num == 0) {
134*4882a593Smuzhiyun *regmap = priv->regmap_pmu;
135*4882a593Smuzhiyun *reg = RK1808_DRV_PMU_OFFSET;
136*4882a593Smuzhiyun } else {
137*4882a593Smuzhiyun *regmap = priv->regmap_base;
138*4882a593Smuzhiyun *reg = RK1808_DRV_GRF_OFFSET;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun *reg += ((pin_num / RK1808_DRV_PINS_PER_REG) * 4);
142*4882a593Smuzhiyun *bit = pin_num % RK1808_DRV_PINS_PER_REG;
143*4882a593Smuzhiyun *bit *= RK1808_DRV_BITS_PER_PIN;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun #define RK1808_SCHMITT_PMU_OFFSET 0x0040
147*4882a593Smuzhiyun #define RK1808_SCHMITT_GRF_OFFSET 0x0100
148*4882a593Smuzhiyun #define RK1808_SCHMITT_BANK_STRIDE 16
149*4882a593Smuzhiyun #define RK1808_SCHMITT_PINS_PER_REG 8
150*4882a593Smuzhiyun
rk1808_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)151*4882a593Smuzhiyun static int rk1808_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
152*4882a593Smuzhiyun int pin_num,
153*4882a593Smuzhiyun struct regmap **regmap,
154*4882a593Smuzhiyun int *reg, u8 *bit)
155*4882a593Smuzhiyun {
156*4882a593Smuzhiyun struct rockchip_pinctrl_priv *priv = bank->priv;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun if (bank->bank_num == 0) {
159*4882a593Smuzhiyun *regmap = priv->regmap_pmu;
160*4882a593Smuzhiyun *reg = RK1808_SCHMITT_PMU_OFFSET;
161*4882a593Smuzhiyun } else {
162*4882a593Smuzhiyun *regmap = priv->regmap_base;
163*4882a593Smuzhiyun *reg = RK1808_SCHMITT_GRF_OFFSET;
164*4882a593Smuzhiyun *reg += (bank->bank_num - 1) * RK1808_SCHMITT_BANK_STRIDE;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun *reg += ((pin_num / RK1808_SCHMITT_PINS_PER_REG) * 4);
167*4882a593Smuzhiyun *bit = pin_num % RK1808_SCHMITT_PINS_PER_REG;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun return 0;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun
rk1808_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)172*4882a593Smuzhiyun static int rk1808_set_pull(struct rockchip_pin_bank *bank,
173*4882a593Smuzhiyun int pin_num, int pull)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun struct regmap *regmap;
176*4882a593Smuzhiyun int reg, ret;
177*4882a593Smuzhiyun u8 bit, type;
178*4882a593Smuzhiyun u32 data;
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
181*4882a593Smuzhiyun return -ENOTSUPP;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun rk1808_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
184*4882a593Smuzhiyun type = bank->pull_type[pin_num / 8];
185*4882a593Smuzhiyun ret = rockchip_translate_pull_value(type, pull);
186*4882a593Smuzhiyun if (ret < 0) {
187*4882a593Smuzhiyun debug("unsupported pull setting %d\n", pull);
188*4882a593Smuzhiyun return ret;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* enable the write to the equivalent lower bits */
192*4882a593Smuzhiyun data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun data |= (ret << bit);
195*4882a593Smuzhiyun ret = regmap_write(regmap, reg, data);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun return ret;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun
rk1808_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)200*4882a593Smuzhiyun static int rk1808_set_drive(struct rockchip_pin_bank *bank,
201*4882a593Smuzhiyun int pin_num, int strength)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun struct regmap *regmap;
204*4882a593Smuzhiyun int reg;
205*4882a593Smuzhiyun u32 data;
206*4882a593Smuzhiyun u8 bit;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun rk1808_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* enable the write to the equivalent lower bits */
211*4882a593Smuzhiyun data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
212*4882a593Smuzhiyun data |= (strength << bit);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun return regmap_write(regmap, reg, data);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
rk1808_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)217*4882a593Smuzhiyun static int rk1808_set_schmitt(struct rockchip_pin_bank *bank,
218*4882a593Smuzhiyun int pin_num, int enable)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun struct regmap *regmap;
221*4882a593Smuzhiyun int reg;
222*4882a593Smuzhiyun u8 bit;
223*4882a593Smuzhiyun u32 data;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun rk1808_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
226*4882a593Smuzhiyun /* enable the write to the equivalent lower bits */
227*4882a593Smuzhiyun data = BIT(bit + 16) | (enable << bit);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun return regmap_write(regmap, reg, data);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun static struct rockchip_pin_bank rk1808_pin_banks[] = {
233*4882a593Smuzhiyun PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0",
234*4882a593Smuzhiyun IOMUX_SOURCE_PMU,
235*4882a593Smuzhiyun IOMUX_SOURCE_PMU,
236*4882a593Smuzhiyun IOMUX_SOURCE_PMU,
237*4882a593Smuzhiyun IOMUX_SOURCE_PMU),
238*4882a593Smuzhiyun PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1",
239*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
240*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
241*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
242*4882a593Smuzhiyun IOMUX_WIDTH_4BIT),
243*4882a593Smuzhiyun PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2",
244*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
245*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
246*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
247*4882a593Smuzhiyun IOMUX_WIDTH_4BIT),
248*4882a593Smuzhiyun PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
249*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
250*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
251*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
252*4882a593Smuzhiyun IOMUX_WIDTH_4BIT),
253*4882a593Smuzhiyun PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4",
254*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
255*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
256*4882a593Smuzhiyun IOMUX_WIDTH_4BIT,
257*4882a593Smuzhiyun IOMUX_WIDTH_4BIT),
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun static const struct rockchip_pin_ctrl rk1808_pin_ctrl = {
261*4882a593Smuzhiyun .pin_banks = rk1808_pin_banks,
262*4882a593Smuzhiyun .nr_banks = ARRAY_SIZE(rk1808_pin_banks),
263*4882a593Smuzhiyun .nr_pins = 160,
264*4882a593Smuzhiyun .iomux_routes = rk1808_mux_route_data,
265*4882a593Smuzhiyun .niomux_routes = ARRAY_SIZE(rk1808_mux_route_data),
266*4882a593Smuzhiyun .grf_mux_offset = 0x0,
267*4882a593Smuzhiyun .pmu_mux_offset = 0x0,
268*4882a593Smuzhiyun .set_mux = rk1808_set_mux,
269*4882a593Smuzhiyun .set_pull = rk1808_set_pull,
270*4882a593Smuzhiyun .set_drive = rk1808_set_drive,
271*4882a593Smuzhiyun .set_schmitt = rk1808_set_schmitt,
272*4882a593Smuzhiyun };
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun static const struct udevice_id rk1808_pinctrl_ids[] = {
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun .compatible = "rockchip,rk1808-pinctrl",
277*4882a593Smuzhiyun .data = (ulong)&rk1808_pin_ctrl
278*4882a593Smuzhiyun },
279*4882a593Smuzhiyun { }
280*4882a593Smuzhiyun };
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun U_BOOT_DRIVER(pinctrl_rk1808) = {
283*4882a593Smuzhiyun .name = "rockchip_rk1808_pinctrl",
284*4882a593Smuzhiyun .id = UCLASS_PINCTRL,
285*4882a593Smuzhiyun .of_match = rk1808_pinctrl_ids,
286*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
287*4882a593Smuzhiyun .ops = &rockchip_pinctrl_ops,
288*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(OF_PLATDATA)
289*4882a593Smuzhiyun .bind = dm_scan_fdt_dev,
290*4882a593Smuzhiyun #endif
291*4882a593Smuzhiyun .probe = rockchip_pinctrl_probe,
292*4882a593Smuzhiyun };
293