diff options
Diffstat (limited to 'drivers/macintosh')
-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 76d21775fc3..741a93a3eb6 100644 --- a/drivers/macintosh/via-cuda.c +++ b/drivers/macintosh/via-cuda.c @@ -82,6 +82,7 @@ static unsigned char cuda_rbuf[16]; static unsigned char *reply_ptr; static int reading_reply; static int data_index; +static int cuda_irq; #ifdef CONFIG_PPC static struct device_node *vias; #endif @@ -160,10 +161,8 @@ int __init find_via_cuda(void) /* Clear and enable interrupts, but only on PPC. On 68K it's done */ /* for us by the main VIA driver in arch/m68k/mac/via.c */ -#ifndef CONFIG_MAC out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ -#endif /* enable autopoll */ cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); @@ -181,24 +180,22 @@ int __init find_via_cuda(void) static int __init via_cuda_start(void) { - unsigned int irq; - if (via == NULL) return -ENODEV; #ifdef CONFIG_MAC - irq = IRQ_MAC_ADB; + cuda_irq = IRQ_MAC_ADB; #else /* CONFIG_MAC */ - irq = irq_of_parse_and_map(vias, 0); - if (irq == NO_IRQ) { + cuda_irq = irq_of_parse_and_map(vias, 0); + if (cuda_irq == NO_IRQ) { printk(KERN_ERR "via-cuda: can't map interrupts for %s\n", vias->full_name); return -ENODEV; } -#endif /* CONFIG_MAP */ +#endif /* CONFIG_MAC */ - if (request_irq(irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { - printk(KERN_ERR "via-cuda: can't request irq %d\n", irq); + if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) { + printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq); return -EAGAIN; } @@ -238,6 +235,7 @@ cuda_init(void) printk(KERN_ERR "cuda_init_via() failed\n"); return -ENODEV; } + out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ return via_cuda_start(); #endif @@ -263,15 +261,17 @@ cuda_init_via(void) out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ (void)in_8(&via[SR]); /* clear any left-over data */ -#ifndef CONFIG_MAC +#ifdef CONFIG_PPC out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ (void)in_8(&via[IER]); +#else + out_8(&via[IER], SR_INT); /* disable SR interrupt from VIA */ #endif /* delay 4ms and then clear any pending interrupt */ mdelay(4); (void)in_8(&via[SR]); - out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); + out_8(&via[IFR], SR_INT); /* sync with the CUDA - assert TACK without TIP */ out_8(&via[B], in_8(&via[B]) & ~TACK); @@ -282,7 +282,7 @@ cuda_init_via(void) /* wait for the interrupt and then clear it */ WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); (void)in_8(&via[SR]); - out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); + out_8(&via[IFR], SR_INT); /* finish the sync by negating TACK */ out_8(&via[B], in_8(&via[B]) | TACK); @@ -291,7 +291,7 @@ cuda_init_via(void) WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); (void)in_8(&via[SR]); - out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); + out_8(&via[IFR], SR_INT); out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ return 0; @@ -428,16 +428,12 @@ cuda_start(void) void cuda_poll(void) { - unsigned long flags; - /* cuda_interrupt only takes a normal lock, we disable * interrupts here to avoid re-entering and thus deadlocking. - * An option would be to disable only the IRQ source with - * disable_irq(), would that work on m68k ? --BenH */ - local_irq_save(flags); + disable_irq(cuda_irq); cuda_interrupt(0, NULL); - local_irq_restore(flags); + enable_irq(cuda_irq); } static irqreturn_t @@ -448,15 +444,25 @@ cuda_interrupt(int irq, void *arg) unsigned char ibuf[16]; int ibuf_len = 0; int complete = 0; - unsigned char virq; spin_lock(&cuda_lock); - virq = in_8(&via[IFR]) & 0x7f; - out_8(&via[IFR], virq); - if ((virq & SR_INT) == 0) { - spin_unlock(&cuda_lock); - return IRQ_NONE; + /* On powermacs, this handler is registered for the VIA IRQ. But it uses + * just the shift register IRQ -- other VIA interrupt sources are disabled. + * On m68k macs, the VIA IRQ sources are dispatched individually. Unless + * we are polling, the shift register IRQ flag has already been cleared. + */ + +#ifdef CONFIG_MAC + if (!arg) +#endif + { + if ((in_8(&via[IFR]) & SR_INT) == 0) { + spin_unlock(&cuda_lock); + return IRQ_NONE; + } else { + out_8(&via[IFR], SR_INT); + } } status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); |