diff options
-rw-r--r-- | drivers/macintosh/via-cuda.c | 58 |
1 files changed, 32 insertions, 26 deletions
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c index 76d21775fc35..741a93a3eb61 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c | |||
@@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16]; | |||
82 | static unsigned char *reply_ptr; | 82 | static unsigned char *reply_ptr; |
83 | static int reading_reply; | 83 | static int reading_reply; |
84 | static int data_index; | 84 | static int data_index; |
85 | static int cuda_irq; | ||
85 | #ifdef CONFIG_PPC | 86 | #ifdef CONFIG_PPC |
86 | static struct device_node *vias; | 87 | static struct device_node *vias; |
87 | #endif | 88 | #endif |
@@ -160,10 +161,8 @@ int __init find_via_cuda(void) | |||
160 | /* Clear and enable interrupts, but only on PPC. On 68K it's done */ | 161 | /* Clear and enable interrupts, but only on PPC. On 68K it's done */ |
161 | /* for us by the main VIA driver in arch/m68k/mac/via.c */ | 162 | /* for us by the main VIA driver in arch/m68k/mac/via.c */ |
162 | 163 | ||
163 | #ifndef CONFIG_MAC | ||
164 | out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ | 164 | out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ |
165 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ | 165 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ |
166 | #endif | ||
167 | 166 | ||
168 | /* enable autopoll */ | 167 | /* enable autopoll */ |
169 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); | 168 | cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); |
@@ -181,24 +180,22 @@ int __init find_via_cuda(void) | |||
181 | 180 | ||
182 | static int __init via_cuda_start(void) | 181 | static int __init via_cuda_start(void) |
183 | { | 182 | { |
184 | unsigned int irq; | ||
185 | |||
186 | if (via == NULL) | 183 | if (via == NULL) |
187 | return -ENODEV; | 184 | return -ENODEV; |
188 | 185 | ||
189 | #ifdef CONFIG_MAC | 186 | #ifdef CONFIG_MAC |
190 | irq = IRQ_MAC_ADB; | 187 | cuda_irq = IRQ_MAC_ADB; |
191 | #else /* CONFIG_MAC */ | 188 | #else /* CONFIG_MAC */ |
192 | irq = irq_of_parse_and_map(vias, 0); | 189 | cuda_irq = irq_of_parse_and_map(vias, 0); |
193 | if (irq == NO_IRQ) { | 190 | if (cuda_irq == NO_IRQ) { |
194 | printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", | 191 | printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", |
195 | vias->full_name); | 192 | vias->full_name); |
196 | return -ENODEV; | 193 | return -ENODEV; |
197 | } | 194 | } |
198 | #endif /* CONFIG_MAP */ | 195 | #endif /* CONFIG_MAC */ |
199 | 196 | ||
200 | if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { | 197 | if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { |
201 | printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); | 198 | printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq); |
202 | return -EAGAIN; | 199 | return -EAGAIN; |
203 | } | 200 | } |
204 | 201 | ||
@@ -238,6 +235,7 @@ cuda_init(void) | |||
238 | printk(KERN_ERR "cuda_init_via() failed\n"); | 235 | printk(KERN_ERR "cuda_init_via() failed\n"); |
239 | return -ENODEV; | 236 | return -ENODEV; |
240 | } | 237 | } |
238 | out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ | ||
241 | 239 | ||
242 | return via_cuda_start(); | 240 | return via_cuda_start(); |
243 | #endif | 241 | #endif |
@@ -263,15 +261,17 @@ cuda_init_via(void) | |||
263 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ | 261 | out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ |
264 | out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ | 262 | out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ |
265 | (void)in_8(&via[SR]); /* clear any left-over data */ | 263 | (void)in_8(&via[SR]); /* clear any left-over data */ |
266 | #ifndef CONFIG_MAC | 264 | #ifdef CONFIG_PPC |
267 | out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ | 265 | out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ |
268 | (void)in_8(&via[IER]); | 266 | (void)in_8(&via[IER]); |
267 | #else | ||
268 | out_8(&via[IER], SR_INT); /* disable SR interrupt from VIA */ | ||
269 | #endif | 269 | #endif |
270 | 270 | ||
271 | /* delay 4ms and then clear any pending interrupt */ | 271 | /* delay 4ms and then clear any pending interrupt */ |
272 | mdelay(4); | 272 | mdelay(4); |
273 | (void)in_8(&via[SR]); | 273 | (void)in_8(&via[SR]); |
274 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 274 | out_8(&via[IFR], SR_INT); |
275 | 275 | ||
276 | /* sync with the CUDA - assert TACK without TIP */ | 276 | /* sync with the CUDA - assert TACK without TIP */ |
277 | out_8(&via[B], in_8(&via[B]) & ~TACK); | 277 | out_8(&via[B], in_8(&via[B]) & ~TACK); |
@@ -282,7 +282,7 @@ cuda_init_via(void) | |||
282 | /* wait for the interrupt and then clear it */ | 282 | /* wait for the interrupt and then clear it */ |
283 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); | 283 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); |
284 | (void)in_8(&via[SR]); | 284 | (void)in_8(&via[SR]); |
285 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 285 | out_8(&via[IFR], SR_INT); |
286 | 286 | ||
287 | /* finish the sync by negating TACK */ | 287 | /* finish the sync by negating TACK */ |
288 | out_8(&via[B], in_8(&via[B]) | TACK); | 288 | out_8(&via[B], in_8(&via[B]) | TACK); |
@@ -291,7 +291,7 @@ cuda_init_via(void) | |||
291 | WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); | 291 | WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); |
292 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); | 292 | WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); |
293 | (void)in_8(&via[SR]); | 293 | (void)in_8(&via[SR]); |
294 | out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); | 294 | out_8(&via[IFR], SR_INT); |
295 | out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ | 295 | out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ |
296 | 296 | ||
297 | return 0; | 297 | return 0; |
@@ -428,16 +428,12 @@ cuda_start(void) | |||
428 | void | 428 | void |
429 | cuda_poll(void) | 429 | cuda_poll(void) |
430 | { | 430 | { |
431 | unsigned long flags; | ||
432 | |||
433 | /* cuda_interrupt only takes a normal lock, we disable | 431 | /* cuda_interrupt only takes a normal lock, we disable |
434 | * interrupts here to avoid re-entering and thus deadlocking. | 432 | * interrupts here to avoid re-entering and thus deadlocking. |
435 | * An option would be to disable only the IRQ source with | ||
436 | * disable_irq(), would that work on m68k ? --BenH | ||
437 | */ | 433 | */ |
438 | local_irq_save(flags); | 434 | disable_irq(cuda_irq); |
439 | cuda_interrupt(0, NULL); | 435 | cuda_interrupt(0, NULL); |
440 | local_irq_restore(flags); | 436 | enable_irq(cuda_irq); |
441 | } | 437 | } |
442 | 438 | ||
443 | static irqreturn_t | 439 | static irqreturn_t |
@@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg) | |||
448 | unsigned char ibuf[16]; | 444 | unsigned char ibuf[16]; |
449 | int ibuf_len = 0; | 445 | int ibuf_len = 0; |
450 | int complete = 0; | 446 | int complete = 0; |
451 | unsigned char virq; | ||
452 | 447 | ||
453 | spin_lock(&cuda_lock); | 448 | spin_lock(&cuda_lock); |
454 | 449 | ||
455 | virq = in_8(&via[IFR]) & 0x7f; | 450 | /* On powermacs, this handler is registered for the VIA IRQ. But it uses |
456 | out_8(&via[IFR], virq); | 451 | * just the shift register IRQ -- other VIA interrupt sources are disabled. |
457 | if ((virq & SR_INT) == 0) { | 452 | * On m68k macs, the VIA IRQ sources are dispatched individually. Unless |
458 | spin_unlock(&cuda_lock); | 453 | * we are polling, the shift register IRQ flag has already been cleared. |
459 | return IRQ_NONE; | 454 | */ |
455 | |||
456 | #ifdef CONFIG_MAC | ||
457 | if (!arg) | ||
458 | #endif | ||
459 | { | ||
460 | if ((in_8(&via[IFR]) & SR_INT) == 0) { | ||
461 | spin_unlock(&cuda_lock); | ||
462 | return IRQ_NONE; | ||
463 | } else { | ||
464 | out_8(&via[IFR], SR_INT); | ||
465 | } | ||
460 | } | 466 | } |
461 | 467 | ||
462 | status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); | 468 | status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); |