ARM: plat-versatile: use simple irqdomain for FPGA IRQ
authorLinus Walleij <linus.walleij@linaro.org>
Fri, 26 Oct 2012 23:05:06 +0000 (01:05 +0200)
committerLinus Walleij <linus.walleij@linaro.org>
Fri, 26 Oct 2012 23:05:06 +0000 (01:05 +0200)
This switches the FPGA IRQ driver over to using the simple IRQ
domain. We can then use the same codepath for this in the
DT and non-DT cases.

To be able to use quicker irq_find_mapping() in the handlers
we first call irq_create_mapping() on all the valid HW IRQ
numbers so that descriptors will be created for them in the
DT case where a linear domain will be the outcome of the
call.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
arch/arm/plat-versatile/fpga-irq.c

index 091ae103004519dadb6d119ccc186795ac8eee5d..dfe317c20354c6781f24b61c2c383aacd65100f4 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Support for Versatile FPGA-based IRQ controllers
  */
+#include <linux/bitops.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/irqdomain.h>
@@ -117,13 +118,12 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
        struct fpga_irq_data *f = d->host_data;
 
        /* Skip invalid IRQs, only register handlers for the real ones */
-       if (!(f->valid & (1 << hwirq)))
+       if (!(f->valid & BIT(hwirq)))
                return -ENOTSUPP;
        irq_set_chip_data(irq, f);
        irq_set_chip_and_handler(irq, &f->chip,
                                handle_level_irq);
        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-       f->used_irqs++;
        return 0;
 }
 
@@ -132,13 +132,15 @@ static struct irq_domain_ops fpga_irqdomain_ops = {
        .xlate = irq_domain_xlate_onetwocell,
 };
 
-static __init struct fpga_irq_data *
-fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
+void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
+                         int parent_irq, u32 valid, struct device_node *node)
+{
        struct fpga_irq_data *f;
+       int i;
 
        if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
-               printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
-               return NULL;
+               pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
+               return;
        }
        f = &fpga_irq_devices[fpga_irq_id];
        f->base = base;
@@ -147,29 +149,28 @@ fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
        f->chip.irq_mask = fpga_irq_mask;
        f->chip.irq_unmask = fpga_irq_unmask;
        f->valid = valid;
-       fpga_irq_id++;
-
-       return f;
-}
-
-void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
-                         int parent_irq, u32 valid, struct device_node *node)
-{
-       struct fpga_irq_data *f;
-
-       f = fpga_irq_prep_struct(base, name, valid);
-       if (!f)
-               return;
 
        if (parent_irq != -1) {
                irq_set_handler_data(parent_irq, f);
                irq_set_chained_handler(parent_irq, fpga_irq_handle);
        }
 
-       f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0,
+       /* This will also allocate irq descriptors */
+       f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
                                          &fpga_irqdomain_ops, f);
+
+       /* This will allocate all valid descriptors in the linear case */
+       for (i = 0; i < fls(valid); i++)
+               if (valid & BIT(i)) {
+                       if (!irq_start)
+                               irq_create_mapping(f->domain, i);
+                       f->used_irqs++;
+               }
+
        pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
                fpga_irq_id, name, base, f->used_irqs);
+
+       fpga_irq_id++;
 }
 
 #ifdef CONFIG_OF
@@ -193,18 +194,11 @@ int __init fpga_irq_of_init(struct device_node *node,
        if (of_property_read_u32(node, "valid-mask", &valid_mask))
                valid_mask = 0;
 
-       f = fpga_irq_prep_struct(base, node->name, valid_mask);
-       if (!f)
-               return -ENOMEM;
+       fpga_irq_init(base, node->name, 0, -1, valid_mask, node);
 
        writel(clear_mask, base + IRQ_ENABLE_CLEAR);
        writel(clear_mask, base + FIQ_ENABLE_CLEAR);
 
-       f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
-       f->used_irqs = hweight32(valid_mask);
-
-       pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
-               fpga_irq_id, node->name, base, f->used_irqs);
        return 0;
 }
 #endif