.. | .. |
---|
| 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, |
---|