67dfb153a3
Make sure that there are no slot IRQs asserted before leaving the nubus handler. If there are and we don't then the nubus gets wedged because this prevents a CA1 transition, which means no more nubus IRQs. Make the interrupt dispatch loops terminate sooner. Explicitly initialise the VIA latches to make the code more easily understood. Also some cleanups. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
130 lines
2.6 KiB
C
130 lines
2.6 KiB
C
/*
|
|
* Baboon Custom IC Management
|
|
*
|
|
* The Baboon custom IC controls the IDE, PCMCIA and media bay on the
|
|
* PowerBook 190. It multiplexes multiple interrupt sources onto the
|
|
* Nubus slot $C interrupt.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/init.h>
|
|
#include <linux/ide.h>
|
|
|
|
#include <asm/traps.h>
|
|
#include <asm/bootinfo.h>
|
|
#include <asm/macintosh.h>
|
|
#include <asm/macints.h>
|
|
#include <asm/mac_baboon.h>
|
|
|
|
/* #define DEBUG_BABOON */
|
|
/* #define DEBUG_IRQS */
|
|
|
|
int baboon_present,baboon_active;
|
|
volatile struct baboon *baboon;
|
|
|
|
irqreturn_t baboon_irq(int, void *);
|
|
|
|
#if 0
|
|
extern int macide_ack_intr(struct ata_channel *);
|
|
#endif
|
|
|
|
/*
|
|
* Baboon initialization.
|
|
*/
|
|
|
|
void __init baboon_init(void)
|
|
{
|
|
if (macintosh_config->ident != MAC_MODEL_PB190) {
|
|
baboon = NULL;
|
|
baboon_present = 0;
|
|
return;
|
|
}
|
|
|
|
baboon = (struct baboon *) BABOON_BASE;
|
|
baboon_present = 1;
|
|
baboon_active = 0;
|
|
|
|
printk("Baboon detected at %p\n", baboon);
|
|
}
|
|
|
|
/*
|
|
* Register the Baboon interrupt dispatcher on nubus slot $C.
|
|
*/
|
|
|
|
void __init baboon_register_interrupts(void)
|
|
{
|
|
request_irq(IRQ_NUBUS_C, baboon_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
|
|
"baboon", (void *) baboon);
|
|
}
|
|
|
|
/*
|
|
* Baboon interrupt handler. This works a lot like a VIA.
|
|
*/
|
|
|
|
irqreturn_t baboon_irq(int irq, void *dev_id)
|
|
{
|
|
int irq_bit, irq_num;
|
|
unsigned char events;
|
|
|
|
#ifdef DEBUG_IRQS
|
|
printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X active %02X\n",
|
|
(uint) baboon->mb_control, (uint) baboon->mb_ifr,
|
|
(uint) baboon->mb_status, baboon_active);
|
|
#endif
|
|
|
|
if (!(events = baboon->mb_ifr & 0x07))
|
|
return IRQ_NONE;
|
|
|
|
irq_num = IRQ_BABOON_0;
|
|
irq_bit = 1;
|
|
do {
|
|
if (events & irq_bit/* & baboon_active*/) {
|
|
baboon_active &= ~irq_bit;
|
|
baboon->mb_ifr &= ~irq_bit;
|
|
m68k_handle_int(irq_num);
|
|
baboon_active |= irq_bit;
|
|
}
|
|
irq_bit <<= 1;
|
|
irq_num++;
|
|
} while(events >= irq_bit);
|
|
#if 0
|
|
if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL);
|
|
/* for now we need to smash all interrupts */
|
|
baboon->mb_ifr &= ~events;
|
|
#endif
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
void baboon_irq_enable(int irq) {
|
|
int irq_idx = IRQ_IDX(irq);
|
|
|
|
#ifdef DEBUG_IRQUSE
|
|
printk("baboon_irq_enable(%d)\n", irq);
|
|
#endif
|
|
baboon_active |= (1 << irq_idx);
|
|
}
|
|
|
|
void baboon_irq_disable(int irq) {
|
|
int irq_idx = IRQ_IDX(irq);
|
|
|
|
#ifdef DEBUG_IRQUSE
|
|
printk("baboon_irq_disable(%d)\n", irq);
|
|
#endif
|
|
baboon_active &= ~(1 << irq_idx);
|
|
}
|
|
|
|
void baboon_irq_clear(int irq) {
|
|
int irq_idx = IRQ_IDX(irq);
|
|
|
|
baboon->mb_ifr &= ~(1 << irq_idx);
|
|
}
|
|
|
|
int baboon_irq_pending(int irq)
|
|
{
|
|
int irq_idx = IRQ_IDX(irq);
|
|
|
|
return baboon->mb_ifr & (1 << irq_idx);
|
|
}
|