Merge branch 'fix/hda' of git://github.com/tiwai/sound
[pandora-kernel.git] / arch / mips / pmc-sierra / msp71xx / msp_irq.c
1 /*
2  * IRQ vector handles
3  *
4  * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License.  See the file "COPYING" in the main directory of this archive
8  * for more details.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/irq.h>
14 #include <linux/interrupt.h>
15 #include <linux/ptrace.h>
16 #include <linux/time.h>
17
18 #include <asm/irq_cpu.h>
19
20 #include <msp_int.h>
21
22 /* SLP bases systems */
23 extern void msp_slp_irq_init(void);
24 extern void msp_slp_irq_dispatch(void);
25
26 /* CIC based systems */
27 extern void msp_cic_irq_init(void);
28 extern void msp_cic_irq_dispatch(void);
29
30 /* VSMP support init */
31 extern void msp_vsmp_int_init(void);
32
33 /* vectored interrupt implementation */
34
35 /* SW0/1 interrupts are used for SMP/SMTC */
36 static inline void mac0_int_dispatch(void) { do_IRQ(MSP_INT_MAC0); }
37 static inline void mac1_int_dispatch(void) { do_IRQ(MSP_INT_MAC1); }
38 static inline void mac2_int_dispatch(void) { do_IRQ(MSP_INT_SAR); }
39 static inline void usb_int_dispatch(void)  { do_IRQ(MSP_INT_USB);  }
40 static inline void sec_int_dispatch(void)  { do_IRQ(MSP_INT_SEC);  }
41
42 /*
43  * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
44  * hierarchical system.  The first level are the direct MIPS interrupts
45  * and are assigned the interrupt range 0-7.  The second level is the SLM
46  * interrupt controller and is assigned the range 8-39.  The third level
47  * comprises the Peripherial block, the PCI block, the PCI MSI block and
48  * the SLP.  The PCI interrupts and the SLP errors are handled by the
49  * relevant subsystems so the core interrupt code needs only concern
50  * itself with the Peripheral block.  These are assigned interrupts in
51  * the range 40-71.
52  */
53
54 asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
55 {
56         u32 pending;
57
58         pending = read_c0_status() & read_c0_cause();
59
60         /*
61          * jump to the correct interrupt routine
62          * These are arranged in priority order and the timer
63          * comes first!
64          */
65
66 #ifdef CONFIG_IRQ_MSP_CIC       /* break out the CIC stuff for now */
67         if (pending & C_IRQ4)   /* do the peripherals first, that's the timer */
68                 msp_cic_irq_dispatch();
69
70         else if (pending & C_IRQ0)
71                 do_IRQ(MSP_INT_MAC0);
72
73         else if (pending & C_IRQ1)
74                 do_IRQ(MSP_INT_MAC1);
75
76         else if (pending & C_IRQ2)
77                 do_IRQ(MSP_INT_USB);
78
79         else if (pending & C_IRQ3)
80                 do_IRQ(MSP_INT_SAR);
81
82         else if (pending & C_IRQ5)
83                 do_IRQ(MSP_INT_SEC);
84
85 #else
86         if (pending & C_IRQ5)
87                 do_IRQ(MSP_INT_TIMER);
88
89         else if (pending & C_IRQ0)
90                 do_IRQ(MSP_INT_MAC0);
91
92         else if (pending & C_IRQ1)
93                 do_IRQ(MSP_INT_MAC1);
94
95         else if (pending & C_IRQ3)
96                 do_IRQ(MSP_INT_VE);
97
98         else if (pending & C_IRQ4)
99                 msp_slp_irq_dispatch();
100 #endif
101
102         else if (pending & C_SW0)       /* do software after hardware */
103                 do_IRQ(MSP_INT_SW0);
104
105         else if (pending & C_SW1)
106                 do_IRQ(MSP_INT_SW1);
107 }
108
109 static struct irqaction cic_cascade_msp = {
110         .handler = no_action,
111         .name    = "MSP CIC cascade",
112         .flags   = IRQF_NO_THREAD,
113 };
114
115 static struct irqaction per_cascade_msp = {
116         .handler = no_action,
117         .name    = "MSP PER cascade",
118         .flags   = IRQF_NO_THREAD,
119 };
120
121 void __init arch_init_irq(void)
122 {
123         /* assume we'll be using vectored interrupt mode except in UP mode*/
124 #ifdef CONFIG_MIPS_MT
125         BUG_ON(!cpu_has_vint);
126 #endif
127         /* initialize the 1st-level CPU based interrupt controller */
128         mips_cpu_irq_init();
129
130 #ifdef CONFIG_IRQ_MSP_CIC
131         msp_cic_irq_init();
132 #ifdef CONFIG_MIPS_MT
133         set_vi_handler(MSP_INT_CIC, msp_cic_irq_dispatch);
134         set_vi_handler(MSP_INT_MAC0, mac0_int_dispatch);
135         set_vi_handler(MSP_INT_MAC1, mac1_int_dispatch);
136         set_vi_handler(MSP_INT_SAR, mac2_int_dispatch);
137         set_vi_handler(MSP_INT_USB, usb_int_dispatch);
138         set_vi_handler(MSP_INT_SEC, sec_int_dispatch);
139 #ifdef CONFIG_MIPS_MT_SMP
140         msp_vsmp_int_init();
141 #elif defined CONFIG_MIPS_MT_SMTC
142         /*Set hwmask for all platform devices */
143         irq_hwmask[MSP_INT_MAC0] = C_IRQ0;
144         irq_hwmask[MSP_INT_MAC1] = C_IRQ1;
145         irq_hwmask[MSP_INT_USB] = C_IRQ2;
146         irq_hwmask[MSP_INT_SAR] = C_IRQ3;
147         irq_hwmask[MSP_INT_SEC] = C_IRQ5;
148
149 #endif  /* CONFIG_MIPS_MT_SMP */
150 #endif  /* CONFIG_MIPS_MT */
151         /* setup the cascaded interrupts */
152         setup_irq(MSP_INT_CIC, &cic_cascade_msp);
153         setup_irq(MSP_INT_PER, &per_cascade_msp);
154
155 #else
156         /* setup the 2nd-level SLP register based interrupt controller */
157         /* VSMP /SMTC support support is not enabled for SLP */
158         msp_slp_irq_init();
159
160         /* setup the cascaded SLP/PER interrupts */
161         setup_irq(MSP_INT_SLP, &cic_cascade_msp);
162         setup_irq(MSP_INT_PER, &per_cascade_msp);
163 #endif
164 }