1/* 2 * Carsten Langgaard, carstenl@mips.com 3 * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. 4 * 5 * ######################################################################## 6 * 7 * This program is free software; you can distribute it and/or modify it 8 * under the terms of the GNU General Public License (Version 2) as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 19 * 20 * ######################################################################## 21 * 22 * Routines for generic manipulation of the interrupts found on the MIPS 23 * Sead board. 24 * 25 */ 26#include <linux/config.h> 27#include <linux/init.h> 28#include <linux/sched.h> 29#include <linux/slab.h> 30#include <linux/interrupt.h> 31#include <linux/kernel_stat.h> 32 33#include <asm/irq.h> 34#include <asm/mips-boards/sead.h> 35#include <asm/mips-boards/seadint.h> 36 37extern asmlinkage void mipsIRQ(void); 38extern void do_IRQ(int irq, struct pt_regs *regs); 39 40void disable_sead_irq(unsigned int irq_nr) 41{ 42 if (irq_nr == SEADINT_UART0) 43 clear_c0_status(0x00000400); 44 else 45 if (irq_nr == SEADINT_UART1) 46 clear_c0_status(0x00000800); 47} 48 49void enable_sead_irq(unsigned int irq_nr) 50{ 51 if (irq_nr == SEADINT_UART0) 52 set_c0_status(0x00000400); 53 else 54 if (irq_nr == SEADINT_UART1) 55 set_c0_status(0x00000800); 56} 57 58static unsigned int startup_sead_irq(unsigned int irq) 59{ 60 enable_sead_irq(irq); 61 return 0; /* never anything pending */ 62} 63 64#define shutdown_sead_irq disable_sead_irq 65 66#define mask_and_ack_sead_irq disable_sead_irq 67 68static void end_sead_irq(unsigned int irq) 69{ 70 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 71 enable_sead_irq(irq); 72} 73 74static struct hw_interrupt_type sead_irq_type = { 75 "SEAD", 76 startup_sead_irq, 77 shutdown_sead_irq, 78 enable_sead_irq, 79 disable_sead_irq, 80 mask_and_ack_sead_irq, 81 end_sead_irq, 82 NULL 83}; 84 85void sead_hw0_irqdispatch(struct pt_regs *regs) 86{ 87 do_IRQ(0, regs); 88} 89 90void sead_hw1_irqdispatch(struct pt_regs *regs) 91{ 92 do_IRQ(1, regs); 93} 94 95void __init init_IRQ(void) 96{ 97 int i; 98 99 /* 100 * Mask out all interrupt 101 */ 102 clear_c0_status(0x0000ff00); 103 104 /* Now safe to set the exception vector. */ 105 set_except_vector(0, mipsIRQ); 106 107 init_generic_irq(); 108 109 for (i = 0; i <= SEADINT_END; i++) { 110 irq_desc[i].status = IRQ_DISABLED; 111 irq_desc[i].action = NULL; 112 irq_desc[i].depth = 1; 113 irq_desc[i].lock = SPIN_LOCK_UNLOCKED; 114 irq_desc[i].handler = &sead_irq_type; 115 } 116} 117