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 23extern void mac_enable_irq(unsigned int); 24extern void mac_disable_irq(unsigned int); 25 26int baboon_present; 27static volatile struct baboon *baboon; 28static unsigned char baboon_disabled; 29 30 31/* 32 * Baboon initialization. 33 */ 34 35void __init baboon_init(void) 36{ 37 if (macintosh_config->ident != MAC_MODEL_PB190) { 38 baboon = NULL; 39 baboon_present = 0; 40 return; 41 } 42 43 baboon = (struct baboon *) BABOON_BASE; 44 baboon_present = 1; 45 46 printk("Baboon detected at %p\n", baboon); 47} 48 49/* 50 * Baboon interrupt handler. This works a lot like a VIA. 51 */ 52 53static irqreturn_t baboon_irq(int irq, void *dev_id) 54{ 55 int irq_bit, irq_num; 56 unsigned char events; 57 58#ifdef DEBUG_IRQS 59 printk("baboon_irq: mb_control %02X mb_ifr %02X mb_status %02X\n", 60 (uint) baboon->mb_control, (uint) baboon->mb_ifr, 61 (uint) baboon->mb_status); 62#endif 63 64 if (!(events = baboon->mb_ifr & 0x07)) 65 return IRQ_NONE; 66 67 irq_num = IRQ_BABOON_0; 68 irq_bit = 1; 69 do { 70 if (events & irq_bit) { 71 baboon->mb_ifr &= ~irq_bit; 72 m68k_handle_int(irq_num); 73 } 74 irq_bit <<= 1; 75 irq_num++; 76 } while(events >= irq_bit); 77 return IRQ_HANDLED; 78} 79 80/* 81 * Register the Baboon interrupt dispatcher on nubus slot $C. 82 */ 83 84void __init baboon_register_interrupts(void) 85{ 86 baboon_disabled = 0; 87 if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon)) 88 pr_err("Couldn't register baboon interrupt\n"); 89} 90 91/* 92 * The means for masking individual baboon interrupts remains a mystery, so 93 * enable the umbrella interrupt only when no baboon interrupt is disabled. 94 */ 95 96void baboon_irq_enable(int irq) 97{ 98 int irq_idx = IRQ_IDX(irq); 99 100#ifdef DEBUG_IRQUSE 101 printk("baboon_irq_enable(%d)\n", irq); 102#endif 103 104 baboon_disabled &= ~(1 << irq_idx); 105 if (!baboon_disabled) 106 mac_enable_irq(IRQ_NUBUS_C); 107} 108 109void baboon_irq_disable(int irq) 110{ 111 int irq_idx = IRQ_IDX(irq); 112 113#ifdef DEBUG_IRQUSE 114 printk("baboon_irq_disable(%d)\n", irq); 115#endif 116 117 baboon_disabled |= 1 << irq_idx; 118 if (baboon_disabled) 119 mac_disable_irq(IRQ_NUBUS_C); 120} 121 122void baboon_irq_clear(int irq) 123{ 124 int irq_idx = IRQ_IDX(irq); 125 126 baboon->mb_ifr &= ~(1 << irq_idx); 127} 128 129int baboon_irq_pending(int irq) 130{ 131 int irq_idx = IRQ_IDX(irq); 132 133 return baboon->mb_ifr & (1 << irq_idx); 134} 135