blob: f9ac6347eaf15fbf839d9940794a14f43bd5c08c [file] [log] [blame]
David Wufd2fdf72019-12-03 19:26:50 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
4 */
5
6#include <common.h>
7#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -06008#include <log.h>
David Wufd2fdf72019-12-03 19:26:50 +08009#include <dm/pinctrl.h>
10#include <regmap.h>
11#include <syscon.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060012#include <linux/bitops.h>
David Wufd2fdf72019-12-03 19:26:50 +080013
14#include "pinctrl-rockchip.h"
15
16static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = {
17 {
18 .num = 1,
19 .pin = 14,
20 .reg = 0x28,
21 .bit = 12,
22 .mask = 0xf
23 }, {
24 .num = 1,
25 .pin = 15,
26 .reg = 0x2c,
27 .bit = 0,
28 .mask = 0x3
29 }, {
30 .num = 1,
31 .pin = 18,
32 .reg = 0x30,
33 .bit = 4,
34 .mask = 0xf
35 }, {
36 .num = 1,
37 .pin = 19,
38 .reg = 0x30,
39 .bit = 8,
40 .mask = 0xf
41 }, {
42 .num = 1,
43 .pin = 20,
44 .reg = 0x30,
45 .bit = 12,
46 .mask = 0xf
47 }, {
48 .num = 1,
49 .pin = 21,
50 .reg = 0x34,
51 .bit = 0,
52 .mask = 0xf
53 }, {
54 .num = 1,
55 .pin = 22,
56 .reg = 0x34,
57 .bit = 4,
58 .mask = 0xf
59 }, {
60 .num = 1,
61 .pin = 23,
62 .reg = 0x34,
63 .bit = 8,
64 .mask = 0xf
65 }, {
66 .num = 3,
67 .pin = 12,
68 .reg = 0x68,
69 .bit = 8,
70 .mask = 0xf
71 }, {
72 .num = 3,
73 .pin = 13,
74 .reg = 0x68,
75 .bit = 12,
76 .mask = 0xf
77 }, {
78 .num = 2,
79 .pin = 2,
80 .reg = 0x608,
81 .bit = 0,
82 .mask = 0x7
83 }, {
84 .num = 2,
85 .pin = 3,
86 .reg = 0x608,
87 .bit = 4,
88 .mask = 0x7
89 }, {
90 .num = 2,
91 .pin = 16,
92 .reg = 0x610,
93 .bit = 8,
94 .mask = 0x7
95 }, {
96 .num = 3,
97 .pin = 10,
98 .reg = 0x610,
99 .bit = 0,
100 .mask = 0x7
101 }, {
102 .num = 3,
103 .pin = 11,
104 .reg = 0x610,
105 .bit = 4,
106 .mask = 0x7
107 },
108};
109
110static struct rockchip_mux_route_data rk3308_mux_route_data[] = {
111 {
112 /* rtc_clk */
113 .bank_num = 0,
114 .pin = 19,
115 .func = 1,
116 .route_offset = 0x314,
117 .route_val = BIT(16 + 0) | BIT(0),
118 }, {
119 /* uart2_rxm0 */
120 .bank_num = 1,
121 .pin = 22,
122 .func = 2,
123 .route_offset = 0x314,
124 .route_val = BIT(16 + 2) | BIT(16 + 3),
125 }, {
126 /* uart2_rxm1 */
127 .bank_num = 4,
128 .pin = 26,
129 .func = 2,
130 .route_offset = 0x314,
131 .route_val = BIT(16 + 2) | BIT(16 + 3) | BIT(2),
132 }, {
133 /* i2c3_sdam0 */
134 .bank_num = 0,
135 .pin = 15,
136 .func = 2,
137 .route_offset = 0x608,
138 .route_val = BIT(16 + 8) | BIT(16 + 9),
139 }, {
140 /* i2c3_sdam1 */
141 .bank_num = 3,
142 .pin = 12,
143 .func = 2,
144 .route_offset = 0x608,
145 .route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(8),
146 }, {
147 /* i2c3_sdam2 */
148 .bank_num = 2,
149 .pin = 0,
150 .func = 3,
151 .route_offset = 0x608,
152 .route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(9),
153 }, {
154 /* i2s-8ch-1-sclktxm0 */
155 .bank_num = 1,
156 .pin = 3,
157 .func = 2,
158 .route_offset = 0x308,
159 .route_val = BIT(16 + 3),
160 }, {
161 /* i2s-8ch-1-sclkrxm0 */
162 .bank_num = 1,
163 .pin = 4,
164 .func = 2,
165 .route_offset = 0x308,
166 .route_val = BIT(16 + 3),
167 }, {
168 /* i2s-8ch-1-sclktxm1 */
169 .bank_num = 1,
170 .pin = 13,
171 .func = 2,
172 .route_offset = 0x308,
173 .route_val = BIT(16 + 3) | BIT(3),
174 }, {
175 /* i2s-8ch-1-sclkrxm1 */
176 .bank_num = 1,
177 .pin = 14,
178 .func = 2,
179 .route_offset = 0x308,
180 .route_val = BIT(16 + 3) | BIT(3),
181 }, {
182 /* pdm-clkm0 */
183 .bank_num = 1,
184 .pin = 4,
185 .func = 3,
186 .route_offset = 0x308,
187 .route_val = BIT(16 + 12) | BIT(16 + 13),
188 }, {
189 /* pdm-clkm1 */
190 .bank_num = 1,
191 .pin = 14,
192 .func = 4,
193 .route_offset = 0x308,
194 .route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(12),
195 }, {
196 /* pdm-clkm2 */
197 .bank_num = 2,
198 .pin = 6,
199 .func = 2,
200 .route_offset = 0x308,
201 .route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(13),
202 }, {
203 /* pdm-clkm-m2 */
204 .bank_num = 2,
205 .pin = 4,
206 .func = 3,
207 .route_offset = 0x600,
208 .route_val = BIT(16 + 2) | BIT(2),
209 }, {
210 /* spi1_miso */
211 .bank_num = 3,
212 .pin = 10,
213 .func = 3,
214 .route_offset = 0x314,
215 .route_val = BIT(16 + 9),
216 }, {
217 /* spi1_miso_m1 */
218 .bank_num = 2,
219 .pin = 4,
220 .func = 2,
221 .route_offset = 0x314,
222 .route_val = BIT(16 + 9) | BIT(9),
223 }, {
224 /* mac_rxd0_m0 */
225 .bank_num = 1,
226 .pin = 20,
227 .func = 3,
228 .route_offset = 0x314,
229 .route_val = BIT(16 + 14),
230 }, {
231 /* mac_rxd0_m1 */
232 .bank_num = 4,
233 .pin = 2,
234 .func = 2,
235 .route_offset = 0x314,
236 .route_val = BIT(16 + 14) | BIT(14),
237 }, {
238 /* uart3_rx */
239 .bank_num = 3,
240 .pin = 12,
241 .func = 4,
242 .route_offset = 0x314,
243 .route_val = BIT(16 + 15),
244 }, {
245 /* uart3_rx_m1 */
246 .bank_num = 0,
247 .pin = 17,
248 .func = 3,
249 .route_offset = 0x314,
250 .route_val = BIT(16 + 15) | BIT(15),
251 },
252};
253
254static int rk3308_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
255{
256 struct rockchip_pinctrl_priv *priv = bank->priv;
257 int iomux_num = (pin / 8);
258 struct regmap *regmap;
259 int reg, ret, mask, mux_type;
260 u8 bit;
Jagan Teki9e0e6812022-12-14 23:20:56 +0530261 u32 data;
David Wufd2fdf72019-12-03 19:26:50 +0800262
263 regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
264 ? priv->regmap_pmu : priv->regmap_base;
265
266 /* get basic quadrupel of mux registers and the correct reg inside */
267 mux_type = bank->iomux[iomux_num].type;
268 reg = bank->iomux[iomux_num].offset;
269 reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
270
271 if (bank->recalced_mask & BIT(pin))
272 rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
273
David Wufd2fdf72019-12-03 19:26:50 +0800274 data = (mask << (bit + 16));
275 data |= (mux & mask) << bit;
276 ret = regmap_write(regmap, reg, data);
277
278 return ret;
279}
280
281#define RK3308_PULL_OFFSET 0xa0
282
283static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
284 int pin_num, struct regmap **regmap,
285 int *reg, u8 *bit)
286{
287 struct rockchip_pinctrl_priv *priv = bank->priv;
288
289 *regmap = priv->regmap_base;
290 *reg = RK3308_PULL_OFFSET;
291 *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE;
292 *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4);
293
294 *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG);
295 *bit *= ROCKCHIP_PULL_BITS_PER_PIN;
296}
297
298static int rk3308_set_pull(struct rockchip_pin_bank *bank,
299 int pin_num, int pull)
300{
301 struct regmap *regmap;
302 int reg, ret;
303 u8 bit, type;
304 u32 data;
305
306 if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
307 return -ENOTSUPP;
308
309 rk3308_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
310 type = bank->pull_type[pin_num / 8];
311 ret = rockchip_translate_pull_value(type, pull);
312 if (ret < 0) {
313 debug("unsupported pull setting %d\n", pull);
314 return ret;
315 }
316
317 /* enable the write to the equivalent lower bits */
318 data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
319 data |= (ret << bit);
320
321 ret = regmap_write(regmap, reg, data);
322
323 return ret;
324}
325
326#define RK3308_DRV_GRF_OFFSET 0x100
327
328static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
329 int pin_num, struct regmap **regmap,
330 int *reg, u8 *bit)
331{
332 struct rockchip_pinctrl_priv *priv = bank->priv;
333
334 *regmap = priv->regmap_base;
335 *reg = RK3308_DRV_GRF_OFFSET;
336 *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE;
337 *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4);
338
339 *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG);
340 *bit *= ROCKCHIP_DRV_BITS_PER_PIN;
341}
342
343static int rk3308_set_drive(struct rockchip_pin_bank *bank,
344 int pin_num, int strength)
345{
346 struct regmap *regmap;
347 int reg, ret;
348 u32 data;
349 u8 bit;
350 int type = bank->drv[pin_num / 8].drv_type;
351
352 rk3308_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
353 ret = rockchip_translate_drive_value(type, strength);
354 if (ret < 0) {
355 debug("unsupported driver strength %d\n", strength);
356 return ret;
357 }
358
359 /* enable the write to the equivalent lower bits */
360 data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
361 data |= (ret << bit);
362 ret = regmap_write(regmap, reg, data);
363 return ret;
364}
365
366#define RK3308_SCHMITT_PINS_PER_REG 8
367#define RK3308_SCHMITT_BANK_STRIDE 16
368#define RK3308_SCHMITT_GRF_OFFSET 0x1a0
369
370static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
371 int pin_num,
372 struct regmap **regmap,
373 int *reg, u8 *bit)
374{
375 struct rockchip_pinctrl_priv *priv = bank->priv;
376
377 *regmap = priv->regmap_base;
378 *reg = RK3308_SCHMITT_GRF_OFFSET;
379
380 *reg += bank->bank_num * RK3308_SCHMITT_BANK_STRIDE;
381 *reg += ((pin_num / RK3308_SCHMITT_PINS_PER_REG) * 4);
382 *bit = pin_num % RK3308_SCHMITT_PINS_PER_REG;
383
384 return 0;
385}
386
387static int rk3308_set_schmitt(struct rockchip_pin_bank *bank,
388 int pin_num, int enable)
389{
390 struct regmap *regmap;
391 int reg;
392 u8 bit;
393 u32 data;
394
395 rk3308_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
396 /* enable the write to the equivalent lower bits */
397 data = BIT(bit + 16) | (enable << bit);
398
399 return regmap_write(regmap, reg, data);
400}
401
402static struct rockchip_pin_bank rk3308_pin_banks[] = {
403 PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_8WIDTH_2BIT,
404 IOMUX_8WIDTH_2BIT,
405 IOMUX_8WIDTH_2BIT,
406 IOMUX_8WIDTH_2BIT),
407 PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_8WIDTH_2BIT,
408 IOMUX_8WIDTH_2BIT,
409 IOMUX_8WIDTH_2BIT,
410 IOMUX_8WIDTH_2BIT),
411 PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_8WIDTH_2BIT,
412 IOMUX_8WIDTH_2BIT,
413 IOMUX_8WIDTH_2BIT,
414 IOMUX_8WIDTH_2BIT),
415 PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_8WIDTH_2BIT,
416 IOMUX_8WIDTH_2BIT,
417 IOMUX_8WIDTH_2BIT,
418 IOMUX_8WIDTH_2BIT),
419 PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_8WIDTH_2BIT,
420 IOMUX_8WIDTH_2BIT,
421 IOMUX_8WIDTH_2BIT,
422 IOMUX_8WIDTH_2BIT),
423};
424
425static struct rockchip_pin_ctrl rk3308_pin_ctrl = {
426 .pin_banks = rk3308_pin_banks,
427 .nr_banks = ARRAY_SIZE(rk3308_pin_banks),
428 .grf_mux_offset = 0x0,
429 .iomux_recalced = rk3308_mux_recalced_data,
430 .niomux_recalced = ARRAY_SIZE(rk3308_mux_recalced_data),
431 .iomux_routes = rk3308_mux_route_data,
432 .niomux_routes = ARRAY_SIZE(rk3308_mux_route_data),
433 .set_mux = rk3308_set_mux,
434 .set_drive = rk3308_set_drive,
435 .set_pull = rk3308_set_pull,
436 .set_schmitt = rk3308_set_schmitt,
437};
438
439static const struct udevice_id rk3308_pinctrl_ids[] = {
440 {
441 .compatible = "rockchip,rk3308-pinctrl",
442 .data = (ulong)&rk3308_pin_ctrl
443 },
444 { }
445};
446
447U_BOOT_DRIVER(pinctrl_rk3308) = {
448 .name = "rockchip_rk3308_pinctrl",
449 .id = UCLASS_PINCTRL,
450 .of_match = rk3308_pinctrl_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700451 .priv_auto = sizeof(struct rockchip_pinctrl_priv),
David Wufd2fdf72019-12-03 19:26:50 +0800452 .ops = &rockchip_pinctrl_ops,
Simon Glass92882652021-08-07 07:24:04 -0600453#if CONFIG_IS_ENABLED(OF_REAL)
David Wufd2fdf72019-12-03 19:26:50 +0800454 .bind = dm_scan_fdt_dev,
455#endif
456 .probe = rockchip_pinctrl_probe,
457};