aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k/mac
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2011-10-23 10:11:18 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2011-12-10 13:52:47 -0500
commitda3fb3c9aaa357421ade92910303af82340c2ff5 (patch)
tree707a75995ef4638355229e096e4cdad32c5c9246 /arch/m68k/mac
parentc4af5da7f24ff1bf60db2d6ff3e9d9bd912ca47a (diff)
m68k/mac: oss irq fixes
The IOP driver calls into the OSS driver to enable its IRQ. This undesirable coupling between drivers only exists because the OSS driver doesn't correctly handle all of its machspec IRQs. Fix OSS handling of enable/disable for VIA1 IRQs (8 thru 15) which includes MAC_IRQ_ADB. Back when I implemented pmac_zilog support I redefined IRQ_MAC_SCC incorrectly. Change this to a machspec IRQ so that it works on OSS. Clean up the unused OSS audio IRQ and OSS_IRQLEV_* cruft that only confuses things. Fix the OSS description in macints.c and remove an obsolete comment. Don't enable the VIA1 irq before registering the handler. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68k/mac')
-rw-r--r--arch/m68k/mac/config.c10
-rw-r--r--arch/m68k/mac/iop.c8
-rw-r--r--arch/m68k/mac/macints.c45
-rw-r--r--arch/m68k/mac/oss.c97
4 files changed, 73 insertions, 87 deletions
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 12e564c62957..101a8b7e2d52 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -893,8 +893,14 @@ static void __init mac_identify(void)
893 scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC_B; 893 scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC_B;
894 break; 894 break;
895 default: 895 default:
896 scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC; 896 /* On non-PSC machines, the serial ports share an IRQ. */
897 scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC; 897 if (macintosh_config->ident == MAC_MODEL_IIFX) {
898 scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_MAC_SCC;
899 scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_MAC_SCC;
900 } else {
901 scc_a_rsrcs[1].start = scc_a_rsrcs[1].end = IRQ_AUTO_4;
902 scc_b_rsrcs[1].start = scc_b_rsrcs[1].end = IRQ_AUTO_4;
903 }
898 break; 904 break;
899 } 905 }
900 906
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index a5462cc0bfd6..7d8d46127ad9 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -115,7 +115,6 @@
115#include <asm/macintosh.h> 115#include <asm/macintosh.h>
116#include <asm/macints.h> 116#include <asm/macints.h>
117#include <asm/mac_iop.h> 117#include <asm/mac_iop.h>
118#include <asm/mac_oss.h>
119 118
120/*#define DEBUG_IOP*/ 119/*#define DEBUG_IOP*/
121 120
@@ -149,8 +148,6 @@ static struct listener iop_listeners[NUM_IOPS][NUM_IOP_CHAN];
149 148
150irqreturn_t iop_ism_irq(int, void *); 149irqreturn_t iop_ism_irq(int, void *);
151 150
152extern void oss_irq_enable(int);
153
154/* 151/*
155 * Private access functions 152 * Private access functions
156 */ 153 */
@@ -304,11 +301,10 @@ void __init iop_init(void)
304void __init iop_register_interrupts(void) 301void __init iop_register_interrupts(void)
305{ 302{
306 if (iop_ism_present) { 303 if (iop_ism_present) {
307 if (oss_present) { 304 if (macintosh_config->ident == MAC_MODEL_IIFX) {
308 if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0, 305 if (request_irq(IRQ_MAC_ADB, iop_ism_irq, 0,
309 "ISM IOP", (void *)IOP_NUM_ISM)) 306 "ISM IOP", (void *)IOP_NUM_ISM))
310 pr_err("Couldn't register ISM IOP interrupt\n"); 307 pr_err("Couldn't register ISM IOP interrupt\n");
311 oss_irq_enable(IRQ_MAC_ADB);
312 } else { 308 } else {
313 if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP", 309 if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
314 (void *)IOP_NUM_ISM)) 310 (void *)IOP_NUM_ISM))
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 74f5a97c9860..5c1a6b2ff0af 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -26,10 +26,6 @@
26 * - slot 6: timer 1 (not on IIci) 26 * - slot 6: timer 1 (not on IIci)
27 * - slot 7: status of IRQ; signals 'any enabled int.' 27 * - slot 7: status of IRQ; signals 'any enabled int.'
28 * 28 *
29 * 2 - OSS (IIfx only?)
30 * - slot 0: SCSI interrupt
31 * - slot 1: Sound interrupt
32 *
33 * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes: 29 * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes:
34 * 30 *
35 * 3 - unused (?) 31 * 3 - unused (?)
@@ -54,21 +50,18 @@
54 * 50 *
55 * 6 - VIA1 51 * 6 - VIA1
56 * 52 *
57 * For OSS Macintoshes (IIfx only at this point): 53 * For OSS Macintoshes (IIfx only), we apply an interrupt mapping similar to
54 * the Quadra (A/UX) mapping:
58 * 55 *
59 * 3 - Nubus interrupt 56 * 1 - ISM IOP (ADB)
60 * - slot 0: Slot $9
61 * - slot 1: Slot $A
62 * - slot 2: Slot $B
63 * - slot 3: Slot $C
64 * - slot 4: Slot $D
65 * - slot 5: Slot $E
66 * 57 *
67 * 4 - SCC IOP 58 * 2 - SCSI
68 * 59 *
69 * 5 - ISM IOP (ADB?) 60 * 3 - NuBus
70 * 61 *
71 * 6 - unused 62 * 4 - SCC IOP
63 *
64 * 6 - VIA1
72 * 65 *
73 * For PSC Macintoshes (660AV, 840AV): 66 * For PSC Macintoshes (660AV, 840AV):
74 * 67 *
@@ -112,14 +105,6 @@
112 * case. They're hidden behind the Nubus slot $C interrupt thus adding a 105 * case. They're hidden behind the Nubus slot $C interrupt thus adding a
113 * third layer of indirection. Why oh why did the Apple engineers do that? 106 * third layer of indirection. Why oh why did the Apple engineers do that?
114 * 107 *
115 * - We support "fast" and "slow" handlers, just like the Amiga port. The
116 * fast handlers are called first and with all interrupts disabled. They
117 * are expected to execute quickly (hence the name). The slow handlers are
118 * called last with interrupts enabled and the interrupt level restored.
119 * They must therefore be reentrant.
120 *
121 * TODO:
122 *
123 */ 108 */
124 109
125#include <linux/types.h> 110#include <linux/types.h>
@@ -216,8 +201,6 @@ void mac_irq_enable(struct irq_data *data)
216 201
217 switch(irq_src) { 202 switch(irq_src) {
218 case 1: 203 case 1:
219 via_irq_enable(irq);
220 break;
221 case 2: 204 case 2:
222 case 7: 205 case 7:
223 if (oss_present) 206 if (oss_present)
@@ -226,6 +209,7 @@ void mac_irq_enable(struct irq_data *data)
226 via_irq_enable(irq); 209 via_irq_enable(irq);
227 break; 210 break;
228 case 3: 211 case 3:
212 case 4:
229 case 5: 213 case 5:
230 case 6: 214 case 6:
231 if (psc_present) 215 if (psc_present)
@@ -233,10 +217,6 @@ void mac_irq_enable(struct irq_data *data)
233 else if (oss_present) 217 else if (oss_present)
234 oss_irq_enable(irq); 218 oss_irq_enable(irq);
235 break; 219 break;
236 case 4:
237 if (psc_present)
238 psc_irq_enable(irq);
239 break;
240 case 8: 220 case 8:
241 if (baboon_present) 221 if (baboon_present)
242 baboon_irq_enable(irq); 222 baboon_irq_enable(irq);
@@ -251,8 +231,6 @@ void mac_irq_disable(struct irq_data *data)
251 231
252 switch(irq_src) { 232 switch(irq_src) {
253 case 1: 233 case 1:
254 via_irq_disable(irq);
255 break;
256 case 2: 234 case 2:
257 case 7: 235 case 7:
258 if (oss_present) 236 if (oss_present)
@@ -261,6 +239,7 @@ void mac_irq_disable(struct irq_data *data)
261 via_irq_disable(irq); 239 via_irq_disable(irq);
262 break; 240 break;
263 case 3: 241 case 3:
242 case 4:
264 case 5: 243 case 5:
265 case 6: 244 case 6:
266 if (psc_present) 245 if (psc_present)
@@ -268,10 +247,6 @@ void mac_irq_disable(struct irq_data *data)
268 else if (oss_present) 247 else if (oss_present)
269 oss_irq_disable(irq); 248 oss_irq_disable(irq);
270 break; 249 break;
271 case 4:
272 if (psc_present)
273 psc_irq_disable(irq);
274 break;
275 case 8: 250 case 8:
276 if (baboon_present) 251 if (baboon_present)
277 baboon_irq_disable(irq); 252 baboon_irq_disable(irq);
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index fdc0f843ff6f..6c4c882c126e 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * OSS handling 2 * Operating System Services (OSS) chip handling
3 * Written by Joshua M. Thompson (funaho@jurai.org) 3 * Written by Joshua M. Thompson (funaho@jurai.org)
4 * 4 *
5 * 5 *
@@ -49,10 +49,8 @@ void __init oss_init(void)
49 /* do this by setting the source's interrupt level to zero. */ 49 /* do this by setting the source's interrupt level to zero. */
50 50
51 for (i = 0; i <= OSS_NUM_SOURCES; i++) { 51 for (i = 0; i <= OSS_NUM_SOURCES; i++) {
52 oss->irq_level[i] = OSS_IRQLEV_DISABLED; 52 oss->irq_level[i] = 0;
53 } 53 }
54 /* If we disable VIA1 here, we never really handle it... */
55 oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
56} 54}
57 55
58/* 56/*
@@ -64,17 +62,13 @@ void __init oss_nubus_init(void)
64} 62}
65 63
66/* 64/*
67 * Handle miscellaneous OSS interrupts. Right now that's just sound 65 * Handle miscellaneous OSS interrupts.
68 * and SCSI; everything else is routed to its own autovector IRQ.
69 */ 66 */
70 67
71static void oss_irq(unsigned int irq, struct irq_desc *desc) 68static void oss_irq(unsigned int irq, struct irq_desc *desc)
72{ 69{
73 int events; 70 int events = oss->irq_pending &
74 71 (OSS_IP_IOPSCC | OSS_IP_SCSI | OSS_IP_IOPISM);
75 events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
76 if (!events)
77 return;
78 72
79#ifdef DEBUG_IRQS 73#ifdef DEBUG_IRQS
80 if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) { 74 if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
@@ -82,16 +76,20 @@ static void oss_irq(unsigned int irq, struct irq_desc *desc)
82 (int) oss->irq_pending); 76 (int) oss->irq_pending);
83 } 77 }
84#endif 78#endif
85 /* FIXME: how do you clear a pending IRQ? */
86 79
87 if (events & OSS_IP_SOUND) { 80 if (events & OSS_IP_IOPSCC) {
88 oss->irq_pending &= ~OSS_IP_SOUND; 81 oss->irq_pending &= ~OSS_IP_IOPSCC;
89 /* FIXME: call sound handler */ 82 generic_handle_irq(IRQ_MAC_SCC);
90 } else if (events & OSS_IP_SCSI) { 83 }
84
85 if (events & OSS_IP_SCSI) {
91 oss->irq_pending &= ~OSS_IP_SCSI; 86 oss->irq_pending &= ~OSS_IP_SCSI;
92 generic_handle_irq(IRQ_MAC_SCSI); 87 generic_handle_irq(IRQ_MAC_SCSI);
93 } else { 88 }
94 /* FIXME: error check here? */ 89
90 if (events & OSS_IP_IOPISM) {
91 oss->irq_pending &= ~OSS_IP_IOPISM;
92 generic_handle_irq(IRQ_MAC_ADB);
95 } 93 }
96} 94}
97 95
@@ -130,14 +128,29 @@ static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
130 128
131/* 129/*
132 * Register the OSS and NuBus interrupt dispatchers. 130 * Register the OSS and NuBus interrupt dispatchers.
131 *
132 * This IRQ mapping is laid out with two things in mind: first, we try to keep
133 * things on their own levels to avoid having to do double-dispatches. Second,
134 * the levels match as closely as possible the alternate IRQ mapping mode (aka
135 * "A/UX mode") available on some VIA machines.
133 */ 136 */
134 137
138#define OSS_IRQLEV_IOPISM IRQ_AUTO_1
139#define OSS_IRQLEV_SCSI IRQ_AUTO_2
140#define OSS_IRQLEV_NUBUS IRQ_AUTO_3
141#define OSS_IRQLEV_IOPSCC IRQ_AUTO_4
142#define OSS_IRQLEV_VIA1 IRQ_AUTO_6
143
135void __init oss_register_interrupts(void) 144void __init oss_register_interrupts(void)
136{ 145{
137 irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq); 146 irq_set_chained_handler(OSS_IRQLEV_IOPISM, oss_irq);
138 irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq); 147 irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
139 irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq); 148 irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
140 irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq); 149 irq_set_chained_handler(OSS_IRQLEV_IOPSCC, oss_irq);
150 irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
151
152 /* OSS_VIA1 gets enabled here because it has no machspec interrupt. */
153 oss->irq_level[OSS_VIA1] = IRQ_AUTO_6;
141} 154}
142 155
143/* 156/*
@@ -156,13 +169,13 @@ void oss_irq_enable(int irq) {
156 switch(irq) { 169 switch(irq) {
157 case IRQ_MAC_SCC: 170 case IRQ_MAC_SCC:
158 oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC; 171 oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_IOPSCC;
159 break; 172 return;
160 case IRQ_MAC_ADB: 173 case IRQ_MAC_ADB:
161 oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM; 174 oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_IOPISM;
162 break; 175 return;
163 case IRQ_MAC_SCSI: 176 case IRQ_MAC_SCSI:
164 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI; 177 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
165 break; 178 return;
166 case IRQ_NUBUS_9: 179 case IRQ_NUBUS_9:
167 case IRQ_NUBUS_A: 180 case IRQ_NUBUS_A:
168 case IRQ_NUBUS_B: 181 case IRQ_NUBUS_B:
@@ -171,13 +184,11 @@ void oss_irq_enable(int irq) {
171 case IRQ_NUBUS_E: 184 case IRQ_NUBUS_E:
172 irq -= NUBUS_SOURCE_BASE; 185 irq -= NUBUS_SOURCE_BASE;
173 oss->irq_level[irq] = OSS_IRQLEV_NUBUS; 186 oss->irq_level[irq] = OSS_IRQLEV_NUBUS;
174 break; 187 return;
175#ifdef DEBUG_IRQUSE
176 default:
177 printk("%s unknown irq %d\n", __func__, irq);
178 break;
179#endif
180 } 188 }
189
190 if (IRQ_SRC(irq) == 1)
191 via_irq_enable(irq);
181} 192}
182 193
183/* 194/*
@@ -193,14 +204,14 @@ void oss_irq_disable(int irq) {
193#endif 204#endif
194 switch(irq) { 205 switch(irq) {
195 case IRQ_MAC_SCC: 206 case IRQ_MAC_SCC:
196 oss->irq_level[OSS_IOPSCC] = OSS_IRQLEV_DISABLED; 207 oss->irq_level[OSS_IOPSCC] = 0;
197 break; 208 return;
198 case IRQ_MAC_ADB: 209 case IRQ_MAC_ADB:
199 oss->irq_level[OSS_IOPISM] = OSS_IRQLEV_DISABLED; 210 oss->irq_level[OSS_IOPISM] = 0;
200 break; 211 return;
201 case IRQ_MAC_SCSI: 212 case IRQ_MAC_SCSI:
202 oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED; 213 oss->irq_level[OSS_SCSI] = 0;
203 break; 214 return;
204 case IRQ_NUBUS_9: 215 case IRQ_NUBUS_9:
205 case IRQ_NUBUS_A: 216 case IRQ_NUBUS_A:
206 case IRQ_NUBUS_B: 217 case IRQ_NUBUS_B:
@@ -208,12 +219,10 @@ void oss_irq_disable(int irq) {
208 case IRQ_NUBUS_D: 219 case IRQ_NUBUS_D:
209 case IRQ_NUBUS_E: 220 case IRQ_NUBUS_E:
210 irq -= NUBUS_SOURCE_BASE; 221 irq -= NUBUS_SOURCE_BASE;
211 oss->irq_level[irq] = OSS_IRQLEV_DISABLED; 222 oss->irq_level[irq] = 0;
212 break; 223 return;
213#ifdef DEBUG_IRQUSE
214 default:
215 printk("%s unknown irq %d\n", __func__, irq);
216 break;
217#endif
218 } 224 }
225
226 if (IRQ_SRC(irq) == 1)
227 via_irq_disable(irq);
219} 228}