1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2024 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
rockchip_set_rmio(struct rockchip_pin_bank * bank,int pin,int * mux)14 static int rockchip_set_rmio(struct rockchip_pin_bank *bank, int pin, int *mux)
15 {
16 struct rockchip_pinctrl_priv *priv = bank->priv;
17 struct regmap *regmap;
18 int reg, function;
19 u32 data;
20 int ret = 0;
21 u32 iomux_max = (1 << 4) - 1;
22
23 if (*mux > iomux_max)
24 function = *mux - iomux_max;
25 else
26 return 0;
27
28 regmap = priv->regmap_rmio;
29 if (bank->bank_num == 0) {
30 if (pin < 24)
31 reg = 0x80 + 0x4 * pin;
32 else
33 ret = -EINVAL;
34 } else if (bank->bank_num == 1) {
35 if (pin >= 9 && pin <= 11)
36 reg = 0xbc + 0x4 * pin;
37 else if (pin >= 18 && pin <= 19)
38 reg = 0xa4 + 0x4 * pin;
39 else if (pin >= 25 && pin <= 27)
40 reg = 0x90 + 0x4 * pin;
41 else
42 ret = -EINVAL;
43 } else {
44 ret = -EINVAL;
45 }
46 if (ret) {
47 pr_err("rmio unsupported bank_num %d function %d\n",
48 bank->bank_num, function);
49
50 return -EINVAL;
51 }
52
53 data = 0x7f0000 | function;
54 *mux = 7;
55 ret = regmap_write(regmap, reg, data);
56 if (ret)
57 return ret;
58
59 return 0;
60 }
61
rk3506_set_mux(struct rockchip_pin_bank * bank,int pin,int mux)62 static int rk3506_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
63 {
64 struct rockchip_pinctrl_priv *priv = bank->priv;
65 int iomux_num = (pin / 8);
66 struct regmap *regmap;
67 int reg, ret, mask;
68 u8 bit;
69 u32 data;
70
71 debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
72
73 ret = rockchip_set_rmio(bank, pin, &mux);
74 if (ret)
75 return ret;
76
77 if (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
78 regmap = priv->regmap_pmu;
79 else
80 regmap = priv->regmap_base;
81
82 if (bank->bank_num == 1)
83 regmap = priv->regmap_ioc1;
84 else if (bank->bank_num == 4)
85 return 0;
86
87 reg = bank->iomux[iomux_num].offset;
88 if ((pin % 8) >= 4)
89 reg += 0x4;
90 bit = (pin % 4) * 4;
91 mask = 0xf;
92
93 if (bank->recalced_mask & BIT(pin))
94 rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask);
95 data = (mask << (bit + 16));
96 data |= (mux & mask) << bit;
97
98 debug("iomux write reg = %x data = %x\n", reg, data);
99
100 ret = regmap_write(regmap, reg, data);
101
102 return ret;
103 }
104
105 #define RK3506_DRV_BITS_PER_PIN 8
106 #define RK3506_DRV_PINS_PER_REG 2
107 #define RK3506_DRV_GPIO0_A_OFFSET 0x100
108 #define RK3506_DRV_GPIO0_D_OFFSET 0x830
109 #define RK3506_DRV_GPIO1_OFFSET 0x140
110 #define RK3506_DRV_GPIO2_OFFSET 0x180
111 #define RK3506_DRV_GPIO3_OFFSET 0x1c0
112 #define RK3506_DRV_GPIO4_OFFSET 0x840
113
rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)114 static int rk3506_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
115 int pin_num, struct regmap **regmap,
116 int *reg, u8 *bit)
117 {
118 struct rockchip_pinctrl_priv *priv = bank->priv;
119 int ret = 0;
120
121 switch (bank->bank_num) {
122 case 0:
123 *regmap = priv->regmap_pmu;
124 if (pin_num > 24) {
125 ret = -EINVAL;
126 } else if (pin_num < 24) {
127 *reg = RK3506_DRV_GPIO0_A_OFFSET;
128 } else {
129 *reg = RK3506_DRV_GPIO0_D_OFFSET;
130 *bit = 3;
131
132 return 0;
133 }
134 break;
135
136 case 1:
137 *regmap = priv->regmap_ioc1;
138 if (pin_num < 28)
139 *reg = RK3506_DRV_GPIO1_OFFSET;
140 else
141 ret = -EINVAL;
142 break;
143
144 case 2:
145 *regmap = priv->regmap_base;
146 if (pin_num < 17)
147 *reg = RK3506_DRV_GPIO2_OFFSET;
148 else
149 ret = -EINVAL;
150 break;
151
152 case 3:
153 *regmap = priv->regmap_base;
154 if (pin_num < 15)
155 *reg = RK3506_DRV_GPIO3_OFFSET;
156 else
157 ret = -EINVAL;
158 break;
159
160 case 4:
161 *regmap = priv->regmap_base;
162 if (pin_num < 8 || pin_num > 11) {
163 ret = -EINVAL;
164 } else {
165 *reg = RK3506_DRV_GPIO4_OFFSET;
166 *bit = 10;
167
168 return 0;
169 }
170 break;
171
172 default:
173 ret = -EINVAL;
174 break;
175 }
176
177 if (ret) {
178 debug("unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
179
180 return ret;
181 }
182
183 *reg += ((pin_num / RK3506_DRV_PINS_PER_REG) * 4);
184 *bit = pin_num % RK3506_DRV_PINS_PER_REG;
185 *bit *= RK3506_DRV_BITS_PER_PIN;
186
187 return 0;
188 }
189
rk3506_set_drive(struct rockchip_pin_bank * bank,int pin_num,int strength)190 static int rk3506_set_drive(struct rockchip_pin_bank *bank,
191 int pin_num, int strength)
192 {
193 struct regmap *regmap;
194 int reg, ret, i;
195 u32 data;
196 u8 bit;
197 int rmask_bits = RK3506_DRV_BITS_PER_PIN;
198
199 ret = rk3506_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit);
200 if (ret)
201 return ret;
202
203 for (i = 0, ret = 1; i < strength; i++)
204 ret = (ret << 1) | 1;
205
206 if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
207 rmask_bits = 2;
208 ret = strength;
209 }
210
211 /* enable the write to the equivalent lower bits */
212 data = ((1 << rmask_bits) - 1) << (bit + 16);
213 data |= (ret << bit);
214 ret = regmap_write(regmap, reg, data);
215
216 return ret;
217 }
218
219 #define RK3506_PULL_BITS_PER_PIN 2
220 #define RK3506_PULL_PINS_PER_REG 8
221 #define RK3506_PULL_GPIO0_A_OFFSET 0x200
222 #define RK3506_PULL_GPIO0_D_OFFSET 0x830
223 #define RK3506_PULL_GPIO1_OFFSET 0x210
224 #define RK3506_PULL_GPIO2_OFFSET 0x220
225 #define RK3506_PULL_GPIO3_OFFSET 0x230
226 #define RK3506_PULL_GPIO4_OFFSET 0x840
227
rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)228 static int rk3506_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
229 int pin_num, struct regmap **regmap,
230 int *reg, u8 *bit)
231 {
232 struct rockchip_pinctrl_priv *priv = bank->priv;
233 int ret = 0;
234
235 switch (bank->bank_num) {
236 case 0:
237 *regmap = priv->regmap_pmu;
238 if (pin_num > 24) {
239 ret = -EINVAL;
240 } else if (pin_num < 24) {
241 *reg = RK3506_PULL_GPIO0_A_OFFSET;
242 } else {
243 *reg = RK3506_PULL_GPIO0_D_OFFSET;
244 *bit = 5;
245
246 return 0;
247 }
248 break;
249
250 case 1:
251 *regmap = priv->regmap_ioc1;
252 if (pin_num < 28)
253 *reg = RK3506_PULL_GPIO1_OFFSET;
254 else
255 ret = -EINVAL;
256 break;
257
258 case 2:
259 *regmap = priv->regmap_base;
260 if (pin_num < 17)
261 *reg = RK3506_PULL_GPIO2_OFFSET;
262 else
263 ret = -EINVAL;
264 break;
265
266 case 3:
267 *regmap = priv->regmap_base;
268 if (pin_num < 15)
269 *reg = RK3506_PULL_GPIO3_OFFSET;
270 else
271 ret = -EINVAL;
272 break;
273
274 case 4:
275 *regmap = priv->regmap_base;
276 if (pin_num < 8 || pin_num > 11) {
277 ret = -EINVAL;
278 } else {
279 *reg = RK3506_PULL_GPIO4_OFFSET;
280 *bit = 13;
281
282 return 0;
283 }
284 break;
285
286 default:
287 ret = -EINVAL;
288 break;
289 }
290
291 if (ret) {
292 debug("unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
293
294 return ret;
295 }
296
297 *reg += ((pin_num / RK3506_PULL_PINS_PER_REG) * 4);
298 *bit = pin_num % RK3506_PULL_PINS_PER_REG;
299 *bit *= RK3506_PULL_BITS_PER_PIN;
300
301 return 0;
302 }
303
rk3506_set_pull(struct rockchip_pin_bank * bank,int pin_num,int pull)304 static int rk3506_set_pull(struct rockchip_pin_bank *bank,
305 int pin_num, int pull)
306 {
307 struct regmap *regmap;
308 int reg, ret;
309 u8 bit, type;
310 u32 data;
311
312 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
313 return -ENOTSUPP;
314
315 ret = rk3506_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit);
316 if (ret)
317 return ret;
318 type = bank->pull_type[pin_num / 8];
319
320 if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4)
321 type = 1;
322
323 ret = rockchip_translate_pull_value(type, pull);
324 if (ret < 0) {
325 debug("unsupported pull setting %d\n", pull);
326
327 return ret;
328 }
329
330 /* enable the write to the equivalent lower bits */
331 data = ((1 << RK3506_PULL_BITS_PER_PIN) - 1) << (bit + 16);
332
333 data |= (ret << bit);
334 ret = regmap_write(regmap, reg, data);
335
336 return ret;
337 }
338
339 #define RK3506_SMT_BITS_PER_PIN 1
340 #define RK3506_SMT_PINS_PER_REG 8
341 #define RK3506_SMT_GPIO0_A_OFFSET 0x400
342 #define RK3506_SMT_GPIO0_D_OFFSET 0x830
343 #define RK3506_SMT_GPIO1_OFFSET 0x410
344 #define RK3506_SMT_GPIO2_OFFSET 0x420
345 #define RK3506_SMT_GPIO3_OFFSET 0x430
346 #define RK3506_SMT_GPIO4_OFFSET 0x840
347
rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank * bank,int pin_num,struct regmap ** regmap,int * reg,u8 * bit)348 static int rk3506_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
349 int pin_num,
350 struct regmap **regmap,
351 int *reg, u8 *bit)
352 {
353 struct rockchip_pinctrl_priv *priv = bank->priv;
354 int ret = 0;
355
356 switch (bank->bank_num) {
357 case 0:
358 *regmap = priv->regmap_pmu;
359 if (pin_num > 24) {
360 ret = -EINVAL;
361 } else if (pin_num < 24) {
362 *reg = RK3506_SMT_GPIO0_A_OFFSET;
363 } else {
364 *reg = RK3506_SMT_GPIO0_D_OFFSET;
365 *bit = 9;
366
367 return 0;
368 }
369 break;
370
371 case 1:
372 *regmap = priv->regmap_ioc1;
373 if (pin_num < 28)
374 *reg = RK3506_SMT_GPIO1_OFFSET;
375 else
376 ret = -EINVAL;
377 break;
378
379 case 2:
380 *regmap = priv->regmap_base;
381 if (pin_num < 17)
382 *reg = RK3506_SMT_GPIO2_OFFSET;
383 else
384 ret = -EINVAL;
385 break;
386
387 case 3:
388 *regmap = priv->regmap_base;
389 if (pin_num < 15)
390 *reg = RK3506_SMT_GPIO3_OFFSET;
391 else
392 ret = -EINVAL;
393 break;
394
395 case 4:
396 *regmap = priv->regmap_base;
397 if (pin_num < 8 || pin_num > 11) {
398 ret = -EINVAL;
399 } else {
400 *reg = RK3506_SMT_GPIO4_OFFSET;
401 *bit = 8;
402
403 return 0;
404 }
405 break;
406
407 default:
408 ret = -EINVAL;
409 break;
410 }
411
412 if (ret) {
413 dev_err(priv->dev, "unsupported bank_num %d pin_num %d\n", bank->bank_num, pin_num);
414
415 return ret;
416 }
417
418 *reg += ((pin_num / RK3506_SMT_PINS_PER_REG) * 4);
419 *bit = pin_num % RK3506_SMT_PINS_PER_REG;
420 *bit *= RK3506_SMT_BITS_PER_PIN;
421
422 return 0;
423 }
424
rk3506_set_schmitt(struct rockchip_pin_bank * bank,int pin_num,int enable)425 static int rk3506_set_schmitt(struct rockchip_pin_bank *bank,
426 int pin_num, int enable)
427 {
428 struct regmap *regmap;
429 int reg, ret;
430 u32 data;
431 u8 bit;
432
433 ret = rk3506_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit);
434 if (ret)
435 return ret;
436
437 /* enable the write to the equivalent lower bits */
438 data = ((1 << RK3506_SMT_BITS_PER_PIN) - 1) << (bit + 16);
439 data |= (enable << bit);
440
441 if ((bank->bank_num == 0 && pin_num == 24) || bank->bank_num == 4) {
442 data = 0x3 << (bit + 16);
443 data |= ((enable ? 0x3 : 0) << bit);
444 }
445 ret = regmap_write(regmap, reg, data);
446
447 return ret;
448 }
449
450 static struct rockchip_mux_recalced_data rk3506_mux_recalced_data[] = {
451 {
452 .num = 0,
453 .pin = 24,
454 .reg = 0x830,
455 .bit = 0,
456 .mask = 0x3
457 },
458 };
459
460 static struct rockchip_pin_bank rk3506_pin_banks[] = {
461 PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
462 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
463 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
464 IOMUX_WIDTH_4BIT | IOMUX_SOURCE_PMU,
465 IOMUX_8WIDTH_2BIT | IOMUX_SOURCE_PMU,
466 0x0, 0x8, 0x10, 0x830),
467 PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
468 IOMUX_WIDTH_4BIT,
469 IOMUX_WIDTH_4BIT,
470 IOMUX_WIDTH_4BIT,
471 IOMUX_WIDTH_4BIT,
472 0x20, 0x28, 0x30, 0x38),
473 PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
474 IOMUX_WIDTH_4BIT,
475 IOMUX_WIDTH_4BIT,
476 IOMUX_WIDTH_4BIT,
477 IOMUX_WIDTH_4BIT,
478 0x40, 0x48, 0x50, 0x58),
479 PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
480 IOMUX_WIDTH_4BIT,
481 IOMUX_WIDTH_4BIT,
482 IOMUX_WIDTH_4BIT,
483 IOMUX_WIDTH_4BIT,
484 0x60, 0x68, 0x70, 0x78),
485 PIN_BANK_IOMUX_FLAGS_OFFSET(4, 32, "gpio4",
486 IOMUX_WIDTH_4BIT,
487 IOMUX_WIDTH_4BIT,
488 IOMUX_WIDTH_4BIT,
489 IOMUX_WIDTH_4BIT,
490 0x80, 0x88, 0x90, 0x98),
491 };
492
493 static const struct rockchip_pin_ctrl rk3506_pin_ctrl = {
494 .pin_banks = rk3506_pin_banks,
495 .nr_banks = ARRAY_SIZE(rk3506_pin_banks),
496 .nr_pins = 160,
497 .iomux_recalced = rk3506_mux_recalced_data,
498 .niomux_recalced = ARRAY_SIZE(rk3506_mux_recalced_data),
499 .set_mux = rk3506_set_mux,
500 .set_pull = rk3506_set_pull,
501 .set_drive = rk3506_set_drive,
502 .set_schmitt = rk3506_set_schmitt,
503 };
504
505 static const struct udevice_id rk3506_pinctrl_ids[] = {
506 {
507 .compatible = "rockchip,rk3506-pinctrl",
508 .data = (ulong)&rk3506_pin_ctrl
509 },
510 { }
511 };
512
513 U_BOOT_DRIVER(pinctrl_rk3506) = {
514 .name = "rockchip_rk3506_pinctrl",
515 .id = UCLASS_PINCTRL,
516 .of_match = rk3506_pinctrl_ids,
517 .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
518 .ops = &rockchip_pinctrl_ops,
519 #if !CONFIG_IS_ENABLED(OF_PLATDATA)
520 .bind = dm_scan_fdt_dev,
521 #endif
522 .probe = rockchip_pinctrl_probe,
523 };
524