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