cns3xxx: Adopt irq_domain support for cns3xxx gpio driver
authorFelix Fietkau <nbd@openwrt.org>
Wed, 8 Oct 2014 10:28:10 +0000 (10:28 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 8 Oct 2014 10:28:10 +0000 (10:28 +0000)
Have gpio driver adopt irqdomain support so that there are
non-overlapping allocations of irq numbers mapped to gpio's.

Signed-off-by: Pushpal Sidhu <psidhu@gateworks.com>
SVN-Revision: 42844

target/linux/cns3xxx/files/arch/arm/mach-cns3xxx/gpio.c

index 35434f8..b6e4061 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach/irq.h>
 
@@ -45,9 +46,9 @@
 
 struct cns3xxx_gpio_chip {
        struct gpio_chip    chip;
+       struct irq_domain   *domain;
        spinlock_t          lock;
        void __iomem        *base;
-       int                 secondary_irq_base;
 };
 
 static struct cns3xxx_gpio_chip cns3xxx_gpio_chips[2];
@@ -127,7 +128,7 @@ static int cns3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
        struct cns3xxx_gpio_chip *cchip =
                container_of(chip, struct cns3xxx_gpio_chip, chip);
 
-       return cchip->secondary_irq_base + pin;
+       return irq_find_mapping(cchip->domain, pin);
 }
 
 
@@ -152,7 +153,7 @@ static void cns3xxx_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        for (i = 0; i < 32; i++) {
                if (reg & (1 << i)) {
                        /* let the generic IRQ layer handle an interrupt */
-                       generic_handle_irq(cchip->secondary_irq_base + i);
+                       generic_handle_irq(irq_find_mapping(cchip->domain, i));
                }
        }
 
@@ -163,7 +164,7 @@ static int cns3xxx_gpio_irq_set_type(struct irq_data *d, u32 irqtype)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct cns3xxx_gpio_chip *cchip = gc->private;
-       u32 gpio = d->irq - cchip->secondary_irq_base;
+       u32 gpio = d->hwirq;
        unsigned long flags;
        u32 method, edges, type;
 
@@ -224,6 +225,7 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
        char gc_label[16];
+       int irq_base;
 
        if (cns3xxx_gpio_chip_count == ARRAY_SIZE(cns3xxx_gpio_chips))
                return;
@@ -243,7 +245,6 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
        cchip->chip.can_sleep = 0;
        spin_lock_init(&cchip->lock);
        cchip->base = (void __iomem *)base;
-       cchip->secondary_irq_base = secondary_irq_base;
 
        BUG_ON(gpiochip_add(&cchip->chip) < 0);
        cns3xxx_gpio_chip_count++;
@@ -251,11 +252,22 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
        /* clear GPIO interrupts */
        __raw_writel(0xffff, cchip->base + GPIO_INTERRUPT_CLEAR);
 
+       irq_base = irq_alloc_descs(-1, secondary_irq_base, ngpio,
+               numa_node_id());
+       if (irq_base < 0)
+               goto out_irqdesc_free;
+
+       cchip->domain = irq_domain_add_legacy(NULL, ngpio, irq_base, 0,
+               &irq_domain_simple_ops, NULL);
+       if (!cchip->domain)
+               goto out_irqdesc_free;
+
        /*
         * IRQ chip init
         */
-       gc = irq_alloc_generic_chip("cns3xxx_gpio_irq", 1, secondary_irq_base,
+       gc = irq_alloc_generic_chip("cns3xxx_gpio_irq", 1, irq_base,
                cchip->base, handle_edge_irq);
+
        gc->private = cchip;
 
        ct = gc->chip_types;
@@ -270,7 +282,11 @@ void __init cns3xxx_gpio_init(int gpio_base, int ngpio,
 
        irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
                IRQ_NOREQUEST, 0);
-
        irq_set_chained_handler(irq, cns3xxx_gpio_irq_handler);
        irq_set_handler_data(irq, cchip);
+
+       return;
+
+out_irqdesc_free:
+       irq_free_descs(irq_base, ngpio);
 }