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