1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Driver for BCM6318 GPIO unit (pinctrl + GPIO)
4 *
5 * Copyright (C) 2021 Álvaro Fernández Rojas <noltari@gmail.com>
6 * Copyright (C) 2016 Jonas Gorski <jonas.gorski@gmail.com>
7 */
8
9#include <linux/bits.h>
10#include <linux/gpio/driver.h>
11#include <linux/kernel.h>
12#include <linux/of.h>
13#include <linux/pinctrl/pinmux.h>
14#include <linux/platform_device.h>
15#include <linux/regmap.h>
16
17#include "../pinctrl-utils.h"
18
19#include "pinctrl-bcm63xx.h"
20
21#define BCM6318_NUM_GPIOS 50
22#define BCM6318_NUM_MUX 48
23
24#define BCM6318_MODE_REG 0x18
25#define BCM6318_MUX_REG 0x1c
26#define BCM6328_MUX_MASK GENMASK(1, 0)
27#define BCM6318_PAD_REG 0x54
28#define BCM6328_PAD_MASK GENMASK(3, 0)
29
30struct bcm6318_function {
31 const char *name;
32 const char * const *groups;
33 const unsigned num_groups;
34
35 unsigned mode_val:1;
36 unsigned mux_val:2;
37};
38
39static const struct pinctrl_pin_desc bcm6318_pins[] = {
40 PINCTRL_PIN(0, "gpio0"),
41 PINCTRL_PIN(1, "gpio1"),
42 PINCTRL_PIN(2, "gpio2"),
43 PINCTRL_PIN(3, "gpio3"),
44 PINCTRL_PIN(4, "gpio4"),
45 PINCTRL_PIN(5, "gpio5"),
46 PINCTRL_PIN(6, "gpio6"),
47 PINCTRL_PIN(7, "gpio7"),
48 PINCTRL_PIN(8, "gpio8"),
49 PINCTRL_PIN(9, "gpio9"),
50 PINCTRL_PIN(10, "gpio10"),
51 PINCTRL_PIN(11, "gpio11"),
52 PINCTRL_PIN(12, "gpio12"),
53 PINCTRL_PIN(13, "gpio13"),
54 PINCTRL_PIN(14, "gpio14"),
55 PINCTRL_PIN(15, "gpio15"),
56 PINCTRL_PIN(16, "gpio16"),
57 PINCTRL_PIN(17, "gpio17"),
58 PINCTRL_PIN(18, "gpio18"),
59 PINCTRL_PIN(19, "gpio19"),
60 PINCTRL_PIN(20, "gpio20"),
61 PINCTRL_PIN(21, "gpio21"),
62 PINCTRL_PIN(22, "gpio22"),
63 PINCTRL_PIN(23, "gpio23"),
64 PINCTRL_PIN(24, "gpio24"),
65 PINCTRL_PIN(25, "gpio25"),
66 PINCTRL_PIN(26, "gpio26"),
67 PINCTRL_PIN(27, "gpio27"),
68 PINCTRL_PIN(28, "gpio28"),
69 PINCTRL_PIN(29, "gpio29"),
70 PINCTRL_PIN(30, "gpio30"),
71 PINCTRL_PIN(31, "gpio31"),
72 PINCTRL_PIN(32, "gpio32"),
73 PINCTRL_PIN(33, "gpio33"),
74 PINCTRL_PIN(34, "gpio34"),
75 PINCTRL_PIN(35, "gpio35"),
76 PINCTRL_PIN(36, "gpio36"),
77 PINCTRL_PIN(37, "gpio37"),
78 PINCTRL_PIN(38, "gpio38"),
79 PINCTRL_PIN(39, "gpio39"),
80 PINCTRL_PIN(40, "gpio40"),
81 PINCTRL_PIN(41, "gpio41"),
82 PINCTRL_PIN(42, "gpio42"),
83 PINCTRL_PIN(43, "gpio43"),
84 PINCTRL_PIN(44, "gpio44"),
85 PINCTRL_PIN(45, "gpio45"),
86 PINCTRL_PIN(46, "gpio46"),
87 PINCTRL_PIN(47, "gpio47"),
88 PINCTRL_PIN(48, "gpio48"),
89 PINCTRL_PIN(49, "gpio49"),
90};
91
92static unsigned gpio0_pins[] = { 0 };
93static unsigned gpio1_pins[] = { 1 };
94static unsigned gpio2_pins[] = { 2 };
95static unsigned gpio3_pins[] = { 3 };
96static unsigned gpio4_pins[] = { 4 };
97static unsigned gpio5_pins[] = { 5 };
98static unsigned gpio6_pins[] = { 6 };
99static unsigned gpio7_pins[] = { 7 };
100static unsigned gpio8_pins[] = { 8 };
101static unsigned gpio9_pins[] = { 9 };
102static unsigned gpio10_pins[] = { 10 };
103static unsigned gpio11_pins[] = { 11 };
104static unsigned gpio12_pins[] = { 12 };
105static unsigned gpio13_pins[] = { 13 };
106static unsigned gpio14_pins[] = { 14 };
107static unsigned gpio15_pins[] = { 15 };
108static unsigned gpio16_pins[] = { 16 };
109static unsigned gpio17_pins[] = { 17 };
110static unsigned gpio18_pins[] = { 18 };
111static unsigned gpio19_pins[] = { 19 };
112static unsigned gpio20_pins[] = { 20 };
113static unsigned gpio21_pins[] = { 21 };
114static unsigned gpio22_pins[] = { 22 };
115static unsigned gpio23_pins[] = { 23 };
116static unsigned gpio24_pins[] = { 24 };
117static unsigned gpio25_pins[] = { 25 };
118static unsigned gpio26_pins[] = { 26 };
119static unsigned gpio27_pins[] = { 27 };
120static unsigned gpio28_pins[] = { 28 };
121static unsigned gpio29_pins[] = { 29 };
122static unsigned gpio30_pins[] = { 30 };
123static unsigned gpio31_pins[] = { 31 };
124static unsigned gpio32_pins[] = { 32 };
125static unsigned gpio33_pins[] = { 33 };
126static unsigned gpio34_pins[] = { 34 };
127static unsigned gpio35_pins[] = { 35 };
128static unsigned gpio36_pins[] = { 36 };
129static unsigned gpio37_pins[] = { 37 };
130static unsigned gpio38_pins[] = { 38 };
131static unsigned gpio39_pins[] = { 39 };
132static unsigned gpio40_pins[] = { 40 };
133static unsigned gpio41_pins[] = { 41 };
134static unsigned gpio42_pins[] = { 42 };
135static unsigned gpio43_pins[] = { 43 };
136static unsigned gpio44_pins[] = { 44 };
137static unsigned gpio45_pins[] = { 45 };
138static unsigned gpio46_pins[] = { 46 };
139static unsigned gpio47_pins[] = { 47 };
140static unsigned gpio48_pins[] = { 48 };
141static unsigned gpio49_pins[] = { 49 };
142
143static struct pingroup bcm6318_groups[] = {
144 BCM_PIN_GROUP(gpio0),
145 BCM_PIN_GROUP(gpio1),
146 BCM_PIN_GROUP(gpio2),
147 BCM_PIN_GROUP(gpio3),
148 BCM_PIN_GROUP(gpio4),
149 BCM_PIN_GROUP(gpio5),
150 BCM_PIN_GROUP(gpio6),
151 BCM_PIN_GROUP(gpio7),
152 BCM_PIN_GROUP(gpio8),
153 BCM_PIN_GROUP(gpio9),
154 BCM_PIN_GROUP(gpio10),
155 BCM_PIN_GROUP(gpio11),
156 BCM_PIN_GROUP(gpio12),
157 BCM_PIN_GROUP(gpio13),
158 BCM_PIN_GROUP(gpio14),
159 BCM_PIN_GROUP(gpio15),
160 BCM_PIN_GROUP(gpio16),
161 BCM_PIN_GROUP(gpio17),
162 BCM_PIN_GROUP(gpio18),
163 BCM_PIN_GROUP(gpio19),
164 BCM_PIN_GROUP(gpio20),
165 BCM_PIN_GROUP(gpio21),
166 BCM_PIN_GROUP(gpio22),
167 BCM_PIN_GROUP(gpio23),
168 BCM_PIN_GROUP(gpio24),
169 BCM_PIN_GROUP(gpio25),
170 BCM_PIN_GROUP(gpio26),
171 BCM_PIN_GROUP(gpio27),
172 BCM_PIN_GROUP(gpio28),
173 BCM_PIN_GROUP(gpio29),
174 BCM_PIN_GROUP(gpio30),
175 BCM_PIN_GROUP(gpio31),
176 BCM_PIN_GROUP(gpio32),
177 BCM_PIN_GROUP(gpio33),
178 BCM_PIN_GROUP(gpio34),
179 BCM_PIN_GROUP(gpio35),
180 BCM_PIN_GROUP(gpio36),
181 BCM_PIN_GROUP(gpio37),
182 BCM_PIN_GROUP(gpio38),
183 BCM_PIN_GROUP(gpio39),
184 BCM_PIN_GROUP(gpio40),
185 BCM_PIN_GROUP(gpio41),
186 BCM_PIN_GROUP(gpio42),
187 BCM_PIN_GROUP(gpio43),
188 BCM_PIN_GROUP(gpio44),
189 BCM_PIN_GROUP(gpio45),
190 BCM_PIN_GROUP(gpio46),
191 BCM_PIN_GROUP(gpio47),
192 BCM_PIN_GROUP(gpio48),
193 BCM_PIN_GROUP(gpio49),
194};
195
196/* GPIO_MODE */
197static const char * const led_groups[] = {
198 "gpio0",
199 "gpio1",
200 "gpio2",
201 "gpio3",
202 "gpio4",
203 "gpio5",
204 "gpio6",
205 "gpio7",
206 "gpio8",
207 "gpio9",
208 "gpio10",
209 "gpio11",
210 "gpio12",
211 "gpio13",
212 "gpio14",
213 "gpio15",
214 "gpio16",
215 "gpio17",
216 "gpio18",
217 "gpio19",
218 "gpio20",
219 "gpio21",
220 "gpio22",
221 "gpio23",
222};
223
224/* PINMUX_SEL */
225static const char * const ephy0_spd_led_groups[] = {
226 "gpio0",
227};
228
229static const char * const ephy1_spd_led_groups[] = {
230 "gpio1",
231};
232
233static const char * const ephy2_spd_led_groups[] = {
234 "gpio2",
235};
236
237static const char * const ephy3_spd_led_groups[] = {
238 "gpio3",
239};
240
241static const char * const ephy0_act_led_groups[] = {
242 "gpio4",
243};
244
245static const char * const ephy1_act_led_groups[] = {
246 "gpio5",
247};
248
249static const char * const ephy2_act_led_groups[] = {
250 "gpio6",
251};
252
253static const char * const ephy3_act_led_groups[] = {
254 "gpio7",
255};
256
257static const char * const serial_led_data_groups[] = {
258 "gpio6",
259};
260
261static const char * const serial_led_clk_groups[] = {
262 "gpio7",
263};
264
265static const char * const inet_act_led_groups[] = {
266 "gpio8",
267};
268
269static const char * const inet_fail_led_groups[] = {
270 "gpio9",
271};
272
273static const char * const dsl_led_groups[] = {
274 "gpio10",
275};
276
277static const char * const post_fail_led_groups[] = {
278 "gpio11",
279};
280
281static const char * const wlan_wps_led_groups[] = {
282 "gpio12",
283};
284
285static const char * const usb_pwron_groups[] = {
286 "gpio13",
287};
288
289static const char * const usb_device_led_groups[] = {
290 "gpio13",
291};
292
293static const char * const usb_active_groups[] = {
294 "gpio40",
295};
296
297#define BCM6318_MODE_FUN(n) \
298 { \
299 .name = #n, \
300 .groups = n##_groups, \
301 .num_groups = ARRAY_SIZE(n##_groups), \
302 .mode_val = 1, \
303 }
304
305#define BCM6318_MUX_FUN(n, mux) \
306 { \
307 .name = #n, \
308 .groups = n##_groups, \
309 .num_groups = ARRAY_SIZE(n##_groups), \
310 .mux_val = mux, \
311 }
312
313static const struct bcm6318_function bcm6318_funcs[] = {
314 BCM6318_MODE_FUN(led),
315 BCM6318_MUX_FUN(ephy0_spd_led, 1),
316 BCM6318_MUX_FUN(ephy1_spd_led, 1),
317 BCM6318_MUX_FUN(ephy2_spd_led, 1),
318 BCM6318_MUX_FUN(ephy3_spd_led, 1),
319 BCM6318_MUX_FUN(ephy0_act_led, 1),
320 BCM6318_MUX_FUN(ephy1_act_led, 1),
321 BCM6318_MUX_FUN(ephy2_act_led, 1),
322 BCM6318_MUX_FUN(ephy3_act_led, 1),
323 BCM6318_MUX_FUN(serial_led_data, 3),
324 BCM6318_MUX_FUN(serial_led_clk, 3),
325 BCM6318_MUX_FUN(inet_act_led, 1),
326 BCM6318_MUX_FUN(inet_fail_led, 1),
327 BCM6318_MUX_FUN(dsl_led, 1),
328 BCM6318_MUX_FUN(post_fail_led, 1),
329 BCM6318_MUX_FUN(wlan_wps_led, 1),
330 BCM6318_MUX_FUN(usb_pwron, 1),
331 BCM6318_MUX_FUN(usb_device_led, 2),
332 BCM6318_MUX_FUN(usb_active, 2),
333};
334
335static inline unsigned int bcm6318_mux_off(unsigned int pin)
336{
337 return BCM6318_MUX_REG + (pin / 16) * 4;
338}
339
340static inline unsigned int bcm6318_pad_off(unsigned int pin)
341{
342 return BCM6318_PAD_REG + (pin / 8) * 4;
343}
344
345static int bcm6318_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
346{
347 return ARRAY_SIZE(bcm6318_groups);
348}
349
350static const char *bcm6318_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
351 unsigned group)
352{
353 return bcm6318_groups[group].name;
354}
355
356static int bcm6318_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
357 unsigned group, const unsigned **pins,
358 unsigned *npins)
359{
360 *pins = bcm6318_groups[group].pins;
361 *npins = bcm6318_groups[group].npins;
362
363 return 0;
364}
365
366static int bcm6318_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
367{
368 return ARRAY_SIZE(bcm6318_funcs);
369}
370
371static const char *bcm6318_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
372 unsigned selector)
373{
374 return bcm6318_funcs[selector].name;
375}
376
377static int bcm6318_pinctrl_get_groups(struct pinctrl_dev *pctldev,
378 unsigned selector,
379 const char * const **groups,
380 unsigned * const num_groups)
381{
382 *groups = bcm6318_funcs[selector].groups;
383 *num_groups = bcm6318_funcs[selector].num_groups;
384
385 return 0;
386}
387
388static inline void bcm6318_rmw_mux(struct bcm63xx_pinctrl *pc, unsigned pin,
389 unsigned int mode, unsigned int mux)
390{
391 if (pin < BCM63XX_BANK_GPIOS)
392 regmap_update_bits(map: pc->regs, BCM6318_MODE_REG, BIT(pin),
393 val: mode ? BIT(pin) : 0);
394
395 if (pin < BCM6318_NUM_MUX)
396 regmap_update_bits(map: pc->regs,
397 reg: bcm6318_mux_off(pin),
398 BCM6328_MUX_MASK << ((pin % 16) * 2),
399 val: mux << ((pin % 16) * 2));
400}
401
402static inline void bcm6318_set_pad(struct bcm63xx_pinctrl *pc, unsigned pin,
403 uint8_t val)
404{
405 regmap_update_bits(map: pc->regs, reg: bcm6318_pad_off(pin),
406 BCM6328_PAD_MASK << ((pin % 8) * 4),
407 val: val << ((pin % 8) * 4));
408}
409
410static int bcm6318_pinctrl_set_mux(struct pinctrl_dev *pctldev,
411 unsigned selector, unsigned group)
412{
413 struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
414 const struct pingroup *pg = &bcm6318_groups[group];
415 const struct bcm6318_function *f = &bcm6318_funcs[selector];
416
417 bcm6318_rmw_mux(pc, pin: pg->pins[0], mode: f->mode_val, mux: f->mux_val);
418
419 return 0;
420}
421
422static int bcm6318_gpio_request_enable(struct pinctrl_dev *pctldev,
423 struct pinctrl_gpio_range *range,
424 unsigned offset)
425{
426 struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
427
428 /* disable all functions using this pin */
429 if (offset < 13) {
430 /* GPIOs 0-12 use mux 0 as GPIO function */
431 bcm6318_rmw_mux(pc, pin: offset, mode: 0, mux: 0);
432 } else if (offset < 42) {
433 /* GPIOs 13-41 use mux 3 as GPIO function */
434 bcm6318_rmw_mux(pc, pin: offset, mode: 0, mux: 3);
435
436 bcm6318_set_pad(pc, pin: offset, val: 0);
437 }
438
439 return 0;
440}
441
442static const struct pinctrl_ops bcm6318_pctl_ops = {
443 .dt_free_map = pinctrl_utils_free_map,
444 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
445 .get_group_name = bcm6318_pinctrl_get_group_name,
446 .get_group_pins = bcm6318_pinctrl_get_group_pins,
447 .get_groups_count = bcm6318_pinctrl_get_group_count,
448};
449
450static const struct pinmux_ops bcm6318_pmx_ops = {
451 .get_function_groups = bcm6318_pinctrl_get_groups,
452 .get_function_name = bcm6318_pinctrl_get_func_name,
453 .get_functions_count = bcm6318_pinctrl_get_func_count,
454 .gpio_request_enable = bcm6318_gpio_request_enable,
455 .set_mux = bcm6318_pinctrl_set_mux,
456 .strict = true,
457};
458
459static const struct bcm63xx_pinctrl_soc bcm6318_soc = {
460 .ngpios = BCM6318_NUM_GPIOS,
461 .npins = ARRAY_SIZE(bcm6318_pins),
462 .pctl_ops = &bcm6318_pctl_ops,
463 .pins = bcm6318_pins,
464 .pmx_ops = &bcm6318_pmx_ops,
465};
466
467static int bcm6318_pinctrl_probe(struct platform_device *pdev)
468{
469 return bcm63xx_pinctrl_probe(pdev, soc: &bcm6318_soc, NULL);
470}
471
472static const struct of_device_id bcm6318_pinctrl_match[] = {
473 { .compatible = "brcm,bcm6318-pinctrl", },
474 { /* sentinel */ }
475};
476
477static struct platform_driver bcm6318_pinctrl_driver = {
478 .probe = bcm6318_pinctrl_probe,
479 .driver = {
480 .name = "bcm6318-pinctrl",
481 .of_match_table = bcm6318_pinctrl_match,
482 },
483};
484
485builtin_platform_driver(bcm6318_pinctrl_driver);
486

source code of linux/drivers/pinctrl/bcm/pinctrl-bcm6318.c