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

pinctrl: bcm2835: Add support for wake-up interrupts

Leverage the IRQCHIP_MASK_ON_SUSPEND flag in order to avoid having to
specifically treat the GPIO interrupts during suspend and resume, and
simply implement an irq_set_wake() callback that is responsible for
enabling the parent wake-up interrupt as a wake-up interrupt.

To avoid allocating unnecessary resources for other chips, the wake-up
interrupts are only initialized if we have a brcm,bcm7211-gpio
compatibility string.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Link: https://lore.kernel.org/r/20200531001101.24945-5-f.fainelli@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Florian Fainelli and committed by
Linus Walleij
920fecc1 562c856f

+75 -1
+75 -1
drivers/pinctrl/bcm/pinctrl-bcm2835.c
··· 19 19 #include <linux/irq.h> 20 20 #include <linux/irqdesc.h> 21 21 #include <linux/init.h> 22 + #include <linux/interrupt.h> 22 23 #include <linux/of_address.h> 23 24 #include <linux/of.h> 24 25 #include <linux/of_irq.h> ··· 77 76 struct bcm2835_pinctrl { 78 77 struct device *dev; 79 78 void __iomem *base; 79 + int *wake_irq; 80 80 81 81 /* note: locking assumes each bank will have its own unsigned long */ 82 82 unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; ··· 437 435 chained_irq_exit(host_chip, desc); 438 436 } 439 437 438 + static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id) 439 + { 440 + return IRQ_HANDLED; 441 + } 442 + 440 443 static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, 441 444 unsigned reg, unsigned offset, bool enable) 442 445 { ··· 641 634 bcm2835_gpio_set_bit(pc, GPEDS0, gpio); 642 635 } 643 636 637 + static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) 638 + { 639 + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); 640 + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); 641 + unsigned gpio = irqd_to_hwirq(data); 642 + unsigned int irqgroup; 643 + int ret = -EINVAL; 644 + 645 + if (!pc->wake_irq) 646 + return ret; 647 + 648 + if (gpio <= 27) 649 + irqgroup = 0; 650 + else if (gpio >= 28 && gpio <= 45) 651 + irqgroup = 1; 652 + else if (gpio >= 46 && gpio <= 57) 653 + irqgroup = 2; 654 + else 655 + return ret; 656 + 657 + if (on) 658 + ret = enable_irq_wake(pc->wake_irq[irqgroup]); 659 + else 660 + ret = disable_irq_wake(pc->wake_irq[irqgroup]); 661 + 662 + return ret; 663 + } 664 + 644 665 static struct irq_chip bcm2835_gpio_irq_chip = { 645 666 .name = MODULE_NAME, 646 667 .irq_enable = bcm2835_gpio_irq_enable, ··· 677 642 .irq_ack = bcm2835_gpio_irq_ack, 678 643 .irq_mask = bcm2835_gpio_irq_disable, 679 644 .irq_unmask = bcm2835_gpio_irq_enable, 645 + .irq_set_wake = bcm2835_gpio_irq_set_wake, 646 + .flags = IRQCHIP_MASK_ON_SUSPEND, 680 647 }; 681 648 682 649 static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) ··· 1191 1154 struct resource iomem; 1192 1155 int err, i; 1193 1156 const struct of_device_id *match; 1157 + int is_7211 = 0; 1194 1158 1195 1159 BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); 1196 1160 BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); ··· 1218 1180 return -EINVAL; 1219 1181 1220 1182 pdata = match->data; 1183 + is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio"); 1221 1184 1222 1185 pc->gpio_chip = *pdata->gpio_chip; 1223 1186 pc->gpio_chip.parent = dev; ··· 1253 1214 GFP_KERNEL); 1254 1215 if (!girq->parents) 1255 1216 return -ENOMEM; 1217 + 1218 + if (is_7211) { 1219 + pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, 1220 + sizeof(*pc->wake_irq), 1221 + GFP_KERNEL); 1222 + if (!pc->wake_irq) 1223 + return -ENOMEM; 1224 + } 1225 + 1256 1226 /* 1257 1227 * Use the same handler for all groups: this is necessary 1258 1228 * since we use one gpiochip to cover all lines - the ··· 1269 1221 * bank that was firing the IRQ and look up the per-group 1270 1222 * and bank data. 1271 1223 */ 1272 - for (i = 0; i < BCM2835_NUM_IRQS; i++) 1224 + for (i = 0; i < BCM2835_NUM_IRQS; i++) { 1225 + int len; 1226 + char *name; 1227 + 1273 1228 girq->parents[i] = irq_of_parse_and_map(np, i); 1229 + if (!is_7211) 1230 + continue; 1231 + 1232 + /* Skip over the all banks interrupts */ 1233 + pc->wake_irq[i] = irq_of_parse_and_map(np, i + 1234 + BCM2835_NUM_IRQS + 1); 1235 + 1236 + len = strlen(dev_name(pc->dev)) + 16; 1237 + name = devm_kzalloc(pc->dev, len, GFP_KERNEL); 1238 + if (!name) 1239 + return -ENOMEM; 1240 + 1241 + snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); 1242 + 1243 + /* These are optional interrupts */ 1244 + err = devm_request_irq(dev, pc->wake_irq[i], 1245 + bcm2835_gpio_wake_irq_handler, 1246 + IRQF_SHARED, name, pc); 1247 + if (err) 1248 + dev_warn(dev, "unable to request wake IRQ %d\n", 1249 + pc->wake_irq[i]); 1250 + } 1251 + 1274 1252 girq->default_type = IRQ_TYPE_NONE; 1275 1253 girq->handler = handle_level_irq; 1276 1254