linux/drivers/pinctrl/bcm/pinctrl-bcm6362.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for BCM6362 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 BCM6362_BANK_GPIOS      32
  22#define BCM6362_NUM_GPIOS       48
  23#define BCM6362_NUM_LEDS        24
  24
  25#define BCM6362_LED_REG         0x10
  26#define BCM6362_MODE_REG        0x18
  27#define BCM6362_CTRL_REG        0x1c
  28#define BCM6362_BASEMODE_REG    0x38
  29#define  BASEMODE_NAND          BIT(2)
  30
  31enum bcm6362_pinctrl_reg {
  32        BCM6362_LEDCTRL,
  33        BCM6362_MODE,
  34        BCM6362_CTRL,
  35        BCM6362_BASEMODE,
  36};
  37
  38struct bcm6362_pingroup {
  39        const char *name;
  40        const unsigned * const pins;
  41        const unsigned num_pins;
  42};
  43
  44struct bcm6362_function {
  45        const char *name;
  46        const char * const *groups;
  47        const unsigned num_groups;
  48
  49        enum bcm6362_pinctrl_reg reg;
  50        uint32_t basemode_mask;
  51};
  52
  53#define BCM6362_PIN(a, b, mask)                 \
  54        {                                       \
  55                .number = a,                    \
  56                .name = b,                      \
  57                .drv_data = (void *)(mask),     \
  58        }
  59
  60static const struct pinctrl_pin_desc bcm6362_pins[] = {
  61        PINCTRL_PIN(0, "gpio0"),
  62        PINCTRL_PIN(1, "gpio1"),
  63        PINCTRL_PIN(2, "gpio2"),
  64        PINCTRL_PIN(3, "gpio3"),
  65        PINCTRL_PIN(4, "gpio4"),
  66        PINCTRL_PIN(5, "gpio5"),
  67        PINCTRL_PIN(6, "gpio6"),
  68        PINCTRL_PIN(7, "gpio7"),
  69        BCM6362_PIN(8, "gpio8", BASEMODE_NAND),
  70        PINCTRL_PIN(9, "gpio9"),
  71        PINCTRL_PIN(10, "gpio10"),
  72        PINCTRL_PIN(11, "gpio11"),
  73        BCM6362_PIN(12, "gpio12", BASEMODE_NAND),
  74        BCM6362_PIN(13, "gpio13", BASEMODE_NAND),
  75        BCM6362_PIN(14, "gpio14", BASEMODE_NAND),
  76        BCM6362_PIN(15, "gpio15", BASEMODE_NAND),
  77        BCM6362_PIN(16, "gpio16", BASEMODE_NAND),
  78        BCM6362_PIN(17, "gpio17", BASEMODE_NAND),
  79        BCM6362_PIN(18, "gpio18", BASEMODE_NAND),
  80        BCM6362_PIN(19, "gpio19", BASEMODE_NAND),
  81        BCM6362_PIN(20, "gpio20", BASEMODE_NAND),
  82        BCM6362_PIN(21, "gpio21", BASEMODE_NAND),
  83        BCM6362_PIN(22, "gpio22", BASEMODE_NAND),
  84        BCM6362_PIN(23, "gpio23", BASEMODE_NAND),
  85        PINCTRL_PIN(24, "gpio24"),
  86        PINCTRL_PIN(25, "gpio25"),
  87        PINCTRL_PIN(26, "gpio26"),
  88        BCM6362_PIN(27, "gpio27", BASEMODE_NAND),
  89        PINCTRL_PIN(28, "gpio28"),
  90        PINCTRL_PIN(29, "gpio29"),
  91        PINCTRL_PIN(30, "gpio30"),
  92        PINCTRL_PIN(31, "gpio31"),
  93        PINCTRL_PIN(32, "gpio32"),
  94        PINCTRL_PIN(33, "gpio33"),
  95        PINCTRL_PIN(34, "gpio34"),
  96        PINCTRL_PIN(35, "gpio35"),
  97        PINCTRL_PIN(36, "gpio36"),
  98        PINCTRL_PIN(37, "gpio37"),
  99        PINCTRL_PIN(38, "gpio38"),
 100        PINCTRL_PIN(39, "gpio39"),
 101        PINCTRL_PIN(40, "gpio40"),
 102        PINCTRL_PIN(41, "gpio41"),
 103        PINCTRL_PIN(42, "gpio42"),
 104        PINCTRL_PIN(43, "gpio43"),
 105        PINCTRL_PIN(44, "gpio44"),
 106        PINCTRL_PIN(45, "gpio45"),
 107        PINCTRL_PIN(46, "gpio46"),
 108        PINCTRL_PIN(47, "gpio47"),
 109};
 110
 111static unsigned gpio0_pins[] = { 0 };
 112static unsigned gpio1_pins[] = { 1 };
 113static unsigned gpio2_pins[] = { 2 };
 114static unsigned gpio3_pins[] = { 3 };
 115static unsigned gpio4_pins[] = { 4 };
 116static unsigned gpio5_pins[] = { 5 };
 117static unsigned gpio6_pins[] = { 6 };
 118static unsigned gpio7_pins[] = { 7 };
 119static unsigned gpio8_pins[] = { 8 };
 120static unsigned gpio9_pins[] = { 9 };
 121static unsigned gpio10_pins[] = { 10 };
 122static unsigned gpio11_pins[] = { 11 };
 123static unsigned gpio12_pins[] = { 12 };
 124static unsigned gpio13_pins[] = { 13 };
 125static unsigned gpio14_pins[] = { 14 };
 126static unsigned gpio15_pins[] = { 15 };
 127static unsigned gpio16_pins[] = { 16 };
 128static unsigned gpio17_pins[] = { 17 };
 129static unsigned gpio18_pins[] = { 18 };
 130static unsigned gpio19_pins[] = { 19 };
 131static unsigned gpio20_pins[] = { 20 };
 132static unsigned gpio21_pins[] = { 21 };
 133static unsigned gpio22_pins[] = { 22 };
 134static unsigned gpio23_pins[] = { 23 };
 135static unsigned gpio24_pins[] = { 24 };
 136static unsigned gpio25_pins[] = { 25 };
 137static unsigned gpio26_pins[] = { 26 };
 138static unsigned gpio27_pins[] = { 27 };
 139static unsigned gpio28_pins[] = { 28 };
 140static unsigned gpio29_pins[] = { 29 };
 141static unsigned gpio30_pins[] = { 30 };
 142static unsigned gpio31_pins[] = { 31 };
 143static unsigned gpio32_pins[] = { 32 };
 144static unsigned gpio33_pins[] = { 33 };
 145static unsigned gpio34_pins[] = { 34 };
 146static unsigned gpio35_pins[] = { 35 };
 147static unsigned gpio36_pins[] = { 36 };
 148static unsigned gpio37_pins[] = { 37 };
 149static unsigned gpio38_pins[] = { 38 };
 150static unsigned gpio39_pins[] = { 39 };
 151static unsigned gpio40_pins[] = { 40 };
 152static unsigned gpio41_pins[] = { 41 };
 153static unsigned gpio42_pins[] = { 42 };
 154static unsigned gpio43_pins[] = { 43 };
 155static unsigned gpio44_pins[] = { 44 };
 156static unsigned gpio45_pins[] = { 45 };
 157static unsigned gpio46_pins[] = { 46 };
 158static unsigned gpio47_pins[] = { 47 };
 159
 160static unsigned nand_grp_pins[] = {
 161        8, 12, 13, 14, 15, 16, 17,
 162        18, 19, 20, 21, 22, 23, 27,
 163};
 164
 165#define BCM6362_GROUP(n)                                \
 166        {                                               \
 167                .name = #n,                             \
 168                .pins = n##_pins,                       \
 169                .num_pins = ARRAY_SIZE(n##_pins),       \
 170        }
 171
 172static struct bcm6362_pingroup bcm6362_groups[] = {
 173        BCM6362_GROUP(gpio0),
 174        BCM6362_GROUP(gpio1),
 175        BCM6362_GROUP(gpio2),
 176        BCM6362_GROUP(gpio3),
 177        BCM6362_GROUP(gpio4),
 178        BCM6362_GROUP(gpio5),
 179        BCM6362_GROUP(gpio6),
 180        BCM6362_GROUP(gpio7),
 181        BCM6362_GROUP(gpio8),
 182        BCM6362_GROUP(gpio9),
 183        BCM6362_GROUP(gpio10),
 184        BCM6362_GROUP(gpio11),
 185        BCM6362_GROUP(gpio12),
 186        BCM6362_GROUP(gpio13),
 187        BCM6362_GROUP(gpio14),
 188        BCM6362_GROUP(gpio15),
 189        BCM6362_GROUP(gpio16),
 190        BCM6362_GROUP(gpio17),
 191        BCM6362_GROUP(gpio18),
 192        BCM6362_GROUP(gpio19),
 193        BCM6362_GROUP(gpio20),
 194        BCM6362_GROUP(gpio21),
 195        BCM6362_GROUP(gpio22),
 196        BCM6362_GROUP(gpio23),
 197        BCM6362_GROUP(gpio24),
 198        BCM6362_GROUP(gpio25),
 199        BCM6362_GROUP(gpio26),
 200        BCM6362_GROUP(gpio27),
 201        BCM6362_GROUP(gpio28),
 202        BCM6362_GROUP(gpio29),
 203        BCM6362_GROUP(gpio30),
 204        BCM6362_GROUP(gpio31),
 205        BCM6362_GROUP(gpio32),
 206        BCM6362_GROUP(gpio33),
 207        BCM6362_GROUP(gpio34),
 208        BCM6362_GROUP(gpio35),
 209        BCM6362_GROUP(gpio36),
 210        BCM6362_GROUP(gpio37),
 211        BCM6362_GROUP(gpio38),
 212        BCM6362_GROUP(gpio39),
 213        BCM6362_GROUP(gpio40),
 214        BCM6362_GROUP(gpio41),
 215        BCM6362_GROUP(gpio42),
 216        BCM6362_GROUP(gpio43),
 217        BCM6362_GROUP(gpio44),
 218        BCM6362_GROUP(gpio45),
 219        BCM6362_GROUP(gpio46),
 220        BCM6362_GROUP(gpio47),
 221        BCM6362_GROUP(nand_grp),
 222};
 223
 224static const char * const led_groups[] = {
 225        "gpio0",
 226        "gpio1",
 227        "gpio2",
 228        "gpio3",
 229        "gpio4",
 230        "gpio5",
 231        "gpio6",
 232        "gpio7",
 233        "gpio8",
 234        "gpio9",
 235        "gpio10",
 236        "gpio11",
 237        "gpio12",
 238        "gpio13",
 239        "gpio14",
 240        "gpio15",
 241        "gpio16",
 242        "gpio17",
 243        "gpio18",
 244        "gpio19",
 245        "gpio20",
 246        "gpio21",
 247        "gpio22",
 248        "gpio23",
 249};
 250
 251static const char * const usb_device_led_groups[] = {
 252        "gpio0",
 253};
 254
 255static const char * const sys_irq_groups[] = {
 256        "gpio1",
 257};
 258
 259static const char * const serial_led_clk_groups[] = {
 260        "gpio2",
 261};
 262
 263static const char * const serial_led_data_groups[] = {
 264        "gpio3",
 265};
 266
 267static const char * const robosw_led_data_groups[] = {
 268        "gpio4",
 269};
 270
 271static const char * const robosw_led_clk_groups[] = {
 272        "gpio5",
 273};
 274
 275static const char * const robosw_led0_groups[] = {
 276        "gpio6",
 277};
 278
 279static const char * const robosw_led1_groups[] = {
 280        "gpio7",
 281};
 282
 283static const char * const inet_led_groups[] = {
 284        "gpio8",
 285};
 286
 287static const char * const spi_cs2_groups[] = {
 288        "gpio9",
 289};
 290
 291static const char * const spi_cs3_groups[] = {
 292        "gpio10",
 293};
 294
 295static const char * const ntr_pulse_groups[] = {
 296        "gpio11",
 297};
 298
 299static const char * const uart1_scts_groups[] = {
 300        "gpio12",
 301};
 302
 303static const char * const uart1_srts_groups[] = {
 304        "gpio13",
 305};
 306
 307static const char * const uart1_sdin_groups[] = {
 308        "gpio14",
 309};
 310
 311static const char * const uart1_sdout_groups[] = {
 312        "gpio15",
 313};
 314
 315static const char * const adsl_spi_miso_groups[] = {
 316        "gpio16",
 317};
 318
 319static const char * const adsl_spi_mosi_groups[] = {
 320        "gpio17",
 321};
 322
 323static const char * const adsl_spi_clk_groups[] = {
 324        "gpio18",
 325};
 326
 327static const char * const adsl_spi_cs_groups[] = {
 328        "gpio19",
 329};
 330
 331static const char * const ephy0_led_groups[] = {
 332        "gpio20",
 333};
 334
 335static const char * const ephy1_led_groups[] = {
 336        "gpio21",
 337};
 338
 339static const char * const ephy2_led_groups[] = {
 340        "gpio22",
 341};
 342
 343static const char * const ephy3_led_groups[] = {
 344        "gpio23",
 345};
 346
 347static const char * const ext_irq0_groups[] = {
 348        "gpio24",
 349};
 350
 351static const char * const ext_irq1_groups[] = {
 352        "gpio25",
 353};
 354
 355static const char * const ext_irq2_groups[] = {
 356        "gpio26",
 357};
 358
 359static const char * const ext_irq3_groups[] = {
 360        "gpio27",
 361};
 362
 363static const char * const wifi_groups[] = {
 364        "gpio32",
 365        "gpio33",
 366        "gpio34",
 367        "gpio35",
 368        "gpio36",
 369        "gpio37",
 370        "gpio38",
 371        "gpio39",
 372        "gpio40",
 373        "gpio41",
 374        "gpio42",
 375        "gpio43",
 376        "gpio44",
 377        "gpio45",
 378        "gpio46",
 379        "gpio47",
 380};
 381
 382static const char * const nand_groups[] = {
 383        "nand_grp",
 384};
 385
 386#define BCM6362_LED_FUN(n)                              \
 387        {                                               \
 388                .name = #n,                             \
 389                .groups = n##_groups,                   \
 390                .num_groups = ARRAY_SIZE(n##_groups),   \
 391                .reg = BCM6362_LEDCTRL,                 \
 392        }
 393
 394#define BCM6362_MODE_FUN(n)                             \
 395        {                                               \
 396                .name = #n,                             \
 397                .groups = n##_groups,                   \
 398                .num_groups = ARRAY_SIZE(n##_groups),   \
 399                .reg = BCM6362_MODE,                    \
 400        }
 401
 402#define BCM6362_CTRL_FUN(n)                             \
 403        {                                               \
 404                .name = #n,                             \
 405                .groups = n##_groups,                   \
 406                .num_groups = ARRAY_SIZE(n##_groups),   \
 407                .reg = BCM6362_CTRL,                    \
 408        }
 409
 410#define BCM6362_BASEMODE_FUN(n, mask)                   \
 411        {                                               \
 412                .name = #n,                             \
 413                .groups = n##_groups,                   \
 414                .num_groups = ARRAY_SIZE(n##_groups),   \
 415                .reg = BCM6362_BASEMODE,                \
 416                .basemode_mask = (mask),                \
 417        }
 418
 419static const struct bcm6362_function bcm6362_funcs[] = {
 420        BCM6362_LED_FUN(led),
 421        BCM6362_MODE_FUN(usb_device_led),
 422        BCM6362_MODE_FUN(sys_irq),
 423        BCM6362_MODE_FUN(serial_led_clk),
 424        BCM6362_MODE_FUN(serial_led_data),
 425        BCM6362_MODE_FUN(robosw_led_data),
 426        BCM6362_MODE_FUN(robosw_led_clk),
 427        BCM6362_MODE_FUN(robosw_led0),
 428        BCM6362_MODE_FUN(robosw_led1),
 429        BCM6362_MODE_FUN(inet_led),
 430        BCM6362_MODE_FUN(spi_cs2),
 431        BCM6362_MODE_FUN(spi_cs3),
 432        BCM6362_MODE_FUN(ntr_pulse),
 433        BCM6362_MODE_FUN(uart1_scts),
 434        BCM6362_MODE_FUN(uart1_srts),
 435        BCM6362_MODE_FUN(uart1_sdin),
 436        BCM6362_MODE_FUN(uart1_sdout),
 437        BCM6362_MODE_FUN(adsl_spi_miso),
 438        BCM6362_MODE_FUN(adsl_spi_mosi),
 439        BCM6362_MODE_FUN(adsl_spi_clk),
 440        BCM6362_MODE_FUN(adsl_spi_cs),
 441        BCM6362_MODE_FUN(ephy0_led),
 442        BCM6362_MODE_FUN(ephy1_led),
 443        BCM6362_MODE_FUN(ephy2_led),
 444        BCM6362_MODE_FUN(ephy3_led),
 445        BCM6362_MODE_FUN(ext_irq0),
 446        BCM6362_MODE_FUN(ext_irq1),
 447        BCM6362_MODE_FUN(ext_irq2),
 448        BCM6362_MODE_FUN(ext_irq3),
 449        BCM6362_CTRL_FUN(wifi),
 450        BCM6362_BASEMODE_FUN(nand, BASEMODE_NAND),
 451};
 452
 453static int bcm6362_pinctrl_get_group_count(struct pinctrl_dev *pctldev)
 454{
 455        return ARRAY_SIZE(bcm6362_groups);
 456}
 457
 458static const char *bcm6362_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
 459                                                  unsigned group)
 460{
 461        return bcm6362_groups[group].name;
 462}
 463
 464static int bcm6362_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
 465                                          unsigned group, const unsigned **pins,
 466                                          unsigned *num_pins)
 467{
 468        *pins = bcm6362_groups[group].pins;
 469        *num_pins = bcm6362_groups[group].num_pins;
 470
 471        return 0;
 472}
 473
 474static int bcm6362_pinctrl_get_func_count(struct pinctrl_dev *pctldev)
 475{
 476        return ARRAY_SIZE(bcm6362_funcs);
 477}
 478
 479static const char *bcm6362_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
 480                                                 unsigned selector)
 481{
 482        return bcm6362_funcs[selector].name;
 483}
 484
 485static int bcm6362_pinctrl_get_groups(struct pinctrl_dev *pctldev,
 486                                      unsigned selector,
 487                                      const char * const **groups,
 488                                      unsigned * const num_groups)
 489{
 490        *groups = bcm6362_funcs[selector].groups;
 491        *num_groups = bcm6362_funcs[selector].num_groups;
 492
 493        return 0;
 494}
 495
 496static void bcm6362_set_gpio(struct bcm63xx_pinctrl *pc, unsigned pin)
 497{
 498        const struct pinctrl_pin_desc *desc = &bcm6362_pins[pin];
 499        unsigned int basemode = (uintptr_t)desc->drv_data;
 500        unsigned int mask = bcm63xx_bank_pin(pin);
 501
 502        if (basemode)
 503                regmap_update_bits(pc->regs, BCM6362_BASEMODE_REG, basemode, 0);
 504
 505        if (pin < BCM63XX_BANK_GPIOS) {
 506                /* base mode 0 => gpio 1 => mux function */
 507                regmap_update_bits(pc->regs, BCM6362_MODE_REG, mask, 0);
 508
 509                /* pins 0-23 might be muxed to led */
 510                if (pin < BCM6362_NUM_LEDS)
 511                        regmap_update_bits(pc->regs, BCM6362_LED_REG, mask, 0);
 512        } else {
 513                /* ctrl reg 0 => wifi function 1 => gpio */
 514                regmap_update_bits(pc->regs, BCM6362_CTRL_REG, mask, mask);
 515        }
 516}
 517
 518static int bcm6362_pinctrl_set_mux(struct pinctrl_dev *pctldev,
 519                                   unsigned selector, unsigned group)
 520{
 521        struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
 522        const struct bcm6362_pingroup *pg = &bcm6362_groups[group];
 523        const struct bcm6362_function *f = &bcm6362_funcs[selector];
 524        unsigned i;
 525        unsigned int reg;
 526        unsigned int val, mask;
 527
 528        for (i = 0; i < pg->num_pins; i++)
 529                bcm6362_set_gpio(pc, pg->pins[i]);
 530
 531        switch (f->reg) {
 532        case BCM6362_LEDCTRL:
 533                reg = BCM6362_LED_REG;
 534                mask = BIT(pg->pins[0]);
 535                val = BIT(pg->pins[0]);
 536                break;
 537        case BCM6362_MODE:
 538                reg = BCM6362_MODE_REG;
 539                mask = BIT(pg->pins[0]);
 540                val = BIT(pg->pins[0]);
 541                break;
 542        case BCM6362_CTRL:
 543                reg = BCM6362_CTRL_REG;
 544                mask = BIT(pg->pins[0]);
 545                val = 0;
 546                break;
 547        case BCM6362_BASEMODE:
 548                reg = BCM6362_BASEMODE_REG;
 549                mask = f->basemode_mask;
 550                val = f->basemode_mask;
 551                break;
 552        default:
 553                WARN_ON(1);
 554                return -EINVAL;
 555        }
 556
 557        regmap_update_bits(pc->regs, reg, mask, val);
 558
 559        return 0;
 560}
 561
 562static int bcm6362_gpio_request_enable(struct pinctrl_dev *pctldev,
 563                                       struct pinctrl_gpio_range *range,
 564                                       unsigned offset)
 565{
 566        struct bcm63xx_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
 567
 568        /* disable all functions using this pin */
 569        bcm6362_set_gpio(pc, offset);
 570
 571        return 0;
 572}
 573
 574static const struct pinctrl_ops bcm6362_pctl_ops = {
 575        .dt_free_map = pinctrl_utils_free_map,
 576        .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
 577        .get_group_name = bcm6362_pinctrl_get_group_name,
 578        .get_group_pins = bcm6362_pinctrl_get_group_pins,
 579        .get_groups_count = bcm6362_pinctrl_get_group_count,
 580};
 581
 582static const struct pinmux_ops bcm6362_pmx_ops = {
 583        .get_function_groups = bcm6362_pinctrl_get_groups,
 584        .get_function_name = bcm6362_pinctrl_get_func_name,
 585        .get_functions_count = bcm6362_pinctrl_get_func_count,
 586        .gpio_request_enable = bcm6362_gpio_request_enable,
 587        .set_mux = bcm6362_pinctrl_set_mux,
 588        .strict = true,
 589};
 590
 591static const struct bcm63xx_pinctrl_soc bcm6362_soc = {
 592        .ngpios = BCM6362_NUM_GPIOS,
 593        .npins = ARRAY_SIZE(bcm6362_pins),
 594        .pctl_ops = &bcm6362_pctl_ops,
 595        .pins = bcm6362_pins,
 596        .pmx_ops = &bcm6362_pmx_ops,
 597};
 598
 599static int bcm6362_pinctrl_probe(struct platform_device *pdev)
 600{
 601        return bcm63xx_pinctrl_probe(pdev, &bcm6362_soc, NULL);
 602}
 603
 604static const struct of_device_id bcm6362_pinctrl_match[] = {
 605        { .compatible = "brcm,bcm6362-pinctrl", },
 606        { /* sentinel */ }
 607};
 608
 609static struct platform_driver bcm6362_pinctrl_driver = {
 610        .probe = bcm6362_pinctrl_probe,
 611        .driver = {
 612                .name = "bcm6362-pinctrl",
 613                .of_match_table = bcm6362_pinctrl_match,
 614        },
 615};
 616
 617builtin_platform_driver(bcm6362_pinctrl_driver);
 618