1 /* 2 * Baboon Custom IC Management 3 * 4 * The Baboon custom IC controls the IDE, PCMCIA and media bay on the 5 * PowerBook 190. It multiplexes multiple interrupt sources onto the 6 * Nubus slot $C interrupt. 7 */ 8 9 #include <linux/types.h> 10 #include <linux/kernel.h> 11 #include <linux/mm.h> 12 #include <linux/delay.h> 13 #include <linux/init.h> 14 15 #include <asm/traps.h> 16 #include <asm/bootinfo.h> 17 #include <asm/macintosh.h> 18 #include <asm/macints.h> 19 #include <asm/mac_baboon.h> 20 21 /* #define DEBUG_IRQS */ 22 23 extern void mac_enable_irq(unsigned int); 24 extern void mac_disable_irq(unsigned int); 25 26 int baboon_present; 27 static volatile struct baboon *baboon; 28 static unsigned char baboon_disabled; 29 30 #if 0 31 extern int macide_ack_intr(struct ata_channel *); 32 #endif 33 34 /* 35 * Baboon initialization. 36 */ 37 38 void __init baboon_init(void) 39 { 40 if (macintosh_config->ident != MAC_MODEL_PB190) { 41 baboon = NULL; 42 baboon_present = 0; 43 return; 44 } 45 46 baboon = (struct baboon *) BABOON_BASE; 47 baboon_present = 1; 48 49 printk("Baboon detected at %p\n", baboon); 50 } 51 52 /* 53 * Baboon interrupt handler. This works a lot like a VIA. 54 */ 55 56 static irqreturn_t baboon_irq(int irq, void *dev_id) 57 { 58 int irq_bit, irq_num; 59 unsigned char events; 60 61 #ifdef DEBUG_IRQS 62 printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n", 63 (uint) baboon->mb_control, (uint) baboon->mb_ifr, 64 (uint) baboon->mb_status); 65 #endif 66 67 if (!(events = baboon->mb_ifr & 0x07)) 68 return IRQ_NONE; 69 70 irq_num = IRQ_BABOON_0; 71 irq_bit = 1; 72 do { 73 if (events & irq_bit) { 74 baboon->mb_ifr &= ~irq_bit; 75 m68k_handle_int(irq_num); 76 } 77 irq_bit <<= 1; 78 irq_num++; 79 } while(events >= irq_bit); 80 #if 0 81 if (baboon->mb_ifr & 0x02) macide_ack_intr(NULL); 82 /* for now we need to smash all interrupts */ 83 baboon->mb_ifr &= ~events; 84 #endif 85 return IRQ_HANDLED; 86 } 87 88 /* 89 * Register the Baboon interrupt dispatcher on nubus slot $C. 90 */ 91 92 void __init baboon_register_interrupts(void) 93 { 94 baboon_disabled = 0; 95 if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon)) 96 pr_err("Couldn't register baboon interrupt\n"); 97 } 98 99 /* 100 * The means for masking individual baboon interrupts remains a mystery, so 101 * enable the umbrella interrupt only when no baboon interrupt is disabled. 102 */ 103 104 void baboon_irq_enable(int irq) 105 { 106 int irq_idx = IRQ_IDX(irq); 107 108 #ifdef DEBUG_IRQUSE 109 printk("baboon_irq_enable(%d)\n", irq); 110 #endif 111 112 baboon_disabled &= ~(1 << irq_idx); 113 if (!baboon_disabled) 114 mac_enable_irq(IRQ_NUBUS_C); 115 } 116 117 void baboon_irq_disable(int irq) 118 { 119 int irq_idx = IRQ_IDX(irq); 120 121 #ifdef DEBUG_IRQUSE 122 printk("baboon_irq_disable(%d)\n", irq); 123 #endif 124 125 baboon_disabled |= 1 << irq_idx; 126 if (baboon_disabled) 127 mac_disable_irq(IRQ_NUBUS_C); 128 } 129 130 void baboon_irq_clear(int irq) 131 { 132 int irq_idx = IRQ_IDX(irq); 133 134 baboon->mb_ifr &= ~(1 << irq_idx); 135 } 136 137 int baboon_irq_pending(int irq) 138 { 139 int irq_idx = IRQ_IDX(irq); 140 141 return baboon->mb_ifr & (1 << irq_idx); 142 } 143