arm: orion: Use generic irq chip
authorThomas Gleixner <tglx@linutronix.de>
Thu, 14 Apr 2011 17:17:57 +0000 (19:17 +0200)
committerNicolas Pitre <nico@fluxnic.net>
Mon, 16 May 2011 18:34:54 +0000 (14:34 -0400)
The core interrupt chip is a straight forward conversion. The gpio
chip is implemented with two instances of the irq_chip_type which can
be switched with the irq_set_type function. That allows us to use the
generic callbacks and avoids the conditionals in them.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
arch/arm/plat-orion/gpio.c
arch/arm/plat-orion/include/plat/gpio.h
arch/arm/plat-orion/irq.c

index a431a13..5b4fffa 100644 (file)
@@ -321,59 +321,16 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
  *        polarity    LEVEL          mask
  *
  ****************************************************************************/
-static void gpio_irq_ack(struct irq_data *d)
-{
-       struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type = irqd_get_trigger_type(d);
-
-       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-               int pin = d->irq - ochip->secondary_irq_base;
-
-               writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip));
-       }
-}
-
-static void gpio_irq_mask(struct irq_data *d)
-{
-       struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type = irqd_get_trigger_type(d);
-       void __iomem *reg;
-       int pin;
-
-       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
-               reg = GPIO_EDGE_MASK(ochip);
-       else
-               reg = GPIO_LEVEL_MASK(ochip);
-
-       pin = d->irq - ochip->secondary_irq_base;
-
-       writel(readl(reg) & ~(1 << pin), reg);
-}
-
-static void gpio_irq_unmask(struct irq_data *d)
-{
-       struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
-       int type = irqd_get_trigger_type(d);
-       void __iomem *reg;
-       int pin;
-
-       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
-               reg = GPIO_EDGE_MASK(ochip);
-       else
-               reg = GPIO_LEVEL_MASK(ochip);
-
-       pin = d->irq - ochip->secondary_irq_base;
-
-       writel(readl(reg) | (1 << pin), reg);
-}
 
 static int gpio_irq_set_type(struct irq_data *d, u32 type)
 {
-       struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+       struct irq_chip_type *ct = irq_data_get_chip_type(d);
+       struct orion_gpio_chip *ochip = gc->private;
        int pin;
        u32 u;
 
-       pin = d->irq - ochip->secondary_irq_base;
+       pin = d->irq - gc->irq_base;
 
        u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
        if (!u) {
@@ -382,18 +339,14 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
                return -EINVAL;
        }
 
-       /*
-        * Set edge/level type.
-        */
-       if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-               __irq_set_handler_locked(d->irq, handle_edge_irq);
-       } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-               __irq_set_handler_locked(d->irq, handle_level_irq);
-       } else {
-               printk(KERN_ERR "failed to set irq=%d (type=%d)\n",
-                      d->irq, type);
+       type &= IRQ_TYPE_SENSE_MASK;
+       if (type == IRQ_TYPE_NONE)
                return -EINVAL;
-       }
+
+       /* Check if we need to change chip and handler */
+       if (!(ct->type & type))
+               if (irq_setup_alt_chip(d, type))
+                       return -EINVAL;
 
        /*
         * Configure interrupt polarity.
@@ -425,19 +378,12 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
        return 0;
 }
 
-struct irq_chip orion_gpio_irq_chip = {
-       .name           = "orion_gpio_irq",
-       .irq_ack        = gpio_irq_ack,
-       .irq_mask       = gpio_irq_mask,
-       .irq_unmask     = gpio_irq_unmask,
-       .irq_set_type   = gpio_irq_set_type,
-};
-
 void __init orion_gpio_init(int gpio_base, int ngpio,
                            u32 base, int mask_offset, int secondary_irq_base)
 {
        struct orion_gpio_chip *ochip;
-       int i;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
 
        if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
                return;
@@ -471,15 +417,29 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
        writel(0, GPIO_EDGE_MASK(ochip));
        writel(0, GPIO_LEVEL_MASK(ochip));
 
-       for (i = 0; i < ngpio; i++) {
-               unsigned int irq = secondary_irq_base + i;
-
-               irq_set_chip_and_handler(irq, &orion_gpio_irq_chip,
-                                        handle_level_irq);
-               irq_set_chip_data(irq, ochip);
-               irq_set_status_flags(irq, IRQ_LEVEL);
-               set_irq_flags(irq, IRQF_VALID);
-       }
+       gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base,
+                                   ochip->base, handle_level_irq);
+       gc->private = ochip;
+
+       ct = gc->chip_types;
+       ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
+       ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->chip.irq_set_type = gpio_irq_set_type;
+
+       ct++;
+       ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;
+       ct->regs.ack = GPIO_EDGE_CAUSE_OFF;
+       ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+       ct->chip.irq_ack = irq_gc_ack;
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       ct->chip.irq_set_type = gpio_irq_set_type;
+       ct->handler = handle_edge_irq;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 }
 
 void orion_gpio_irq_handler(int pinoff)
index 5578b98..3075b9f 100644 (file)
@@ -39,7 +39,6 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
 /*
  * GPIO interrupt handling.
  */
-extern struct irq_chip orion_gpio_irq_chip;
 void orion_gpio_irq_handler(int irqoff);
 
 
index d8d638e..2d5b9c1 100644 (file)
 #include <linux/io.h>
 #include <plat/irq.h>
 
-static void orion_irq_mask(struct irq_data *d)
-{
-       void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
-       u32 mask;
-
-       mask = readl(maskaddr);
-       mask &= ~(1 << (d->irq & 31));
-       writel(mask, maskaddr);
-}
-
-static void orion_irq_unmask(struct irq_data *d)
-{
-       void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
-       u32 mask;
-
-       mask = readl(maskaddr);
-       mask |= 1 << (d->irq & 31);
-       writel(mask, maskaddr);
-}
-
-static struct irq_chip orion_irq_chip = {
-       .name           = "orion_irq",
-       .irq_mask       = orion_irq_mask,
-       .irq_mask_ack   = orion_irq_mask,
-       .irq_unmask     = orion_irq_unmask,
-};
-
 void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
 {
-       unsigned int i;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
 
        /*
         * Mask all interrupts initially.
         */
        writel(0, maskaddr);
 
-       /*
-        * Register IRQ sources.
-        */
-       for (i = 0; i < 32; i++) {
-               unsigned int irq = irq_start + i;
-
-               irq_set_chip_and_handler(irq, &orion_irq_chip,
-                                        handle_level_irq);
-               irq_set_chip_data(irq, maskaddr);
-               irq_set_status_flags(irq, IRQ_LEVEL);
-               set_irq_flags(irq, IRQF_VALID);
-       }
+       gc = irq_alloc_generic_chip("orion_irq", 1, irq_start, maskaddr,
+                                   handle_level_irq);
+       ct = gc->chip_types;
+       ct->chip.irq_mask = irq_gc_mask_clr_bit;
+       ct->chip.irq_unmask = irq_gc_mask_set_bit;
+       irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 }