[sparc] remove broken flag
[openwrt.git] / target / linux / leon / patches / 004-extended_irq_controller.patch
1 From a729672f117df3602b6d3171d8ab7a84bf53b053 Mon Sep 17 00:00:00 2001
2 From: Daniel Hellstrom <daniel@gaisler.com>
3 Date: Thu, 16 Sep 2010 11:12:41 +0200
4 Subject: [PATCH] SPARC/LEON: added support for Extended IRQ controller, partial patches are already in git tree.
5
6 Signed-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();