diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /arch/m68k/platform/68328/ints.c | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'arch/m68k/platform/68328/ints.c')
-rw-r--r-- | arch/m68k/platform/68328/ints.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/arch/m68k/platform/68328/ints.c b/arch/m68k/platform/68328/ints.c new file mode 100644 index 00000000000..4bd456531f9 --- /dev/null +++ b/arch/m68k/platform/68328/ints.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * linux/arch/m68knommu/platform/68328/ints.c | ||
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 | * Copyright 1996 Roman Zippel | ||
9 | * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <asm/traps.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/machdep.h> | ||
20 | |||
21 | #if defined(CONFIG_M68328) | ||
22 | #include <asm/MC68328.h> | ||
23 | #elif defined(CONFIG_M68EZ328) | ||
24 | #include <asm/MC68EZ328.h> | ||
25 | #elif defined(CONFIG_M68VZ328) | ||
26 | #include <asm/MC68VZ328.h> | ||
27 | #endif | ||
28 | |||
29 | /* assembler routines */ | ||
30 | asmlinkage void system_call(void); | ||
31 | asmlinkage void buserr(void); | ||
32 | asmlinkage void trap(void); | ||
33 | asmlinkage void trap3(void); | ||
34 | asmlinkage void trap4(void); | ||
35 | asmlinkage void trap5(void); | ||
36 | asmlinkage void trap6(void); | ||
37 | asmlinkage void trap7(void); | ||
38 | asmlinkage void trap8(void); | ||
39 | asmlinkage void trap9(void); | ||
40 | asmlinkage void trap10(void); | ||
41 | asmlinkage void trap11(void); | ||
42 | asmlinkage void trap12(void); | ||
43 | asmlinkage void trap13(void); | ||
44 | asmlinkage void trap14(void); | ||
45 | asmlinkage void trap15(void); | ||
46 | asmlinkage void trap33(void); | ||
47 | asmlinkage void trap34(void); | ||
48 | asmlinkage void trap35(void); | ||
49 | asmlinkage void trap36(void); | ||
50 | asmlinkage void trap37(void); | ||
51 | asmlinkage void trap38(void); | ||
52 | asmlinkage void trap39(void); | ||
53 | asmlinkage void trap40(void); | ||
54 | asmlinkage void trap41(void); | ||
55 | asmlinkage void trap42(void); | ||
56 | asmlinkage void trap43(void); | ||
57 | asmlinkage void trap44(void); | ||
58 | asmlinkage void trap45(void); | ||
59 | asmlinkage void trap46(void); | ||
60 | asmlinkage void trap47(void); | ||
61 | asmlinkage irqreturn_t bad_interrupt(int, void *); | ||
62 | asmlinkage irqreturn_t inthandler(void); | ||
63 | asmlinkage irqreturn_t inthandler1(void); | ||
64 | asmlinkage irqreturn_t inthandler2(void); | ||
65 | asmlinkage irqreturn_t inthandler3(void); | ||
66 | asmlinkage irqreturn_t inthandler4(void); | ||
67 | asmlinkage irqreturn_t inthandler5(void); | ||
68 | asmlinkage irqreturn_t inthandler6(void); | ||
69 | asmlinkage irqreturn_t inthandler7(void); | ||
70 | |||
71 | extern e_vector *_ramvec; | ||
72 | |||
73 | /* The 68k family did not have a good way to determine the source | ||
74 | * of interrupts until later in the family. The EC000 core does | ||
75 | * not provide the vector number on the stack, we vector everything | ||
76 | * into one vector and look in the blasted mask register... | ||
77 | * This code is designed to be fast, almost constant time, not clean! | ||
78 | */ | ||
79 | void process_int(int vec, struct pt_regs *fp) | ||
80 | { | ||
81 | int irq; | ||
82 | int mask; | ||
83 | |||
84 | unsigned long pend = ISR; | ||
85 | |||
86 | while (pend) { | ||
87 | if (pend & 0x0000ffff) { | ||
88 | if (pend & 0x000000ff) { | ||
89 | if (pend & 0x0000000f) { | ||
90 | mask = 0x00000001; | ||
91 | irq = 0; | ||
92 | } else { | ||
93 | mask = 0x00000010; | ||
94 | irq = 4; | ||
95 | } | ||
96 | } else { | ||
97 | if (pend & 0x00000f00) { | ||
98 | mask = 0x00000100; | ||
99 | irq = 8; | ||
100 | } else { | ||
101 | mask = 0x00001000; | ||
102 | irq = 12; | ||
103 | } | ||
104 | } | ||
105 | } else { | ||
106 | if (pend & 0x00ff0000) { | ||
107 | if (pend & 0x000f0000) { | ||
108 | mask = 0x00010000; | ||
109 | irq = 16; | ||
110 | } else { | ||
111 | mask = 0x00100000; | ||
112 | irq = 20; | ||
113 | } | ||
114 | } else { | ||
115 | if (pend & 0x0f000000) { | ||
116 | mask = 0x01000000; | ||
117 | irq = 24; | ||
118 | } else { | ||
119 | mask = 0x10000000; | ||
120 | irq = 28; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | while (! (mask & pend)) { | ||
126 | mask <<=1; | ||
127 | irq++; | ||
128 | } | ||
129 | |||
130 | do_IRQ(irq, fp); | ||
131 | pend &= ~mask; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void intc_irq_unmask(struct irq_data *d) | ||
136 | { | ||
137 | IMR &= ~(1 << d->irq); | ||
138 | } | ||
139 | |||
140 | static void intc_irq_mask(struct irq_data *d) | ||
141 | { | ||
142 | IMR |= (1 << d->irq); | ||
143 | } | ||
144 | |||
145 | static struct irq_chip intc_irq_chip = { | ||
146 | .name = "M68K-INTC", | ||
147 | .irq_mask = intc_irq_mask, | ||
148 | .irq_unmask = intc_irq_unmask, | ||
149 | }; | ||
150 | |||
151 | /* | ||
152 | * This function should be called during kernel startup to initialize | ||
153 | * the machine vector table. | ||
154 | */ | ||
155 | void __init trap_init(void) | ||
156 | { | ||
157 | int i; | ||
158 | |||
159 | /* set up the vectors */ | ||
160 | for (i = 72; i < 256; ++i) | ||
161 | _ramvec[i] = (e_vector) bad_interrupt; | ||
162 | |||
163 | _ramvec[32] = system_call; | ||
164 | |||
165 | _ramvec[65] = (e_vector) inthandler1; | ||
166 | _ramvec[66] = (e_vector) inthandler2; | ||
167 | _ramvec[67] = (e_vector) inthandler3; | ||
168 | _ramvec[68] = (e_vector) inthandler4; | ||
169 | _ramvec[69] = (e_vector) inthandler5; | ||
170 | _ramvec[70] = (e_vector) inthandler6; | ||
171 | _ramvec[71] = (e_vector) inthandler7; | ||
172 | } | ||
173 | |||
174 | void __init init_IRQ(void) | ||
175 | { | ||
176 | int i; | ||
177 | |||
178 | IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ | ||
179 | |||
180 | /* turn off all interrupts */ | ||
181 | IMR = ~0; | ||
182 | |||
183 | for (i = 0; (i < NR_IRQS); i++) { | ||
184 | irq_set_chip(i, &intc_irq_chip); | ||
185 | irq_set_handler(i, handle_level_irq); | ||
186 | } | ||
187 | } | ||
188 | |||