1/* 2 * Generic interrupt control functions for Broadcom MIPS boards 3 * 4 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: irq.c,v 1.1 2007-09-04 04:41:12 $ 19 */ 20 21#include <linux/config.h> 22#include <linux/init.h> 23#include <linux/kernel.h> 24#include <linux/types.h> 25#include <linux/interrupt.h> 26#include <linux/irq.h> 27 28#include <asm/irq.h> 29#include <asm/mipsregs.h> 30#include <asm/gdb-stub.h> 31 32#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) 33 34extern asmlinkage void brcmIRQ(void); 35extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs); 36 37void 38plat_irq_dispatch(struct pt_regs *regs) 39{ 40 u32 cause; 41 42 cause = read_c0_cause() & 43 read_c0_status() & 44 CAUSEF_IP; 45 46#ifdef CONFIG_KERNPROF 47 change_c0_status(cause | 1, 1); 48#else 49 clear_c0_status(cause); 50#endif 51 52 if (cause & CAUSEF_IP7) 53 do_IRQ(7, regs); 54 if (cause & CAUSEF_IP2) 55 do_IRQ(2, regs); 56 if (cause & CAUSEF_IP3) 57 do_IRQ(3, regs); 58 if (cause & CAUSEF_IP4) 59 do_IRQ(4, regs); 60 if (cause & CAUSEF_IP5) 61 do_IRQ(5, regs); 62 if (cause & CAUSEF_IP6) 63 do_IRQ(6, regs); 64} 65 66static void 67enable_brcm_irq(unsigned int irq) 68{ 69 if (irq < 8) 70 set_c0_status(1 << (irq + 8)); 71 else 72 set_c0_status(IE_IRQ0); 73} 74 75static void 76disable_brcm_irq(unsigned int irq) 77{ 78 if (irq < 8) 79 clear_c0_status(1 << (irq + 8)); 80 else 81 clear_c0_status(IE_IRQ0); 82} 83 84static void 85ack_brcm_irq(unsigned int irq) 86{ 87 /* Already done in plat_irq_dispatch */ 88} 89 90static unsigned int 91startup_brcm_irq(unsigned int irq) 92{ 93 enable_brcm_irq(irq); 94 95 return 0; /* never anything pending */ 96} 97 98static void 99end_brcm_irq(unsigned int irq) 100{ 101 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 102 enable_brcm_irq(irq); 103} 104 105static struct hw_interrupt_type brcm_irq_type = { 106 typename: "MIPS", 107 startup: startup_brcm_irq, 108 shutdown: disable_brcm_irq, 109 enable: enable_brcm_irq, 110 disable: disable_brcm_irq, 111 ack: ack_brcm_irq, 112 end: end_brcm_irq, 113 NULL 114}; 115 116void __init 117init_IRQ(void) 118{ 119 int i; 120 121 for (i = 0; i < NR_IRQS; i++) { 122 irq_desc[i].status = IRQ_DISABLED; 123 irq_desc[i].action = 0; 124 irq_desc[i].depth = 1; 125 irq_desc[i].handler = &brcm_irq_type; 126 } 127 128 change_c0_status(ST0_IM, ALLINTS); 129 130#ifdef CONFIG_KGDB 131 printk("Breaking into debugger...\n"); 132 set_debug_traps(); 133 breakpoint(); 134#endif 135} 136