18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Amiga Linux interrupt handling code 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 58c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 68c2ecf20Sopenharmony_ci * for more details. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 118c2ecf20Sopenharmony_ci#include <linux/errno.h> 128c2ecf20Sopenharmony_ci#include <linux/irq.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <asm/irq.h> 158c2ecf20Sopenharmony_ci#include <asm/traps.h> 168c2ecf20Sopenharmony_ci#include <asm/amigahw.h> 178c2ecf20Sopenharmony_ci#include <asm/amigaints.h> 188c2ecf20Sopenharmony_ci#include <asm/amipcmcia.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * Enable/disable a particular machine specific interrupt source. 238c2ecf20Sopenharmony_ci * Note that this may affect other interrupts in case of a shared interrupt. 248c2ecf20Sopenharmony_ci * This function should only be called for a _very_ short time to change some 258c2ecf20Sopenharmony_ci * internal data, that may not be changed by the interrupt at the same time. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic void amiga_irq_enable(struct irq_data *data) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER)); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic void amiga_irq_disable(struct irq_data *data) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci amiga_custom.intena = 1 << (data->irq - IRQ_USER); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic struct irq_chip amiga_irq_chip = { 398c2ecf20Sopenharmony_ci .name = "amiga", 408c2ecf20Sopenharmony_ci .irq_enable = amiga_irq_enable, 418c2ecf20Sopenharmony_ci .irq_disable = amiga_irq_disable, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * The builtin Amiga hardware interrupt handlers. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void ami_int1(struct irq_desc *desc) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* if serial transmit buffer empty, interrupt */ 548c2ecf20Sopenharmony_ci if (ints & IF_TBE) { 558c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_TBE; 568c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_TBE); 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* if floppy disk transfer complete, interrupt */ 608c2ecf20Sopenharmony_ci if (ints & IF_DSKBLK) { 618c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_DSKBLK; 628c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_DSKBLK); 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* if software interrupt set, interrupt */ 668c2ecf20Sopenharmony_ci if (ints & IF_SOFT) { 678c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_SOFT; 688c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_SOFT); 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void ami_int3(struct irq_desc *desc) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci /* if a blitter interrupt */ 778c2ecf20Sopenharmony_ci if (ints & IF_BLIT) { 788c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_BLIT; 798c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_BLIT); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* if a copper interrupt */ 838c2ecf20Sopenharmony_ci if (ints & IF_COPER) { 848c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_COPER; 858c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_COPPER); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* if a vertical blank interrupt */ 898c2ecf20Sopenharmony_ci if (ints & IF_VERTB) { 908c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_VERTB; 918c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_VERTB); 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void ami_int4(struct irq_desc *desc) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* if audio 0 interrupt */ 1008c2ecf20Sopenharmony_ci if (ints & IF_AUD0) { 1018c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_AUD0; 1028c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_AUD0); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci /* if audio 1 interrupt */ 1068c2ecf20Sopenharmony_ci if (ints & IF_AUD1) { 1078c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_AUD1; 1088c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_AUD1); 1098c2ecf20Sopenharmony_ci } 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* if audio 2 interrupt */ 1128c2ecf20Sopenharmony_ci if (ints & IF_AUD2) { 1138c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_AUD2; 1148c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_AUD2); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* if audio 3 interrupt */ 1188c2ecf20Sopenharmony_ci if (ints & IF_AUD3) { 1198c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_AUD3; 1208c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_AUD3); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic void ami_int5(struct irq_desc *desc) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci /* if serial receive buffer full interrupt */ 1298c2ecf20Sopenharmony_ci if (ints & IF_RBF) { 1308c2ecf20Sopenharmony_ci /* acknowledge of IF_RBF must be done by the serial interrupt */ 1318c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_RBF); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* if a disk sync interrupt */ 1358c2ecf20Sopenharmony_ci if (ints & IF_DSKSYN) { 1368c2ecf20Sopenharmony_ci amiga_custom.intreq = IF_DSKSYN; 1378c2ecf20Sopenharmony_ci generic_handle_irq(IRQ_AMIGA_DSKSYN); 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* 1438c2ecf20Sopenharmony_ci * void amiga_init_IRQ(void) 1448c2ecf20Sopenharmony_ci * 1458c2ecf20Sopenharmony_ci * Parameters: None 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * Returns: Nothing 1488c2ecf20Sopenharmony_ci * 1498c2ecf20Sopenharmony_ci * This function should be called during kernel startup to initialize 1508c2ecf20Sopenharmony_ci * the amiga IRQ handling routines. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_civoid __init amiga_init_IRQ(void) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER, 1568c2ecf20Sopenharmony_ci AMI_STD_IRQS); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci irq_set_chained_handler(IRQ_AUTO_1, ami_int1); 1598c2ecf20Sopenharmony_ci irq_set_chained_handler(IRQ_AUTO_3, ami_int3); 1608c2ecf20Sopenharmony_ci irq_set_chained_handler(IRQ_AUTO_4, ami_int4); 1618c2ecf20Sopenharmony_ci irq_set_chained_handler(IRQ_AUTO_5, ami_int5); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* turn off PCMCIA interrupts */ 1648c2ecf20Sopenharmony_ci if (AMIGAHW_PRESENT(PCMCIA)) 1658c2ecf20Sopenharmony_ci gayle.inten = GAYLE_IRQ_IDE; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* turn off all interrupts and enable the master interrupt bit */ 1688c2ecf20Sopenharmony_ci amiga_custom.intena = 0x7fff; 1698c2ecf20Sopenharmony_ci amiga_custom.intreq = 0x7fff; 1708c2ecf20Sopenharmony_ci amiga_custom.intena = IF_SETCLR | IF_INTEN; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci cia_init_IRQ(&ciaa_base); 1738c2ecf20Sopenharmony_ci cia_init_IRQ(&ciab_base); 1748c2ecf20Sopenharmony_ci} 175