1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Baboon Custom IC Management 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * The Baboon custom IC controls the IDE, PCMCIA and media bay on the 6*4882a593Smuzhiyun * PowerBook 190. It multiplexes multiple interrupt sources onto the 7*4882a593Smuzhiyun * Nubus slot $C interrupt. 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #include <linux/types.h> 11*4882a593Smuzhiyun #include <linux/kernel.h> 12*4882a593Smuzhiyun #include <linux/irq.h> 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #include <asm/macintosh.h> 15*4882a593Smuzhiyun #include <asm/macints.h> 16*4882a593Smuzhiyun #include <asm/mac_baboon.h> 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun int baboon_present; 19*4882a593Smuzhiyun static volatile struct baboon *baboon; 20*4882a593Smuzhiyun 21*4882a593Smuzhiyun /* 22*4882a593Smuzhiyun * Baboon initialization. 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun baboon_init(void)25*4882a593Smuzhiyunvoid __init baboon_init(void) 26*4882a593Smuzhiyun { 27*4882a593Smuzhiyun if (macintosh_config->ident != MAC_MODEL_PB190) { 28*4882a593Smuzhiyun baboon = NULL; 29*4882a593Smuzhiyun baboon_present = 0; 30*4882a593Smuzhiyun return; 31*4882a593Smuzhiyun } 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun baboon = (struct baboon *) BABOON_BASE; 34*4882a593Smuzhiyun baboon_present = 1; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun pr_debug("Baboon detected at %p\n", baboon); 37*4882a593Smuzhiyun } 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun /* 40*4882a593Smuzhiyun * Baboon interrupt handler. 41*4882a593Smuzhiyun * XXX how do you clear a pending IRQ? is it even necessary? 42*4882a593Smuzhiyun */ 43*4882a593Smuzhiyun baboon_irq(struct irq_desc * desc)44*4882a593Smuzhiyunstatic void baboon_irq(struct irq_desc *desc) 45*4882a593Smuzhiyun { 46*4882a593Smuzhiyun short events, irq_bit; 47*4882a593Smuzhiyun int irq_num; 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun events = baboon->mb_ifr & 0x07; 50*4882a593Smuzhiyun irq_num = IRQ_BABOON_0; 51*4882a593Smuzhiyun irq_bit = 1; 52*4882a593Smuzhiyun do { 53*4882a593Smuzhiyun if (events & irq_bit) { 54*4882a593Smuzhiyun events &= ~irq_bit; 55*4882a593Smuzhiyun generic_handle_irq(irq_num); 56*4882a593Smuzhiyun } 57*4882a593Smuzhiyun ++irq_num; 58*4882a593Smuzhiyun irq_bit <<= 1; 59*4882a593Smuzhiyun } while (events); 60*4882a593Smuzhiyun } 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun /* 63*4882a593Smuzhiyun * Register the Baboon interrupt dispatcher on nubus slot $C. 64*4882a593Smuzhiyun */ 65*4882a593Smuzhiyun baboon_register_interrupts(void)66*4882a593Smuzhiyunvoid __init baboon_register_interrupts(void) 67*4882a593Smuzhiyun { 68*4882a593Smuzhiyun irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); 69*4882a593Smuzhiyun } 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun /* 72*4882a593Smuzhiyun * The means for masking individual Baboon interrupts remains a mystery. 73*4882a593Smuzhiyun * However, since we only use the IDE IRQ, we can just enable/disable all 74*4882a593Smuzhiyun * Baboon interrupts. If/when we handle more than one Baboon IRQ, we must 75*4882a593Smuzhiyun * either figure out how to mask them individually or else implement the 76*4882a593Smuzhiyun * same workaround that's used for NuBus slots (see nubus_disabled and 77*4882a593Smuzhiyun * via_nubus_irq_shutdown). 78*4882a593Smuzhiyun */ 79*4882a593Smuzhiyun baboon_irq_enable(int irq)80*4882a593Smuzhiyunvoid baboon_irq_enable(int irq) 81*4882a593Smuzhiyun { 82*4882a593Smuzhiyun mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C)); 83*4882a593Smuzhiyun } 84*4882a593Smuzhiyun baboon_irq_disable(int irq)85*4882a593Smuzhiyunvoid baboon_irq_disable(int irq) 86*4882a593Smuzhiyun { 87*4882a593Smuzhiyun mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C)); 88*4882a593Smuzhiyun } 89