Root/target/linux/leon/patches-2.6.36/004-extended_irq_controller.patch

1From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001
2From: Daniel Hellstrom <daniel@gaisler.com>
3Date: Thu, 16 Sep 2010 11:12:41 +0200
4Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree.
5
6Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
7---
8 arch/sparc/include/asm/irq_32.h | 4 ++++
9 arch/sparc/kernel/irq_32.c | 32 ++++++++++++++++++++++++++------
10 arch/sparc/kernel/leon_kernel.c | 8 +++++++-
11 3 files changed, 37 insertions(+), 7 deletions(-)
12
13--- a/arch/sparc/include/asm/irq_32.h
14+++ b/arch/sparc/include/asm/irq_32.h
15@@ -6,7 +6,11 @@
16 #ifndef _SPARC_IRQ_H
17 #define _SPARC_IRQ_H
18 
19+#ifdef CONFIG_SPARC_LEON
20+#define NR_IRQS 32
21+#else
22 #define NR_IRQS 16
23+#endif
24 
25 #include <linux/interrupt.h>
26 
27--- a/arch/sparc/kernel/irq_32.c
28+++ b/arch/sparc/kernel/irq_32.c
29@@ -110,6 +110,11 @@ EXPORT_SYMBOL(__raw_local_irq_save);
30 EXPORT_SYMBOL(raw_local_irq_enable);
31 EXPORT_SYMBOL(raw_local_irq_restore);
32 
33+#ifdef CONFIG_SPARC_LEON
34+extern unsigned int sparc_leon_eirq;
35+extern int sparc_leon_eirq_get(int eirq, int cpu);
36+#endif
37+
38 /*
39  * Dave Redman (djhr@tadpole.co.uk)
40  *
41@@ -222,10 +227,11 @@ void free_irq(unsigned int irq, void *de
42         return;
43     }
44     cpu_irq = irq & (NR_IRQS - 1);
45- if (cpu_irq > 14) { /* 14 irq levels on the sparc */
46- printk("Trying to free bogus IRQ %d\n", irq);
47- return;
48- }
49+ /* 14 irq levels on the sparc, however some LEON systems have 31 IRQs */
50+ if ((cpu_irq == 15) || (cpu_irq >= NR_IRQS)) {
51+ printk("Trying to free bogus IRQ %d\n", irq);
52+ return;
53+ }
54 
55     spin_lock_irqsave(&irq_action_lock, flags);
56 
57@@ -303,7 +309,14 @@ void unexpected_irq(int irq, void *dev_i
58         int i;
59     struct irqaction * action;
60     unsigned int cpu_irq;
61-
62+
63+#ifdef CONFIG_SPARC_LEON
64+ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */
65+ if ( sparc_leon_eirq == irq ) {
66+ irq = sparc_leon_eirq_get(irq, smp_processor_id());
67+ }
68+#endif
69+
70     cpu_irq = irq & (NR_IRQS - 1);
71     action = sparc_irq[cpu_irq].action;
72 
73@@ -330,6 +343,13 @@ void handler_irq(int irq, struct pt_regs
74     extern void smp4m_irq_rotate(int cpu);
75 #endif
76 
77+#ifdef CONFIG_SPARC_LEON
78+ /* LEON Extended IRQ requires one extra IRQ Number fetch stage */
79+ if ( sparc_leon_eirq == irq ) {
80+ irq = sparc_leon_eirq_get(irq, cpu);
81+ }
82+#endif
83+
84     old_regs = set_irq_regs(regs);
85     irq_enter();
86     disable_pil_irq(irq);
87@@ -526,7 +546,7 @@ int request_irq(unsigned int irq,
88         return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
89     }
90     cpu_irq = irq & (NR_IRQS - 1);
91- if(cpu_irq > 14) {
92+ if(cpu_irq == 15) {
93         ret = -EINVAL;
94         goto out;
95     }
96--- a/arch/sparc/kernel/leon_kernel.c
97+++ b/arch/sparc/kernel/leon_kernel.c
98@@ -104,7 +104,7 @@ static void leon_disable_irq(unsigned in
99 
100 void __init leon_init_timers(irq_handler_t counter_fn)
101 {
102- int irq;
103+ int irq, eirq;
104     struct device_node *rootnp, *np;
105     struct property *pp;
106     int len;
107@@ -153,6 +153,12 @@ void __init leon_init_timers(irq_handler
108         LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0);
109 # endif
110 
111+ LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
112+ eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus) >> 16) & 0xf;
113+ if ( eirq != 0 ) {
114+ /* Extended IRQ controller available */
115+ sparc_leon_eirq_register(eirq);
116+ }
117     } else {
118         printk(KERN_ERR "No Timer/irqctrl found\n");
119         BUG();
120

Archive Download this file



interactive