diff options
-rw-r--r-- | arch/x86/include/asm/irq_controller.h | 12 | ||||
-rw-r--r-- | arch/x86/include/asm/prom.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/devicetree.c | 46 |
3 files changed, 59 insertions, 1 deletions
diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h new file mode 100644 index 000000000000..423bbbddf36d --- /dev/null +++ b/arch/x86/include/asm/irq_controller.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __IRQ_CONTROLLER__ | ||
2 | #define __IRQ_CONTROLLER__ | ||
3 | |||
4 | struct irq_domain { | ||
5 | int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize, | ||
6 | u32 *out_hwirq, u32 *out_type); | ||
7 | void *priv; | ||
8 | struct device_node *controller; | ||
9 | struct list_head l; | ||
10 | }; | ||
11 | |||
12 | #endif | ||
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index e46f2a2b57a1..83833ac33dd1 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h | |||
@@ -20,9 +20,11 @@ | |||
20 | #include <asm/irq.h> | 20 | #include <asm/irq.h> |
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | #include <asm/setup.h> | 22 | #include <asm/setup.h> |
23 | #include <asm/irq_controller.h> | ||
23 | 24 | ||
24 | #ifdef CONFIG_OF | 25 | #ifdef CONFIG_OF |
25 | extern void add_dtb(u64 data); | 26 | extern void add_dtb(u64 data); |
27 | void add_interrupt_host(struct irq_domain *ih); | ||
26 | #else | 28 | #else |
27 | static inline void add_dtb(u64 data) { } | 29 | static inline void add_dtb(u64 data) { } |
28 | #endif | 30 | #endif |
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 0b8f0daef933..ef98e4edada1 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c | |||
@@ -3,19 +3,63 @@ | |||
3 | */ | 3 | */ |
4 | #include <linux/bootmem.h> | 4 | #include <linux/bootmem.h> |
5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
6 | #include <linux/interrupt.h> | ||
6 | #include <linux/list.h> | 7 | #include <linux/list.h> |
7 | #include <linux/of.h> | 8 | #include <linux/of.h> |
8 | #include <linux/of_fdt.h> | 9 | #include <linux/of_fdt.h> |
9 | #include <linux/of_platform.h> | 10 | #include <linux/of_platform.h> |
10 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
11 | 12 | ||
13 | #include <asm/irq_controller.h> | ||
14 | |||
12 | char __initdata cmd_line[COMMAND_LINE_SIZE]; | 15 | char __initdata cmd_line[COMMAND_LINE_SIZE]; |
16 | static LIST_HEAD(irq_domains); | ||
17 | static DEFINE_RAW_SPINLOCK(big_irq_lock); | ||
18 | |||
19 | void add_interrupt_host(struct irq_domain *ih) | ||
20 | { | ||
21 | unsigned long flags; | ||
22 | |||
23 | raw_spin_lock_irqsave(&big_irq_lock, flags); | ||
24 | list_add(&ih->l, &irq_domains); | ||
25 | raw_spin_unlock_irqrestore(&big_irq_lock, flags); | ||
26 | } | ||
27 | |||
28 | static struct irq_domain *get_ih_from_node(struct device_node *controller) | ||
29 | { | ||
30 | struct irq_domain *ih, *found = NULL; | ||
31 | unsigned long flags; | ||
32 | |||
33 | raw_spin_lock_irqsave(&big_irq_lock, flags); | ||
34 | list_for_each_entry(ih, &irq_domains, l) { | ||
35 | if (ih->controller == controller) { | ||
36 | found = ih; | ||
37 | break; | ||
38 | } | ||
39 | } | ||
40 | raw_spin_unlock_irqrestore(&big_irq_lock, flags); | ||
41 | return found; | ||
42 | } | ||
13 | 43 | ||
14 | unsigned int irq_create_of_mapping(struct device_node *controller, | 44 | unsigned int irq_create_of_mapping(struct device_node *controller, |
15 | const u32 *intspec, unsigned int intsize) | 45 | const u32 *intspec, unsigned int intsize) |
16 | { | 46 | { |
17 | return intspec[0]; | 47 | struct irq_domain *ih; |
48 | u32 virq, type; | ||
49 | int ret; | ||
18 | 50 | ||
51 | ih = get_ih_from_node(controller); | ||
52 | if (!ih) | ||
53 | return 0; | ||
54 | ret = ih->xlate(ih, intspec, intsize, &virq, &type); | ||
55 | if (ret) | ||
56 | return ret; | ||
57 | if (type == IRQ_TYPE_NONE) | ||
58 | return virq; | ||
59 | /* set the mask if it is different from current */ | ||
60 | if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK)) | ||
61 | set_irq_type(virq, type); | ||
62 | return virq; | ||
19 | } | 63 | } |
20 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); | 64 | EXPORT_SYMBOL_GPL(irq_create_of_mapping); |
21 | 65 | ||