Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1742484 > unrolled thread
| Started by | Doug Berger <opendmb@gmail.com> |
|---|---|
| First post | 2017-09-30 05:50 +0200 |
| Last post | 2017-09-30 07:40 +0200 |
| Articles | 7 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/7] gpio: brcmstb: improved interrupt and wake support Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
[PATCH 4/7] gpio: brcmstb: correct the configuration of level interrupts Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
[PATCH 5/7] gpio: brcmstb: enable masking of interrupts when changing type Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
[PATCH 1/7] gpio: brcmstb: allow all instances to be wakeup sources Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
[PATCH 3/7] gpio: brcmstb: switch to handle_level_irq flow Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
[PATCH 2/7] gpio: brcmstb: release the bgpio lock during irq handlers Doug Berger <opendmb@gmail.com> - 2017-09-30 05:50 +0200
Re: [PATCH 0/7] gpio: brcmstb: improved interrupt and wake support Florian Fainelli <f.fainelli@gmail.com> - 2017-09-30 07:40 +0200
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 0/7] gpio: brcmstb: improved interrupt and wake support |
| Message-ID | <uvgWR-78I-3@gated-at.bofh.it> |
This patch set collects a number of improvements to the GPIO driver used by Broadcom Set-Top-Box devices. Primarily they are aimed at correcting problems with the interrupt controller implementation, but they also extend the functionality for waking on GPIO interrupts. Doug Berger (7): gpio: brcmstb: allow all instances to be wakeup sources gpio: brcmstb: release the bgpio lock during irq handlers gpio: brcmstb: switch to handle_level_irq flow gpio: brcmstb: correct the configuration of level interrupts gpio: brcmstb: enable masking of interrupts when changing type gpio: brcmstb: consolidate interrupt domains gpio: brcmstb: implement suspend/resume/shutdown drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-brcmstb.c | 419 +++++++++++++++++++++++++++++++++----------- 2 files changed, 321 insertions(+), 100 deletions(-) -- 2.14.1
[toc] | [next] | [standalone]
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 4/7] gpio: brcmstb: correct the configuration of level interrupts |
| Message-ID | <uvgWR-78I-7@gated-at.bofh.it> |
| In reply to | #1742484 |
This commit corrects a bug when configuring the GPIO hardware for
IRQ_TYPE_LEVEL_LOW and IRQ_TYPE_LEVEL_HIGH interrupt types. The
hardware is now correctly configured to support those types.
Fixes: 19a7b6940b78 ("gpio: brcmstb: Add interrupt and wakeup source support")
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/gpio/gpio-brcmstb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index c186141927bb..0418cb266586 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -137,13 +137,13 @@ static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
switch (type) {
case IRQ_TYPE_LEVEL_LOW:
- level = 0;
+ level = mask;
edge_config = 0;
edge_insensitive = 0;
break;
case IRQ_TYPE_LEVEL_HIGH:
level = mask;
- edge_config = 0;
+ edge_config = mask;
edge_insensitive = 0;
break;
case IRQ_TYPE_EDGE_FALLING:
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 5/7] gpio: brcmstb: enable masking of interrupts when changing type |
| Message-ID | <uvgWS-78I-13@gated-at.bofh.it> |
| In reply to | #1742484 |
Mask the GPIO interrupt while its type is being changed, just in case
it can prevent a spurious interrupt.
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/gpio/gpio-brcmstb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 0418cb266586..e2fff559c1ca 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -363,7 +363,9 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type;
/* Ensures that all non-wakeup IRQs are disabled at suspend */
- bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
+ /* and that interrupts are masked when changing their type */
+ bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SET_TYPE_MASKED;
if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->parent_wake_irq &&
of_property_read_bool(np, "wakeup-source")) {
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 1/7] gpio: brcmstb: allow all instances to be wakeup sources |
| Message-ID | <uvgWR-78I-9@gated-at.bofh.it> |
| In reply to | #1742484 |
This commit allows a wakeup parent interrupt to be shared between
instances.
It also removes the redundant can_wake member of the private data
structure by using whether the parent_wake_irq has been defined to
indicate that the GPIO device can wake.
Fixes: 19a7b6940b78 ("gpio: brcmstb: Add interrupt and wakeup source support")
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/gpio/gpio-brcmstb.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 27e92e57adae..7f39b160a4d5 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Broadcom Corporation
+ * Copyright (C) 2015-2017 Broadcom
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -46,7 +46,6 @@ struct brcmstb_gpio_priv {
struct platform_device *pdev;
int parent_irq;
int gpio_base;
- bool can_wake;
int parent_wake_irq;
struct notifier_block reboot_notifier;
};
@@ -349,10 +348,11 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
/* Ensures that all non-wakeup IRQs are disabled at suspend */
bank->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
- if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->can_wake &&
+ if (IS_ENABLED(CONFIG_PM_SLEEP) && !priv->parent_wake_irq &&
of_property_read_bool(np, "wakeup-source")) {
priv->parent_wake_irq = platform_get_irq(pdev, 1);
if (priv->parent_wake_irq < 0) {
+ priv->parent_wake_irq = 0;
dev_warn(dev,
"Couldn't get wake IRQ - GPIOs will not be able to wake from sleep");
} else {
@@ -364,8 +364,9 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
device_set_wakeup_capable(dev, true);
device_wakeup_enable(dev);
err = devm_request_irq(dev, priv->parent_wake_irq,
- brcmstb_gpio_wake_irq_handler, 0,
- "brcmstb-gpio-wake", priv);
+ brcmstb_gpio_wake_irq_handler,
+ IRQF_SHARED,
+ "brcmstb-gpio-wake", priv);
if (err < 0) {
dev_err(dev, "Couldn't request wake IRQ");
@@ -375,11 +376,10 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
priv->reboot_notifier.notifier_call =
brcmstb_gpio_reboot;
register_reboot_notifier(&priv->reboot_notifier);
- priv->can_wake = true;
}
}
- if (priv->can_wake)
+ if (priv->parent_wake_irq)
bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake;
err = gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0,
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 3/7] gpio: brcmstb: switch to handle_level_irq flow |
| Message-ID | <uvgWS-78I-17@gated-at.bofh.it> |
| In reply to | #1742484 |
Reading and writing the gpio bank status register each time a pending
interrupt bit is serviced could cause new pending bits to be cleared
without servicing the associated interrupts.
By using the handle_level_irq flow instead of the handle_simple_irq
flow we get proper handling of interrupt masking as well as acking
of interrupts. The irq_ack method is added to support this.
Fixes: 19a7b6940b78 ("gpio: brcmstb: Add interrupt and wakeup source support")
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/gpio/gpio-brcmstb.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 8945861876f9..c186141927bb 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -114,6 +114,16 @@ static void brcmstb_gpio_irq_unmask(struct irq_data *d)
brcmstb_gpio_set_imask(bank, d->hwirq, true);
}
+static void brcmstb_gpio_irq_ack(struct irq_data *d)
+{
+ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+ struct brcmstb_gpio_bank *bank = gpiochip_get_data(gc);
+ struct brcmstb_gpio_priv *priv = bank->parent_priv;
+ u32 mask = BIT(d->hwirq);
+
+ gc->write_reg(priv->reg_base + GIO_STAT(bank->id), mask);
+}
+
static int brcmstb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -217,21 +227,16 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
{
struct brcmstb_gpio_priv *priv = bank->parent_priv;
struct irq_domain *irq_domain = bank->gc.irqdomain;
- void __iomem *reg_base = priv->reg_base;
unsigned long status;
while ((status = brcmstb_gpio_get_active_irqs(bank))) {
int bit;
for_each_set_bit(bit, &status, 32) {
- u32 stat = bank->gc.read_reg(reg_base +
- GIO_STAT(bank->id));
if (bit >= bank->width)
dev_warn(&priv->pdev->dev,
"IRQ for invalid GPIO (bank=%d, offset=%d)\n",
bank->id, bit);
- bank->gc.write_reg(reg_base + GIO_STAT(bank->id),
- stat | BIT(bit));
generic_handle_irq(irq_find_mapping(irq_domain, bit));
}
}
@@ -354,6 +359,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
bank->irq_chip.name = dev_name(dev);
bank->irq_chip.irq_mask = brcmstb_gpio_irq_mask;
bank->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask;
+ bank->irq_chip.irq_ack = brcmstb_gpio_irq_ack;
bank->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type;
/* Ensures that all non-wakeup IRQs are disabled at suspend */
@@ -394,7 +400,7 @@ static int brcmstb_gpio_irq_setup(struct platform_device *pdev,
bank->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake;
err = gpiochip_irqchip_add(&bank->gc, &bank->irq_chip, 0,
- handle_simple_irq, IRQ_TYPE_NONE);
+ handle_level_irq, IRQ_TYPE_NONE);
if (err)
return err;
gpiochip_set_chained_irqchip(&bank->gc, &bank->irq_chip,
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Doug Berger <opendmb@gmail.com> |
|---|---|
| Date | 2017-09-30 05:50 +0200 |
| Subject | [PATCH 2/7] gpio: brcmstb: release the bgpio lock during irq handlers |
| Message-ID | <uvgWS-78I-15@gated-at.bofh.it> |
| In reply to | #1742484 |
The basic memory-mapped GPIO controller lock must be released
before calling the registered GPIO interrupt handlers to allow
the interrupt handlers to access the hardware. Otherwise, the
hardware accesses will deadlock when they attempt to grab the
lock.
Since the lock is only needed to protect the calculation of
unmasked pending interrupts create a dedicated function to
perform this and hide the complexity.
Fixes: 19a7b6940b78 ("gpio: brcmstb: Add interrupt and wakeup source support")
Signed-off-by: Doug Berger <opendmb@gmail.com>
---
drivers/gpio/gpio-brcmstb.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c
index 7f39b160a4d5..8945861876f9 100644
--- a/drivers/gpio/gpio-brcmstb.c
+++ b/drivers/gpio/gpio-brcmstb.c
@@ -62,6 +62,21 @@ brcmstb_gpio_gc_to_priv(struct gpio_chip *gc)
return bank->parent_priv;
}
+static unsigned long
+brcmstb_gpio_get_active_irqs(struct brcmstb_gpio_bank *bank)
+{
+ void __iomem *reg_base = bank->parent_priv->reg_base;
+ unsigned long status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
+ status = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) &
+ bank->gc.read_reg(reg_base + GIO_MASK(bank->id));
+ spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
+
+ return status;
+}
+
static void brcmstb_gpio_set_imask(struct brcmstb_gpio_bank *bank,
unsigned int offset, bool enable)
{
@@ -204,11 +219,8 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
struct irq_domain *irq_domain = bank->gc.irqdomain;
void __iomem *reg_base = priv->reg_base;
unsigned long status;
- unsigned long flags;
- spin_lock_irqsave(&bank->gc.bgpio_lock, flags);
- while ((status = bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) &
- bank->gc.read_reg(reg_base + GIO_MASK(bank->id)))) {
+ while ((status = brcmstb_gpio_get_active_irqs(bank))) {
int bit;
for_each_set_bit(bit, &status, 32) {
@@ -223,7 +235,6 @@ static void brcmstb_gpio_irq_bank_handler(struct brcmstb_gpio_bank *bank)
generic_handle_irq(irq_find_mapping(irq_domain, bit));
}
}
- spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags);
}
/* Each UPG GIO block has one IRQ for all banks */
--
2.14.1
[toc] | [prev] | [next] | [standalone]
| From | Florian Fainelli <f.fainelli@gmail.com> |
|---|---|
| Date | 2017-09-30 07:40 +0200 |
| Message-ID | <uviFj-8kJ-11@gated-at.bofh.it> |
| In reply to | #1742484 |
On 09/29/2017 08:40 PM, Doug Berger wrote: > This patch set collects a number of improvements to the GPIO driver > used by Broadcom Set-Top-Box devices. > > Primarily they are aimed at correcting problems with the interrupt > controller implementation, but they also extend the functionality for > waking on GPIO interrupts. This all looks good to me, thanks a lot for sending those patches out! Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> > > Doug Berger (7): > gpio: brcmstb: allow all instances to be wakeup sources > gpio: brcmstb: release the bgpio lock during irq handlers > gpio: brcmstb: switch to handle_level_irq flow > gpio: brcmstb: correct the configuration of level interrupts > gpio: brcmstb: enable masking of interrupts when changing type > gpio: brcmstb: consolidate interrupt domains > gpio: brcmstb: implement suspend/resume/shutdown > > drivers/gpio/Kconfig | 2 +- > drivers/gpio/gpio-brcmstb.c | 419 +++++++++++++++++++++++++++++++++----------- > 2 files changed, 321 insertions(+), 100 deletions(-) > -- Florian
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web