MIPS: Loongson: Add oprofile support
[pandora-kernel.git] / arch / mips / lemote / lm2e / irq.c
1 /*
2  * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
3  * Author: Fuxin Zhang, zhangfx@lemote.com
4  *
5  *  This program is free software; you can redistribute  it and/or modify it
6  *  under  the terms of  the GNU General  Public License as published by the
7  *  Free Software Foundation;  either version 2 of the  License, or (at your
8  *  option) any later version.
9  */
10 #include <linux/delay.h>
11 #include <linux/interrupt.h>
12
13 #include <asm/irq_cpu.h>
14 #include <asm/i8259.h>
15
16 #include <loongson.h>
17 /*
18  * the first level int-handler will jump here if it is a bonito irq
19  */
20 static void bonito_irqdispatch(void)
21 {
22         u32 int_status;
23         int i;
24
25         /* workaround the IO dma problem: let cpu looping to allow DMA finish */
26         int_status = BONITO_INTISR;
27         if (int_status & (1 << 10)) {
28                 while (int_status & (1 << 10)) {
29                         udelay(1);
30                         int_status = BONITO_INTISR;
31                 }
32         }
33
34         /* Get pending sources, masked by current enables */
35         int_status = BONITO_INTISR & BONITO_INTEN;
36
37         if (int_status != 0) {
38                 i = __ffs(int_status);
39                 int_status &= ~(1 << i);
40                 do_IRQ(BONITO_IRQ_BASE + i);
41         }
42 }
43
44 static void i8259_irqdispatch(void)
45 {
46         int irq;
47
48         irq = i8259_irq();
49         if (irq >= 0)
50                 do_IRQ(irq);
51         else
52                 spurious_interrupt();
53 }
54
55 asmlinkage void plat_irq_dispatch(void)
56 {
57         unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
58
59         if (pending & CAUSEF_IP7)
60                 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
61         else if (pending & CAUSEF_IP6) /* perf counter loverflow */
62                 do_IRQ(LOONGSON2_PERFCNT_IRQ);
63         else if (pending & CAUSEF_IP5)
64                 i8259_irqdispatch();
65         else if (pending & CAUSEF_IP2)
66                 bonito_irqdispatch();
67         else
68                 spurious_interrupt();
69 }
70
71 static struct irqaction cascade_irqaction = {
72         .handler = no_action,
73         .name = "cascade",
74 };
75
76 void __init arch_init_irq(void)
77 {
78         /*
79          * Clear all of the interrupts while we change the able around a bit.
80          * int-handler is not on bootstrap
81          */
82         clear_c0_status(ST0_IM | ST0_BEV);
83         local_irq_disable();
84
85         /* most bonito irq should be level triggered */
86         BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
87                 BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
88         BONITO_INTSTEER = 0;
89
90         /*
91          * Mask out all interrupt by writing "1" to all bit position in
92          * the interrupt reset reg.
93          */
94         BONITO_INTENCLR = ~0;
95
96         /* init all controller
97          *   0-15         ------> i8259 interrupt
98          *   16-23        ------> mips cpu interrupt
99          *   32-63        ------> bonito irq
100          */
101
102         /* Sets the first-level interrupt dispatcher. */
103         mips_cpu_irq_init();
104         init_i8259_irqs();
105         bonito_irq_init();
106
107         /* bonito irq at IP2 */
108         setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
109         /* 8259 irq at IP5 */
110         setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
111 }