softlockup: fix invalid proc_handler for softlockup_panic
[pandora-kernel.git] / arch / ppc / syslib / mpc52xx_pic.c
1 /*
2  * Programmable Interrupt Controller functions for the Freescale MPC52xx 
3  * embedded CPU.
4  *
5  * 
6  * Maintainer : Sylvain Munaut <tnt@246tNt.com>
7  *
8  * Based on (well, mostly copied from) the code from the 2.4 kernel by
9  * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
10  * 
11  * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
12  * Copyright (C) 2003 Montavista Software, Inc
13  * 
14  * This file is licensed under the terms of the GNU General Public License
15  * version 2. This program is licensed "as is" without any warranty of any
16  * kind, whether express or implied.
17  */
18
19 #include <linux/stddef.h>
20 #include <linux/init.h>
21 #include <linux/sched.h>
22 #include <linux/signal.h>
23 #include <linux/delay.h>
24 #include <linux/irq.h>
25
26 #include <asm/io.h>
27 #include <asm/processor.h>
28 #include <asm/system.h>
29 #include <asm/irq.h>
30 #include <asm/mpc52xx.h>
31
32
33 static struct mpc52xx_intr __iomem *intr;
34 static struct mpc52xx_sdma __iomem *sdma;
35
36 static void
37 mpc52xx_ic_disable(unsigned int irq)
38 {
39         u32 val;
40
41         if (irq == MPC52xx_IRQ0) {
42                 val = in_be32(&intr->ctrl);
43                 val &= ~(1 << 11);
44                 out_be32(&intr->ctrl, val);
45         }
46         else if (irq < MPC52xx_IRQ1) {
47                 BUG();
48         }
49         else if (irq <= MPC52xx_IRQ3) {
50                 val = in_be32(&intr->ctrl);
51                 val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));
52                 out_be32(&intr->ctrl, val);
53         }
54         else if (irq < MPC52xx_SDMA_IRQ_BASE) {
55                 val = in_be32(&intr->main_mask);
56                 val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));
57                 out_be32(&intr->main_mask, val);
58         }
59         else if (irq < MPC52xx_PERP_IRQ_BASE) {
60                 val = in_be32(&sdma->IntMask);
61                 val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);
62                 out_be32(&sdma->IntMask, val);
63         }
64         else {
65                 val = in_be32(&intr->per_mask);
66                 val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));
67                 out_be32(&intr->per_mask, val);
68         }
69 }
70
71 static void
72 mpc52xx_ic_enable(unsigned int irq)
73 {
74         u32 val;
75
76         if (irq == MPC52xx_IRQ0) {
77                 val = in_be32(&intr->ctrl);
78                 val |= 1 << 11;
79                 out_be32(&intr->ctrl, val);
80         }
81         else if (irq < MPC52xx_IRQ1) {
82                 BUG();
83         }
84         else if (irq <= MPC52xx_IRQ3) {
85                 val = in_be32(&intr->ctrl);
86                 val |= 1 << (10 - (irq - MPC52xx_IRQ1));
87                 out_be32(&intr->ctrl, val);
88         }
89         else if (irq < MPC52xx_SDMA_IRQ_BASE) {
90                 val = in_be32(&intr->main_mask);
91                 val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));
92                 out_be32(&intr->main_mask, val);
93         }
94         else if (irq < MPC52xx_PERP_IRQ_BASE) {
95                 val = in_be32(&sdma->IntMask);
96                 val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));
97                 out_be32(&sdma->IntMask, val);
98         }
99         else {
100                 val = in_be32(&intr->per_mask);
101                 val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));
102                 out_be32(&intr->per_mask, val);
103         }
104 }
105
106 static void
107 mpc52xx_ic_ack(unsigned int irq)
108 {
109         u32 val;
110
111         /*
112          * Only some irqs are reset here, others in interrupting hardware.
113          */
114
115         switch (irq) {
116         case MPC52xx_IRQ0:
117                 val = in_be32(&intr->ctrl);
118                 val |= 0x08000000;
119                 out_be32(&intr->ctrl, val);
120                 break;
121         case MPC52xx_CCS_IRQ:
122                 val = in_be32(&intr->enc_status);
123                 val |= 0x00000400;
124                 out_be32(&intr->enc_status, val);
125                 break;
126         case MPC52xx_IRQ1:
127                 val = in_be32(&intr->ctrl);
128                 val |= 0x04000000;
129                 out_be32(&intr->ctrl, val);
130                 break;
131         case MPC52xx_IRQ2:
132                 val = in_be32(&intr->ctrl);
133                 val |= 0x02000000;
134                 out_be32(&intr->ctrl, val);
135                 break;
136         case MPC52xx_IRQ3:
137                 val = in_be32(&intr->ctrl);
138                 val |= 0x01000000;
139                 out_be32(&intr->ctrl, val);
140                 break;
141         default:
142                 if (irq >= MPC52xx_SDMA_IRQ_BASE
143                     && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {
144                         out_be32(&sdma->IntPend,
145                                  1 << (irq - MPC52xx_SDMA_IRQ_BASE));
146                 }
147                 break;
148         }
149 }
150
151 static void
152 mpc52xx_ic_disable_and_ack(unsigned int irq)
153 {
154         mpc52xx_ic_disable(irq);
155         mpc52xx_ic_ack(irq);
156 }
157
158 static void
159 mpc52xx_ic_end(unsigned int irq)
160 {
161         if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
162                 mpc52xx_ic_enable(irq);
163 }
164
165 static struct hw_interrupt_type mpc52xx_ic = {
166         .typename       = " MPC52xx  ",
167         .enable         = mpc52xx_ic_enable,
168         .disable        = mpc52xx_ic_disable,
169         .ack            = mpc52xx_ic_disable_and_ack,
170         .end            = mpc52xx_ic_end,
171 };
172
173 void __init
174 mpc52xx_init_irq(void)
175 {
176         int i;
177         u32 intr_ctrl;
178
179         /* Remap the necessary zones */
180         intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
181         sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
182
183         if ((intr==NULL) || (sdma==NULL))
184                 panic("Can't ioremap PIC/SDMA register for init_irq !");
185
186         /* Disable all interrupt sources. */
187         out_be32(&sdma->IntPend, 0xffffffff);   /* 1 means clear pending */
188         out_be32(&sdma->IntMask, 0xffffffff);   /* 1 means disabled */
189         out_be32(&intr->per_mask, 0x7ffffc00);  /* 1 means disabled */
190         out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
191         intr_ctrl = in_be32(&intr->ctrl);
192         intr_ctrl &=    0x00ff0000;     /* Keeps IRQ[0-3] config */
193         intr_ctrl |=    0x0f000000 |    /* clear IRQ 0-3 */
194                         0x00001000 |    /* MEE master external enable */
195                         0x00000000 |    /* 0 means disable IRQ 0-3 */
196                         0x00000001;     /* CEb route critical normally */
197         out_be32(&intr->ctrl, intr_ctrl);
198
199         /* Zero a bunch of the priority settings.  */
200         out_be32(&intr->per_pri1, 0);
201         out_be32(&intr->per_pri2, 0);
202         out_be32(&intr->per_pri3, 0);
203         out_be32(&intr->main_pri1, 0);
204         out_be32(&intr->main_pri2, 0);
205
206         /* Initialize irq_desc[i].chip's with mpc52xx_ic. */
207         for (i = 0; i < NR_IRQS; i++) {
208                 irq_desc[i].chip = &mpc52xx_ic;
209                 irq_desc[i].status = IRQ_LEVEL;
210         }
211
212         #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)
213         for (i=0 ; i<4 ; i++) {
214                 int mode;
215                 mode = IRQn_MODE(intr_ctrl,i);
216                 if ((mode == 0x1) || (mode == 0x2))
217                         irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;
218         }
219 }
220
221 int
222 mpc52xx_get_irq(void)
223 {
224         u32 status;
225         int irq = -1;
226
227         status = in_be32(&intr->enc_status);
228
229         if (status & 0x00000400) {              /* critical */
230                 irq = (status >> 8) & 0x3;
231                 if (irq == 2)                   /* high priority peripheral */
232                         goto peripheral;
233                 irq += MPC52xx_CRIT_IRQ_BASE;
234         }
235         else if (status & 0x00200000) {         /* main */
236                 irq = (status >> 16) & 0x1f;
237                 if (irq == 4)                   /* low priority peripheral */
238                         goto peripheral;
239                 irq += MPC52xx_MAIN_IRQ_BASE;
240         }
241         else if (status & 0x20000000) {         /* peripheral */
242 peripheral:
243                 irq = (status >> 24) & 0x1f;
244                 if (irq == 0) {                 /* bestcomm */
245                         status = in_be32(&sdma->IntPend);
246                         irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;
247                 }
248                 else
249                         irq += MPC52xx_PERP_IRQ_BASE;
250         }
251
252         return irq;
253 }
254