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