1/* 2 * Toshiba RBTX4939 interrupt routines 3 * Based on linux/arch/mips/txx9/rbtx4938/irq.c, 4 * and RBTX49xx patch from CELF patch archive. 5 * 6 * Copyright (C) 2000-2001,2005-2006 Toshiba Corporation 7 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the 8 * terms of the GNU General Public License version 2. This program is 9 * licensed "as is" without any warranty of any kind, whether express 10 * or implied. 11 */ 12#include <linux/init.h> 13#include <linux/interrupt.h> 14#include <linux/irq.h> 15#include <asm/mipsregs.h> 16#include <asm/txx9/rbtx4939.h> 17 18/* 19 * RBTX4939 IOC controller definition 20 */ 21 22static void rbtx4939_ioc_irq_unmask(struct irq_data *d) 23{ 24 int ioc_nr = d->irq - RBTX4939_IRQ_IOC; 25 26 writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr); 27} 28 29static void rbtx4939_ioc_irq_mask(struct irq_data *d) 30{ 31 int ioc_nr = d->irq - RBTX4939_IRQ_IOC; 32 33 writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr); 34 mmiowb(); 35} 36 37static struct irq_chip rbtx4939_ioc_irq_chip = { 38 .name = "IOC", 39 .irq_mask = rbtx4939_ioc_irq_mask, 40 .irq_unmask = rbtx4939_ioc_irq_unmask, 41}; 42 43 44static inline int rbtx4939_ioc_irqroute(void) 45{ 46 unsigned char istat = readb(rbtx4939_ifac2_addr); 47 48 if (unlikely(istat == 0)) 49 return -1; 50 return RBTX4939_IRQ_IOC + __fls8(istat); 51} 52 53static int rbtx4939_irq_dispatch(int pending) 54{ 55 int irq; 56 57 if (pending & CAUSEF_IP7) 58 return MIPS_CPU_IRQ_BASE + 7; 59 irq = tx4939_irq(); 60 if (likely(irq >= 0)) { 61 /* redirect IOC interrupts */ 62 switch (irq) { 63 case RBTX4939_IRQ_IOCINT: 64 irq = rbtx4939_ioc_irqroute(); 65 break; 66 } 67 } else if (pending & CAUSEF_IP0) 68 irq = MIPS_CPU_IRQ_BASE + 0; 69 else if (pending & CAUSEF_IP1) 70 irq = MIPS_CPU_IRQ_BASE + 1; 71 else 72 irq = -1; 73 return irq; 74} 75 76void __init rbtx4939_irq_setup(void) 77{ 78 int i; 79 80 /* mask all IOC interrupts */ 81 writeb(0, rbtx4939_ien_addr); 82 83 /* clear SoftInt interrupts */ 84 writeb(0, rbtx4939_softint_addr); 85 86 txx9_irq_dispatch = rbtx4939_irq_dispatch; 87 88 tx4939_irq_init(); 89 for (i = RBTX4939_IRQ_IOC; 90 i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++) 91 irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip, 92 handle_level_irq); 93 94 irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq); 95} 96