Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: add a pincontrol driver for BCM6318

Add a pincontrol driver for BCM6318. BCM6318 allows muxing most GPIOs
to different functions. BCM6318 is similar to BCM6328 with the addition
of a pad register, and the GPIO meaning of the mux register changes
based on the GPIO number.

Co-developed-by: Jonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://lore.kernel.org/r/20210324081923.20379-23-noltari@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Álvaro Fernández Rojas and committed by
Linus Walleij
d28039fc b6d46b94

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