]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
gpio: pl061: enable interrupts with DT style binding
authorRob Herring <rob.herring@calxeda.com>
Fri, 9 Dec 2011 20:24:25 +0000 (14:24 -0600)
committerRob Herring <rob.herring@calxeda.com>
Mon, 5 Mar 2012 03:36:05 +0000 (21:36 -0600)
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 <rob.herring@calxeda.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Linus Walleij <linus.ml.walleij@gmail.com>
Documentation/devicetree/bindings/gpio/pl061-gpio.txt
drivers/gpio/gpio-pl061.c

index a2c416bcbccce950741ce69db3d5817fac26fa6d..9671d4e30022e76c16d2346dad8260a4983bcc49 100644 (file)
@@ -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
+
index 77c9cc70fa7753fb406b87dbbf201021b4b6eb18..b271a17bd6987b17cac463831415d49d567b3b28 100644 (file)
@@ -15,6 +15,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>
@@ -56,7 +58,6 @@ struct pl061_gpio {
        spinlock_t              lock;           /* GPIO registers */
 
        void __iomem            *base;
-       int                     irq_base;
        struct irq_chip_generic *irq_gc;
        struct gpio_chip        gc;
 
@@ -126,18 +127,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_gc)
+               return -ENXIO;
+       return irq_find_mapping(chip->irq_gc->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;
 
@@ -197,30 +196,25 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
        chained_irq_exit(irqchip, desc);
 }
 
-static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
+static void __init pl061_init_gc(struct irq_chip_generic *gc)
 {
-       struct irq_chip_type *ct;
+       struct irq_chip_type *ct = gc->chip_types;
+       struct pl061_gpio *chip = gc->private;
 
-       chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
-                                             chip->base, handle_simple_irq);
-       chip->irq_gc->private = chip;
+       chip->irq_gc = gc;
 
-       ct = chip->irq_gc->chip_types;
        ct->chip.irq_mask = irq_gc_mask_clr_bit;
        ct->chip.irq_unmask = irq_gc_mask_set_bit;
        ct->chip.irq_set_type = pl061_irq_type;
        ct->chip.irq_set_wake = irq_gc_set_wake;
        ct->regs.mask = GPIOIE;
-
-       irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
-                              IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
 }
 
 static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 {
        struct pl061_platform_data *pdata;
        struct pl061_gpio *chip;
-       int ret, irq, i;
+       int ret, irq, i, irq_base;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL)
@@ -229,10 +223,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;
@@ -267,13 +264,18 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
                goto iounmap;
 
        /*
-        * irq_chip support
+        * irq_chip support. If irq_base is 0, then we don't support interrupts
+        * on gpio lines and just return now. Otherwise setup the interrupts.
         */
-
-       if (chip->irq_base <= 0)
+       if (!irq_base)
                return 0;
 
-       pl061_init_gc(chip, chip->irq_base);
+       irq_setup_generic_chip_domain("gpio-pl061",
+                                     of_node_get(dev->dev.of_node),
+                                     1, irq_base, chip->base,
+                                     handle_simple_irq,
+                                     PL061_GPIO_NR, IRQ_GC_INIT_NESTED_LOCK,
+                                     IRQ_NOREQUEST, 0, pl061_init_gc, chip);
 
        writeb(0, chip->base + GPIOIE); /* disable irqs */
        irq = dev->irq[0];