Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney...
[pandora-kernel.git] / arch / powerpc / platforms / 52xx / mpc52xx_pic.c
1 /*
2  *
3  * Programmable Interrupt Controller functions for the Freescale MPC52xx.
4  *
5  * Copyright (C) 2006 bplan GmbH
6  *
7  * Based on the code from the 2.4 kernel by
8  * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
9  *
10  * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
11  * Copyright (C) 2003 Montavista Software, Inc
12  *
13  * This file is licensed under the terms of the GNU General Public License
14  * version 2. This program is licensed "as is" without any warranty of any
15  * kind, whether express or implied.
16  *
17  */
18
19 #undef DEBUG
20
21 #include <linux/interrupt.h>
22 #include <linux/irq.h>
23 #include <linux/of.h>
24 #include <asm/io.h>
25 #include <asm/prom.h>
26 #include <asm/mpc52xx.h>
27 #include "mpc52xx_pic.h"
28
29 /*
30  *
31 */
32
33 /* MPC5200 device tree match tables */
34 static struct of_device_id mpc52xx_pic_ids[] __initdata = {
35         { .compatible = "fsl,mpc5200-pic", },
36         { .compatible = "mpc5200-pic", },
37         {}
38 };
39 static struct of_device_id mpc52xx_sdma_ids[] __initdata = {
40         { .compatible = "fsl,mpc5200-bestcomm", },
41         { .compatible = "mpc5200-bestcomm", },
42         {}
43 };
44
45 static struct mpc52xx_intr __iomem *intr;
46 static struct mpc52xx_sdma __iomem *sdma;
47 static struct irq_host *mpc52xx_irqhost = NULL;
48
49 static unsigned char mpc52xx_map_senses[4] = {
50         IRQ_TYPE_LEVEL_HIGH,
51         IRQ_TYPE_EDGE_RISING,
52         IRQ_TYPE_EDGE_FALLING,
53         IRQ_TYPE_LEVEL_LOW,
54 };
55
56 /*
57  *
58 */
59
60 static inline void io_be_setbit(u32 __iomem *addr, int bitno)
61 {
62         out_be32(addr, in_be32(addr) | (1 << bitno));
63 }
64
65 static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
66 {
67         out_be32(addr, in_be32(addr) & ~(1 << bitno));
68 }
69
70 /*
71  * IRQ[0-3] interrupt irq_chip
72 */
73
74 static void mpc52xx_extirq_mask(unsigned int virq)
75 {
76         int irq;
77         int l2irq;
78
79         irq = irq_map[virq].hwirq;
80         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
81
82         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
83
84         io_be_clrbit(&intr->ctrl, 11 - l2irq);
85 }
86
87 static void mpc52xx_extirq_unmask(unsigned int virq)
88 {
89         int irq;
90         int l2irq;
91
92         irq = irq_map[virq].hwirq;
93         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
94
95         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
96
97         io_be_setbit(&intr->ctrl, 11 - l2irq);
98 }
99
100 static void mpc52xx_extirq_ack(unsigned int virq)
101 {
102         int irq;
103         int l2irq;
104
105         irq = irq_map[virq].hwirq;
106         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
107
108         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
109
110         io_be_setbit(&intr->ctrl, 27-l2irq);
111 }
112
113 static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
114 {
115         u32 ctrl_reg, type;
116         int irq;
117         int l2irq;
118
119         irq = irq_map[virq].hwirq;
120         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
121
122         pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
123
124         switch (flow_type) {
125         case IRQF_TRIGGER_HIGH:
126                 type = 0;
127                 break;
128         case IRQF_TRIGGER_RISING:
129                 type = 1;
130                 break;
131         case IRQF_TRIGGER_FALLING:
132                 type = 2;
133                 break;
134         case IRQF_TRIGGER_LOW:
135                 type = 3;
136                 break;
137         default:
138                 type = 0;
139         }
140
141         ctrl_reg = in_be32(&intr->ctrl);
142         ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
143         ctrl_reg |= (type << (22 - (l2irq * 2)));
144         out_be32(&intr->ctrl, ctrl_reg);
145
146         return 0;
147 }
148
149 static struct irq_chip mpc52xx_extirq_irqchip = {
150         .typename = " MPC52xx IRQ[0-3] ",
151         .mask = mpc52xx_extirq_mask,
152         .unmask = mpc52xx_extirq_unmask,
153         .ack = mpc52xx_extirq_ack,
154         .set_type = mpc52xx_extirq_set_type,
155 };
156
157 /*
158  * Main interrupt irq_chip
159 */
160
161 static void mpc52xx_main_mask(unsigned int virq)
162 {
163         int irq;
164         int l2irq;
165
166         irq = irq_map[virq].hwirq;
167         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
168
169         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
170
171         io_be_setbit(&intr->main_mask, 16 - l2irq);
172 }
173
174 static void mpc52xx_main_unmask(unsigned int virq)
175 {
176         int irq;
177         int l2irq;
178
179         irq = irq_map[virq].hwirq;
180         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
181
182         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
183
184         io_be_clrbit(&intr->main_mask, 16 - l2irq);
185 }
186
187 static struct irq_chip mpc52xx_main_irqchip = {
188         .typename = "MPC52xx Main",
189         .mask = mpc52xx_main_mask,
190         .mask_ack = mpc52xx_main_mask,
191         .unmask = mpc52xx_main_unmask,
192 };
193
194 /*
195  * Peripherals interrupt irq_chip
196 */
197
198 static void mpc52xx_periph_mask(unsigned int virq)
199 {
200         int irq;
201         int l2irq;
202
203         irq = irq_map[virq].hwirq;
204         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
205
206         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
207
208         io_be_setbit(&intr->per_mask, 31 - l2irq);
209 }
210
211 static void mpc52xx_periph_unmask(unsigned int virq)
212 {
213         int irq;
214         int l2irq;
215
216         irq = irq_map[virq].hwirq;
217         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
218
219         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
220
221         io_be_clrbit(&intr->per_mask, 31 - l2irq);
222 }
223
224 static struct irq_chip mpc52xx_periph_irqchip = {
225         .typename = "MPC52xx Peripherals",
226         .mask = mpc52xx_periph_mask,
227         .mask_ack = mpc52xx_periph_mask,
228         .unmask = mpc52xx_periph_unmask,
229 };
230
231 /*
232  * SDMA interrupt irq_chip
233 */
234
235 static void mpc52xx_sdma_mask(unsigned int virq)
236 {
237         int irq;
238         int l2irq;
239
240         irq = irq_map[virq].hwirq;
241         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
242
243         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
244
245         io_be_setbit(&sdma->IntMask, l2irq);
246 }
247
248 static void mpc52xx_sdma_unmask(unsigned int virq)
249 {
250         int irq;
251         int l2irq;
252
253         irq = irq_map[virq].hwirq;
254         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
255
256         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
257
258         io_be_clrbit(&sdma->IntMask, l2irq);
259 }
260
261 static void mpc52xx_sdma_ack(unsigned int virq)
262 {
263         int irq;
264         int l2irq;
265
266         irq = irq_map[virq].hwirq;
267         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
268
269         pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
270
271         out_be32(&sdma->IntPend, 1 << l2irq);
272 }
273
274 static struct irq_chip mpc52xx_sdma_irqchip = {
275         .typename = "MPC52xx SDMA",
276         .mask = mpc52xx_sdma_mask,
277         .unmask = mpc52xx_sdma_unmask,
278         .ack = mpc52xx_sdma_ack,
279 };
280
281 /*
282  * irq_host
283 */
284
285 static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
286                                  u32 * intspec, unsigned int intsize,
287                                  irq_hw_number_t * out_hwirq,
288                                  unsigned int *out_flags)
289 {
290         int intrvect_l1;
291         int intrvect_l2;
292         int intrvect_type;
293         int intrvect_linux;
294
295         if (intsize != 3)
296                 return -1;
297
298         intrvect_l1 = (int)intspec[0];
299         intrvect_l2 = (int)intspec[1];
300         intrvect_type = (int)intspec[2];
301
302         intrvect_linux =
303             (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
304         intrvect_linux |=
305             (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
306
307         pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
308                  intrvect_l2);
309
310         *out_hwirq = intrvect_linux;
311         *out_flags = mpc52xx_map_senses[intrvect_type];
312
313         return 0;
314 }
315
316 /*
317  * this function retrieves the correct IRQ type out
318  * of the MPC regs
319  * Only externals IRQs needs this
320 */
321 static int mpc52xx_irqx_gettype(int irq)
322 {
323         int type;
324         u32 ctrl_reg;
325
326         ctrl_reg = in_be32(&intr->ctrl);
327         type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
328
329         return mpc52xx_map_senses[type];
330 }
331
332 static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
333                                irq_hw_number_t irq)
334 {
335         int l1irq;
336         int l2irq;
337         struct irq_chip *good_irqchip;
338         void *good_handle;
339         int type;
340
341         l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
342         l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
343
344         /*
345          * Most of ours IRQs will be level low
346          * Only external IRQs on some platform may be others
347          */
348         type = IRQ_TYPE_LEVEL_LOW;
349
350         switch (l1irq) {
351         case MPC52xx_IRQ_L1_CRIT:
352                 pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
353
354                 BUG_ON(l2irq != 0);
355
356                 type = mpc52xx_irqx_gettype(l2irq);
357                 good_irqchip = &mpc52xx_extirq_irqchip;
358                 break;
359
360         case MPC52xx_IRQ_L1_MAIN:
361                 pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
362
363                 if ((l2irq >= 1) && (l2irq <= 3)) {
364                         type = mpc52xx_irqx_gettype(l2irq);
365                         good_irqchip = &mpc52xx_extirq_irqchip;
366                 } else {
367                         good_irqchip = &mpc52xx_main_irqchip;
368                 }
369                 break;
370
371         case MPC52xx_IRQ_L1_PERP:
372                 pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
373                 good_irqchip = &mpc52xx_periph_irqchip;
374                 break;
375
376         case MPC52xx_IRQ_L1_SDMA:
377                 pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
378                 good_irqchip = &mpc52xx_sdma_irqchip;
379                 break;
380
381         default:
382                 pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
383                 printk(KERN_ERR "Unknow IRQ!\n");
384                 return -EINVAL;
385         }
386
387         switch (type) {
388         case IRQ_TYPE_EDGE_FALLING:
389         case IRQ_TYPE_EDGE_RISING:
390                 good_handle = handle_edge_irq;
391                 break;
392         default:
393                 good_handle = handle_level_irq;
394         }
395
396         set_irq_chip_and_handler(virq, good_irqchip, good_handle);
397
398         pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
399                  (int)irq, type);
400
401         return 0;
402 }
403
404 static struct irq_host_ops mpc52xx_irqhost_ops = {
405         .xlate = mpc52xx_irqhost_xlate,
406         .map = mpc52xx_irqhost_map,
407 };
408
409 /*
410  * init (public)
411 */
412
413 void __init mpc52xx_init_irq(void)
414 {
415         u32 intr_ctrl;
416         struct device_node *picnode;
417         struct device_node *np;
418
419         /* Remap the necessary zones */
420         picnode = of_find_matching_node(NULL, mpc52xx_pic_ids);
421         intr = of_iomap(picnode, 0);
422         if (!intr)
423                 panic(__FILE__  ": find_and_map failed on 'mpc5200-pic'. "
424                                 "Check node !");
425
426         np = of_find_matching_node(NULL, mpc52xx_sdma_ids);
427         sdma = of_iomap(np, 0);
428         of_node_put(np);
429         if (!sdma)
430                 panic(__FILE__  ": find_and_map failed on 'mpc5200-bestcomm'. "
431                                 "Check node !");
432
433         /* Disable all interrupt sources. */
434         out_be32(&sdma->IntPend, 0xffffffff);   /* 1 means clear pending */
435         out_be32(&sdma->IntMask, 0xffffffff);   /* 1 means disabled */
436         out_be32(&intr->per_mask, 0x7ffffc00);  /* 1 means disabled */
437         out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
438         intr_ctrl = in_be32(&intr->ctrl);
439         intr_ctrl &= 0x00ff0000;        /* Keeps IRQ[0-3] config */
440         intr_ctrl |=    0x0f000000 |    /* clear IRQ 0-3 */
441                         0x00001000 |    /* MEE master external enable */
442                         0x00000000 |    /* 0 means disable IRQ 0-3 */
443                         0x00000001;     /* CEb route critical normally */
444         out_be32(&intr->ctrl, intr_ctrl);
445
446         /* Zero a bunch of the priority settings. */
447         out_be32(&intr->per_pri1, 0);
448         out_be32(&intr->per_pri2, 0);
449         out_be32(&intr->per_pri3, 0);
450         out_be32(&intr->main_pri1, 0);
451         out_be32(&intr->main_pri2, 0);
452
453         /*
454          * As last step, add an irq host to translate the real
455          * hw irq information provided by the ofw to linux virq
456          */
457
458         mpc52xx_irqhost = irq_alloc_host(picnode, IRQ_HOST_MAP_LINEAR,
459                                          MPC52xx_IRQ_HIGHTESTHWIRQ,
460                                          &mpc52xx_irqhost_ops, -1);
461
462         if (!mpc52xx_irqhost)
463                 panic(__FILE__ ": Cannot allocate the IRQ host\n");
464
465         printk(KERN_INFO "MPC52xx PIC is up and running!\n");
466 }
467
468 /*
469  * get_irq (public)
470 */
471 unsigned int mpc52xx_get_irq(void)
472 {
473         u32 status;
474         int irq = NO_IRQ_IGNORE;
475
476         status = in_be32(&intr->enc_status);
477         if (status & 0x00000400) {      /* critical */
478                 irq = (status >> 8) & 0x3;
479                 if (irq == 2)   /* high priority peripheral */
480                         goto peripheral;
481                 irq |=  (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
482                         MPC52xx_IRQ_L1_MASK;
483         } else if (status & 0x00200000) {       /* main */
484                 irq = (status >> 16) & 0x1f;
485                 if (irq == 4)   /* low priority peripheral */
486                         goto peripheral;
487                 irq |=  (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
488                         MPC52xx_IRQ_L1_MASK;
489         } else if (status & 0x20000000) {       /* peripheral */
490               peripheral:
491                 irq = (status >> 24) & 0x1f;
492                 if (irq == 0) { /* bestcomm */
493                         status = in_be32(&sdma->IntPend);
494                         irq = ffs(status) - 1;
495                         irq |=  (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
496                                 MPC52xx_IRQ_L1_MASK;
497                 } else {
498                         irq |=  (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
499                                 MPC52xx_IRQ_L1_MASK;
500                 }
501         }
502
503         pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
504                  irq_linear_revmap(mpc52xx_irqhost, irq));
505
506         return irq_linear_revmap(mpc52xx_irqhost, irq);
507 }