x86: dtb: Add irq domain abstraction
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Tue, 22 Feb 2011 20:07:39 +0000 (21:07 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 23 Feb 2011 21:27:53 +0000 (22:27 +0100)
The here introduced irq_domain abstraction represents a generic irq
controller. It is a subset of powerpc's irq_host which is going to be
renamed to irq_domain and then become generic. This implementation will
be removed once it is generic.

The xlate callback is resposible to parse irq informations like irq type
and number and returns the hardware irq number which is reported by the
hardware as active.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Tested-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Cc: sodaville@linutronix.de
Cc: devicetree-discuss@lists.ozlabs.org
LKML-Reference: <1298405266-1624-5-git-send-email-bigeasy@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/include/asm/irq_controller.h [new file with mode: 0644]
arch/x86/include/asm/prom.h
arch/x86/kernel/devicetree.c

diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h
new file mode 100644 (file)
index 0000000..423bbbd
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __IRQ_CONTROLLER__
+#define __IRQ_CONTROLLER__
+
+struct irq_domain {
+       int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
+                       u32 *out_hwirq, u32 *out_type);
+       void *priv;
+       struct device_node *controller;
+       struct list_head l;
+};
+
+#endif
index e46f2a2b57a11b986ea73505f902c7d5f3acc2e7..83833ac33dd10398f6675d75b08a1886963b1b34 100644 (file)
 #include <asm/irq.h>
 #include <asm/atomic.h>
 #include <asm/setup.h>
+#include <asm/irq_controller.h>
 
 #ifdef CONFIG_OF
 extern void add_dtb(u64 data);
+void add_interrupt_host(struct irq_domain *ih);
 #else
 static inline void add_dtb(u64 data) { }
 #endif
index 0b8f0daef9333d1db13448ab425c15bf260f1e52..ef98e4edada1748b03c30d4c4d11415e338c937b 100644 (file)
@@ -3,19 +3,63 @@
  */
 #include <linux/bootmem.h>
 #include <linux/io.h>
+#include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_platform.h>
 #include <linux/slab.h>
 
+#include <asm/irq_controller.h>
+
 char __initdata cmd_line[COMMAND_LINE_SIZE];
+static LIST_HEAD(irq_domains);
+static DEFINE_RAW_SPINLOCK(big_irq_lock);
+
+void add_interrupt_host(struct irq_domain *ih)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&big_irq_lock, flags);
+       list_add(&ih->l, &irq_domains);
+       raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+}
+
+static struct irq_domain *get_ih_from_node(struct device_node *controller)
+{
+       struct irq_domain *ih, *found = NULL;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&big_irq_lock, flags);
+       list_for_each_entry(ih, &irq_domains, l) {
+               if (ih->controller ==  controller) {
+                       found = ih;
+                       break;
+               }
+       }
+       raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+       return found;
+}
 
 unsigned int irq_create_of_mapping(struct device_node *controller,
                                   const u32 *intspec, unsigned int intsize)
 {
-       return intspec[0];
+       struct irq_domain *ih;
+       u32 virq, type;
+       int ret;
 
+       ih = get_ih_from_node(controller);
+       if (!ih)
+               return 0;
+       ret = ih->xlate(ih, intspec, intsize, &virq, &type);
+       if (ret)
+               return ret;
+       if (type == IRQ_TYPE_NONE)
+               return virq;
+       /* set the mask if it is different from current */
+       if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
+               set_irq_type(virq, type);
+       return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);