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