blob: dad036610c9e489eba6d49975f34fbb45f1bc9ec [file] [log] [blame]
Sean Anderson087dfce2020-09-14 11:01:58 -04001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
4 */
5
Sean Anderson087dfce2020-09-14 11:01:58 -04006#include <clk.h>
7#include <dm.h>
8#include <dm/pinctrl.h>
9#include <dt-bindings/pinctrl/k210-pinctrl.h>
10#include <mapmem.h>
11#include <regmap.h>
12#include <syscon.h>
13#include <asm/io.h>
14#include <linux/err.h>
15#include <linux/bitfield.h>
16#include <linux/bitops.h>
17
18/*
19 * The K210 only implements 8 drive levels, even though there is register space
20 * for 16
21 */
22#define K210_PC_DRIVE_MASK GENMASK(11, 8)
23#define K210_PC_DRIVE_SHIFT 8
24#define K210_PC_DRIVE_0 (0 << K210_PC_DRIVE_SHIFT)
25#define K210_PC_DRIVE_1 (1 << K210_PC_DRIVE_SHIFT)
26#define K210_PC_DRIVE_2 (2 << K210_PC_DRIVE_SHIFT)
27#define K210_PC_DRIVE_3 (3 << K210_PC_DRIVE_SHIFT)
28#define K210_PC_DRIVE_4 (4 << K210_PC_DRIVE_SHIFT)
29#define K210_PC_DRIVE_5 (5 << K210_PC_DRIVE_SHIFT)
30#define K210_PC_DRIVE_6 (6 << K210_PC_DRIVE_SHIFT)
31#define K210_PC_DRIVE_7 (7 << K210_PC_DRIVE_SHIFT)
32#define K210_PC_DRIVE_MAX 7
33
34#define K210_PC_MODE_MASK GENMASK(23, 12)
35/*
36 * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE) where FUNCTION_OE is a
37 * physical signal from the function
38 */
39#define K210_PC_OE BIT(12) /* Output Enable */
40#define K210_PC_OE_INV BIT(13) /* INVert function-controlled Output Enable */
41#define K210_PC_DO_OE BIT(14) /* set Data Out to the Output Enable signal */
42#define K210_PC_DO_INV BIT(15) /* INVert final Data Output */
43#define K210_PC_PU BIT(16) /* Pull Up */
44#define K210_PC_PD BIT(17) /* Pull Down */
45/* Strong pull up not implemented on K210 */
46#define K210_PC_SL BIT(19) /* reduce SLew rate to prevent overshoot */
47/* Same semantics as OE above */
48#define K210_PC_IE BIT(20) /* Input Enable */
49#define K210_PC_IE_INV BIT(21) /* INVert function-controlled Input Enable */
50#define K210_PC_DI_INV BIT(22) /* INVert Data Input */
51#define K210_PC_ST BIT(23) /* Schmitt Trigger */
52#define K210_PC_DI BIT(31) /* raw Data Input */
53#define K210_PC_BIAS_MASK (K210_PC_PU & K210_PC_PD)
54
55#define K210_PC_MODE_IN (K210_PC_IE | K210_PC_ST)
56#define K210_PC_MODE_OUT (K210_PC_DRIVE_7 | K210_PC_OE)
Sean Anderson57888ac2020-11-13 08:43:39 -050057#define K210_PC_MODE_I2C (K210_PC_MODE_IN | K210_PC_SL | K210_PC_OE | \
58 K210_PC_PU)
59#define K210_PC_MODE_SCCB (K210_PC_MODE_I2C | K210_PC_OE_INV | K210_PC_IE_INV)
Sean Anderson087dfce2020-09-14 11:01:58 -040060#define K210_PC_MODE_SPI (K210_PC_MODE_IN | K210_PC_IE_INV | \
61 K210_PC_MODE_OUT | K210_PC_OE_INV)
62#define K210_PC_MODE_GPIO (K210_PC_MODE_IN | K210_PC_MODE_OUT)
63
64#define K210_PG_FUNC GENMASK(7, 0)
65#define K210_PG_DO BIT(8)
66#define K210_PG_PIN GENMASK(22, 16)
67
68#define PIN_CONFIG_OUTPUT_INVERT (PIN_CONFIG_END + 1)
69#define PIN_CONFIG_INPUT_INVERT (PIN_CONFIG_END + 2)
70
71struct k210_fpioa {
72 u32 pins[48];
73 u32 tie_en[8];
74 u32 tie_val[8];
75};
76
77struct k210_pc_priv {
78 struct clk clk;
79 struct k210_fpioa __iomem *fpioa; /* FPIOA register */
80 struct regmap *sysctl; /* Sysctl regmap */
81 u32 power_offset; /* Power bank register offset */
82};
83
84#ifdef CONFIG_CMD_PINMUX
85static const char k210_pc_pin_names[][6] = {
86#define PIN(i) \
87 [i] = "IO_" #i
88 PIN(0),
89 PIN(1),
90 PIN(2),
91 PIN(3),
92 PIN(4),
93 PIN(5),
94 PIN(6),
95 PIN(7),
96 PIN(8),
97 PIN(9),
98 PIN(10),
99 PIN(11),
100 PIN(12),
101 PIN(13),
102 PIN(14),
103 PIN(15),
104 PIN(16),
105 PIN(17),
106 PIN(18),
107 PIN(19),
108 PIN(20),
109 PIN(21),
110 PIN(22),
111 PIN(23),
112 PIN(24),
113 PIN(25),
114 PIN(26),
115 PIN(27),
116 PIN(28),
117 PIN(29),
118 PIN(30),
119 PIN(31),
120 PIN(32),
121 PIN(33),
122 PIN(34),
123 PIN(35),
124 PIN(36),
125 PIN(37),
126 PIN(38),
127 PIN(39),
128 PIN(40),
129 PIN(41),
130 PIN(42),
131 PIN(43),
132 PIN(44),
133 PIN(45),
134 PIN(46),
135 PIN(47),
136#undef PIN
137};
138
139static int k210_pc_get_pins_count(struct udevice *dev)
140{
141 return ARRAY_SIZE(k210_pc_pin_names);
142};
143
144static const char *k210_pc_get_pin_name(struct udevice *dev, unsigned selector)
145{
146 return k210_pc_pin_names[selector];
147}
148#endif /* CONFIG_CMD_PINMUX */
149
150/* These are just power domains */
151static const char k210_pc_group_names[][3] = {
152 [0] = "A0",
153 [1] = "A1",
154 [2] = "A2",
Sean Anderson8656f582020-11-13 08:43:40 -0500155 [3] = "B3",
156 [4] = "B4",
157 [5] = "B5",
158 [6] = "C6",
159 [7] = "C7",
Sean Anderson087dfce2020-09-14 11:01:58 -0400160};
161
162static int k210_pc_get_groups_count(struct udevice *dev)
163{
164 return ARRAY_SIZE(k210_pc_group_names);
165}
166
167static const char *k210_pc_get_group_name(struct udevice *dev,
168 unsigned selector)
169{
170 return k210_pc_group_names[selector];
171}
172
173enum k210_pc_mode_id {
174 K210_PC_DEFAULT_DISABLED,
175 K210_PC_DEFAULT_IN,
176 K210_PC_DEFAULT_IN_TIE,
177 K210_PC_DEFAULT_OUT,
178 K210_PC_DEFAULT_I2C,
Sean Anderson57888ac2020-11-13 08:43:39 -0500179 K210_PC_DEFAULT_SCCB,
Sean Anderson087dfce2020-09-14 11:01:58 -0400180 K210_PC_DEFAULT_SPI,
181 K210_PC_DEFAULT_GPIO,
182 K210_PC_DEFAULT_INT13,
183};
184
185static const u32 k210_pc_mode_id_to_mode[] = {
186#define DEFAULT(mode) \
187 [K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
188 [K210_PC_DEFAULT_DISABLED] = 0,
189 DEFAULT(IN),
190 [K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
191 DEFAULT(OUT),
192 DEFAULT(I2C),
Sean Anderson57888ac2020-11-13 08:43:39 -0500193 DEFAULT(SCCB),
Sean Anderson087dfce2020-09-14 11:01:58 -0400194 DEFAULT(SPI),
195 DEFAULT(GPIO),
196 [K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
197#undef DEFAULT
198};
199
200/* This saves around 2K vs having a pointer+mode */
201struct k210_pcf_info {
202#ifdef CONFIG_CMD_PINMUX
203 char name[15];
204#endif
205 u8 mode_id;
206};
207
208static const struct k210_pcf_info k210_pcf_infos[] = {
209#ifdef CONFIG_CMD_PINMUX
210#define FUNC(id, mode) \
211 [K210_PCF_##id] = { \
212 .name = #id, \
213 .mode_id = K210_PC_DEFAULT_##mode \
214 }
215#else
216#define FUNC(id, mode) \
217 [K210_PCF_##id] = { \
218 .mode_id = K210_PC_DEFAULT_##mode \
219 }
220#endif
221 FUNC(JTAG_TCLK, IN),
222 FUNC(JTAG_TDI, IN),
223 FUNC(JTAG_TMS, IN),
224 FUNC(JTAG_TDO, OUT),
225 FUNC(SPI0_D0, SPI),
226 FUNC(SPI0_D1, SPI),
227 FUNC(SPI0_D2, SPI),
228 FUNC(SPI0_D3, SPI),
229 FUNC(SPI0_D4, SPI),
230 FUNC(SPI0_D5, SPI),
231 FUNC(SPI0_D6, SPI),
232 FUNC(SPI0_D7, SPI),
233 FUNC(SPI0_SS0, OUT),
234 FUNC(SPI0_SS1, OUT),
235 FUNC(SPI0_SS2, OUT),
236 FUNC(SPI0_SS3, OUT),
237 FUNC(SPI0_ARB, IN_TIE),
238 FUNC(SPI0_SCLK, OUT),
239 FUNC(UARTHS_RX, IN),
240 FUNC(UARTHS_TX, OUT),
241 FUNC(RESV6, IN),
242 FUNC(RESV7, IN),
243 FUNC(CLK_SPI1, OUT),
244 FUNC(CLK_I2C1, OUT),
245 FUNC(GPIOHS0, GPIO),
246 FUNC(GPIOHS1, GPIO),
247 FUNC(GPIOHS2, GPIO),
248 FUNC(GPIOHS3, GPIO),
249 FUNC(GPIOHS4, GPIO),
250 FUNC(GPIOHS5, GPIO),
251 FUNC(GPIOHS6, GPIO),
252 FUNC(GPIOHS7, GPIO),
253 FUNC(GPIOHS8, GPIO),
254 FUNC(GPIOHS9, GPIO),
255 FUNC(GPIOHS10, GPIO),
256 FUNC(GPIOHS11, GPIO),
257 FUNC(GPIOHS12, GPIO),
258 FUNC(GPIOHS13, GPIO),
259 FUNC(GPIOHS14, GPIO),
260 FUNC(GPIOHS15, GPIO),
261 FUNC(GPIOHS16, GPIO),
262 FUNC(GPIOHS17, GPIO),
263 FUNC(GPIOHS18, GPIO),
264 FUNC(GPIOHS19, GPIO),
265 FUNC(GPIOHS20, GPIO),
266 FUNC(GPIOHS21, GPIO),
267 FUNC(GPIOHS22, GPIO),
268 FUNC(GPIOHS23, GPIO),
269 FUNC(GPIOHS24, GPIO),
270 FUNC(GPIOHS25, GPIO),
271 FUNC(GPIOHS26, GPIO),
272 FUNC(GPIOHS27, GPIO),
273 FUNC(GPIOHS28, GPIO),
274 FUNC(GPIOHS29, GPIO),
275 FUNC(GPIOHS30, GPIO),
276 FUNC(GPIOHS31, GPIO),
277 FUNC(GPIO0, GPIO),
278 FUNC(GPIO1, GPIO),
279 FUNC(GPIO2, GPIO),
280 FUNC(GPIO3, GPIO),
281 FUNC(GPIO4, GPIO),
282 FUNC(GPIO5, GPIO),
283 FUNC(GPIO6, GPIO),
284 FUNC(GPIO7, GPIO),
285 FUNC(UART1_RX, IN),
286 FUNC(UART1_TX, OUT),
287 FUNC(UART2_RX, IN),
288 FUNC(UART2_TX, OUT),
289 FUNC(UART3_RX, IN),
290 FUNC(UART3_TX, OUT),
291 FUNC(SPI1_D0, SPI),
292 FUNC(SPI1_D1, SPI),
293 FUNC(SPI1_D2, SPI),
294 FUNC(SPI1_D3, SPI),
295 FUNC(SPI1_D4, SPI),
296 FUNC(SPI1_D5, SPI),
297 FUNC(SPI1_D6, SPI),
298 FUNC(SPI1_D7, SPI),
299 FUNC(SPI1_SS0, OUT),
300 FUNC(SPI1_SS1, OUT),
301 FUNC(SPI1_SS2, OUT),
302 FUNC(SPI1_SS3, OUT),
303 FUNC(SPI1_ARB, IN_TIE),
304 FUNC(SPI1_SCLK, OUT),
305 FUNC(SPI2_D0, SPI),
306 FUNC(SPI2_SS, IN),
307 FUNC(SPI2_SCLK, IN),
308 FUNC(I2S0_MCLK, OUT),
309 FUNC(I2S0_SCLK, OUT),
310 FUNC(I2S0_WS, OUT),
311 FUNC(I2S0_IN_D0, IN),
312 FUNC(I2S0_IN_D1, IN),
313 FUNC(I2S0_IN_D2, IN),
314 FUNC(I2S0_IN_D3, IN),
315 FUNC(I2S0_OUT_D0, OUT),
316 FUNC(I2S0_OUT_D1, OUT),
317 FUNC(I2S0_OUT_D2, OUT),
318 FUNC(I2S0_OUT_D3, OUT),
319 FUNC(I2S1_MCLK, OUT),
320 FUNC(I2S1_SCLK, OUT),
321 FUNC(I2S1_WS, OUT),
322 FUNC(I2S1_IN_D0, IN),
323 FUNC(I2S1_IN_D1, IN),
324 FUNC(I2S1_IN_D2, IN),
325 FUNC(I2S1_IN_D3, IN),
326 FUNC(I2S1_OUT_D0, OUT),
327 FUNC(I2S1_OUT_D1, OUT),
328 FUNC(I2S1_OUT_D2, OUT),
329 FUNC(I2S1_OUT_D3, OUT),
330 FUNC(I2S2_MCLK, OUT),
331 FUNC(I2S2_SCLK, OUT),
332 FUNC(I2S2_WS, OUT),
333 FUNC(I2S2_IN_D0, IN),
334 FUNC(I2S2_IN_D1, IN),
335 FUNC(I2S2_IN_D2, IN),
336 FUNC(I2S2_IN_D3, IN),
337 FUNC(I2S2_OUT_D0, OUT),
338 FUNC(I2S2_OUT_D1, OUT),
339 FUNC(I2S2_OUT_D2, OUT),
340 FUNC(I2S2_OUT_D3, OUT),
341 FUNC(RESV0, DISABLED),
342 FUNC(RESV1, DISABLED),
343 FUNC(RESV2, DISABLED),
344 FUNC(RESV3, DISABLED),
345 FUNC(RESV4, DISABLED),
346 FUNC(RESV5, DISABLED),
347 FUNC(I2C0_SCLK, I2C),
348 FUNC(I2C0_SDA, I2C),
349 FUNC(I2C1_SCLK, I2C),
350 FUNC(I2C1_SDA, I2C),
351 FUNC(I2C2_SCLK, I2C),
352 FUNC(I2C2_SDA, I2C),
353 FUNC(DVP_XCLK, OUT),
354 FUNC(DVP_RST, OUT),
355 FUNC(DVP_PWDN, OUT),
356 FUNC(DVP_VSYNC, IN),
357 FUNC(DVP_HSYNC, IN),
358 FUNC(DVP_PCLK, IN),
359 FUNC(DVP_D0, IN),
360 FUNC(DVP_D1, IN),
361 FUNC(DVP_D2, IN),
362 FUNC(DVP_D3, IN),
363 FUNC(DVP_D4, IN),
364 FUNC(DVP_D5, IN),
365 FUNC(DVP_D6, IN),
366 FUNC(DVP_D7, IN),
Sean Anderson57888ac2020-11-13 08:43:39 -0500367 FUNC(SCCB_SCLK, SCCB),
368 FUNC(SCCB_SDA, SCCB),
Sean Anderson087dfce2020-09-14 11:01:58 -0400369 FUNC(UART1_CTS, IN),
370 FUNC(UART1_DSR, IN),
371 FUNC(UART1_DCD, IN),
372 FUNC(UART1_RI, IN),
373 FUNC(UART1_SIR_IN, IN),
374 FUNC(UART1_DTR, OUT),
375 FUNC(UART1_RTS, OUT),
376 FUNC(UART1_OUT2, OUT),
377 FUNC(UART1_OUT1, OUT),
378 FUNC(UART1_SIR_OUT, OUT),
379 FUNC(UART1_BAUD, OUT),
380 FUNC(UART1_RE, OUT),
381 FUNC(UART1_DE, OUT),
382 FUNC(UART1_RS485_EN, OUT),
383 FUNC(UART2_CTS, IN),
384 FUNC(UART2_DSR, IN),
385 FUNC(UART2_DCD, IN),
386 FUNC(UART2_RI, IN),
387 FUNC(UART2_SIR_IN, IN),
388 FUNC(UART2_DTR, OUT),
389 FUNC(UART2_RTS, OUT),
390 FUNC(UART2_OUT2, OUT),
391 FUNC(UART2_OUT1, OUT),
392 FUNC(UART2_SIR_OUT, OUT),
393 FUNC(UART2_BAUD, OUT),
394 FUNC(UART2_RE, OUT),
395 FUNC(UART2_DE, OUT),
396 FUNC(UART2_RS485_EN, OUT),
397 FUNC(UART3_CTS, IN),
398 FUNC(UART3_DSR, IN),
399 FUNC(UART3_DCD, IN),
400 FUNC(UART3_RI, IN),
401 FUNC(UART3_SIR_IN, IN),
402 FUNC(UART3_DTR, OUT),
403 FUNC(UART3_RTS, OUT),
404 FUNC(UART3_OUT2, OUT),
405 FUNC(UART3_OUT1, OUT),
406 FUNC(UART3_SIR_OUT, OUT),
407 FUNC(UART3_BAUD, OUT),
408 FUNC(UART3_RE, OUT),
409 FUNC(UART3_DE, OUT),
410 FUNC(UART3_RS485_EN, OUT),
411 FUNC(TIMER0_TOGGLE1, OUT),
412 FUNC(TIMER0_TOGGLE2, OUT),
413 FUNC(TIMER0_TOGGLE3, OUT),
414 FUNC(TIMER0_TOGGLE4, OUT),
415 FUNC(TIMER1_TOGGLE1, OUT),
416 FUNC(TIMER1_TOGGLE2, OUT),
417 FUNC(TIMER1_TOGGLE3, OUT),
418 FUNC(TIMER1_TOGGLE4, OUT),
419 FUNC(TIMER2_TOGGLE1, OUT),
420 FUNC(TIMER2_TOGGLE2, OUT),
421 FUNC(TIMER2_TOGGLE3, OUT),
422 FUNC(TIMER2_TOGGLE4, OUT),
423 FUNC(CLK_SPI2, OUT),
424 FUNC(CLK_I2C2, OUT),
425 FUNC(INTERNAL0, OUT),
426 FUNC(INTERNAL1, OUT),
427 FUNC(INTERNAL2, OUT),
428 FUNC(INTERNAL3, OUT),
429 FUNC(INTERNAL4, OUT),
430 FUNC(INTERNAL5, OUT),
431 FUNC(INTERNAL6, OUT),
432 FUNC(INTERNAL7, OUT),
433 FUNC(INTERNAL8, OUT),
434 FUNC(INTERNAL9, IN),
435 FUNC(INTERNAL10, IN),
436 FUNC(INTERNAL11, IN),
437 FUNC(INTERNAL12, IN),
438 FUNC(INTERNAL13, INT13),
439 FUNC(INTERNAL14, I2C),
440 FUNC(INTERNAL15, IN),
441 FUNC(INTERNAL16, IN),
442 FUNC(INTERNAL17, IN),
443 FUNC(CONSTANT, DISABLED),
444 FUNC(INTERNAL18, IN),
445 FUNC(DEBUG0, OUT),
446 FUNC(DEBUG1, OUT),
447 FUNC(DEBUG2, OUT),
448 FUNC(DEBUG3, OUT),
449 FUNC(DEBUG4, OUT),
450 FUNC(DEBUG5, OUT),
451 FUNC(DEBUG6, OUT),
452 FUNC(DEBUG7, OUT),
453 FUNC(DEBUG8, OUT),
454 FUNC(DEBUG9, OUT),
455 FUNC(DEBUG10, OUT),
456 FUNC(DEBUG11, OUT),
457 FUNC(DEBUG12, OUT),
458 FUNC(DEBUG13, OUT),
459 FUNC(DEBUG14, OUT),
460 FUNC(DEBUG15, OUT),
461 FUNC(DEBUG16, OUT),
462 FUNC(DEBUG17, OUT),
463 FUNC(DEBUG18, OUT),
464 FUNC(DEBUG19, OUT),
465 FUNC(DEBUG20, OUT),
466 FUNC(DEBUG21, OUT),
467 FUNC(DEBUG22, OUT),
468 FUNC(DEBUG23, OUT),
469 FUNC(DEBUG24, OUT),
470 FUNC(DEBUG25, OUT),
471 FUNC(DEBUG26, OUT),
472 FUNC(DEBUG27, OUT),
473 FUNC(DEBUG28, OUT),
474 FUNC(DEBUG29, OUT),
475 FUNC(DEBUG30, OUT),
476 FUNC(DEBUG31, OUT),
477#undef FUNC
478};
479
480static int k210_pc_pinmux_set(struct udevice *dev, u32 pinmux_group)
481{
482 unsigned pin = FIELD_GET(K210_PG_PIN, pinmux_group);
483 bool do_oe = FIELD_GET(K210_PG_DO, pinmux_group);
484 unsigned func = FIELD_GET(K210_PG_FUNC, pinmux_group);
485 struct k210_pc_priv *priv = dev_get_priv(dev);
486 const struct k210_pcf_info *info = &k210_pcf_infos[func];
487 u32 mode = k210_pc_mode_id_to_mode[info->mode_id];
488 u32 val = func | mode | (do_oe ? K210_PC_DO_OE : 0);
489
490 debug("%s(%.8x): IO_%.2u = %3u | %.8x\n", __func__, pinmux_group, pin,
491 func, mode);
492
493 writel(val, &priv->fpioa->pins[pin]);
494 return pin;
495}
496
497/* Max drive strength in uA */
498static const int k210_pc_drive_strength[] = {
499 [0] = 11200,
500 [1] = 16800,
501 [2] = 22300,
502 [3] = 27800,
503 [4] = 33300,
504 [5] = 38700,
505 [6] = 44100,
506 [7] = 49500,
507};
508
509static int k210_pc_get_drive(unsigned max_strength_ua)
510{
511 int i;
512
Niklas Cassel3da2cd92022-03-01 10:35:44 +0000513 for (i = K210_PC_DRIVE_MAX; i >= 0; i--)
Sean Anderson087dfce2020-09-14 11:01:58 -0400514 if (k210_pc_drive_strength[i] < max_strength_ua)
515 return i;
516
517 return -EINVAL;
518}
519
520static int k210_pc_pinconf_set(struct udevice *dev, unsigned pin_selector,
521 unsigned param, unsigned argument)
522{
523 struct k210_pc_priv *priv = dev_get_priv(dev);
524 u32 val = readl(&priv->fpioa->pins[pin_selector]);
525
526 switch (param) {
527 case PIN_CONFIG_BIAS_DISABLE:
528 val &= ~K210_PC_BIAS_MASK;
529 break;
530 case PIN_CONFIG_BIAS_PULL_DOWN:
531 if (argument)
532 val |= K210_PC_PD;
533 else
534 return -EINVAL;
535 break;
536 case PIN_CONFIG_BIAS_PULL_UP:
537 if (argument)
Niklas Cassel3566af92022-03-01 10:35:45 +0000538 val |= K210_PC_PU;
Sean Anderson087dfce2020-09-14 11:01:58 -0400539 else
540 return -EINVAL;
541 break;
542 case PIN_CONFIG_DRIVE_STRENGTH:
543 argument *= 1000;
544 case PIN_CONFIG_DRIVE_STRENGTH_UA: {
545 int drive = k210_pc_get_drive(argument);
546
547 if (IS_ERR_VALUE(drive))
548 return drive;
549 val &= ~K210_PC_DRIVE_MASK;
550 val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
551 break;
552 }
553 case PIN_CONFIG_INPUT_ENABLE:
554 if (argument)
555 val |= K210_PC_IE;
556 else
557 val &= ~K210_PC_IE;
558 break;
559 case PIN_CONFIG_INPUT_SCHMITT:
560 argument = 1;
561 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
562 if (argument)
563 val |= K210_PC_ST;
564 else
565 val &= ~K210_PC_ST;
566 break;
567 case PIN_CONFIG_OUTPUT:
568 k210_pc_pinmux_set(dev,
569 K210_FPIOA(pin_selector, K210_PCF_CONSTANT));
570 val = readl(&priv->fpioa->pins[pin_selector]);
571 val |= K210_PC_MODE_OUT;
572
573 if (!argument)
574 val |= K210_PC_DO_INV;
575 break;
576 case PIN_CONFIG_OUTPUT_ENABLE:
577 if (argument)
578 val |= K210_PC_OE;
579 else
580 val &= ~K210_PC_OE;
581 break;
582 case PIN_CONFIG_SLEW_RATE:
583 if (argument)
584 val |= K210_PC_SL;
585 else
586 val &= ~K210_PC_SL;
587 break;
588 case PIN_CONFIG_OUTPUT_INVERT:
589 if (argument)
590 val |= K210_PC_DO_INV;
591 else
592 val &= ~K210_PC_DO_INV;
593 break;
594 case PIN_CONFIG_INPUT_INVERT:
595 if (argument)
596 val |= K210_PC_DI_INV;
597 else
598 val &= ~K210_PC_DI_INV;
599 break;
600 default:
601 return -EINVAL;
602 }
603
604 writel(val, &priv->fpioa->pins[pin_selector]);
605 return 0;
606}
607
608static int k210_pc_pinconf_group_set(struct udevice *dev,
609 unsigned group_selector, unsigned param,
610 unsigned argument)
611{
612 struct k210_pc_priv *priv = dev_get_priv(dev);
613
614 if (param == PIN_CONFIG_POWER_SOURCE) {
615 u32 bit = BIT(group_selector);
616
617 regmap_update_bits(priv->sysctl, priv->power_offset, bit,
618 argument ? bit : 0);
619 } else {
620 return -EINVAL;
621 }
622
623 return 0;
624}
625
626#ifdef CONFIG_CMD_PINMUX
627static int k210_pc_get_pin_muxing(struct udevice *dev, unsigned int selector,
628 char *buf, int size)
629{
630 struct k210_pc_priv *priv = dev_get_priv(dev);
631 u32 val = readl(&priv->fpioa->pins[selector]);
632 const struct k210_pcf_info *info = &k210_pcf_infos[val & K210_PCF_MASK];
633
634 strncpy(buf, info->name, min((size_t)size, sizeof(info->name)));
635 return 0;
636}
637#endif
638
639static const struct pinconf_param k210_pc_pinconf_params[] = {
640 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
641 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
642 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
643 { "drive-strength", PIN_CONFIG_DRIVE_STRENGTH, U32_MAX },
644 { "drive-strength-ua", PIN_CONFIG_DRIVE_STRENGTH_UA, U32_MAX },
645 { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 },
646 { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
647 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
648 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
649 { "power-source", PIN_CONFIG_POWER_SOURCE, K210_PC_POWER_1V8 },
650 { "output-low", PIN_CONFIG_OUTPUT, 0 },
651 { "output-high", PIN_CONFIG_OUTPUT, 1 },
652 { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 },
653 { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 },
654 { "slew-rate", PIN_CONFIG_SLEW_RATE, 1 },
655 { "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1},
656 { "input-polarity-invert", PIN_CONFIG_INPUT_INVERT, 1},
657};
658
659static const struct pinctrl_ops k210_pc_pinctrl_ops = {
660#ifdef CONFIG_CMD_PINMUX
661 .get_pins_count = k210_pc_get_pins_count,
662 .get_pin_name = k210_pc_get_pin_name,
663#endif
664 .get_groups_count = k210_pc_get_groups_count,
665 .get_group_name = k210_pc_get_group_name,
666 .pinmux_property_set = k210_pc_pinmux_set,
667 .pinconf_num_params = ARRAY_SIZE(k210_pc_pinconf_params),
668 .pinconf_params = k210_pc_pinconf_params,
669 .pinconf_set = k210_pc_pinconf_set,
670 .pinconf_group_set = k210_pc_pinconf_group_set,
671 .set_state = pinctrl_generic_set_state,
672#ifdef CONFIG_CMD_PINMUX
673 .get_pin_muxing = k210_pc_get_pin_muxing,
674#endif
675};
676
677static int k210_pc_probe(struct udevice *dev)
678{
679 int ret, i, j;
680 struct k210_pc_priv *priv = dev_get_priv(dev);
Damien Le Moalb2c0bb42022-03-01 10:35:41 +0000681 struct ofnode_phandle_args args;
Sean Anderson087dfce2020-09-14 11:01:58 -0400682
683 priv->fpioa = dev_read_addr_ptr(dev);
684 if (!priv->fpioa)
685 return -EINVAL;
686
687 ret = clk_get_by_index(dev, 0, &priv->clk);
688 if (ret)
689 return ret;
690
691 ret = clk_enable(&priv->clk);
692 if (ret && ret != -ENOSYS && ret != -ENOTSUPP)
Sean Andersond318eb32023-12-16 14:38:42 -0500693 return ret;
Sean Anderson087dfce2020-09-14 11:01:58 -0400694
Damien Le Moalb2c0bb42022-03-01 10:35:41 +0000695 ret = dev_read_phandle_with_args(dev, "canaan,k210-sysctl-power",
696 NULL, 1, 0, &args);
697 if (ret)
Sean Andersond318eb32023-12-16 14:38:42 -0500698 return ret;
Damien Le Moalb2c0bb42022-03-01 10:35:41 +0000699
Sean Andersond318eb32023-12-16 14:38:42 -0500700 if (args.args_count != 1)
701 return -EINVAL;
Damien Le Moalb2c0bb42022-03-01 10:35:41 +0000702
703 priv->sysctl = syscon_node_to_regmap(args.node);
Sean Andersond318eb32023-12-16 14:38:42 -0500704 if (IS_ERR(priv->sysctl))
705 return PTR_ERR(priv->sysctl);
Sean Anderson087dfce2020-09-14 11:01:58 -0400706
Damien Le Moalb2c0bb42022-03-01 10:35:41 +0000707 priv->power_offset = args.args[0];
Sean Anderson087dfce2020-09-14 11:01:58 -0400708
709 debug("%s: fpioa = %p sysctl = %p power offset = %x\n", __func__,
710 priv->fpioa, (void *)priv->sysctl->ranges[0].start,
711 priv->power_offset);
712
713 /* Init input ties */
714 for (i = 0; i < ARRAY_SIZE(priv->fpioa->tie_en); i++) {
715 u32 val = 0;
716
717 for (j = 0; j < 32; j++)
718 if (k210_pcf_infos[i * 32 + j].mode_id ==
719 K210_PC_DEFAULT_IN_TIE)
720 val |= BIT(j);
721 writel(val, &priv->fpioa->tie_en[i]);
722 writel(val, &priv->fpioa->tie_val[i]);
723 }
724
725 return 0;
Sean Anderson087dfce2020-09-14 11:01:58 -0400726}
727
728static const struct udevice_id k210_pc_ids[] = {
Damien Le Moal6e5a8b72022-03-01 10:35:39 +0000729 { .compatible = "canaan,k210-fpioa" },
Sean Anderson087dfce2020-09-14 11:01:58 -0400730 { }
731};
732
733U_BOOT_DRIVER(pinctrl_k210) = {
734 .name = "pinctrl_k210",
735 .id = UCLASS_PINCTRL,
736 .of_match = k210_pc_ids,
737 .probe = k210_pc_probe,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700738 .priv_auto = sizeof(struct k210_pc_priv),
Sean Anderson087dfce2020-09-14 11:01:58 -0400739 .ops = &k210_pc_pinctrl_ops,
740};