b57b49d35f777f2f5278263cec76619dc45656f3
[openwrt/staging/chunkeey.git] / target / linux / bmips / patches-5.10 / 411-pinctrl-add-a-pincontrol-driver-for-BCM6318.patch
1 From e1764f96eb563a11c822ff91d1c6d7ed01c3925b Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
3 Date: Fri, 24 Jun 2016 22:20:39 +0200
4 Subject: [PATCH 12/12] pinctrl: add a pincontrol driver for BCM6318
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 Add a pincontrol driver for BCM6318. BCM6318 allows muxing most GPIOs
10 to different functions. BCM6318 is similar to BCM6328 with the addition
11 of a pad register, and the GPIO meaning of the mux register changes
12 based on the GPIO number.
13
14 Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
15 Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
16 ---
17 drivers/pinctrl/bcm/Kconfig | 11 +
18 drivers/pinctrl/bcm/Makefile | 1 +
19 drivers/pinctrl/bcm/pinctrl-bcm6318.c | 674 ++++++++++++++++++++++++++
20 3 files changed, 686 insertions(+)
21 create mode 100644 drivers/pinctrl/bcm/pinctrl-bcm6318.c
22
23 --- a/drivers/pinctrl/bcm/Kconfig
24 +++ b/drivers/pinctrl/bcm/Kconfig
25 @@ -29,6 +29,17 @@ config PINCTRL_BCM2835
26 help
27 Say Y here to enable the Broadcom BCM2835 GPIO driver.
28
29 +config PINCTRL_BCM6318
30 + bool "Broadcom BCM6318 GPIO driver"
31 + depends on OF_GPIO && (BMIPS_GENERIC || COMPILE_TEST)
32 + select PINMUX
33 + select PINCONF
34 + select GENERIC_PINCONF
35 + select MFD_SYSCON
36 + default BMIPS_GENERIC
37 + help
38 + Say Y here to enable the Broadcom BCM6318 GPIO driver.
39 +
40 config PINCTRL_BCM6328
41 bool "Broadcom BCM6328 GPIO driver"
42 depends on OF_GPIO && (BMIPS_GENERIC || COMPILE_TEST)
43 --- a/drivers/pinctrl/bcm/Makefile
44 +++ b/drivers/pinctrl/bcm/Makefile
45 @@ -3,6 +3,7 @@
46
47 obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
48 obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
49 +obj-$(CONFIG_PINCTRL_BCM6318) += pinctrl-bcm6318.o
50 obj-$(CONFIG_PINCTRL_BCM6328) += pinctrl-bcm6328.o
51 obj-$(CONFIG_PINCTRL_BCM6358) += pinctrl-bcm6358.o
52 obj-$(CONFIG_PINCTRL_BCM6362) += pinctrl-bcm6362.o
53 --- /dev/null
54 +++ b/drivers/pinctrl/bcm/pinctrl-bcm6318.c
55 @@ -0,0 +1,674 @@
56 +// SPDX-License-Identifier: GPL-2.0+
57 +/*
58 + * Driver for BCM6318 GPIO unit (pinctrl + GPIO)
59 + *
60 + * Copyright (C) 2021 Álvaro Fernández Rojas <noltari@gmail.com>
61 + * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
62 + */
63 +
64 +#include <linux/bitops.h>
65 +#include <linux/gpio.h>
66 +#include <linux/kernel.h>
67 +#include <linux/mfd/syscon.h>
68 +#include <linux/of.h>
69 +#include <linux/of_gpio.h>
70 +#include <linux/of_irq.h>
71 +#include <linux/platform_device.h>
72 +#include <linux/regmap.h>
73 +
74 +#include <linux/pinctrl/machine.h>
75 +#include <linux/pinctrl/pinconf.h>
76 +#include <linux/pinctrl/pinconf-generic.h>
77 +#include <linux/pinctrl/pinmux.h>
78 +
79 +#include "../core.h"
80 +#include "../pinctrl-utils.h"
81 +
82 +#define MODULE_NAME "bcm6318-pinctrl"
83 +#define BCM6318_NUM_GPIOS 50
84 +#define BCM6318_NUM_MUX 48
85 +
86 +#define BANK_SIZE sizeof(uint32_t)
87 +#define PINS_PER_BANK (BANK_SIZE * BITS_PER_BYTE)
88 +
89 +#define BCM6318_DIROUT_REG 0x04
90 +#define BCM6318_DATA_REG 0x0c
91 +#define BCM6318_MODE_REG 0x18
92 +#define BCM6318_MUX_REG 0x1c
93 +#define BCM6318_PAD_REG 0x54
94 +
95 +struct bcm6318_pingroup {
96 + const char *name;
97 + const unsigned * const pins;
98 + const unsigned num_pins;
99 +};
100 +
101 +struct bcm6318_function {
102 + const char *name;
103 + const char * const *groups;
104 + const unsigned num_groups;
105 +
106 + unsigned mode_val:1;
107 + unsigned mux_val:2;
108 +};
109 +
110 +struct bcm6318_pinctrl {
111 + struct device *dev;
112 + struct regmap *regs;
113 +
114 + struct pinctrl_dev *pctl_dev;
115 + struct gpio_chip gpio_chip;
116 + struct pinctrl_desc pctl_desc;
117 + struct pinctrl_gpio_range gpio_range;
118 +};
119 +
120 +static const struct pinctrl_pin_desc bcm6318_pins[] = {
121 + PINCTRL_PIN(0, "gpio0"),
122 + PINCTRL_PIN(1, "gpio1"),
123 + PINCTRL_PIN(2, "gpio2"),
124 + PINCTRL_PIN(3, "gpio3"),
125 + PINCTRL_PIN(4, "gpio4"),
126 + PINCTRL_PIN(5, "gpio5"),
127 + PINCTRL_PIN(6, "gpio6"),
128 + PINCTRL_PIN(7, "gpio7"),
129 + PINCTRL_PIN(8, "gpio8"),
130 + PINCTRL_PIN(9, "gpio9"),
131 + PINCTRL_PIN(10, "gpio10"),
132 + PINCTRL_PIN(11, "gpio11"),
133 + PINCTRL_PIN(12, "gpio12"),
134 + PINCTRL_PIN(13, "gpio13"),
135 + PINCTRL_PIN(14, "gpio14"),
136 + PINCTRL_PIN(15, "gpio15"),
137 + PINCTRL_PIN(16, "gpio16"),
138 + PINCTRL_PIN(17, "gpio17"),
139 + PINCTRL_PIN(18, "gpio18"),
140 + PINCTRL_PIN(19, "gpio19"),
141 + PINCTRL_PIN(20, "gpio20"),
142 + PINCTRL_PIN(21, "gpio21"),
143 + PINCTRL_PIN(22, "gpio22"),
144 + PINCTRL_PIN(23, "gpio23"),
145 + PINCTRL_PIN(24, "gpio24"),
146 + PINCTRL_PIN(25, "gpio25"),
147 + PINCTRL_PIN(26, "gpio26"),
148 + PINCTRL_PIN(27, "gpio27"),
149 + PINCTRL_PIN(28, "gpio28"),
150 + PINCTRL_PIN(29, "gpio29"),
151 + PINCTRL_PIN(30, "gpio30"),
152 + PINCTRL_PIN(31, "gpio31"),
153 + PINCTRL_PIN(32, "gpio32"),
154 + PINCTRL_PIN(33, "gpio33"),
155 + PINCTRL_PIN(34, "gpio34"),
156 + PINCTRL_PIN(35, "gpio35"),
157 + PINCTRL_PIN(36, "gpio36"),
158 + PINCTRL_PIN(37, "gpio37"),
159 + PINCTRL_PIN(38, "gpio38"),
160 + PINCTRL_PIN(39, "gpio39"),
161 + PINCTRL_PIN(40, "gpio40"),
162 + PINCTRL_PIN(41, "gpio41"),
163 + PINCTRL_PIN(42, "gpio42"),
164 + PINCTRL_PIN(43, "gpio43"),
165 + PINCTRL_PIN(44, "gpio44"),
166 + PINCTRL_PIN(45, "gpio45"),
167 + PINCTRL_PIN(46, "gpio46"),
168 + PINCTRL_PIN(47, "gpio47"),
169 + PINCTRL_PIN(48, "gpio48"),
170 + PINCTRL_PIN(49, "gpio49"),
171 +};
172 +
173 +static unsigned gpio0_pins[] = { 0 };
174 +static unsigned gpio1_pins[] = { 1 };
175 +static unsigned gpio2_pins[] = { 2 };
176 +static unsigned gpio3_pins[] = { 3 };
177 +static unsigned gpio4_pins[] = { 4 };
178 +static unsigned gpio5_pins[] = { 5 };
179 +static unsigned gpio6_pins[] = { 6 };
180 +static unsigned gpio7_pins[] = { 7 };
181 +static unsigned gpio8_pins[] = { 8 };
182 +static unsigned gpio9_pins[] = { 9 };
183 +static unsigned gpio10_pins[] = { 10 };
184 +static unsigned gpio11_pins[] = { 11 };
185 +static unsigned gpio12_pins[] = { 12 };
186 +static unsigned gpio13_pins[] = { 13 };
187 +static unsigned gpio14_pins[] = { 14 };
188 +static unsigned gpio15_pins[] = { 15 };
189 +static unsigned gpio16_pins[] = { 16 };
190 +static unsigned gpio17_pins[] = { 17 };
191 +static unsigned gpio18_pins[] = { 18 };
192 +static unsigned gpio19_pins[] = { 19 };
193 +static unsigned gpio20_pins[] = { 20 };
194 +static unsigned gpio21_pins[] = { 21 };
195 +static unsigned gpio22_pins[] = { 22 };
196 +static unsigned gpio23_pins[] = { 23 };
197 +static unsigned gpio24_pins[] = { 24 };
198 +static unsigned gpio25_pins[] = { 25 };
199 +static unsigned gpio26_pins[] = { 26 };
200 +static unsigned gpio27_pins[] = { 27 };
201 +static unsigned gpio28_pins[] = { 28 };
202 +static unsigned gpio29_pins[] = { 29 };
203 +static unsigned gpio30_pins[] = { 30 };
204 +static unsigned gpio31_pins[] = { 31 };
205 +static unsigned gpio32_pins[] = { 32 };
206 +static unsigned gpio33_pins[] = { 33 };
207 +static unsigned gpio34_pins[] = { 34 };
208 +static unsigned gpio35_pins[] = { 35 };
209 +static unsigned gpio36_pins[] = { 36 };
210 +static unsigned gpio37_pins[] = { 37 };
211 +static unsigned gpio38_pins[] = { 38 };
212 +static unsigned gpio39_pins[] = { 39 };
213 +static unsigned gpio40_pins[] = { 40 };
214 +static unsigned gpio41_pins[] = { 41 };
215 +static unsigned gpio42_pins[] = { 42 };
216 +static unsigned gpio43_pins[] = { 43 };
217 +static unsigned gpio44_pins[] = { 44 };
218 +static unsigned gpio45_pins[] = { 45 };
219 +static unsigned gpio46_pins[] = { 46 };
220 +static unsigned gpio47_pins[] = { 47 };
221 +static unsigned gpio48_pins[] = { 48 };
222 +static unsigned gpio49_pins[] = { 49 };
223 +
224 +#define BCM6318_GROUP(n) \
225 + { \
226 + .name = #n, \
227 + .pins = n##_pins, \
228 + .num_pins = ARRAY_SIZE(n##_pins), \
229 + }
230 +
231 +static struct bcm6318_pingroup bcm6318_groups[] = {
232 + BCM6318_GROUP(gpio0),
233 + BCM6318_GROUP(gpio1),
234 + BCM6318_GROUP(gpio2),
235 + BCM6318_GROUP(gpio3),
236 + BCM6318_GROUP(gpio4),
237 + BCM6318_GROUP(gpio5),
238 + BCM6318_GROUP(gpio6),
239 + BCM6318_GROUP(gpio7),
240 + BCM6318_GROUP(gpio8),
241 + BCM6318_GROUP(gpio9),
242 + BCM6318_GROUP(gpio10),
243 + BCM6318_GROUP(gpio11),
244 + BCM6318_GROUP(gpio12),
245 + BCM6318_GROUP(gpio13),
246 + BCM6318_GROUP(gpio14),
247 + BCM6318_GROUP(gpio15),
248 + BCM6318_GROUP(gpio16),
249 + BCM6318_GROUP(gpio17),
250 + BCM6318_GROUP(gpio18),
251 + BCM6318_GROUP(gpio19),
252 + BCM6318_GROUP(gpio20),
253 + BCM6318_GROUP(gpio21),
254 + BCM6318_GROUP(gpio22),
255 + BCM6318_GROUP(gpio23),
256 + BCM6318_GROUP(gpio24),
257 + BCM6318_GROUP(gpio25),
258 + BCM6318_GROUP(gpio26),
259 + BCM6318_GROUP(gpio27),
260 + BCM6318_GROUP(gpio28),
261 + BCM6318_GROUP(gpio29),
262 + BCM6318_GROUP(gpio30),
263 + BCM6318_GROUP(gpio31),
264 + BCM6318_GROUP(gpio32),
265 + BCM6318_GROUP(gpio33),
266 + BCM6318_GROUP(gpio34),
267 + BCM6318_GROUP(gpio35),
268 + BCM6318_GROUP(gpio36),
269 + BCM6318_GROUP(gpio37),
270 + BCM6318_GROUP(gpio38),
271 + BCM6318_GROUP(gpio39),
272 + BCM6318_GROUP(gpio40),
273 + BCM6318_GROUP(gpio41),
274 + BCM6318_GROUP(gpio42),
275 + BCM6318_GROUP(gpio43),
276 + BCM6318_GROUP(gpio44),
277 + BCM6318_GROUP(gpio45),
278 + BCM6318_GROUP(gpio46),
279 + BCM6318_GROUP(gpio47),
280 + BCM6318_GROUP(gpio48),
281 + BCM6318_GROUP(gpio49),
282 +};
283 +
284 +/* GPIO_MODE */
285 +static const char * const led_groups[] = {
286 + "gpio0",
287 + "gpio1",
288 + "gpio2",
289 + "gpio3",
290 + "gpio4",
291 + "gpio5",
292 + "gpio6",
293 + "gpio7",
294 + "gpio8",
295 + "gpio9",
296 + "gpio10",
297 + "gpio11",
298 + "gpio12",
299 + "gpio13",
300 + "gpio14",
301 + "gpio15",
302 + "gpio16",
303 + "gpio17",
304 + "gpio18",
305 + "gpio19",
306 + "gpio20",
307 + "gpio21",
308 + "gpio22",
309 + "gpio23",
310 +};
311 +
312 +/* PINMUX_SEL */
313 +static const char * const ephy0_spd_led_groups[] = {
314 + "gpio0",
315 +};
316 +
317 +static const char * const ephy1_spd_led_groups[] = {
318 + "gpio1",
319 +};
320 +
321 +static const char * const ephy2_spd_led_groups[] = {
322 + "gpio2",
323 +};
324 +
325 +static const char * const ephy3_spd_led_groups[] = {
326 + "gpio3",
327 +};
328 +
329 +static const char * const ephy0_act_led_groups[] = {
330 + "gpio4",
331 +};
332 +
333 +static const char * const ephy1_act_led_groups[] = {
334 + "gpio5",
335 +};
336 +
337 +static const char * const ephy2_act_led_groups[] = {
338 + "gpio6",
339 +};
340 +
341 +static const char * const ephy3_act_led_groups[] = {
342 + "gpio7",
343 +};
344 +
345 +static const char * const serial_led_data_groups[] = {
346 + "gpio6",
347 +};
348 +
349 +static const char * const serial_led_clk_groups[] = {
350 + "gpio7",
351 +};
352 +
353 +static const char * const inet_act_led_groups[] = {
354 + "gpio8",
355 +};
356 +
357 +static const char * const inet_fail_led_groups[] = {
358 + "gpio9",
359 +};
360 +
361 +static const char * const dsl_led_groups[] = {
362 + "gpio10",
363 +};
364 +
365 +static const char * const post_fail_led_groups[] = {
366 + "gpio11",
367 +};
368 +
369 +static const char * const wlan_wps_led_groups[] = {
370 + "gpio12",
371 +};
372 +
373 +static const char * const usb_pwron_groups[] = {
374 + "gpio13",
375 +};
376 +
377 +static const char * const usb_device_led_groups[] = {
378 + "gpio13",
379 +};
380 +
381 +static const char * const usb_active_groups[] = {
382 + "gpio40",
383 +};
384 +
385 +#define BCM6318_MODE_FUN(n) \
386 + { \
387 + .name = #n, \
388 + .groups = n##_groups, \
389 + .num_groups = ARRAY_SIZE(n##_groups), \
390 + .mode_val = 1, \
391 + }
392 +
393 +#define BCM6318_MUX_FUN(n, mux) \
394 + { \
395 + .name = #n, \
396 + .groups = n##_groups, \
397 + .num_groups = ARRAY_SIZE(n##_groups), \
398 + .mux_val = mux, \
399 + }
400 +
401 +static const struct bcm6318_function bcm6318_funcs[] = {
402 + BCM6318_MODE_FUN(led),
403 + BCM6318_MUX_FUN(ephy0_spd_led, 1),
404 + BCM6318_MUX_FUN(ephy1_spd_led, 1),
405 + BCM6318_MUX_FUN(ephy2_spd_led, 1),
406 + BCM6318_MUX_FUN(ephy3_spd_led, 1),
407 + BCM6318_MUX_FUN(ephy0_act_led, 1),
408 + BCM6318_MUX_FUN(ephy1_act_led, 1),
409 + BCM6318_MUX_FUN(ephy2_act_led, 1),
410 + BCM6318_MUX_FUN(ephy3_act_led, 1),
411 + BCM6318_MUX_FUN(serial_led_data, 3),
412 + BCM6318_MUX_FUN(serial_led_clk, 3),
413 + BCM6318_MUX_FUN(inet_act_led, 1),
414 + BCM6318_MUX_FUN(inet_fail_led, 1),
415 + BCM6318_MUX_FUN(dsl_led, 1),
416 + BCM6318_MUX_FUN(post_fail_led, 1),
417 + BCM6318_MUX_FUN(wlan_wps_led, 1),
418 + BCM6318_MUX_FUN(usb_pwron, 1),
419 + BCM6318_MUX_FUN(usb_device_led, 2),
420 + BCM6318_MUX_FUN(usb_active, 2),
421 +};
422 +
423 +static inline unsigned int bcm6318_bank_pin(unsigned int pin)
424 +{
425 + return pin % PINS_PER_BANK;
426 +}
427 +
428 +static inline unsigned int bcm6318_mux_off(unsigned int pin)
429 +{
430 + return BCM6318_MUX_REG + (pin / 16) * BANK_SIZE;
431 +}
432 +
433 +static inline unsigned int bcm6318_pad_off(unsigned int pin)
434 +{
435 + return BCM6318_PAD_REG + (pin / 8) * BANK_SIZE;
436 +}
437 +
438 +static inline unsigned int bcm6318_reg_off(unsigned int reg, unsigned int pin)
439 +{
440 + return reg - (pin / PINS_PER_BANK) * BANK_SIZE;
441 +}
442 +
443 +static int bcm6318_gpio_direction_input(struct gpio_chip *chip,
444 + unsigned int pin)
445 +{
446 + struct bcm6318_pinctrl *pc = gpiochip_get_data(chip);
447 + unsigned int dirout = bcm6318_reg_off(BCM6318_DIROUT_REG, pin);
448 + unsigned int bank_pin = bcm6318_bank_pin(pin);
449 + int ret;
450 +
451 + /*
452 + * Check with the pinctrl driver whether this pin is usable as
453 + * an input GPIO
454 + */
455 + ret = pinctrl_gpio_direction_input(chip->base + pin);
456 + if (ret)
457 + return ret;
458 +
459 + regmap_update_bits(pc->regs, dirout, BIT(bank_pin), 0);
460 +
461 + return 0;
462 +}
463 +
464 +static int bcm6318_gpio_direction_output(struct gpio_chip *chip,
465 + unsigned int pin, int value)
466 +{
467 + struct bcm6318_pinctrl *pc = gpiochip_get_data(chip);
468 + unsigned int data = bcm6318_reg_off(BCM6318_DATA_REG, pin);
469 + unsigned int dirout = bcm6318_reg_off(BCM6318_DIROUT_REG, pin);
470 + unsigned int bank_pin = bcm6318_bank_pin(pin);
471 + unsigned int val = value ? BIT(bank_pin) : 0;
472 + int ret;
473 +
474 + /*
475 + * Check with the pinctrl driver whether this pin is usable as
476 + * an output GPIO
477 + */
478 + ret = pinctrl_gpio_direction_output(chip->base + pin);
479 + if (ret)
480 + return ret;
481 +
482 + regmap_update_bits(pc->regs, dirout, BIT(bank_pin), BIT(bank_pin));
483 + regmap_update_bits(pc->regs, data, BIT(bank_pin), val);
484 +
485 + return 0;
486 +}
487 +
488 +static int bcm6318_gpio_get(struct gpio_chip *chip, unsigned int pin)
489 +{
490 + struct bcm6318_pinctrl *pc = gpiochip_get_data(chip);
491 + unsigned int data = bcm6318_reg_off(BCM6318_DATA_REG, pin);
492 + unsigned int bank_pin = bcm6318_bank_pin(pin);
493 + unsigned int val;
494 +
495 + regmap_read(pc->regs, data, &val);
496 +
497 + return !!(val & BIT(bank_pin));
498 +}
499 +
500 +static int bcm6318_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
501 +{
502 + struct bcm6318_pinctrl *pc = gpiochip_get_data(chip);
503 + unsigned int dirout = bcm6318_reg_off(BCM6318_DIROUT_REG, pin);
504 + unsigned int bank_pin = bcm6318_bank_pin(pin);
505 + unsigned int val;
506 +
507 + regmap_read(pc->regs, dirout, &val);
508 +
509 + if (val & BIT(bank_pin))
510 + return GPIO_LINE_DIRECTION_OUT;
511 +
512 + return GPIO_LINE_DIRECTION_IN;
513 +}
514 +
515 +static void bcm6318_gpio_set(struct gpio_chip *chip, unsigned int pin,
516 + int value)
517 +{
518 + struct bcm6318_pinctrl *pc = gpiochip_get_data(chip);
519 + unsigned int data = bcm6318_reg_off(BCM6318_DATA_REG, pin);
520 + unsigned int bank_pin = bcm6318_bank_pin(pin);
521 + unsigned int val = value ? BIT(bank_pin) : 0;
522 +
523 + regmap_update_bits(pc->regs, data, BIT(bank_pin), val);
524 +}
525 +
526 +static int bcm6318_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
527 +{
528 + char irq_name[7];
529 +
530 + sprintf(irq_name, "gpio%d", gpio);
531 +
532 + return of_irq_get_byname(chip->of_node, irq_name);
533 +}
534 +
535 +static int bcm6318_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
536 +{
537 + return ARRAY_SIZE(bcm6318_groups);
538 +}
539 +
540 +static const char *bcm6318_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
541 + unsigned group)
542 +{
543 + return bcm6318_groups[group].name;
544 +}
545 +
546 +static int bcm6318_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
547 + unsigned group, const unsigned **pins,
548 + unsigned *num_pins)
549 +{
550 + *pins = bcm6318_groups[group].pins;
551 + *num_pins = bcm6318_groups[group].num_pins;
552 +
553 + return 0;
554 +}
555 +
556 +static int bcm6318_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
557 +{
558 + return ARRAY_SIZE(bcm6318_funcs);
559 +}
560 +
561 +static const char *bcm6318_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
562 + unsigned selector)
563 +{
564 + return bcm6318_funcs[selector].name;
565 +}
566 +
567 +static int bcm6318_pinctrl_get_groups(struct pinctrl_dev *pctldev,
568 + unsigned selector,
569 + const char * const **groups,
570 + unsigned * const num_groups)
571 +{
572 + *groups = bcm6318_funcs[selector].groups;
573 + *num_groups = bcm6318_funcs[selector].num_groups;
574 +
575 + return 0;
576 +}
577 +
578 +static inline void bcm6318_rmw_mux(struct bcm6318_pinctrl *pc, unsigned pin,
579 + unsigned int mode, unsigned int mux)
580 +{
581 + if (pin < PINS_PER_BANK)
582 + regmap_update_bits(pc->regs, BCM6318_MODE_REG, BIT(pin),
583 + mode ? BIT(pin) : 0);
584 +
585 + if (pin < BCM6318_NUM_MUX)
586 + regmap_update_bits(pc->regs,
587 + bcm6318_mux_off(pin),
588 + 3UL << ((pin % 16) * 2),
589 + mux << ((pin % 16) * 2));
590 +}
591 +
592 +static inline void bcm6318_set_pad(struct bcm6318_pinctrl *pc, unsigned pin,
593 + uint8_t val)
594 +{
595 + regmap_update_bits(pc->regs, bcm6318_pad_off(pin),
596 + 0xfUL << ((pin % 8) * 4),
597 + val << ((pin % 8) * 4));
598 +}
599 +
600 +static int bcm6318_pinctrl_set_mux(struct pinctrl_dev *pctldev,
601 + unsigned selector, unsigned group)
602 +{
603 + struct bcm6318_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
604 + const struct bcm6318_pingroup *pg = &bcm6318_groups[group];
605 + const struct bcm6318_function *f = &bcm6318_funcs[selector];
606 +
607 + bcm6318_rmw_mux(pc, pg->pins[0], f->mode_val, f->mux_val);
608 +
609 + return 0;
610 +}
611 +
612 +static int bcm6318_gpio_request_enable(struct pinctrl_dev *pctldev,
613 + struct pinctrl_gpio_range *range,
614 + unsigned offset)
615 +{
616 + struct bcm6318_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
617 +
618 + /* disable all functions using this pin */
619 + if (offset < 13) {
620 + /* GPIOs 0-12 use mux 0 as GPIO function */
621 + bcm6318_rmw_mux(pc, offset, 0, 0);
622 + } else if (offset < 42) {
623 + /* GPIOs 13-41 use mux 3 as GPIO function */
624 + bcm6318_rmw_mux(pc, offset, 0, 3);
625 +
626 + bcm6318_set_pad(pc, offset, 0);
627 + }
628 +
629 + return 0;
630 +}
631 +
632 +static struct pinctrl_ops bcm6318_pctl_ops = {
633 + .get_groups_count = bcm6318_pinctrl_get_group_count,
634 + .get_group_name = bcm6318_pinctrl_get_group_name,
635 + .get_group_pins = bcm6318_pinctrl_get_group_pins,
636 + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
637 + .dt_free_map = pinctrl_utils_free_map,
638 +};
639 +
640 +static struct pinmux_ops bcm6318_pmx_ops = {
641 + .get_functions_count = bcm6318_pinctrl_get_func_count,
642 + .get_function_name = bcm6318_pinctrl_get_func_name,
643 + .get_function_groups = bcm6318_pinctrl_get_groups,
644 + .set_mux = bcm6318_pinctrl_set_mux,
645 + .gpio_request_enable = bcm6318_gpio_request_enable,
646 + .strict = true,
647 +};
648 +
649 +static int bcm6318_pinctrl_probe(struct platform_device *pdev)
650 +{
651 + struct device *dev = &pdev->dev;
652 + struct device_node *np = dev->of_node;
653 + struct bcm6318_pinctrl *pc;
654 + int err;
655 +
656 + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
657 + if (!pc)
658 + return -ENOMEM;
659 +
660 + platform_set_drvdata(pdev, pc);
661 + pc->dev = dev;
662 +
663 + pc->regs = syscon_node_to_regmap(dev->parent->of_node);
664 + if (IS_ERR(pc->regs))
665 + return PTR_ERR(pc->regs);
666 +
667 + pc->gpio_chip.label = MODULE_NAME;
668 + pc->gpio_chip.owner = THIS_MODULE;
669 + pc->gpio_chip.request = gpiochip_generic_request;
670 + pc->gpio_chip.free = gpiochip_generic_free;
671 + pc->gpio_chip.direction_input = bcm6318_gpio_direction_input;
672 + pc->gpio_chip.direction_output = bcm6318_gpio_direction_output;
673 + pc->gpio_chip.get_direction = bcm6318_gpio_get_direction;
674 + pc->gpio_chip.get = bcm6318_gpio_get;
675 + pc->gpio_chip.set = bcm6318_gpio_set;
676 + pc->gpio_chip.set_config = gpiochip_generic_config;
677 + pc->gpio_chip.base = -1;
678 + pc->gpio_chip.ngpio = BCM6318_NUM_GPIOS;
679 + pc->gpio_chip.can_sleep = false;
680 + pc->gpio_chip.parent = dev;
681 + pc->gpio_chip.of_node = np;
682 +
683 + if (of_get_property(np, "interrupt-names", NULL))
684 + pc->gpio_chip.to_irq = bcm6318_gpio_to_irq;
685 +
686 + err = gpiochip_add_data(&pc->gpio_chip, pc);
687 + if (err) {
688 + dev_err(dev, "could not add GPIO chip\n");
689 + return err;
690 + }
691 +
692 + pc->pctl_desc.name = MODULE_NAME,
693 + pc->pctl_desc.pins = bcm6318_pins,
694 + pc->pctl_desc.npins = ARRAY_SIZE(bcm6318_pins),
695 + pc->pctl_desc.pctlops = &bcm6318_pctl_ops,
696 + pc->pctl_desc.pmxops = &bcm6318_pmx_ops,
697 + pc->pctl_desc.owner = THIS_MODULE,
698 +
699 + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
700 + if (IS_ERR(pc->pctl_dev)) {
701 + gpiochip_remove(&pc->gpio_chip);
702 + return PTR_ERR(pc->pctl_dev);
703 + }
704 +
705 + pc->gpio_range.name = MODULE_NAME;
706 + pc->gpio_range.npins = BCM6318_NUM_GPIOS;
707 + pc->gpio_range.base = pc->gpio_chip.base;
708 + pc->gpio_range.gc = &pc->gpio_chip;
709 + pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
710 +
711 + dev_info(dev, "registered\n");
712 +
713 + return 0;
714 +}
715 +
716 +static const struct of_device_id bcm6318_pinctrl_match[] = {
717 + { .compatible = "brcm,bcm6318-pinctrl", },
718 + { },
719 +};
720 +
721 +static struct platform_driver bcm6318_pinctrl_driver = {
722 + .probe = bcm6318_pinctrl_probe,
723 + .driver = {
724 + .name = MODULE_NAME,
725 + .of_match_table = bcm6318_pinctrl_match,
726 + },
727 +};
728 +
729 +builtin_platform_driver(bcm6318_pinctrl_driver);