18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * ints.c - Generic interrupt controller support 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 * Copyright 1996 Roman Zippel 98c2ecf20Sopenharmony_ci * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/init.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/irq.h> 178c2ecf20Sopenharmony_ci#include <asm/traps.h> 188c2ecf20Sopenharmony_ci#include <asm/io.h> 198c2ecf20Sopenharmony_ci#include <asm/machdep.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#if defined(CONFIG_M68328) 228c2ecf20Sopenharmony_ci#include <asm/MC68328.h> 238c2ecf20Sopenharmony_ci#elif defined(CONFIG_M68EZ328) 248c2ecf20Sopenharmony_ci#include <asm/MC68EZ328.h> 258c2ecf20Sopenharmony_ci#elif defined(CONFIG_M68VZ328) 268c2ecf20Sopenharmony_ci#include <asm/MC68VZ328.h> 278c2ecf20Sopenharmony_ci#endif 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci/* assembler routines */ 308c2ecf20Sopenharmony_ciasmlinkage void system_call(void); 318c2ecf20Sopenharmony_ciasmlinkage void buserr(void); 328c2ecf20Sopenharmony_ciasmlinkage void trap(void); 338c2ecf20Sopenharmony_ciasmlinkage void trap3(void); 348c2ecf20Sopenharmony_ciasmlinkage void trap4(void); 358c2ecf20Sopenharmony_ciasmlinkage void trap5(void); 368c2ecf20Sopenharmony_ciasmlinkage void trap6(void); 378c2ecf20Sopenharmony_ciasmlinkage void trap7(void); 388c2ecf20Sopenharmony_ciasmlinkage void trap8(void); 398c2ecf20Sopenharmony_ciasmlinkage void trap9(void); 408c2ecf20Sopenharmony_ciasmlinkage void trap10(void); 418c2ecf20Sopenharmony_ciasmlinkage void trap11(void); 428c2ecf20Sopenharmony_ciasmlinkage void trap12(void); 438c2ecf20Sopenharmony_ciasmlinkage void trap13(void); 448c2ecf20Sopenharmony_ciasmlinkage void trap14(void); 458c2ecf20Sopenharmony_ciasmlinkage void trap15(void); 468c2ecf20Sopenharmony_ciasmlinkage void trap33(void); 478c2ecf20Sopenharmony_ciasmlinkage void trap34(void); 488c2ecf20Sopenharmony_ciasmlinkage void trap35(void); 498c2ecf20Sopenharmony_ciasmlinkage void trap36(void); 508c2ecf20Sopenharmony_ciasmlinkage void trap37(void); 518c2ecf20Sopenharmony_ciasmlinkage void trap38(void); 528c2ecf20Sopenharmony_ciasmlinkage void trap39(void); 538c2ecf20Sopenharmony_ciasmlinkage void trap40(void); 548c2ecf20Sopenharmony_ciasmlinkage void trap41(void); 558c2ecf20Sopenharmony_ciasmlinkage void trap42(void); 568c2ecf20Sopenharmony_ciasmlinkage void trap43(void); 578c2ecf20Sopenharmony_ciasmlinkage void trap44(void); 588c2ecf20Sopenharmony_ciasmlinkage void trap45(void); 598c2ecf20Sopenharmony_ciasmlinkage void trap46(void); 608c2ecf20Sopenharmony_ciasmlinkage void trap47(void); 618c2ecf20Sopenharmony_ciasmlinkage irqreturn_t bad_interrupt(int, void *); 628c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler(void); 638c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler1(void); 648c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler2(void); 658c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler3(void); 668c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler4(void); 678c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler5(void); 688c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler6(void); 698c2ecf20Sopenharmony_ciasmlinkage irqreturn_t inthandler7(void); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* The 68k family did not have a good way to determine the source 728c2ecf20Sopenharmony_ci * of interrupts until later in the family. The EC000 core does 738c2ecf20Sopenharmony_ci * not provide the vector number on the stack, we vector everything 748c2ecf20Sopenharmony_ci * into one vector and look in the blasted mask register... 758c2ecf20Sopenharmony_ci * This code is designed to be fast, almost constant time, not clean! 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_civoid process_int(int vec, struct pt_regs *fp) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci int irq; 808c2ecf20Sopenharmony_ci int mask; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci unsigned long pend = ISR; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci while (pend) { 858c2ecf20Sopenharmony_ci if (pend & 0x0000ffff) { 868c2ecf20Sopenharmony_ci if (pend & 0x000000ff) { 878c2ecf20Sopenharmony_ci if (pend & 0x0000000f) { 888c2ecf20Sopenharmony_ci mask = 0x00000001; 898c2ecf20Sopenharmony_ci irq = 0; 908c2ecf20Sopenharmony_ci } else { 918c2ecf20Sopenharmony_ci mask = 0x00000010; 928c2ecf20Sopenharmony_ci irq = 4; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci } else { 958c2ecf20Sopenharmony_ci if (pend & 0x00000f00) { 968c2ecf20Sopenharmony_ci mask = 0x00000100; 978c2ecf20Sopenharmony_ci irq = 8; 988c2ecf20Sopenharmony_ci } else { 998c2ecf20Sopenharmony_ci mask = 0x00001000; 1008c2ecf20Sopenharmony_ci irq = 12; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci } else { 1048c2ecf20Sopenharmony_ci if (pend & 0x00ff0000) { 1058c2ecf20Sopenharmony_ci if (pend & 0x000f0000) { 1068c2ecf20Sopenharmony_ci mask = 0x00010000; 1078c2ecf20Sopenharmony_ci irq = 16; 1088c2ecf20Sopenharmony_ci } else { 1098c2ecf20Sopenharmony_ci mask = 0x00100000; 1108c2ecf20Sopenharmony_ci irq = 20; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci } else { 1138c2ecf20Sopenharmony_ci if (pend & 0x0f000000) { 1148c2ecf20Sopenharmony_ci mask = 0x01000000; 1158c2ecf20Sopenharmony_ci irq = 24; 1168c2ecf20Sopenharmony_ci } else { 1178c2ecf20Sopenharmony_ci mask = 0x10000000; 1188c2ecf20Sopenharmony_ci irq = 28; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci while (! (mask & pend)) { 1248c2ecf20Sopenharmony_ci mask <<=1; 1258c2ecf20Sopenharmony_ci irq++; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci do_IRQ(irq, fp); 1298c2ecf20Sopenharmony_ci pend &= ~mask; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic void intc_irq_unmask(struct irq_data *d) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci IMR &= ~(1 << d->irq); 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic void intc_irq_mask(struct irq_data *d) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci IMR |= (1 << d->irq); 1418c2ecf20Sopenharmony_ci} 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistatic struct irq_chip intc_irq_chip = { 1448c2ecf20Sopenharmony_ci .name = "M68K-INTC", 1458c2ecf20Sopenharmony_ci .irq_mask = intc_irq_mask, 1468c2ecf20Sopenharmony_ci .irq_unmask = intc_irq_unmask, 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * This function should be called during kernel startup to initialize 1518c2ecf20Sopenharmony_ci * the machine vector table. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_civoid __init trap_init(void) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci int i; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* set up the vectors */ 1588c2ecf20Sopenharmony_ci for (i = 72; i < 256; ++i) 1598c2ecf20Sopenharmony_ci _ramvec[i] = (e_vector) bad_interrupt; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci _ramvec[32] = system_call; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci _ramvec[65] = (e_vector) inthandler1; 1648c2ecf20Sopenharmony_ci _ramvec[66] = (e_vector) inthandler2; 1658c2ecf20Sopenharmony_ci _ramvec[67] = (e_vector) inthandler3; 1668c2ecf20Sopenharmony_ci _ramvec[68] = (e_vector) inthandler4; 1678c2ecf20Sopenharmony_ci _ramvec[69] = (e_vector) inthandler5; 1688c2ecf20Sopenharmony_ci _ramvec[70] = (e_vector) inthandler6; 1698c2ecf20Sopenharmony_ci _ramvec[71] = (e_vector) inthandler7; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_civoid __init init_IRQ(void) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci int i; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* turn off all interrupts */ 1798c2ecf20Sopenharmony_ci IMR = ~0; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci for (i = 0; (i < NR_IRQS); i++) { 1828c2ecf20Sopenharmony_ci irq_set_chip(i, &intc_irq_chip); 1838c2ecf20Sopenharmony_ci irq_set_handler(i, handle_level_irq); 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 187