Hi Florian, Am 29.05.20 um 21:15 schrieb Florian Fainelli: > 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@xxxxxxxxx> > --- > drivers/pinctrl/bcm/pinctrl-bcm2835.c | 76 ++++++++++++++++++++++++++- > 1 file changed, 75 insertions(+), 1 deletion(-) > > diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c > index 1b00d93aa66e..1fbf067a3eed 100644 > --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c > +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c > @@ -19,6 +19,7 @@ > #include <linux/irq.h> > #include <linux/irqdesc.h> > #include <linux/init.h> > +#include <linux/interrupt.h> > #include <linux/of_address.h> > #include <linux/of.h> > #include <linux/of_irq.h> > @@ -76,6 +77,7 @@ > struct bcm2835_pinctrl { > struct device *dev; > void __iomem *base; > + int *wake_irq; > > /* note: locking assumes each bank will have its own unsigned long */ > unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; > @@ -435,6 +437,11 @@ static void bcm2835_gpio_irq_handler(struct irq_desc *desc) > chained_irq_exit(host_chip, desc); > } > > +static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id) > +{ > + return IRQ_HANDLED; > +} > + > static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, > unsigned reg, unsigned offset, bool enable) > { > @@ -634,6 +641,34 @@ static void bcm2835_gpio_irq_ack(struct irq_data *data) > bcm2835_gpio_set_bit(pc, GPEDS0, gpio); > } > > +static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on) > +{ > + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); > + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); > + unsigned gpio = irqd_to_hwirq(data); > + unsigned int irqgroup; > + int ret = -EINVAL; > + > + if (!pc->wake_irq) > + return ret; > + > + if (gpio <= 27) > + irqgroup = 0; > + else if (gpio >= 28 && gpio <= 45) > + irqgroup = 1; > + else if (gpio >= 46 && gpio <= 53) > + irqgroup = 2; in case the BCM7211 has 58 GPIOs, but the wake up interrupts are only available for the first 54 this should deserve a comment. > + else > + return ret; > + > + if (on) > + ret = enable_irq_wake(pc->wake_irq[irqgroup]); > + else > + ret = disable_irq_wake(pc->wake_irq[irqgroup]); > + > + return ret; > +} > + > static struct irq_chip bcm2835_gpio_irq_chip = { > .name = MODULE_NAME, > .irq_enable = bcm2835_gpio_irq_enable, > @@ -642,6 +677,8 @@ static struct irq_chip bcm2835_gpio_irq_chip = { > .irq_ack = bcm2835_gpio_irq_ack, > .irq_mask = bcm2835_gpio_irq_disable, > .irq_unmask = bcm2835_gpio_irq_enable, > + .irq_set_wake = bcm2835_gpio_irq_set_wake, > + .flags = IRQCHIP_MASK_ON_SUSPEND, > }; > > static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev) > @@ -1154,6 +1191,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) > struct resource iomem; > int err, i; > const struct of_device_id *match; > + int is_7211 = 0; > > BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS); > BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS); > @@ -1180,6 +1218,7 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) > return -EINVAL; > > pdata = match->data; > + is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio"); > > pc->gpio_chip = *pdata->gpio_chip; > pc->gpio_chip.parent = dev; > @@ -1214,6 +1253,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) > GFP_KERNEL); > if (!girq->parents) > return -ENOMEM; > + > + if (is_7211) { > + pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS, > + sizeof(*pc->wake_irq), > + GFP_KERNEL); > + if (!pc->wake_irq) > + return -ENOMEM; > + } > + > /* > * Use the same handler for all groups: this is necessary > * since we use one gpiochip to cover all lines - the > @@ -1221,8 +1269,34 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) > * bank that was firing the IRQ and look up the per-group > * and bank data. > */ > - for (i = 0; i < BCM2835_NUM_IRQS; i++) > + for (i = 0; i < BCM2835_NUM_IRQS; i++) { > + int len; > + char *name; > + > girq->parents[i] = irq_of_parse_and_map(np, i); > + if (!is_7211) > + continue; > + > + /* Skip over the all banks interrupts */ > + pc->wake_irq[i] = irq_of_parse_and_map(np, i + > + BCM2835_NUM_IRQS + 1); > + > + len = strlen(dev_name(pc->dev)) + 16; > + name = devm_kzalloc(pc->dev, len, GFP_KERNEL); > + if (!name) > + return -ENOMEM; > + > + snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); > + > + /* These are optional interrupts */ > + err = devm_request_irq(dev, pc->wake_irq[i], > + bcm2835_gpio_wake_irq_handler, > + IRQF_SHARED, name, pc); > + if (err) > + dev_warn(dev, "unable to request wake IRQ %d\n", > + pc->wake_irq[i]); > + } > + > girq->default_type = IRQ_TYPE_NONE; > girq->handler = handle_level_irq; >