| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO) |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * This driver is inspired by: |
|---|
| 7 | 8 | * pinctrl-nomadik.c, please see original file for copyright information |
|---|
| 8 | 9 | * pinctrl-tegra.c, please see original file for copyright information |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - * (at your option) any later version. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | 10 | */ |
|---|
| 20 | 11 | |
|---|
| 21 | 12 | #include <linux/bitmap.h> |
|---|
| .. | .. |
|---|
| 28 | 19 | #include <linux/irq.h> |
|---|
| 29 | 20 | #include <linux/irqdesc.h> |
|---|
| 30 | 21 | #include <linux/init.h> |
|---|
| 22 | +#include <linux/interrupt.h> |
|---|
| 31 | 23 | #include <linux/of_address.h> |
|---|
| 32 | 24 | #include <linux/of.h> |
|---|
| 33 | 25 | #include <linux/of_irq.h> |
|---|
| .. | .. |
|---|
| 46 | 38 | |
|---|
| 47 | 39 | #define MODULE_NAME "pinctrl-bcm2835" |
|---|
| 48 | 40 | #define BCM2835_NUM_GPIOS 54 |
|---|
| 41 | +#define BCM2711_NUM_GPIOS 58 |
|---|
| 49 | 42 | #define BCM2835_NUM_BANKS 2 |
|---|
| 50 | 43 | #define BCM2835_NUM_IRQS 3 |
|---|
| 51 | | - |
|---|
| 52 | | -#define BCM2835_PIN_BITMAP_SZ \ |
|---|
| 53 | | - DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) |
|---|
| 54 | 44 | |
|---|
| 55 | 45 | /* GPIO register offsets */ |
|---|
| 56 | 46 | #define GPFSEL0 0x0 /* Function Select */ |
|---|
| .. | .. |
|---|
| 66 | 56 | #define GPAFEN0 0x88 /* Pin Async Falling Edge Detect */ |
|---|
| 67 | 57 | #define GPPUD 0x94 /* Pin Pull-up/down Enable */ |
|---|
| 68 | 58 | #define GPPUDCLK0 0x98 /* Pin Pull-up/down Enable Clock */ |
|---|
| 59 | +#define GP_GPIO_PUP_PDN_CNTRL_REG0 0xe4 /* 2711 Pin Pull-up/down select */ |
|---|
| 69 | 60 | |
|---|
| 70 | 61 | #define FSEL_REG(p) (GPFSEL0 + (((p) / 10) * 4)) |
|---|
| 71 | 62 | #define FSEL_SHIFT(p) (((p) % 10) * 3) |
|---|
| 72 | 63 | #define GPIO_REG_OFFSET(p) ((p) / 32) |
|---|
| 73 | 64 | #define GPIO_REG_SHIFT(p) ((p) % 32) |
|---|
| 74 | 65 | |
|---|
| 66 | +#define PUD_2711_MASK 0x3 |
|---|
| 67 | +#define PUD_2711_REG_OFFSET(p) ((p) / 16) |
|---|
| 68 | +#define PUD_2711_REG_SHIFT(p) (((p) % 16) * 2) |
|---|
| 69 | + |
|---|
| 75 | 70 | /* argument: bcm2835_pinconf_pull */ |
|---|
| 76 | 71 | #define BCM2835_PINCONF_PARAM_PULL (PIN_CONFIG_END + 1) |
|---|
| 72 | + |
|---|
| 73 | +#define BCM2711_PULL_NONE 0x0 |
|---|
| 74 | +#define BCM2711_PULL_UP 0x1 |
|---|
| 75 | +#define BCM2711_PULL_DOWN 0x2 |
|---|
| 77 | 76 | |
|---|
| 78 | 77 | struct bcm2835_pinctrl { |
|---|
| 79 | 78 | struct device *dev; |
|---|
| 80 | 79 | void __iomem *base; |
|---|
| 81 | | - int irq[BCM2835_NUM_IRQS]; |
|---|
| 80 | + int *wake_irq; |
|---|
| 82 | 81 | |
|---|
| 83 | 82 | /* note: locking assumes each bank will have its own unsigned long */ |
|---|
| 84 | 83 | unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; |
|---|
| 85 | | - unsigned int irq_type[BCM2835_NUM_GPIOS]; |
|---|
| 84 | + unsigned int irq_type[BCM2711_NUM_GPIOS]; |
|---|
| 86 | 85 | |
|---|
| 87 | 86 | struct pinctrl_dev *pctl_dev; |
|---|
| 88 | 87 | struct gpio_chip gpio_chip; |
|---|
| 88 | + struct pinctrl_desc pctl_desc; |
|---|
| 89 | 89 | struct pinctrl_gpio_range gpio_range; |
|---|
| 90 | 90 | |
|---|
| 91 | 91 | raw_spinlock_t irq_lock[BCM2835_NUM_BANKS]; |
|---|
| .. | .. |
|---|
| 148 | 148 | BCM2835_GPIO_PIN(51), |
|---|
| 149 | 149 | BCM2835_GPIO_PIN(52), |
|---|
| 150 | 150 | BCM2835_GPIO_PIN(53), |
|---|
| 151 | + BCM2835_GPIO_PIN(54), |
|---|
| 152 | + BCM2835_GPIO_PIN(55), |
|---|
| 153 | + BCM2835_GPIO_PIN(56), |
|---|
| 154 | + BCM2835_GPIO_PIN(57), |
|---|
| 151 | 155 | }; |
|---|
| 152 | 156 | |
|---|
| 153 | 157 | /* one pin per group */ |
|---|
| .. | .. |
|---|
| 206 | 210 | "gpio51", |
|---|
| 207 | 211 | "gpio52", |
|---|
| 208 | 212 | "gpio53", |
|---|
| 213 | + "gpio54", |
|---|
| 214 | + "gpio55", |
|---|
| 215 | + "gpio56", |
|---|
| 216 | + "gpio57", |
|---|
| 209 | 217 | }; |
|---|
| 210 | 218 | |
|---|
| 211 | 219 | enum bcm2835_fsel { |
|---|
| .. | .. |
|---|
| 323 | 331 | if (fsel > BCM2835_FSEL_GPIO_OUT) |
|---|
| 324 | 332 | return -EINVAL; |
|---|
| 325 | 333 | |
|---|
| 326 | | - return (fsel == BCM2835_FSEL_GPIO_IN); |
|---|
| 334 | + if (fsel == BCM2835_FSEL_GPIO_IN) |
|---|
| 335 | + return GPIO_LINE_DIRECTION_IN; |
|---|
| 336 | + |
|---|
| 337 | + return GPIO_LINE_DIRECTION_OUT; |
|---|
| 327 | 338 | } |
|---|
| 328 | 339 | |
|---|
| 329 | 340 | static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
|---|
| .. | .. |
|---|
| 350 | 361 | .get_direction = bcm2835_gpio_get_direction, |
|---|
| 351 | 362 | .get = bcm2835_gpio_get, |
|---|
| 352 | 363 | .set = bcm2835_gpio_set, |
|---|
| 364 | + .set_config = gpiochip_generic_config, |
|---|
| 353 | 365 | .base = -1, |
|---|
| 354 | 366 | .ngpio = BCM2835_NUM_GPIOS, |
|---|
| 367 | + .can_sleep = false, |
|---|
| 368 | +}; |
|---|
| 369 | + |
|---|
| 370 | +static const struct gpio_chip bcm2711_gpio_chip = { |
|---|
| 371 | + .label = "pinctrl-bcm2711", |
|---|
| 372 | + .owner = THIS_MODULE, |
|---|
| 373 | + .request = gpiochip_generic_request, |
|---|
| 374 | + .free = gpiochip_generic_free, |
|---|
| 375 | + .direction_input = bcm2835_gpio_direction_input, |
|---|
| 376 | + .direction_output = bcm2835_gpio_direction_output, |
|---|
| 377 | + .get_direction = bcm2835_gpio_get_direction, |
|---|
| 378 | + .get = bcm2835_gpio_get, |
|---|
| 379 | + .set = bcm2835_gpio_set, |
|---|
| 380 | + .set_config = gpiochip_generic_config, |
|---|
| 381 | + .base = -1, |
|---|
| 382 | + .ngpio = BCM2711_NUM_GPIOS, |
|---|
| 355 | 383 | .can_sleep = false, |
|---|
| 356 | 384 | }; |
|---|
| 357 | 385 | |
|---|
| .. | .. |
|---|
| 381 | 409 | int group; |
|---|
| 382 | 410 | int i; |
|---|
| 383 | 411 | |
|---|
| 384 | | - for (i = 0; i < ARRAY_SIZE(pc->irq); i++) { |
|---|
| 385 | | - if (pc->irq[i] == irq) { |
|---|
| 412 | + for (i = 0; i < BCM2835_NUM_IRQS; i++) { |
|---|
| 413 | + if (chip->irq.parents[i] == irq) { |
|---|
| 386 | 414 | group = i; |
|---|
| 387 | 415 | break; |
|---|
| 388 | 416 | } |
|---|
| 389 | 417 | } |
|---|
| 390 | 418 | /* This should not happen, every IRQ has a bank */ |
|---|
| 391 | | - if (i == ARRAY_SIZE(pc->irq)) |
|---|
| 419 | + if (i == BCM2835_NUM_IRQS) |
|---|
| 392 | 420 | BUG(); |
|---|
| 393 | 421 | |
|---|
| 394 | 422 | chained_irq_enter(host_chip, desc); |
|---|
| .. | .. |
|---|
| 401 | 429 | bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); |
|---|
| 402 | 430 | bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); |
|---|
| 403 | 431 | break; |
|---|
| 404 | | - case 2: /* IRQ2 covers GPIOs 46-53 */ |
|---|
| 432 | + case 2: /* IRQ2 covers GPIOs 46-57 */ |
|---|
| 405 | 433 | bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); |
|---|
| 406 | 434 | break; |
|---|
| 407 | 435 | } |
|---|
| 408 | 436 | |
|---|
| 409 | 437 | chained_irq_exit(host_chip, desc); |
|---|
| 438 | +} |
|---|
| 439 | + |
|---|
| 440 | +static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id) |
|---|
| 441 | +{ |
|---|
| 442 | + return IRQ_HANDLED; |
|---|
| 410 | 443 | } |
|---|
| 411 | 444 | |
|---|
| 412 | 445 | static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, |
|---|
| .. | .. |
|---|
| 608 | 641 | bcm2835_gpio_set_bit(pc, GPEDS0, gpio); |
|---|
| 609 | 642 | } |
|---|
| 610 | 643 | |
|---|
| 644 | +static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) |
|---|
| 645 | +{ |
|---|
| 646 | + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); |
|---|
| 647 | + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); |
|---|
| 648 | + unsigned gpio = irqd_to_hwirq(data); |
|---|
| 649 | + unsigned int irqgroup; |
|---|
| 650 | + int ret = -EINVAL; |
|---|
| 651 | + |
|---|
| 652 | + if (!pc->wake_irq) |
|---|
| 653 | + return ret; |
|---|
| 654 | + |
|---|
| 655 | + if (gpio <= 27) |
|---|
| 656 | + irqgroup = 0; |
|---|
| 657 | + else if (gpio >= 28 && gpio <= 45) |
|---|
| 658 | + irqgroup = 1; |
|---|
| 659 | + else if (gpio >= 46 && gpio <= 57) |
|---|
| 660 | + irqgroup = 2; |
|---|
| 661 | + else |
|---|
| 662 | + return ret; |
|---|
| 663 | + |
|---|
| 664 | + if (on) |
|---|
| 665 | + ret = enable_irq_wake(pc->wake_irq[irqgroup]); |
|---|
| 666 | + else |
|---|
| 667 | + ret = disable_irq_wake(pc->wake_irq[irqgroup]); |
|---|
| 668 | + |
|---|
| 669 | + return ret; |
|---|
| 670 | +} |
|---|
| 671 | + |
|---|
| 611 | 672 | static struct irq_chip bcm2835_gpio_irq_chip = { |
|---|
| 612 | 673 | .name = MODULE_NAME, |
|---|
| 613 | 674 | .irq_enable = bcm2835_gpio_irq_enable, |
|---|
| .. | .. |
|---|
| 616 | 677 | .irq_ack = bcm2835_gpio_irq_ack, |
|---|
| 617 | 678 | .irq_mask = bcm2835_gpio_irq_disable, |
|---|
| 618 | 679 | .irq_unmask = bcm2835_gpio_irq_enable, |
|---|
| 680 | + .irq_set_wake = bcm2835_gpio_irq_set_wake, |
|---|
| 681 | + .flags = IRQCHIP_MASK_ON_SUSPEND, |
|---|
| 619 | 682 | }; |
|---|
| 620 | 683 | |
|---|
| 621 | 684 | static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) |
|---|
| 622 | 685 | { |
|---|
| 623 | | - return ARRAY_SIZE(bcm2835_gpio_groups); |
|---|
| 686 | + return BCM2835_NUM_GPIOS; |
|---|
| 624 | 687 | } |
|---|
| 625 | 688 | |
|---|
| 626 | 689 | static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev, |
|---|
| .. | .. |
|---|
| 778 | 841 | err = of_property_read_u32_index(np, "brcm,pins", i, &pin); |
|---|
| 779 | 842 | if (err) |
|---|
| 780 | 843 | goto out; |
|---|
| 781 | | - if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { |
|---|
| 844 | + if (pin >= pc->pctl_desc.npins) { |
|---|
| 782 | 845 | dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n", |
|---|
| 783 | 846 | np, pin); |
|---|
| 784 | 847 | err = -EINVAL; |
|---|
| .. | .. |
|---|
| 854 | 917 | { |
|---|
| 855 | 918 | /* every pin can do every function */ |
|---|
| 856 | 919 | *groups = bcm2835_gpio_groups; |
|---|
| 857 | | - *num_groups = ARRAY_SIZE(bcm2835_gpio_groups); |
|---|
| 920 | + *num_groups = BCM2835_NUM_GPIOS; |
|---|
| 858 | 921 | |
|---|
| 859 | 922 | return 0; |
|---|
| 860 | 923 | } |
|---|
| .. | .. |
|---|
| 969 | 1032 | break; |
|---|
| 970 | 1033 | |
|---|
| 971 | 1034 | default: |
|---|
| 972 | | - return -EINVAL; |
|---|
| 1035 | + return -ENOTSUPP; |
|---|
| 973 | 1036 | |
|---|
| 974 | 1037 | } /* switch param type */ |
|---|
| 975 | 1038 | } /* for each config */ |
|---|
| .. | .. |
|---|
| 978 | 1041 | } |
|---|
| 979 | 1042 | |
|---|
| 980 | 1043 | static const struct pinconf_ops bcm2835_pinconf_ops = { |
|---|
| 1044 | + .is_generic = true, |
|---|
| 981 | 1045 | .pin_config_get = bcm2835_pinconf_get, |
|---|
| 982 | 1046 | .pin_config_set = bcm2835_pinconf_set, |
|---|
| 983 | 1047 | }; |
|---|
| 984 | 1048 | |
|---|
| 985 | | -static struct pinctrl_desc bcm2835_pinctrl_desc = { |
|---|
| 1049 | +static void bcm2711_pull_config_set(struct bcm2835_pinctrl *pc, |
|---|
| 1050 | + unsigned int pin, unsigned int arg) |
|---|
| 1051 | +{ |
|---|
| 1052 | + u32 shifter; |
|---|
| 1053 | + u32 value; |
|---|
| 1054 | + u32 off; |
|---|
| 1055 | + |
|---|
| 1056 | + off = PUD_2711_REG_OFFSET(pin); |
|---|
| 1057 | + shifter = PUD_2711_REG_SHIFT(pin); |
|---|
| 1058 | + |
|---|
| 1059 | + value = bcm2835_gpio_rd(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4)); |
|---|
| 1060 | + value &= ~(PUD_2711_MASK << shifter); |
|---|
| 1061 | + value |= (arg << shifter); |
|---|
| 1062 | + bcm2835_gpio_wr(pc, GP_GPIO_PUP_PDN_CNTRL_REG0 + (off * 4), value); |
|---|
| 1063 | +} |
|---|
| 1064 | + |
|---|
| 1065 | +static int bcm2711_pinconf_set(struct pinctrl_dev *pctldev, |
|---|
| 1066 | + unsigned int pin, unsigned long *configs, |
|---|
| 1067 | + unsigned int num_configs) |
|---|
| 1068 | +{ |
|---|
| 1069 | + struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); |
|---|
| 1070 | + u32 param, arg; |
|---|
| 1071 | + int i; |
|---|
| 1072 | + |
|---|
| 1073 | + for (i = 0; i < num_configs; i++) { |
|---|
| 1074 | + param = pinconf_to_config_param(configs[i]); |
|---|
| 1075 | + arg = pinconf_to_config_argument(configs[i]); |
|---|
| 1076 | + |
|---|
| 1077 | + switch (param) { |
|---|
| 1078 | + /* convert legacy brcm,pull */ |
|---|
| 1079 | + case BCM2835_PINCONF_PARAM_PULL: |
|---|
| 1080 | + if (arg == BCM2835_PUD_UP) |
|---|
| 1081 | + arg = BCM2711_PULL_UP; |
|---|
| 1082 | + else if (arg == BCM2835_PUD_DOWN) |
|---|
| 1083 | + arg = BCM2711_PULL_DOWN; |
|---|
| 1084 | + else |
|---|
| 1085 | + arg = BCM2711_PULL_NONE; |
|---|
| 1086 | + |
|---|
| 1087 | + bcm2711_pull_config_set(pc, pin, arg); |
|---|
| 1088 | + break; |
|---|
| 1089 | + |
|---|
| 1090 | + /* Set pull generic bindings */ |
|---|
| 1091 | + case PIN_CONFIG_BIAS_DISABLE: |
|---|
| 1092 | + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_NONE); |
|---|
| 1093 | + break; |
|---|
| 1094 | + case PIN_CONFIG_BIAS_PULL_DOWN: |
|---|
| 1095 | + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_DOWN); |
|---|
| 1096 | + break; |
|---|
| 1097 | + case PIN_CONFIG_BIAS_PULL_UP: |
|---|
| 1098 | + bcm2711_pull_config_set(pc, pin, BCM2711_PULL_UP); |
|---|
| 1099 | + break; |
|---|
| 1100 | + |
|---|
| 1101 | + /* Set output-high or output-low */ |
|---|
| 1102 | + case PIN_CONFIG_OUTPUT: |
|---|
| 1103 | + bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin); |
|---|
| 1104 | + break; |
|---|
| 1105 | + |
|---|
| 1106 | + default: |
|---|
| 1107 | + return -ENOTSUPP; |
|---|
| 1108 | + } |
|---|
| 1109 | + } /* for each config */ |
|---|
| 1110 | + |
|---|
| 1111 | + return 0; |
|---|
| 1112 | +} |
|---|
| 1113 | + |
|---|
| 1114 | +static const struct pinconf_ops bcm2711_pinconf_ops = { |
|---|
| 1115 | + .is_generic = true, |
|---|
| 1116 | + .pin_config_get = bcm2835_pinconf_get, |
|---|
| 1117 | + .pin_config_set = bcm2711_pinconf_set, |
|---|
| 1118 | +}; |
|---|
| 1119 | + |
|---|
| 1120 | +static const struct pinctrl_desc bcm2835_pinctrl_desc = { |
|---|
| 986 | 1121 | .name = MODULE_NAME, |
|---|
| 987 | 1122 | .pins = bcm2835_gpio_pins, |
|---|
| 988 | | - .npins = ARRAY_SIZE(bcm2835_gpio_pins), |
|---|
| 1123 | + .npins = BCM2835_NUM_GPIOS, |
|---|
| 989 | 1124 | .pctlops = &bcm2835_pctl_ops, |
|---|
| 990 | 1125 | .pmxops = &bcm2835_pmx_ops, |
|---|
| 991 | 1126 | .confops = &bcm2835_pinconf_ops, |
|---|
| 992 | 1127 | .owner = THIS_MODULE, |
|---|
| 993 | 1128 | }; |
|---|
| 994 | 1129 | |
|---|
| 995 | | -static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { |
|---|
| 1130 | +static const struct pinctrl_desc bcm2711_pinctrl_desc = { |
|---|
| 1131 | + .name = "pinctrl-bcm2711", |
|---|
| 1132 | + .pins = bcm2835_gpio_pins, |
|---|
| 1133 | + .npins = BCM2711_NUM_GPIOS, |
|---|
| 1134 | + .pctlops = &bcm2835_pctl_ops, |
|---|
| 1135 | + .pmxops = &bcm2835_pmx_ops, |
|---|
| 1136 | + .confops = &bcm2711_pinconf_ops, |
|---|
| 1137 | + .owner = THIS_MODULE, |
|---|
| 1138 | +}; |
|---|
| 1139 | + |
|---|
| 1140 | +static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = { |
|---|
| 996 | 1141 | .name = MODULE_NAME, |
|---|
| 997 | 1142 | .npins = BCM2835_NUM_GPIOS, |
|---|
| 1143 | +}; |
|---|
| 1144 | + |
|---|
| 1145 | +static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = { |
|---|
| 1146 | + .name = "pinctrl-bcm2711", |
|---|
| 1147 | + .npins = BCM2711_NUM_GPIOS, |
|---|
| 1148 | +}; |
|---|
| 1149 | + |
|---|
| 1150 | +struct bcm_plat_data { |
|---|
| 1151 | + const struct gpio_chip *gpio_chip; |
|---|
| 1152 | + const struct pinctrl_desc *pctl_desc; |
|---|
| 1153 | + const struct pinctrl_gpio_range *gpio_range; |
|---|
| 1154 | +}; |
|---|
| 1155 | + |
|---|
| 1156 | +static const struct bcm_plat_data bcm2835_plat_data = { |
|---|
| 1157 | + .gpio_chip = &bcm2835_gpio_chip, |
|---|
| 1158 | + .pctl_desc = &bcm2835_pinctrl_desc, |
|---|
| 1159 | + .gpio_range = &bcm2835_pinctrl_gpio_range, |
|---|
| 1160 | +}; |
|---|
| 1161 | + |
|---|
| 1162 | +static const struct bcm_plat_data bcm2711_plat_data = { |
|---|
| 1163 | + .gpio_chip = &bcm2711_gpio_chip, |
|---|
| 1164 | + .pctl_desc = &bcm2711_pinctrl_desc, |
|---|
| 1165 | + .gpio_range = &bcm2711_pinctrl_gpio_range, |
|---|
| 1166 | +}; |
|---|
| 1167 | + |
|---|
| 1168 | +static const struct of_device_id bcm2835_pinctrl_match[] = { |
|---|
| 1169 | + { |
|---|
| 1170 | + .compatible = "brcm,bcm2835-gpio", |
|---|
| 1171 | + .data = &bcm2835_plat_data, |
|---|
| 1172 | + }, |
|---|
| 1173 | + { |
|---|
| 1174 | + .compatible = "brcm,bcm2711-gpio", |
|---|
| 1175 | + .data = &bcm2711_plat_data, |
|---|
| 1176 | + }, |
|---|
| 1177 | + { |
|---|
| 1178 | + .compatible = "brcm,bcm7211-gpio", |
|---|
| 1179 | + .data = &bcm2711_plat_data, |
|---|
| 1180 | + }, |
|---|
| 1181 | + {} |
|---|
| 998 | 1182 | }; |
|---|
| 999 | 1183 | |
|---|
| 1000 | 1184 | static int bcm2835_pinctrl_probe(struct platform_device *pdev) |
|---|
| 1001 | 1185 | { |
|---|
| 1002 | 1186 | struct device *dev = &pdev->dev; |
|---|
| 1003 | 1187 | struct device_node *np = dev->of_node; |
|---|
| 1188 | + const struct bcm_plat_data *pdata; |
|---|
| 1004 | 1189 | struct bcm2835_pinctrl *pc; |
|---|
| 1190 | + struct gpio_irq_chip *girq; |
|---|
| 1005 | 1191 | struct resource iomem; |
|---|
| 1006 | 1192 | int err, i; |
|---|
| 1007 | | - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS); |
|---|
| 1008 | | - BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS); |
|---|
| 1193 | + const struct of_device_id *match; |
|---|
| 1194 | + int is_7211 = 0; |
|---|
| 1195 | + |
|---|
| 1196 | + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); |
|---|
| 1197 | + BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); |
|---|
| 1009 | 1198 | |
|---|
| 1010 | 1199 | pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL); |
|---|
| 1011 | 1200 | if (!pc) |
|---|
| .. | .. |
|---|
| 1024 | 1213 | if (IS_ERR(pc->base)) |
|---|
| 1025 | 1214 | return PTR_ERR(pc->base); |
|---|
| 1026 | 1215 | |
|---|
| 1027 | | - pc->gpio_chip = bcm2835_gpio_chip; |
|---|
| 1216 | + match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node); |
|---|
| 1217 | + if (!match) |
|---|
| 1218 | + return -EINVAL; |
|---|
| 1219 | + |
|---|
| 1220 | + pdata = match->data; |
|---|
| 1221 | + is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio"); |
|---|
| 1222 | + |
|---|
| 1223 | + pc->gpio_chip = *pdata->gpio_chip; |
|---|
| 1028 | 1224 | pc->gpio_chip.parent = dev; |
|---|
| 1029 | 1225 | pc->gpio_chip.of_node = np; |
|---|
| 1030 | 1226 | |
|---|
| .. | .. |
|---|
| 1048 | 1244 | raw_spin_lock_init(&pc->irq_lock[i]); |
|---|
| 1049 | 1245 | } |
|---|
| 1050 | 1246 | |
|---|
| 1051 | | - err = gpiochip_add_data(&pc->gpio_chip, pc); |
|---|
| 1052 | | - if (err) { |
|---|
| 1053 | | - dev_err(dev, "could not add GPIO chip\n"); |
|---|
| 1054 | | - return err; |
|---|
| 1055 | | - } |
|---|
| 1056 | | - |
|---|
| 1057 | | - err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip, |
|---|
| 1058 | | - 0, handle_level_irq, IRQ_TYPE_NONE); |
|---|
| 1059 | | - if (err) { |
|---|
| 1060 | | - dev_info(dev, "could not add irqchip\n"); |
|---|
| 1061 | | - return err; |
|---|
| 1062 | | - } |
|---|
| 1063 | | - |
|---|
| 1064 | | - for (i = 0; i < BCM2835_NUM_IRQS; i++) { |
|---|
| 1065 | | - pc->irq[i] = irq_of_parse_and_map(np, i); |
|---|
| 1066 | | - |
|---|
| 1067 | | - if (pc->irq[i] == 0) |
|---|
| 1068 | | - continue; |
|---|
| 1069 | | - |
|---|
| 1070 | | - /* |
|---|
| 1071 | | - * Use the same handler for all groups: this is necessary |
|---|
| 1072 | | - * since we use one gpiochip to cover all lines - the |
|---|
| 1073 | | - * irq handler then needs to figure out which group and |
|---|
| 1074 | | - * bank that was firing the IRQ and look up the per-group |
|---|
| 1075 | | - * and bank data. |
|---|
| 1076 | | - */ |
|---|
| 1077 | | - gpiochip_set_chained_irqchip(&pc->gpio_chip, |
|---|
| 1078 | | - &bcm2835_gpio_irq_chip, |
|---|
| 1079 | | - pc->irq[i], |
|---|
| 1080 | | - bcm2835_gpio_irq_handler); |
|---|
| 1081 | | - } |
|---|
| 1082 | | - |
|---|
| 1083 | | - pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); |
|---|
| 1247 | + pc->pctl_desc = *pdata->pctl_desc; |
|---|
| 1248 | + pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc); |
|---|
| 1084 | 1249 | if (IS_ERR(pc->pctl_dev)) { |
|---|
| 1085 | 1250 | gpiochip_remove(&pc->gpio_chip); |
|---|
| 1086 | 1251 | return PTR_ERR(pc->pctl_dev); |
|---|
| 1087 | 1252 | } |
|---|
| 1088 | 1253 | |
|---|
| 1089 | | - pc->gpio_range = bcm2835_pinctrl_gpio_range; |
|---|
| 1254 | + pc->gpio_range = *pdata->gpio_range; |
|---|
| 1090 | 1255 | pc->gpio_range.base = pc->gpio_chip.base; |
|---|
| 1091 | 1256 | pc->gpio_range.gc = &pc->gpio_chip; |
|---|
| 1092 | 1257 | pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range); |
|---|
| 1093 | 1258 | |
|---|
| 1094 | | - return 0; |
|---|
| 1095 | | -} |
|---|
| 1259 | + girq = &pc->gpio_chip.irq; |
|---|
| 1260 | + girq->chip = &bcm2835_gpio_irq_chip; |
|---|
| 1261 | + girq->parent_handler = bcm2835_gpio_irq_handler; |
|---|
| 1262 | + girq->num_parents = BCM2835_NUM_IRQS; |
|---|
| 1263 | + girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS, |
|---|
| 1264 | + sizeof(*girq->parents), |
|---|
| 1265 | + GFP_KERNEL); |
|---|
| 1266 | + if (!girq->parents) { |
|---|
| 1267 | + err = -ENOMEM; |
|---|
| 1268 | + goto out_remove; |
|---|
| 1269 | + } |
|---|
| 1096 | 1270 | |
|---|
| 1097 | | -static const struct of_device_id bcm2835_pinctrl_match[] = { |
|---|
| 1098 | | - { .compatible = "brcm,bcm2835-gpio" }, |
|---|
| 1099 | | - {} |
|---|
| 1100 | | -}; |
|---|
| 1271 | + if (is_7211) { |
|---|
| 1272 | + pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, |
|---|
| 1273 | + sizeof(*pc->wake_irq), |
|---|
| 1274 | + GFP_KERNEL); |
|---|
| 1275 | + if (!pc->wake_irq) { |
|---|
| 1276 | + err = -ENOMEM; |
|---|
| 1277 | + goto out_remove; |
|---|
| 1278 | + } |
|---|
| 1279 | + } |
|---|
| 1280 | + |
|---|
| 1281 | + /* |
|---|
| 1282 | + * Use the same handler for all groups: this is necessary |
|---|
| 1283 | + * since we use one gpiochip to cover all lines - the |
|---|
| 1284 | + * irq handler then needs to figure out which group and |
|---|
| 1285 | + * bank that was firing the IRQ and look up the per-group |
|---|
| 1286 | + * and bank data. |
|---|
| 1287 | + */ |
|---|
| 1288 | + for (i = 0; i < BCM2835_NUM_IRQS; i++) { |
|---|
| 1289 | + int len; |
|---|
| 1290 | + char *name; |
|---|
| 1291 | + |
|---|
| 1292 | + girq->parents[i] = irq_of_parse_and_map(np, i); |
|---|
| 1293 | + if (!is_7211) |
|---|
| 1294 | + continue; |
|---|
| 1295 | + |
|---|
| 1296 | + /* Skip over the all banks interrupts */ |
|---|
| 1297 | + pc->wake_irq[i] = irq_of_parse_and_map(np, i + |
|---|
| 1298 | + BCM2835_NUM_IRQS + 1); |
|---|
| 1299 | + |
|---|
| 1300 | + len = strlen(dev_name(pc->dev)) + 16; |
|---|
| 1301 | + name = devm_kzalloc(pc->dev, len, GFP_KERNEL); |
|---|
| 1302 | + if (!name) { |
|---|
| 1303 | + err = -ENOMEM; |
|---|
| 1304 | + goto out_remove; |
|---|
| 1305 | + } |
|---|
| 1306 | + |
|---|
| 1307 | + snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); |
|---|
| 1308 | + |
|---|
| 1309 | + /* These are optional interrupts */ |
|---|
| 1310 | + err = devm_request_irq(dev, pc->wake_irq[i], |
|---|
| 1311 | + bcm2835_gpio_wake_irq_handler, |
|---|
| 1312 | + IRQF_SHARED, name, pc); |
|---|
| 1313 | + if (err) |
|---|
| 1314 | + dev_warn(dev, "unable to request wake IRQ %d\n", |
|---|
| 1315 | + pc->wake_irq[i]); |
|---|
| 1316 | + } |
|---|
| 1317 | + |
|---|
| 1318 | + girq->default_type = IRQ_TYPE_NONE; |
|---|
| 1319 | + girq->handler = handle_level_irq; |
|---|
| 1320 | + |
|---|
| 1321 | + err = gpiochip_add_data(&pc->gpio_chip, pc); |
|---|
| 1322 | + if (err) { |
|---|
| 1323 | + dev_err(dev, "could not add GPIO chip\n"); |
|---|
| 1324 | + goto out_remove; |
|---|
| 1325 | + } |
|---|
| 1326 | + |
|---|
| 1327 | + return 0; |
|---|
| 1328 | + |
|---|
| 1329 | +out_remove: |
|---|
| 1330 | + pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range); |
|---|
| 1331 | + return err; |
|---|
| 1332 | +} |
|---|
| 1101 | 1333 | |
|---|
| 1102 | 1334 | static struct platform_driver bcm2835_pinctrl_driver = { |
|---|
| 1103 | 1335 | .probe = bcm2835_pinctrl_probe, |
|---|