Thread (43 messages) 43 messages, 5 authors, 2012-01-02

[PATCH 8/9] gpio: pl061: enable interrupts with DT style binding

From: Grant Likely <hidden>
Date: 2011-12-14 21:39:49
Also in: linux-devicetree, lkml

On Wed, Dec 14, 2011 at 8:28 AM, Rob Herring [off-list ref] wrote:
quoted hunk ↗ jump to hunk
From: Rob Herring <redacted>

Enable DT interrupt binding support for pl061 gpio lines. If the gpio
node has an interrupt-controller property, then it will be setup to
handle interrupts on gpio lines.

Signed-off-by: Rob Herring <redacted>
Cc: Grant Likely <redacted>
Cc: Linus Walleij <redacted>
---
?.../devicetree/bindings/gpio/pl061-gpio.txt ? ? ? ?| ? 15 ++++++++++
?drivers/gpio/gpio-pl061.c ? ? ? ? ? ? ? ? ? ? ? ? ?| ? 29 +++++++++++--------
?2 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
index a2c416b..9671d4e 100644
--- a/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.txt
@@ -8,3 +8,18 @@ Required properties:
?- gpio-controller : Marks the device node as a GPIO controller.
?- interrupts : Interrupt mapping for GPIO IRQ.

+Optional properties:
+- interrupt-controller : Identifies the node as an interrupt controller. Must
+ ?be present if using gpios lines for interrupts.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ ?interrupt source. ?The type shall be a <u32> and the value shall be 2.
+
+ ?The 1st cell contains the interrupt number 0-7 corresponding to the gpio
+ ?line.
+
+ ?The 2nd cell is the flags, encoding trigger type and level flags.
+ ? ? ? 1 = low-to-high edge triggered
+ ? ? ? 2 = high-to-low edge triggered
+ ? ? ? 4 = active high level-sensitive
+ ? ? ? 8 = active low level-sensitive
+
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 4a1874f..0151798 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -16,6 +16,8 @@
?#include <linux/io.h>
?#include <linux/ioport.h>
?#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
?#include <linux/bitops.h>
?#include <linux/workqueue.h>
?#include <linux/gpio.h>
@@ -52,7 +54,7 @@ struct pl061_gpio {
? ? ? ?spinlock_t ? ? ? ? ? ? ?lock; ? ? ? ? ? /* GPIO registers */

? ? ? ?void __iomem ? ? ? ? ? ?*base;
- ? ? ? int ? ? ? ? ? ? ? ? ? ? irq_base;
+ ? ? ? struct irq_domain ? ? ? *irq_domain;
? ? ? ?struct gpio_chip ? ? ? ?gc;
?};
@@ -117,18 +119,16 @@ static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
?static int pl061_to_irq(struct gpio_chip *gc, unsigned offset)
?{
? ? ? ?struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
-
- ? ? ? if (chip->irq_base <= 0)
- ? ? ? ? ? ? ? return -EINVAL;
-
- ? ? ? return chip->irq_base + offset;
+ ? ? ? if (!chip->irq_domain)
+ ? ? ? ? ? ? ? return -ENXIO;
+ ? ? ? return irq_domain_to_irq(chip->irq_domain, offset);
?}

?static int pl061_irq_type(struct irq_data *d, unsigned trigger)
?{
? ? ? ?struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
? ? ? ?struct pl061_gpio *chip = gc->private;
- ? ? ? int offset = d->irq - chip->irq_base;
+ ? ? ? int offset = d->hwirq;
? ? ? ?unsigned long flags;
? ? ? ?u8 gpiois, gpioibe, gpioiev;
@@ -212,6 +212,7 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
? ? ? ?irq_setup_generic_chip(gc, IRQ_MSK(PL061_GPIO_NR),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
+ ? ? ? chip->irq_domain = gc->domain;
I would expect the driver to store chip->gc = gc instead.  Then the
driver has access to both structures, and if ever needed, the gc could
be freed on driver release.
quoted hunk ↗ jump to hunk
?}

?static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
@@ -219,7 +220,7 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
? ? ? ?struct pl061_platform_data *pdata;
? ? ? ?struct pl061_gpio *chip;
? ? ? ?struct list_head *chip_list;
- ? ? ? int ret, irq, i;
+ ? ? ? int ret, irq, i, irq_base;
? ? ? ?static DECLARE_BITMAP(init_irq, NR_IRQS);

? ? ? ?chip = kzalloc(sizeof(*chip), GFP_KERNEL);
@@ -229,10 +230,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
? ? ? ?pdata = dev->dev.platform_data;
? ? ? ?if (pdata) {
? ? ? ? ? ? ? ?chip->gc.base = pdata->gpio_base;
- ? ? ? ? ? ? ? chip->irq_base = pdata->irq_base;
+ ? ? ? ? ? ? ? irq_base = pdata->irq_base;
? ? ? ?} else if (dev->dev.of_node) {
? ? ? ? ? ? ? ?chip->gc.base = -1;
- ? ? ? ? ? ? ? chip->irq_base = 0;
+ ? ? ? ? ? ? ? if (of_get_property(dev->dev.of_node, "interrupt-controller", NULL))
+ ? ? ? ? ? ? ? ? ? ? ? irq_base = -1;
+ ? ? ? ? ? ? ? else
+ ? ? ? ? ? ? ? ? ? ? ? irq_base = 0;
? ? ? ?} else {
? ? ? ? ? ? ? ?ret = -ENODEV;
? ? ? ? ? ? ? ?goto free_mem;
@@ -271,10 +275,11 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
? ? ? ? * irq_chip support
? ? ? ? */

- ? ? ? if (chip->irq_base <= 0)
+ ? ? ? if (!irq_base)
? ? ? ? ? ? ? ?return 0;
A comment would be useful here as it took a bit for me to work out
what the options are here.  What are the possible values of irq_base
at this point, and what do they mean?

Otherwise looks pretty good.

g.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help