18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Toshiba RBTX4938 specific interrupt handlers 38c2ecf20Sopenharmony_ci * Copyright (C) 2000-2001 Toshiba Corporation 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the 68c2ecf20Sopenharmony_ci * terms of the GNU General Public License version 2. This program is 78c2ecf20Sopenharmony_ci * licensed "as is" without any warranty of any kind, whether express 88c2ecf20Sopenharmony_ci * or implied. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+00 Software 0 158c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+01 Software 1 168c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+02 Cascade TX4938-CP0 178c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+03 Multiplexed -- do not use 188c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+04 Multiplexed -- do not use 198c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+05 Multiplexed -- do not use 208c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+06 Multiplexed -- do not use 218c2ecf20Sopenharmony_ci * MIPS_CPU_IRQ_BASE+07 CPU TIMER 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+00 248c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+01 258c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+02 Cascade RBTX4938-IOC 268c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+03 RBTX4938 RTL-8019AS Ethernet 278c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+04 288c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+05 TX4938 ETH1 298c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+06 TX4938 ETH0 308c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+07 318c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+08 TX4938 SIO 0 328c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+09 TX4938 SIO 1 338c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+10 TX4938 DMA0 348c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+11 TX4938 DMA1 358c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+12 TX4938 DMA2 368c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+13 TX4938 DMA3 378c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+14 388c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+15 398c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+16 TX4938 PCIC 408c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+17 TX4938 TMR0 418c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+18 TX4938 TMR1 428c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+19 TX4938 TMR2 438c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+20 448c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+21 458c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+22 TX4938 PCIERR 468c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+23 478c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+24 488c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+25 498c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+26 508c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+27 518c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+28 528c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+29 538c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+30 548c2ecf20Sopenharmony_ci * TXX9_IRQ_BASE+31 TX4938 SPI 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+00 PCI-D 578c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+01 PCI-C 588c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+02 PCI-B 598c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+03 PCI-A 608c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+04 RTC 618c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+05 ATA 628c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+06 MODEM 638c2ecf20Sopenharmony_ci * RBTX4938_IRQ_IOC+07 SWINT 648c2ecf20Sopenharmony_ci */ 658c2ecf20Sopenharmony_ci#include <linux/init.h> 668c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 678c2ecf20Sopenharmony_ci#include <linux/irq.h> 688c2ecf20Sopenharmony_ci#include <asm/mipsregs.h> 698c2ecf20Sopenharmony_ci#include <asm/txx9/generic.h> 708c2ecf20Sopenharmony_ci#include <asm/txx9/rbtx4938.h> 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int toshiba_rbtx4938_irq_nested(int sw_irq) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci u8 level3; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci level3 = readb(rbtx4938_imstat_addr); 778c2ecf20Sopenharmony_ci if (unlikely(!level3)) 788c2ecf20Sopenharmony_ci return -1; 798c2ecf20Sopenharmony_ci /* must use fls so onboard ATA has priority */ 808c2ecf20Sopenharmony_ci return RBTX4938_IRQ_IOC + __fls8(level3); 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic void toshiba_rbtx4938_irq_ioc_enable(struct irq_data *d) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci unsigned char v; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci v = readb(rbtx4938_imask_addr); 888c2ecf20Sopenharmony_ci v |= (1 << (d->irq - RBTX4938_IRQ_IOC)); 898c2ecf20Sopenharmony_ci writeb(v, rbtx4938_imask_addr); 908c2ecf20Sopenharmony_ci mmiowb(); 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic void toshiba_rbtx4938_irq_ioc_disable(struct irq_data *d) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci unsigned char v; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci v = readb(rbtx4938_imask_addr); 988c2ecf20Sopenharmony_ci v &= ~(1 << (d->irq - RBTX4938_IRQ_IOC)); 998c2ecf20Sopenharmony_ci writeb(v, rbtx4938_imask_addr); 1008c2ecf20Sopenharmony_ci mmiowb(); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC" 1048c2ecf20Sopenharmony_cistatic struct irq_chip toshiba_rbtx4938_irq_ioc_type = { 1058c2ecf20Sopenharmony_ci .name = TOSHIBA_RBTX4938_IOC_NAME, 1068c2ecf20Sopenharmony_ci .irq_mask = toshiba_rbtx4938_irq_ioc_disable, 1078c2ecf20Sopenharmony_ci .irq_unmask = toshiba_rbtx4938_irq_ioc_enable, 1088c2ecf20Sopenharmony_ci}; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int rbtx4938_irq_dispatch(int pending) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci int irq; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (pending & STATUSF_IP7) 1158c2ecf20Sopenharmony_ci irq = MIPS_CPU_IRQ_BASE + 7; 1168c2ecf20Sopenharmony_ci else if (pending & STATUSF_IP2) { 1178c2ecf20Sopenharmony_ci irq = txx9_irq(); 1188c2ecf20Sopenharmony_ci if (irq == RBTX4938_IRQ_IOCINT) 1198c2ecf20Sopenharmony_ci irq = toshiba_rbtx4938_irq_nested(irq); 1208c2ecf20Sopenharmony_ci } else if (pending & STATUSF_IP1) 1218c2ecf20Sopenharmony_ci irq = MIPS_CPU_IRQ_BASE + 0; 1228c2ecf20Sopenharmony_ci else if (pending & STATUSF_IP0) 1238c2ecf20Sopenharmony_ci irq = MIPS_CPU_IRQ_BASE + 1; 1248c2ecf20Sopenharmony_ci else 1258c2ecf20Sopenharmony_ci irq = -1; 1268c2ecf20Sopenharmony_ci return irq; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic void __init toshiba_rbtx4938_irq_ioc_init(void) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci int i; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci for (i = RBTX4938_IRQ_IOC; 1348c2ecf20Sopenharmony_ci i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++) 1358c2ecf20Sopenharmony_ci irq_set_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type, 1368c2ecf20Sopenharmony_ci handle_level_irq); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci irq_set_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_civoid __init rbtx4938_irq_setup(void) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci txx9_irq_dispatch = rbtx4938_irq_dispatch; 1448c2ecf20Sopenharmony_ci /* Now, interrupt control disabled, */ 1458c2ecf20Sopenharmony_ci /* all IRC interrupts are masked, */ 1468c2ecf20Sopenharmony_ci /* all IRC interrupt mode are Low Active. */ 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci /* mask all IOC interrupts */ 1498c2ecf20Sopenharmony_ci writeb(0, rbtx4938_imask_addr); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* clear SoftInt interrupts */ 1528c2ecf20Sopenharmony_ci writeb(0, rbtx4938_softint_addr); 1538c2ecf20Sopenharmony_ci tx4938_irq_init(); 1548c2ecf20Sopenharmony_ci toshiba_rbtx4938_irq_ioc_init(); 1558c2ecf20Sopenharmony_ci /* Onboard 10M Ether: High Active */ 1568c2ecf20Sopenharmony_ci irq_set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH); 1578c2ecf20Sopenharmony_ci} 158