1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Pinctrl for Cirrus Logic Madera codecs |
4 | * |
5 | * Copyright (C) 2016-2018 Cirrus Logic |
6 | */ |
7 | |
8 | #include <linux/err.h> |
9 | #include <linux/module.h> |
10 | #include <linux/platform_device.h> |
11 | #include <linux/property.h> |
12 | #include <linux/regmap.h> |
13 | #include <linux/seq_file.h> |
14 | #include <linux/slab.h> |
15 | |
16 | #include <linux/pinctrl/machine.h> |
17 | #include <linux/pinctrl/pinconf-generic.h> |
18 | #include <linux/pinctrl/pinconf.h> |
19 | #include <linux/pinctrl/pinctrl.h> |
20 | #include <linux/pinctrl/pinmux.h> |
21 | |
22 | #include <linux/mfd/madera/core.h> |
23 | #include <linux/mfd/madera/registers.h> |
24 | |
25 | #include "../pinctrl-utils.h" |
26 | |
27 | #include "pinctrl-madera.h" |
28 | |
29 | /* |
30 | * Use pin GPIO names for consistency |
31 | * NOTE: IDs are zero-indexed for coding convenience |
32 | */ |
33 | static const struct pinctrl_pin_desc madera_pins[] = { |
34 | PINCTRL_PIN(0, "gpio1" ), |
35 | PINCTRL_PIN(1, "gpio2" ), |
36 | PINCTRL_PIN(2, "gpio3" ), |
37 | PINCTRL_PIN(3, "gpio4" ), |
38 | PINCTRL_PIN(4, "gpio5" ), |
39 | PINCTRL_PIN(5, "gpio6" ), |
40 | PINCTRL_PIN(6, "gpio7" ), |
41 | PINCTRL_PIN(7, "gpio8" ), |
42 | PINCTRL_PIN(8, "gpio9" ), |
43 | PINCTRL_PIN(9, "gpio10" ), |
44 | PINCTRL_PIN(10, "gpio11" ), |
45 | PINCTRL_PIN(11, "gpio12" ), |
46 | PINCTRL_PIN(12, "gpio13" ), |
47 | PINCTRL_PIN(13, "gpio14" ), |
48 | PINCTRL_PIN(14, "gpio15" ), |
49 | PINCTRL_PIN(15, "gpio16" ), |
50 | PINCTRL_PIN(16, "gpio17" ), |
51 | PINCTRL_PIN(17, "gpio18" ), |
52 | PINCTRL_PIN(18, "gpio19" ), |
53 | PINCTRL_PIN(19, "gpio20" ), |
54 | PINCTRL_PIN(20, "gpio21" ), |
55 | PINCTRL_PIN(21, "gpio22" ), |
56 | PINCTRL_PIN(22, "gpio23" ), |
57 | PINCTRL_PIN(23, "gpio24" ), |
58 | PINCTRL_PIN(24, "gpio25" ), |
59 | PINCTRL_PIN(25, "gpio26" ), |
60 | PINCTRL_PIN(26, "gpio27" ), |
61 | PINCTRL_PIN(27, "gpio28" ), |
62 | PINCTRL_PIN(28, "gpio29" ), |
63 | PINCTRL_PIN(29, "gpio30" ), |
64 | PINCTRL_PIN(30, "gpio31" ), |
65 | PINCTRL_PIN(31, "gpio32" ), |
66 | PINCTRL_PIN(32, "gpio33" ), |
67 | PINCTRL_PIN(33, "gpio34" ), |
68 | PINCTRL_PIN(34, "gpio35" ), |
69 | PINCTRL_PIN(35, "gpio36" ), |
70 | PINCTRL_PIN(36, "gpio37" ), |
71 | PINCTRL_PIN(37, "gpio38" ), |
72 | PINCTRL_PIN(38, "gpio39" ), |
73 | PINCTRL_PIN(39, "gpio40" ), |
74 | }; |
75 | |
76 | /* |
77 | * All single-pin functions can be mapped to any GPIO, however pinmux applies |
78 | * functions to pin groups and only those groups declared as supporting that |
79 | * function. To make this work we must put each pin in its own dummy group so |
80 | * that the functions can be described as applying to all pins. |
81 | * Since these do not correspond to anything in the actual hardware - they are |
82 | * merely an adaptation to pinctrl's view of the world - we use the same name |
83 | * as the pin to avoid confusion when comparing with datasheet instructions |
84 | */ |
85 | static const char * const madera_pin_single_group_names[] = { |
86 | "gpio1" , "gpio2" , "gpio3" , "gpio4" , "gpio5" , "gpio6" , "gpio7" , |
87 | "gpio8" , "gpio9" , "gpio10" , "gpio11" , "gpio12" , "gpio13" , "gpio14" , |
88 | "gpio15" , "gpio16" , "gpio17" , "gpio18" , "gpio19" , "gpio20" , "gpio21" , |
89 | "gpio22" , "gpio23" , "gpio24" , "gpio25" , "gpio26" , "gpio27" , "gpio28" , |
90 | "gpio29" , "gpio30" , "gpio31" , "gpio32" , "gpio33" , "gpio34" , "gpio35" , |
91 | "gpio36" , "gpio37" , "gpio38" , "gpio39" , "gpio40" , |
92 | }; |
93 | |
94 | /* set of pin numbers for single-pin groups, zero-indexed */ |
95 | static const unsigned int madera_pin_single_group_pins[] = { |
96 | 0, 1, 2, 3, 4, 5, 6, |
97 | 7, 8, 9, 10, 11, 12, 13, |
98 | 14, 15, 16, 17, 18, 19, 20, |
99 | 21, 22, 23, 24, 25, 26, 27, |
100 | 28, 29, 30, 31, 32, 33, 34, |
101 | 35, 36, 37, 38, 39, |
102 | }; |
103 | |
104 | static const char * const madera_aif1_group_names[] = { "aif1" }; |
105 | static const char * const madera_aif2_group_names[] = { "aif2" }; |
106 | static const char * const madera_aif3_group_names[] = { "aif3" }; |
107 | static const char * const madera_aif4_group_names[] = { "aif4" }; |
108 | static const char * const madera_mif1_group_names[] = { "mif1" }; |
109 | static const char * const madera_mif2_group_names[] = { "mif2" }; |
110 | static const char * const madera_mif3_group_names[] = { "mif3" }; |
111 | static const char * const madera_dmic3_group_names[] = { "dmic3" }; |
112 | static const char * const madera_dmic4_group_names[] = { "dmic4" }; |
113 | static const char * const madera_dmic5_group_names[] = { "dmic5" }; |
114 | static const char * const madera_dmic6_group_names[] = { "dmic6" }; |
115 | static const char * const madera_spk1_group_names[] = { "pdmspk1" }; |
116 | static const char * const madera_spk2_group_names[] = { "pdmspk2" }; |
117 | |
118 | /* |
119 | * alt-functions always apply to a single pin group, other functions always |
120 | * apply to all pins |
121 | */ |
122 | static const struct { |
123 | const char *name; |
124 | const char * const *group_names; |
125 | u32 func; |
126 | } madera_mux_funcs[] = { |
127 | { |
128 | .name = "aif1" , |
129 | .group_names = madera_aif1_group_names, |
130 | .func = 0x000 |
131 | }, |
132 | { |
133 | .name = "aif2" , |
134 | .group_names = madera_aif2_group_names, |
135 | .func = 0x000 |
136 | }, |
137 | { |
138 | .name = "aif3" , |
139 | .group_names = madera_aif3_group_names, |
140 | .func = 0x000 |
141 | }, |
142 | { |
143 | .name = "aif4" , |
144 | .group_names = madera_aif4_group_names, |
145 | .func = 0x000 |
146 | }, |
147 | { |
148 | .name = "mif1" , |
149 | .group_names = madera_mif1_group_names, |
150 | .func = 0x000 |
151 | }, |
152 | { |
153 | .name = "mif2" , |
154 | .group_names = madera_mif2_group_names, |
155 | .func = 0x000 |
156 | }, |
157 | { |
158 | .name = "mif3" , |
159 | .group_names = madera_mif3_group_names, |
160 | .func = 0x000 |
161 | }, |
162 | { |
163 | .name = "dmic3" , |
164 | .group_names = madera_dmic3_group_names, |
165 | .func = 0x000 |
166 | }, |
167 | { |
168 | .name = "dmic4" , |
169 | .group_names = madera_dmic4_group_names, |
170 | .func = 0x000 |
171 | }, |
172 | { |
173 | .name = "dmic5" , |
174 | .group_names = madera_dmic5_group_names, |
175 | .func = 0x000 |
176 | }, |
177 | { |
178 | .name = "dmic6" , |
179 | .group_names = madera_dmic6_group_names, |
180 | .func = 0x000 |
181 | }, |
182 | { |
183 | .name = "pdmspk1" , |
184 | .group_names = madera_spk1_group_names, |
185 | .func = 0x000 |
186 | }, |
187 | { |
188 | .name = "pdmspk2" , |
189 | .group_names = madera_spk2_group_names, |
190 | .func = 0x000 |
191 | }, |
192 | { |
193 | .name = "io" , |
194 | .group_names = madera_pin_single_group_names, |
195 | .func = 0x001 |
196 | }, |
197 | { |
198 | .name = "dsp-gpio" , |
199 | .group_names = madera_pin_single_group_names, |
200 | .func = 0x002 |
201 | }, |
202 | { |
203 | .name = "irq1" , |
204 | .group_names = madera_pin_single_group_names, |
205 | .func = 0x003 |
206 | }, |
207 | { |
208 | .name = "irq2" , |
209 | .group_names = madera_pin_single_group_names, |
210 | .func = 0x004 |
211 | }, |
212 | { |
213 | .name = "fll1-clk" , |
214 | .group_names = madera_pin_single_group_names, |
215 | .func = 0x010 |
216 | }, |
217 | { |
218 | .name = "fll2-clk" , |
219 | .group_names = madera_pin_single_group_names, |
220 | .func = 0x011 |
221 | }, |
222 | { |
223 | .name = "fll3-clk" , |
224 | .group_names = madera_pin_single_group_names, |
225 | .func = 0x012 |
226 | }, |
227 | { |
228 | .name = "fllao-clk" , |
229 | .group_names = madera_pin_single_group_names, |
230 | .func = 0x013 |
231 | }, |
232 | { |
233 | .name = "fll1-lock" , |
234 | .group_names = madera_pin_single_group_names, |
235 | .func = 0x018 |
236 | }, |
237 | { |
238 | .name = "fll2-lock" , |
239 | .group_names = madera_pin_single_group_names, |
240 | .func = 0x019 |
241 | }, |
242 | { |
243 | .name = "fll3-lock" , |
244 | .group_names = madera_pin_single_group_names, |
245 | .func = 0x01a |
246 | }, |
247 | { |
248 | .name = "fllao-lock" , |
249 | .group_names = madera_pin_single_group_names, |
250 | .func = 0x01b |
251 | }, |
252 | { |
253 | .name = "opclk" , |
254 | .group_names = madera_pin_single_group_names, |
255 | .func = 0x040 |
256 | }, |
257 | { |
258 | .name = "opclk-async" , |
259 | .group_names = madera_pin_single_group_names, |
260 | .func = 0x041 |
261 | }, |
262 | { |
263 | .name = "pwm1" , |
264 | .group_names = madera_pin_single_group_names, |
265 | .func = 0x048 |
266 | }, |
267 | { |
268 | .name = "pwm2" , |
269 | .group_names = madera_pin_single_group_names, |
270 | .func = 0x049 |
271 | }, |
272 | { |
273 | .name = "spdif" , |
274 | .group_names = madera_pin_single_group_names, |
275 | .func = 0x04c |
276 | }, |
277 | { |
278 | .name = "asrc1-in1-lock" , |
279 | .group_names = madera_pin_single_group_names, |
280 | .func = 0x088 |
281 | }, |
282 | { |
283 | .name = "asrc1-in2-lock" , |
284 | .group_names = madera_pin_single_group_names, |
285 | .func = 0x089 |
286 | }, |
287 | { |
288 | .name = "asrc2-in1-lock" , |
289 | .group_names = madera_pin_single_group_names, |
290 | .func = 0x08a |
291 | }, |
292 | { |
293 | .name = "asrc2-in2-lock" , |
294 | .group_names = madera_pin_single_group_names, |
295 | .func = 0x08b |
296 | }, |
297 | { |
298 | .name = "spkl-short-circuit" , |
299 | .group_names = madera_pin_single_group_names, |
300 | .func = 0x0b6 |
301 | }, |
302 | { |
303 | .name = "spkr-short-circuit" , |
304 | .group_names = madera_pin_single_group_names, |
305 | .func = 0x0b7 |
306 | }, |
307 | { |
308 | .name = "spk-shutdown" , |
309 | .group_names = madera_pin_single_group_names, |
310 | .func = 0x0e0 |
311 | }, |
312 | { |
313 | .name = "spk-overheat-shutdown" , |
314 | .group_names = madera_pin_single_group_names, |
315 | .func = 0x0e1 |
316 | }, |
317 | { |
318 | .name = "spk-overheat-warn" , |
319 | .group_names = madera_pin_single_group_names, |
320 | .func = 0x0e2 |
321 | }, |
322 | { |
323 | .name = "timer1-sts" , |
324 | .group_names = madera_pin_single_group_names, |
325 | .func = 0x140 |
326 | }, |
327 | { |
328 | .name = "timer2-sts" , |
329 | .group_names = madera_pin_single_group_names, |
330 | .func = 0x141 |
331 | }, |
332 | { |
333 | .name = "timer3-sts" , |
334 | .group_names = madera_pin_single_group_names, |
335 | .func = 0x142 |
336 | }, |
337 | { |
338 | .name = "timer4-sts" , |
339 | .group_names = madera_pin_single_group_names, |
340 | .func = 0x143 |
341 | }, |
342 | { |
343 | .name = "timer5-sts" , |
344 | .group_names = madera_pin_single_group_names, |
345 | .func = 0x144 |
346 | }, |
347 | { |
348 | .name = "timer6-sts" , |
349 | .group_names = madera_pin_single_group_names, |
350 | .func = 0x145 |
351 | }, |
352 | { |
353 | .name = "timer7-sts" , |
354 | .group_names = madera_pin_single_group_names, |
355 | .func = 0x146 |
356 | }, |
357 | { |
358 | .name = "timer8-sts" , |
359 | .group_names = madera_pin_single_group_names, |
360 | .func = 0x147 |
361 | }, |
362 | { |
363 | .name = "log1-fifo-ne" , |
364 | .group_names = madera_pin_single_group_names, |
365 | .func = 0x150 |
366 | }, |
367 | { |
368 | .name = "log2-fifo-ne" , |
369 | .group_names = madera_pin_single_group_names, |
370 | .func = 0x151 |
371 | }, |
372 | { |
373 | .name = "log3-fifo-ne" , |
374 | .group_names = madera_pin_single_group_names, |
375 | .func = 0x152 |
376 | }, |
377 | { |
378 | .name = "log4-fifo-ne" , |
379 | .group_names = madera_pin_single_group_names, |
380 | .func = 0x153 |
381 | }, |
382 | { |
383 | .name = "log5-fifo-ne" , |
384 | .group_names = madera_pin_single_group_names, |
385 | .func = 0x154 |
386 | }, |
387 | { |
388 | .name = "log6-fifo-ne" , |
389 | .group_names = madera_pin_single_group_names, |
390 | .func = 0x155 |
391 | }, |
392 | { |
393 | .name = "log7-fifo-ne" , |
394 | .group_names = madera_pin_single_group_names, |
395 | .func = 0x156 |
396 | }, |
397 | { |
398 | .name = "log8-fifo-ne" , |
399 | .group_names = madera_pin_single_group_names, |
400 | .func = 0x157 |
401 | }, |
402 | { |
403 | .name = "aux-pdm-clk" , |
404 | .group_names = madera_pin_single_group_names, |
405 | .func = 0x280 |
406 | }, |
407 | { |
408 | .name = "aux-pdm-dat" , |
409 | .group_names = madera_pin_single_group_names, |
410 | .func = 0x281 |
411 | }, |
412 | }; |
413 | |
414 | static u16 madera_pin_make_drv_str(struct madera_pin_private *priv, |
415 | unsigned int milliamps) |
416 | { |
417 | switch (milliamps) { |
418 | case 4: |
419 | return 0; |
420 | case 8: |
421 | return 2 << MADERA_GP1_DRV_STR_SHIFT; |
422 | default: |
423 | break; |
424 | } |
425 | |
426 | dev_warn(priv->dev, "%u mA not a valid drive strength" , milliamps); |
427 | |
428 | return 0; |
429 | } |
430 | |
431 | static unsigned int madera_pin_unmake_drv_str(struct madera_pin_private *priv, |
432 | u16 regval) |
433 | { |
434 | regval = (regval & MADERA_GP1_DRV_STR_MASK) >> MADERA_GP1_DRV_STR_SHIFT; |
435 | |
436 | switch (regval) { |
437 | case 0: |
438 | return 4; |
439 | case 2: |
440 | return 8; |
441 | default: |
442 | return 0; |
443 | } |
444 | } |
445 | |
446 | static int madera_get_groups_count(struct pinctrl_dev *pctldev) |
447 | { |
448 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
449 | |
450 | /* Number of alt function groups plus number of single-pin groups */ |
451 | return priv->chip->n_pin_groups + priv->chip->n_pins; |
452 | } |
453 | |
454 | static const char *madera_get_group_name(struct pinctrl_dev *pctldev, |
455 | unsigned int selector) |
456 | { |
457 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
458 | |
459 | if (selector < priv->chip->n_pin_groups) |
460 | return priv->chip->pin_groups[selector].name; |
461 | |
462 | selector -= priv->chip->n_pin_groups; |
463 | return madera_pin_single_group_names[selector]; |
464 | } |
465 | |
466 | static int madera_get_group_pins(struct pinctrl_dev *pctldev, |
467 | unsigned int selector, |
468 | const unsigned int **pins, |
469 | unsigned int *num_pins) |
470 | { |
471 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
472 | |
473 | if (selector < priv->chip->n_pin_groups) { |
474 | *pins = priv->chip->pin_groups[selector].pins; |
475 | *num_pins = priv->chip->pin_groups[selector].n_pins; |
476 | } else { |
477 | /* return the dummy group for a single pin */ |
478 | selector -= priv->chip->n_pin_groups; |
479 | *pins = &madera_pin_single_group_pins[selector]; |
480 | *num_pins = 1; |
481 | } |
482 | return 0; |
483 | } |
484 | |
485 | static void madera_pin_dbg_show_fn(struct madera_pin_private *priv, |
486 | struct seq_file *s, |
487 | unsigned int pin, unsigned int fn) |
488 | { |
489 | const struct madera_pin_chip *chip = priv->chip; |
490 | int i, g_pin; |
491 | |
492 | if (fn != 0) { |
493 | for (i = 0; i < ARRAY_SIZE(madera_mux_funcs); ++i) { |
494 | if (madera_mux_funcs[i].func == fn) { |
495 | seq_printf(m: s, fmt: " FN=%s" , |
496 | madera_mux_funcs[i].name); |
497 | return; |
498 | } |
499 | } |
500 | return; /* ignore unknown function values */ |
501 | } |
502 | |
503 | /* alt function */ |
504 | for (i = 0; i < chip->n_pin_groups; ++i) { |
505 | for (g_pin = 0; g_pin < chip->pin_groups[i].n_pins; ++g_pin) { |
506 | if (chip->pin_groups[i].pins[g_pin] == pin) { |
507 | seq_printf(m: s, fmt: " FN=%s" , |
508 | chip->pin_groups[i].name); |
509 | return; |
510 | } |
511 | } |
512 | } |
513 | } |
514 | |
515 | static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev, |
516 | struct seq_file *s, |
517 | unsigned int pin) |
518 | { |
519 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
520 | unsigned int conf[2]; |
521 | unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin); |
522 | unsigned int fn; |
523 | int ret; |
524 | |
525 | ret = regmap_read(map: priv->madera->regmap, reg, val: &conf[0]); |
526 | if (ret) |
527 | return; |
528 | |
529 | ret = regmap_read(map: priv->madera->regmap, reg: reg + 1, val: &conf[1]); |
530 | if (ret) |
531 | return; |
532 | |
533 | seq_printf(m: s, fmt: "%04x:%04x" , conf[0], conf[1]); |
534 | |
535 | fn = (conf[0] & MADERA_GP1_FN_MASK) >> MADERA_GP1_FN_SHIFT; |
536 | madera_pin_dbg_show_fn(priv, s, pin, fn); |
537 | |
538 | /* State of direction bit is only relevant if function==1 */ |
539 | if (fn == 1) { |
540 | if (conf[1] & MADERA_GP1_DIR_MASK) |
541 | seq_puts(m: s, s: " IN" ); |
542 | else |
543 | seq_puts(m: s, s: " OUT" ); |
544 | } |
545 | |
546 | if (conf[1] & MADERA_GP1_PU_MASK) |
547 | seq_puts(m: s, s: " PU" ); |
548 | |
549 | if (conf[1] & MADERA_GP1_PD_MASK) |
550 | seq_puts(m: s, s: " PD" ); |
551 | |
552 | if (conf[0] & MADERA_GP1_DB_MASK) |
553 | seq_puts(m: s, s: " DB" ); |
554 | |
555 | if (conf[0] & MADERA_GP1_OP_CFG_MASK) |
556 | seq_puts(m: s, s: " OD" ); |
557 | else |
558 | seq_puts(m: s, s: " CMOS" ); |
559 | |
560 | seq_printf(m: s, fmt: " DRV=%umA" , madera_pin_unmake_drv_str(priv, regval: conf[1])); |
561 | |
562 | if (conf[0] & MADERA_GP1_IP_CFG_MASK) |
563 | seq_puts(m: s, s: " SCHMITT" ); |
564 | } |
565 | |
566 | static const struct pinctrl_ops madera_pin_group_ops = { |
567 | .get_groups_count = madera_get_groups_count, |
568 | .get_group_name = madera_get_group_name, |
569 | .get_group_pins = madera_get_group_pins, |
570 | #if IS_ENABLED(CONFIG_OF) |
571 | .dt_node_to_map = pinconf_generic_dt_node_to_map_all, |
572 | .dt_free_map = pinctrl_utils_free_map, |
573 | #endif |
574 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
575 | .pin_dbg_show = madera_pin_dbg_show, |
576 | #endif |
577 | }; |
578 | |
579 | static int madera_mux_get_funcs_count(struct pinctrl_dev *pctldev) |
580 | { |
581 | return ARRAY_SIZE(madera_mux_funcs); |
582 | } |
583 | |
584 | static const char *madera_mux_get_func_name(struct pinctrl_dev *pctldev, |
585 | unsigned int selector) |
586 | { |
587 | return madera_mux_funcs[selector].name; |
588 | } |
589 | |
590 | static int madera_mux_get_groups(struct pinctrl_dev *pctldev, |
591 | unsigned int selector, |
592 | const char * const **groups, |
593 | unsigned int * const num_groups) |
594 | { |
595 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
596 | |
597 | *groups = madera_mux_funcs[selector].group_names; |
598 | |
599 | if (madera_mux_funcs[selector].func == 0) { |
600 | /* alt func always maps to a single group */ |
601 | *num_groups = 1; |
602 | } else { |
603 | /* other funcs map to all available gpio pins */ |
604 | *num_groups = priv->chip->n_pins; |
605 | } |
606 | |
607 | return 0; |
608 | } |
609 | |
610 | static int madera_mux_set_mux(struct pinctrl_dev *pctldev, |
611 | unsigned int selector, |
612 | unsigned int group) |
613 | { |
614 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
615 | struct madera *madera = priv->madera; |
616 | const struct madera_pin_groups *pin_group = priv->chip->pin_groups; |
617 | unsigned int n_chip_groups = priv->chip->n_pin_groups; |
618 | const char *func_name = madera_mux_funcs[selector].name; |
619 | unsigned int reg; |
620 | int i, ret = 0; |
621 | |
622 | dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n" , |
623 | __func__, selector, func_name, group, |
624 | madera_get_group_name(pctldev, group)); |
625 | |
626 | if (madera_mux_funcs[selector].func == 0) { |
627 | /* alt func pin assignments are codec-specific */ |
628 | for (i = 0; i < n_chip_groups; ++i) { |
629 | if (strcmp(func_name, pin_group->name) == 0) |
630 | break; |
631 | |
632 | ++pin_group; |
633 | } |
634 | |
635 | if (i == n_chip_groups) |
636 | return -EINVAL; |
637 | |
638 | for (i = 0; i < pin_group->n_pins; ++i) { |
639 | reg = MADERA_GPIO1_CTRL_1 + (2 * pin_group->pins[i]); |
640 | |
641 | dev_dbg(priv->dev, "%s setting 0x%x func bits to 0\n" , |
642 | __func__, reg); |
643 | |
644 | ret = regmap_update_bits(map: madera->regmap, reg, |
645 | MADERA_GP1_FN_MASK, val: 0); |
646 | if (ret) |
647 | break; |
648 | |
649 | } |
650 | } else { |
651 | /* |
652 | * for other funcs the group will be the gpio number and will |
653 | * be offset by the number of chip-specific functions at the |
654 | * start of the group list |
655 | */ |
656 | group -= n_chip_groups; |
657 | reg = MADERA_GPIO1_CTRL_1 + (2 * group); |
658 | |
659 | dev_dbg(priv->dev, "%s setting 0x%x func bits to 0x%x\n" , |
660 | __func__, reg, madera_mux_funcs[selector].func); |
661 | |
662 | ret = regmap_update_bits(map: madera->regmap, |
663 | reg, |
664 | MADERA_GP1_FN_MASK, |
665 | val: madera_mux_funcs[selector].func); |
666 | } |
667 | |
668 | if (ret) |
669 | dev_err(priv->dev, "Failed to write to 0x%x (%d)\n" , reg, ret); |
670 | |
671 | return ret; |
672 | } |
673 | |
674 | static int madera_gpio_set_direction(struct pinctrl_dev *pctldev, |
675 | struct pinctrl_gpio_range *range, |
676 | unsigned int offset, |
677 | bool input) |
678 | { |
679 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
680 | struct madera *madera = priv->madera; |
681 | unsigned int reg = MADERA_GPIO1_CTRL_2 + (2 * offset); |
682 | unsigned int val; |
683 | int ret; |
684 | |
685 | if (input) |
686 | val = MADERA_GP1_DIR; |
687 | else |
688 | val = 0; |
689 | |
690 | ret = regmap_update_bits(map: madera->regmap, reg, MADERA_GP1_DIR_MASK, val); |
691 | if (ret) |
692 | dev_err(priv->dev, "Failed to write to 0x%x (%d)\n" , reg, ret); |
693 | |
694 | return ret; |
695 | } |
696 | |
697 | static int madera_gpio_request_enable(struct pinctrl_dev *pctldev, |
698 | struct pinctrl_gpio_range *range, |
699 | unsigned int offset) |
700 | { |
701 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
702 | struct madera *madera = priv->madera; |
703 | unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset); |
704 | int ret; |
705 | |
706 | /* put the pin into GPIO mode */ |
707 | ret = regmap_update_bits(map: madera->regmap, reg, MADERA_GP1_FN_MASK, val: 1); |
708 | if (ret) |
709 | dev_err(priv->dev, "Failed to write to 0x%x (%d)\n" , reg, ret); |
710 | |
711 | return ret; |
712 | } |
713 | |
714 | static void madera_gpio_disable_free(struct pinctrl_dev *pctldev, |
715 | struct pinctrl_gpio_range *range, |
716 | unsigned int offset) |
717 | { |
718 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
719 | struct madera *madera = priv->madera; |
720 | unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * offset); |
721 | int ret; |
722 | |
723 | /* disable GPIO by setting to GPIO IN */ |
724 | madera_gpio_set_direction(pctldev, range, offset, input: true); |
725 | |
726 | ret = regmap_update_bits(map: madera->regmap, reg, MADERA_GP1_FN_MASK, val: 1); |
727 | if (ret) |
728 | dev_err(priv->dev, "Failed to write to 0x%x (%d)\n" , reg, ret); |
729 | } |
730 | |
731 | static const struct pinmux_ops madera_pin_mux_ops = { |
732 | .get_functions_count = madera_mux_get_funcs_count, |
733 | .get_function_name = madera_mux_get_func_name, |
734 | .get_function_groups = madera_mux_get_groups, |
735 | .set_mux = madera_mux_set_mux, |
736 | .gpio_request_enable = madera_gpio_request_enable, |
737 | .gpio_disable_free = madera_gpio_disable_free, |
738 | .gpio_set_direction = madera_gpio_set_direction, |
739 | .strict = true, /* GPIO and other functions are exclusive */ |
740 | }; |
741 | |
742 | static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin, |
743 | unsigned long *config) |
744 | { |
745 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
746 | unsigned int param = pinconf_to_config_param(config: *config); |
747 | unsigned int result = 0; |
748 | unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin); |
749 | unsigned int conf[2]; |
750 | int ret; |
751 | |
752 | ret = regmap_read(map: priv->madera->regmap, reg, val: &conf[0]); |
753 | if (!ret) |
754 | ret = regmap_read(map: priv->madera->regmap, reg: reg + 1, val: &conf[1]); |
755 | |
756 | if (ret) { |
757 | dev_err(priv->dev, "Failed to read GP%d conf (%d)\n" , |
758 | pin + 1, ret); |
759 | return ret; |
760 | } |
761 | |
762 | switch (param) { |
763 | case PIN_CONFIG_BIAS_BUS_HOLD: |
764 | conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
765 | if (conf[1] == (MADERA_GP1_PU | MADERA_GP1_PD)) |
766 | result = 1; |
767 | break; |
768 | case PIN_CONFIG_BIAS_DISABLE: |
769 | conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
770 | if (!conf[1]) |
771 | result = 1; |
772 | break; |
773 | case PIN_CONFIG_BIAS_PULL_DOWN: |
774 | conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
775 | if (conf[1] == MADERA_GP1_PD_MASK) |
776 | result = 1; |
777 | break; |
778 | case PIN_CONFIG_BIAS_PULL_UP: |
779 | conf[1] &= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
780 | if (conf[1] == MADERA_GP1_PU_MASK) |
781 | result = 1; |
782 | break; |
783 | case PIN_CONFIG_DRIVE_OPEN_DRAIN: |
784 | if (conf[0] & MADERA_GP1_OP_CFG_MASK) |
785 | result = 1; |
786 | break; |
787 | case PIN_CONFIG_DRIVE_PUSH_PULL: |
788 | if (!(conf[0] & MADERA_GP1_OP_CFG_MASK)) |
789 | result = 1; |
790 | break; |
791 | case PIN_CONFIG_DRIVE_STRENGTH: |
792 | result = madera_pin_unmake_drv_str(priv, regval: conf[1]); |
793 | break; |
794 | case PIN_CONFIG_INPUT_DEBOUNCE: |
795 | if (conf[0] & MADERA_GP1_DB_MASK) |
796 | result = 1; |
797 | break; |
798 | case PIN_CONFIG_INPUT_ENABLE: |
799 | if (conf[0] & MADERA_GP1_DIR_MASK) |
800 | result = 1; |
801 | break; |
802 | case PIN_CONFIG_INPUT_SCHMITT: |
803 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
804 | if (conf[0] & MADERA_GP1_IP_CFG_MASK) |
805 | result = 1; |
806 | break; |
807 | case PIN_CONFIG_OUTPUT: |
808 | if ((conf[1] & MADERA_GP1_DIR_MASK) && |
809 | (conf[0] & MADERA_GP1_LVL_MASK)) |
810 | result = 1; |
811 | break; |
812 | default: |
813 | return -ENOTSUPP; |
814 | } |
815 | |
816 | *config = pinconf_to_config_packed(param, argument: result); |
817 | |
818 | return 0; |
819 | } |
820 | |
821 | static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin, |
822 | unsigned long *configs, unsigned int num_configs) |
823 | { |
824 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
825 | u16 conf[2] = {0, 0}; |
826 | u16 mask[2] = {0, 0}; |
827 | unsigned int reg = MADERA_GPIO1_CTRL_1 + (2 * pin); |
828 | unsigned int val; |
829 | int ret; |
830 | |
831 | while (num_configs) { |
832 | dev_dbg(priv->dev, "%s config 0x%lx\n" , __func__, *configs); |
833 | |
834 | switch (pinconf_to_config_param(config: *configs)) { |
835 | case PIN_CONFIG_BIAS_BUS_HOLD: |
836 | mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
837 | conf[1] |= MADERA_GP1_PU | MADERA_GP1_PD; |
838 | break; |
839 | case PIN_CONFIG_BIAS_DISABLE: |
840 | mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
841 | conf[1] &= ~(MADERA_GP1_PU | MADERA_GP1_PD); |
842 | break; |
843 | case PIN_CONFIG_BIAS_PULL_DOWN: |
844 | mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
845 | conf[1] |= MADERA_GP1_PD; |
846 | conf[1] &= ~MADERA_GP1_PU; |
847 | break; |
848 | case PIN_CONFIG_BIAS_PULL_UP: |
849 | mask[1] |= MADERA_GP1_PU_MASK | MADERA_GP1_PD_MASK; |
850 | conf[1] |= MADERA_GP1_PU; |
851 | conf[1] &= ~MADERA_GP1_PD; |
852 | break; |
853 | case PIN_CONFIG_DRIVE_OPEN_DRAIN: |
854 | mask[0] |= MADERA_GP1_OP_CFG_MASK; |
855 | conf[0] |= MADERA_GP1_OP_CFG; |
856 | break; |
857 | case PIN_CONFIG_DRIVE_PUSH_PULL: |
858 | mask[0] |= MADERA_GP1_OP_CFG_MASK; |
859 | conf[0] &= ~MADERA_GP1_OP_CFG; |
860 | break; |
861 | case PIN_CONFIG_DRIVE_STRENGTH: |
862 | val = pinconf_to_config_argument(config: *configs); |
863 | mask[1] |= MADERA_GP1_DRV_STR_MASK; |
864 | conf[1] &= ~MADERA_GP1_DRV_STR_MASK; |
865 | conf[1] |= madera_pin_make_drv_str(priv, milliamps: val); |
866 | break; |
867 | case PIN_CONFIG_INPUT_DEBOUNCE: |
868 | mask[0] |= MADERA_GP1_DB_MASK; |
869 | |
870 | /* |
871 | * we can't configure debounce time per-pin so value |
872 | * is just a flag |
873 | */ |
874 | val = pinconf_to_config_argument(config: *configs); |
875 | if (val) |
876 | conf[0] |= MADERA_GP1_DB; |
877 | else |
878 | conf[0] &= ~MADERA_GP1_DB; |
879 | break; |
880 | case PIN_CONFIG_INPUT_ENABLE: |
881 | val = pinconf_to_config_argument(config: *configs); |
882 | mask[1] |= MADERA_GP1_DIR_MASK; |
883 | if (val) |
884 | conf[1] |= MADERA_GP1_DIR; |
885 | else |
886 | conf[1] &= ~MADERA_GP1_DIR; |
887 | break; |
888 | case PIN_CONFIG_INPUT_SCHMITT: |
889 | val = pinconf_to_config_argument(config: *configs); |
890 | mask[0] |= MADERA_GP1_IP_CFG; |
891 | if (val) |
892 | conf[0] |= MADERA_GP1_IP_CFG; |
893 | else |
894 | conf[0] &= ~MADERA_GP1_IP_CFG; |
895 | |
896 | mask[1] |= MADERA_GP1_DIR_MASK; |
897 | conf[1] |= MADERA_GP1_DIR; |
898 | break; |
899 | case PIN_CONFIG_INPUT_SCHMITT_ENABLE: |
900 | mask[0] |= MADERA_GP1_IP_CFG; |
901 | conf[0] |= MADERA_GP1_IP_CFG; |
902 | mask[1] |= MADERA_GP1_DIR_MASK; |
903 | conf[1] |= MADERA_GP1_DIR; |
904 | break; |
905 | case PIN_CONFIG_OUTPUT: |
906 | val = pinconf_to_config_argument(config: *configs); |
907 | mask[0] |= MADERA_GP1_LVL_MASK; |
908 | if (val) |
909 | conf[0] |= MADERA_GP1_LVL; |
910 | else |
911 | conf[0] &= ~MADERA_GP1_LVL; |
912 | |
913 | mask[1] |= MADERA_GP1_DIR_MASK; |
914 | conf[1] &= ~MADERA_GP1_DIR; |
915 | break; |
916 | default: |
917 | return -ENOTSUPP; |
918 | } |
919 | |
920 | ++configs; |
921 | --num_configs; |
922 | } |
923 | |
924 | dev_dbg(priv->dev, |
925 | "%s gpio%d 0x%x:0x%x 0x%x:0x%x\n" , |
926 | __func__, pin + 1, reg, conf[0], reg + 1, conf[1]); |
927 | |
928 | ret = regmap_update_bits(map: priv->madera->regmap, reg, mask: mask[0], val: conf[0]); |
929 | if (ret) |
930 | goto err; |
931 | |
932 | ++reg; |
933 | ret = regmap_update_bits(map: priv->madera->regmap, reg, mask: mask[1], val: conf[1]); |
934 | if (ret) |
935 | goto err; |
936 | |
937 | return 0; |
938 | |
939 | err: |
940 | dev_err(priv->dev, |
941 | "Failed to write GPIO%d conf (%d) reg 0x%x\n" , |
942 | pin + 1, ret, reg); |
943 | |
944 | return ret; |
945 | } |
946 | |
947 | static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev, |
948 | unsigned int selector, |
949 | unsigned long *configs, |
950 | unsigned int num_configs) |
951 | { |
952 | struct madera_pin_private *priv = pinctrl_dev_get_drvdata(pctldev); |
953 | const struct madera_pin_groups *pin_group; |
954 | unsigned int n_groups = priv->chip->n_pin_groups; |
955 | int i, ret; |
956 | |
957 | dev_dbg(priv->dev, "%s setting group %s\n" , __func__, |
958 | madera_get_group_name(pctldev, selector)); |
959 | |
960 | if (selector >= n_groups) { |
961 | /* group is a single pin, convert to pin number and set */ |
962 | return madera_pin_conf_set(pctldev, |
963 | pin: selector - n_groups, |
964 | configs, |
965 | num_configs); |
966 | } else { |
967 | pin_group = &priv->chip->pin_groups[selector]; |
968 | |
969 | for (i = 0; i < pin_group->n_pins; ++i) { |
970 | ret = madera_pin_conf_set(pctldev, |
971 | pin: pin_group->pins[i], |
972 | configs, |
973 | num_configs); |
974 | if (ret) |
975 | return ret; |
976 | } |
977 | } |
978 | |
979 | return 0; |
980 | } |
981 | |
982 | static const struct pinconf_ops madera_pin_conf_ops = { |
983 | .is_generic = true, |
984 | .pin_config_get = madera_pin_conf_get, |
985 | .pin_config_set = madera_pin_conf_set, |
986 | .pin_config_group_set = madera_pin_conf_group_set, |
987 | }; |
988 | |
989 | static struct pinctrl_desc madera_pin_desc = { |
990 | .name = "madera-pinctrl" , |
991 | .pins = madera_pins, |
992 | .pctlops = &madera_pin_group_ops, |
993 | .pmxops = &madera_pin_mux_ops, |
994 | .confops = &madera_pin_conf_ops, |
995 | .owner = THIS_MODULE, |
996 | }; |
997 | |
998 | static int madera_pin_probe(struct platform_device *pdev) |
999 | { |
1000 | struct madera *madera = dev_get_drvdata(dev: pdev->dev.parent); |
1001 | const struct madera_pdata *pdata = &madera->pdata; |
1002 | struct madera_pin_private *priv; |
1003 | int ret; |
1004 | |
1005 | BUILD_BUG_ON(ARRAY_SIZE(madera_pin_single_group_names) != |
1006 | ARRAY_SIZE(madera_pin_single_group_pins)); |
1007 | |
1008 | dev_dbg(&pdev->dev, "%s\n" , __func__); |
1009 | |
1010 | device_set_node(dev: &pdev->dev, dev_fwnode(pdev->dev.parent)); |
1011 | |
1012 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL); |
1013 | if (!priv) |
1014 | return -ENOMEM; |
1015 | |
1016 | priv->dev = &pdev->dev; |
1017 | priv->madera = madera; |
1018 | |
1019 | switch (madera->type) { |
1020 | case CS47L15: |
1021 | if (IS_ENABLED(CONFIG_PINCTRL_CS47L15)) |
1022 | priv->chip = &cs47l15_pin_chip; |
1023 | break; |
1024 | case CS47L35: |
1025 | if (IS_ENABLED(CONFIG_PINCTRL_CS47L35)) |
1026 | priv->chip = &cs47l35_pin_chip; |
1027 | break; |
1028 | case CS47L85: |
1029 | case WM1840: |
1030 | if (IS_ENABLED(CONFIG_PINCTRL_CS47L85)) |
1031 | priv->chip = &cs47l85_pin_chip; |
1032 | break; |
1033 | case CS47L90: |
1034 | case CS47L91: |
1035 | if (IS_ENABLED(CONFIG_PINCTRL_CS47L90)) |
1036 | priv->chip = &cs47l90_pin_chip; |
1037 | break; |
1038 | case CS42L92: |
1039 | case CS47L92: |
1040 | case CS47L93: |
1041 | if (IS_ENABLED(CONFIG_PINCTRL_CS47L92)) |
1042 | priv->chip = &cs47l92_pin_chip; |
1043 | break; |
1044 | default: |
1045 | break; |
1046 | } |
1047 | |
1048 | if (!priv->chip) |
1049 | return -ENODEV; |
1050 | |
1051 | madera_pin_desc.npins = priv->chip->n_pins; |
1052 | |
1053 | ret = devm_pinctrl_register_and_init(dev: &pdev->dev, |
1054 | pctldesc: &madera_pin_desc, |
1055 | driver_data: priv, |
1056 | pctldev: &priv->pctl); |
1057 | if (ret) { |
1058 | dev_err(priv->dev, "Failed pinctrl register (%d)\n" , ret); |
1059 | return ret; |
1060 | } |
1061 | |
1062 | /* if the configuration is provided through pdata, apply it */ |
1063 | if (pdata->gpio_configs) { |
1064 | ret = pinctrl_register_mappings(map: pdata->gpio_configs, |
1065 | num_maps: pdata->n_gpio_configs); |
1066 | if (ret) { |
1067 | dev_err(priv->dev, |
1068 | "Failed to register pdata mappings (%d)\n" , |
1069 | ret); |
1070 | return ret; |
1071 | } |
1072 | } |
1073 | |
1074 | ret = pinctrl_enable(pctldev: priv->pctl); |
1075 | if (ret) { |
1076 | dev_err(priv->dev, "Failed to enable pinctrl (%d)\n" , ret); |
1077 | return ret; |
1078 | } |
1079 | |
1080 | platform_set_drvdata(pdev, data: priv); |
1081 | |
1082 | dev_dbg(priv->dev, "pinctrl probed ok\n" ); |
1083 | |
1084 | return 0; |
1085 | } |
1086 | |
1087 | static void madera_pin_remove(struct platform_device *pdev) |
1088 | { |
1089 | struct madera_pin_private *priv = platform_get_drvdata(pdev); |
1090 | |
1091 | if (priv->madera->pdata.gpio_configs) |
1092 | pinctrl_unregister_mappings(map: priv->madera->pdata.gpio_configs); |
1093 | } |
1094 | |
1095 | static struct platform_driver madera_pin_driver = { |
1096 | .probe = madera_pin_probe, |
1097 | .remove_new = madera_pin_remove, |
1098 | .driver = { |
1099 | .name = "madera-pinctrl" , |
1100 | }, |
1101 | }; |
1102 | |
1103 | module_platform_driver(madera_pin_driver); |
1104 | |
1105 | MODULE_DESCRIPTION("Madera pinctrl driver" ); |
1106 | MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>" ); |
1107 | MODULE_LICENSE("GPL v2" ); |
1108 | |