162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Baboon Custom IC Management 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * The Baboon custom IC controls the IDE, PCMCIA and media bay on the 662306a36Sopenharmony_ci * PowerBook 190. It multiplexes multiple interrupt sources onto the 762306a36Sopenharmony_ci * Nubus slot $C interrupt. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/irq.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <asm/macintosh.h> 1562306a36Sopenharmony_ci#include <asm/macints.h> 1662306a36Sopenharmony_ci#include <asm/mac_baboon.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciint baboon_present; 1962306a36Sopenharmony_cistatic volatile struct baboon *baboon; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* 2262306a36Sopenharmony_ci * Baboon initialization. 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_civoid __init baboon_init(void) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci if (macintosh_config->ident != MAC_MODEL_PB190) { 2862306a36Sopenharmony_ci baboon = NULL; 2962306a36Sopenharmony_ci baboon_present = 0; 3062306a36Sopenharmony_ci return; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci baboon = (struct baboon *) BABOON_BASE; 3462306a36Sopenharmony_ci baboon_present = 1; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci pr_debug("Baboon detected at %p\n", baboon); 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Baboon interrupt handler. 4162306a36Sopenharmony_ci * XXX how do you clear a pending IRQ? is it even necessary? 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic void baboon_irq(struct irq_desc *desc) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci short events, irq_bit; 4762306a36Sopenharmony_ci int irq_num; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci events = baboon->mb_ifr & 0x07; 5062306a36Sopenharmony_ci irq_num = IRQ_BABOON_0; 5162306a36Sopenharmony_ci irq_bit = 1; 5262306a36Sopenharmony_ci do { 5362306a36Sopenharmony_ci if (events & irq_bit) { 5462306a36Sopenharmony_ci events &= ~irq_bit; 5562306a36Sopenharmony_ci generic_handle_irq(irq_num); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci ++irq_num; 5862306a36Sopenharmony_ci irq_bit <<= 1; 5962306a36Sopenharmony_ci } while (events); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Register the Baboon interrupt dispatcher on nubus slot $C. 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_civoid __init baboon_register_interrupts(void) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * The means for masking individual Baboon interrupts remains a mystery. 7362306a36Sopenharmony_ci * However, since we only use the IDE IRQ, we can just enable/disable all 7462306a36Sopenharmony_ci * Baboon interrupts. If/when we handle more than one Baboon IRQ, we must 7562306a36Sopenharmony_ci * either figure out how to mask them individually or else implement the 7662306a36Sopenharmony_ci * same workaround that's used for NuBus slots (see nubus_disabled and 7762306a36Sopenharmony_ci * via_nubus_irq_shutdown). 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_civoid baboon_irq_enable(int irq) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C)); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_civoid baboon_irq_disable(int irq) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C)); 8862306a36Sopenharmony_ci} 89