1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2025 Rockchip Electronics Co., Ltd
4 */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <dm/pinctrl.h>
9 #include <regmap.h>
10 #include <syscon.h>
11
12 #include "pinctrl-rockchip.h"
13
rv1126b_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)14 static int rv1126b_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
15 {
16 struct rockchip_pinctrl_priv *priv = bank->priv;
17 int iomux_num = (pin / 8);
18 struct regmap *regmap;
19 int reg, ret, mask;
20 u8 bit;
21 u32 data;
22
23 debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
24
25 regmap = priv->regmap_base;
26 reg = bank->iomux[iomux_num].offset;
27 if ((pin % 8) >= 4)
28 reg += 0x4;
29 bit = (pin % 4) * 4;
30 mask = 0xf;
31
32 if (bank->recalced_mask & BIT(pin))
33 rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
34 data = (mask << (bit + 16));
35 data |= (mux & mask) << bit;
36
37 debug("iomux write reg = %x data = %x\n", reg, data);
38
39 ret = regmap_write(regmap, reg, data);
40
41 return ret;
42 }
43
44 #define RV1126B_DRV_BITS_PER_PIN 8
45 #define RV1126B_DRV_PINS_PER_REG 2
46 #define RV1126B_DRV_GPIO0_A_OFFSET 0x100
47 #define RV1126B_DRV_GPIO0_C_OFFSET 0x8120
48 #define RV1126B_DRV_GPIO_OFFSET(GPION) (0x8100 + GPION * 0x8040)
49
rv1126b_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)50 static int rv1126b_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
51 int pin_num, struct regmap **regmap,
52 int *reg, u8 *bit)
53 {
54 struct rockchip_pinctrl_priv *priv = bank->priv;
55
56 *regmap = priv->regmap_base;
57 switch (bank->bank_num) {
58 case 0:
59 if (pin_num < 16)
60 *reg = RV1126B_DRV_GPIO0_A_OFFSET;
61 else
62 *reg = RV1126B_DRV_GPIO0_C_OFFSET - 0x20;
63 break;
64
65 case 1:
66 case 2:
67 case 3:
68 case 4:
69 case 5:
70 case 6:
71 case 7:
72 *reg = RV1126B_DRV_GPIO_OFFSET(bank->bank_num);
73 break;
74
75 default:
76 dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
77
78 return -EINVAL;
79 }
80
81 *reg += ((pin_num / RV1126B_DRV_PINS_PER_REG) * 4);
82 *bit = pin_num % RV1126B_DRV_PINS_PER_REG;
83 *bit *= RV1126B_DRV_BITS_PER_PIN;
84
85 return 0;
86 }
87
rv1126b_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)88 static int rv1126b_set_drive(struct rockchip_pin_bank *bank,
89 int pin_num, int strength)
90 {
91 struct regmap *regmap;
92 int reg, ret;
93 u32 data;
94 u8 bit;
95 int rmask_bits = RV1126B_DRV_BITS_PER_PIN;
96
97 ret = rv1126b_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
98 if (ret)
99 return ret;
100
101 /* enable the write to the equivalent lower bits */
102 data = ((1 << rmask_bits) - 1) << (bit + 16);
103 ret = (1 << (strength + 1)) - 1;
104 data |= (ret << bit);
105 ret = regmap_write(regmap, reg, data);
106
107 return ret;
108 }
109
110 #define RV1126B_PULL_BITS_PER_PIN 2
111 #define RV1126B_PULL_PINS_PER_REG 8
112 #define RV1126B_PULL_GPIO0_A_OFFSET 0x300
113 #define RV1126B_PULL_GPIO0_C_OFFSET 0x8308
114 #define RV1126B_PULL_GPIO_OFFSET(GPION) (0x8300 + GPION * 0x8010)
115
rv1126b_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)116 static int rv1126b_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
117 int pin_num, struct regmap **regmap,
118 int *reg, u8 *bit)
119 {
120 struct rockchip_pinctrl_priv *priv = bank->priv;
121
122 *regmap = priv->regmap_base;
123 switch (bank->bank_num) {
124 case 0:
125 if (pin_num < 16)
126 *reg = RV1126B_PULL_GPIO0_A_OFFSET;
127 else
128 *reg = RV1126B_PULL_GPIO0_C_OFFSET - 0x8;
129 break;
130
131 case 1:
132 case 2:
133 case 3:
134 case 4:
135 case 5:
136 case 6:
137 case 7:
138 *reg = RV1126B_PULL_GPIO_OFFSET(bank->bank_num);
139 break;
140
141 default:
142 dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
143
144 return -EINVAL;
145 }
146
147 *reg += ((pin_num / RV1126B_PULL_PINS_PER_REG) * 4);
148 *bit = pin_num % RV1126B_PULL_PINS_PER_REG;
149 *bit *= RV1126B_PULL_BITS_PER_PIN;
150
151 return 0;
152 }
153
rv1126b_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)154 static int rv1126b_set_pull(struct rockchip_pin_bank *bank,
155 int pin_num, int pull)
156 {
157 struct regmap *regmap;
158 int reg, ret;
159 u8 bit, type;
160 u32 data;
161
162 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
163 return -ENOTSUPP;
164
165 ret = rv1126b_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
166 if (ret)
167 return ret;
168 type = bank->pull_type[pin_num / 8];
169
170 ret = rockchip_translate_pull_value(type, pull);
171 if (ret < 0) {
172 debug("unsupported pull setting %d\n", pull);
173
174 return ret;
175 }
176
177 /* enable the write to the equivalent lower bits */
178 data = ((1 << RV1126B_PULL_BITS_PER_PIN) - 1) << (bit + 16);
179 data |= (ret << bit);
180 ret = regmap_write(regmap, reg, data);
181
182 return ret;
183 }
184
185 #define RV1126B_SMT_BITS_PER_PIN 1
186 #define RV1126B_SMT_PINS_PER_REG 8
187 #define RV1126B_SMT_GPIO0_A_OFFSET 0x500
188 #define RV1126B_SMT_GPIO0_C_OFFSET 0x8508
189 #define RV1126B_SMT_GPIO_OFFSET(GPION) (0x8500 + GPION * 0x8010)
190
rv1126b_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)191 static int rv1126b_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
192 int pin_num,
193 struct regmap **regmap,
194 int *reg, u8 *bit)
195 {
196 struct rockchip_pinctrl_priv *priv = bank->priv;
197
198 *regmap = priv->regmap_base;
199 switch (bank->bank_num) {
200 case 0:
201 if (pin_num < 16)
202 *reg = RV1126B_SMT_GPIO0_A_OFFSET;
203 else
204 *reg = RV1126B_SMT_GPIO0_C_OFFSET - 0x8;
205 break;
206
207 case 1:
208 case 2:
209 case 3:
210 case 4:
211 case 5:
212 case 6:
213 case 7:
214 *reg = RV1126B_SMT_GPIO_OFFSET(bank->bank_num);
215 break;
216
217 default:
218 dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
219 return -EINVAL;
220 }
221
222 *reg += ((pin_num / RV1126B_SMT_PINS_PER_REG) * 4);
223 *bit = pin_num % RV1126B_SMT_PINS_PER_REG;
224 *bit *= RV1126B_SMT_BITS_PER_PIN;
225
226 return 0;
227 }
228
rv1126b_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)229 static int rv1126b_set_schmitt(struct rockchip_pin_bank *bank,
230 int pin_num, int enable)
231 {
232 struct regmap *regmap;
233 int reg, ret;
234 u32 data;
235 u8 bit;
236
237 ret = rv1126b_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
238 if (ret)
239 return ret;
240
241 /* enable the write to the equivalent lower bits */
242 data = ((1 << RV1126B_SMT_BITS_PER_PIN) - 1) << (bit + 16);
243 data |= (enable << bit);
244 ret = regmap_write(regmap, reg, data);
245
246 return ret;
247 }
248
249 static struct rockchip_pin_bank rv1126b_pin_banks[] = {
250 PIN_BANK_IOMUX_4_OFFSET(0, 32, "gpio0",
251 0x0, 0x8, 0x8010, 0x8018),
252 PIN_BANK_IOMUX_4_OFFSET(1, 32, "gpio1",
253 0x10020, 0x10028, 0x10030, 0x10038),
254 PIN_BANK_IOMUX_4_OFFSET(2, 32, "gpio2",
255 0x18040, 0x18048, 0x18050, 0x18058),
256 PIN_BANK_IOMUX_4_OFFSET(3, 32, "gpio3",
257 0x20060, 0x20068, 0x20070, 0x20078),
258 PIN_BANK_IOMUX_4_OFFSET(4, 32, "gpio4",
259 0x28080, 0x28088, 0x28090, 0x28098),
260 PIN_BANK_IOMUX_4_OFFSET(5, 32, "gpio5",
261 0x300a0, 0x300a8, 0x300b0, 0x300b8),
262 PIN_BANK_IOMUX_4_OFFSET(6, 32, "gpio6",
263 0x380c0, 0x380c8, 0x380d0, 0x380d8),
264 PIN_BANK_IOMUX_4_OFFSET(7, 32, "gpio7",
265 0x400e0, 0x400e8, 0x400f0, 0x400f8),
266 };
267 static struct rockchip_pin_ctrl rv1126b_pin_ctrl __maybe_unused = {
268 .pin_banks = rv1126b_pin_banks,
269 .nr_banks = ARRAY_SIZE(rv1126b_pin_banks),
270 .nr_pins = 256,
271 .set_mux = rv1126b_set_mux,
272 .set_pull = rv1126b_set_pull,
273 .set_drive = rv1126b_set_drive,
274 .set_schmitt = rv1126b_set_schmitt,
275 };
276
277 static const struct udevice_id rv1126b_pinctrl_ids[] = {
278 {
279 .compatible = "rockchip,rv1126b-pinctrl",
280 .data = (ulong)&rv1126b_pin_ctrl
281 },
282 { }
283 };
284
285 U_BOOT_DRIVER(pinctrl_rv1126b) = {
286 .name = "rockchip_rv1126b_pinctrl",
287 .id = UCLASS_PINCTRL,
288 .of_match = rv1126b_pinctrl_ids,
289 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
290 .ops = &rockchip_pinctrl_ops,
291 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
292 .bind = dm_scan_fdt_dev,
293 #endif
294 .probe = rockchip_pinctrl_probe,
295 };
296