^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Amiga Linux interrupt handling code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/errno.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/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/amigahw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/amigaints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/amipcmcia.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^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) * Enable/disable a particular machine specific interrupt source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Note that this may affect other interrupts in case of a shared interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * This function should only be called for a _very_ short time to change some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * internal data, that may not be changed by the interrupt at the same time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static void amiga_irq_enable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
^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) static void amiga_irq_disable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) amiga_custom.intena = 1 << (data->irq - IRQ_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static struct irq_chip amiga_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) .name = "amiga",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .irq_enable = amiga_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .irq_disable = amiga_irq_disable,
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * The builtin Amiga hardware interrupt handlers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void ami_int1(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* if serial transmit buffer empty, interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (ints & IF_TBE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) amiga_custom.intreq = IF_TBE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) generic_handle_irq(IRQ_AMIGA_TBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* if floppy disk transfer complete, interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (ints & IF_DSKBLK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) amiga_custom.intreq = IF_DSKBLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) generic_handle_irq(IRQ_AMIGA_DSKBLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* if software interrupt set, interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (ints & IF_SOFT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) amiga_custom.intreq = IF_SOFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) generic_handle_irq(IRQ_AMIGA_SOFT);
^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) static void ami_int3(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* if a blitter interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (ints & IF_BLIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) amiga_custom.intreq = IF_BLIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) generic_handle_irq(IRQ_AMIGA_BLIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* if a copper interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (ints & IF_COPER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) amiga_custom.intreq = IF_COPER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) generic_handle_irq(IRQ_AMIGA_COPPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* if a vertical blank interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (ints & IF_VERTB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) amiga_custom.intreq = IF_VERTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) generic_handle_irq(IRQ_AMIGA_VERTB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void ami_int4(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* if audio 0 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (ints & IF_AUD0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) amiga_custom.intreq = IF_AUD0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) generic_handle_irq(IRQ_AMIGA_AUD0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /* if audio 1 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if (ints & IF_AUD1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) amiga_custom.intreq = IF_AUD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) generic_handle_irq(IRQ_AMIGA_AUD1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* if audio 2 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (ints & IF_AUD2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) amiga_custom.intreq = IF_AUD2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) generic_handle_irq(IRQ_AMIGA_AUD2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* if audio 3 interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ints & IF_AUD3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) amiga_custom.intreq = IF_AUD3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) generic_handle_irq(IRQ_AMIGA_AUD3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static void ami_int5(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* if serial receive buffer full interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ints & IF_RBF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* acknowledge of IF_RBF must be done by the serial interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) generic_handle_irq(IRQ_AMIGA_RBF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* if a disk sync interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (ints & IF_DSKSYN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) amiga_custom.intreq = IF_DSKSYN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) generic_handle_irq(IRQ_AMIGA_DSKSYN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * void amiga_init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * Parameters: None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Returns: Nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * This function should be called during kernel startup to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * the amiga IRQ handling routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) void __init amiga_init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) AMI_STD_IRQS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* turn off PCMCIA interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (AMIGAHW_PRESENT(PCMCIA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) gayle.inten = GAYLE_IRQ_IDE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* turn off all interrupts and enable the master interrupt bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) amiga_custom.intena = 0x7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) amiga_custom.intreq = 0x7fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) amiga_custom.intena = IF_SETCLR | IF_INTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) cia_init_IRQ(&ciaa_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) cia_init_IRQ(&ciab_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }