aac2ff4e0b98bebcbc2c10707f518d95a966deb8
[openwrt/staging/yousong.git] / target / linux / adm8668 / files / arch / mips / adm8668 / irq.c
1 /*
2 * Copyright (C) 2010 Scott Nicholas <neutronscott@scottn.us>
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 */
8
9 #include <linux/init.h>
10 #include <linux/kernel_stat.h>
11 #include <linux/signal.h>
12 #include <linux/sched.h>
13 #include <linux/interrupt.h>
14 #include <linux/slab.h>
15 #include <linux/random.h>
16 #include <linux/pm.h>
17 #include <linux/irq.h>
18 #include <asm/mipsregs.h>
19 #include <asm/irq_cpu.h>
20 #include <asm/irq.h>
21 #include <adm8668.h>
22
23
24 void enable_adm8668_irq(unsigned int irq);
25 void disable_adm8668_irq(unsigned int irq);
26 void adm8668_irq_cascade(void);
27
28 void plat_irq_dispatch(void)
29 {
30 unsigned int pending;
31
32 pending = read_c0_cause() & read_c0_status() & ST0_IM;
33
34 /* timer interrupt, that we renumbered */
35 if (pending & STATUSF_IP7)
36 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
37 if (pending & STATUSF_IP2)
38 adm8668_irq_cascade();
39 }
40
41 /*
42 * System irq dispatch
43 */
44 void adm8668_irq_cascade()
45 {
46 int i;
47 unsigned long intsrc;
48
49 intsrc = ADM8668_INTC_REG(IRQ_STATUS_REG) & IRQ_MASK;
50 for (i = 0; intsrc; intsrc >>= 1, i++)
51 if (intsrc & 0x1)
52 do_IRQ(i);
53 }
54
55 /*
56 * irq enable
57 */
58 static __inline void _irq_enable(int irql)
59 {
60 ADM8668_INTC_REG(IRQ_ENABLE_REG) = (1 << irql);
61 }
62
63
64 /*
65 * irq disable
66 */
67 static __inline void _irq_disable(int irql)
68 {
69 ADM8668_INTC_REG(IRQ_DISABLE_REG) = (1 << irql);
70 }
71
72
73 /*
74 * enable 8668 irq
75 */
76 void enable_adm8668_irq(unsigned int irq)
77 {
78 if ((irq < 0) || (irq > NR_IRQS))
79 return;
80
81 _irq_enable(irq);
82 }
83
84
85 /*
86 * disable 8668 irq
87 */
88 void disable_adm8668_irq(unsigned int irq)
89 {
90 if ((irq < 0) || (irq > NR_IRQS))
91 return;
92
93 _irq_disable(irq);
94 }
95
96 static inline void ack_adm8668_irq(unsigned int irq_nr)
97 {
98 ADM8668_INTC_REG(IRQ_DISABLE_REG) = (1 << irq_nr);
99 }
100
101 /*
102 * system irq type
103 */
104
105 static struct irq_chip adm8668_irq_type = {
106 .name = "adm8668",
107 .ack = ack_adm8668_irq,
108 .mask = disable_adm8668_irq,
109 .unmask = enable_adm8668_irq
110 };
111
112 /*
113 * irq init
114 */
115 void __init init_adm8668_irqs(void)
116 {
117 int i;
118
119 for (i = 0; i <= INT_LVL_MAX; i++)
120 set_irq_chip_and_handler(i, &adm8668_irq_type,
121 handle_level_irq);
122
123 /* hw0 is where our interrupts are uh.. interrupted at. */
124 set_c0_status(IE_IRQ0);
125 }
126
127 /*
128 * system init
129 */
130 void __init arch_init_irq(void)
131 {
132 mips_cpu_irq_init();
133 init_adm8668_irqs();
134 }