1/* 2 * Copyright (C) 2003 PMC-Sierra Inc. 3 * Author: Manish Lachwani (lachwani@pmc-sierra.com) 4 * 5 * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 15 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 16 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 17 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 18 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * 23 * You should have received a copy of the GNU General Public License along 24 * with this program; if not, write to the Free Software Foundation, Inc., 25 * 675 Mass Ave, Cambridge, MA 02139, USA. 26 * 27 * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board 28 */ 29#include <linux/errno.h> 30#include <linux/init.h> 31#include <linux/kernel_stat.h> 32#include <linux/module.h> 33#include <linux/signal.h> 34#include <linux/sched.h> 35#include <linux/types.h> 36#include <linux/interrupt.h> 37#include <linux/ioport.h> 38#include <linux/irq.h> 39#include <linux/timex.h> 40#include <linux/slab.h> 41#include <linux/random.h> 42#include <linux/bitops.h> 43#include <asm/bootinfo.h> 44#include <asm/io.h> 45#include <asm/irq.h> 46#include <asm/irq_cpu.h> 47#include <asm/mipsregs.h> 48#include <asm/system.h> 49#include <asm/titan_dep.h> 50 51/* Hypertransport specific */ 52#define IRQ_ACK_BITS 0x00000000 /* Ack bits */ 53 54#define HYPERTRANSPORT_INTA 0x78 /* INTA# */ 55#define HYPERTRANSPORT_INTB 0x79 /* INTB# */ 56#define HYPERTRANSPORT_INTC 0x7a /* INTC# */ 57#define HYPERTRANSPORT_INTD 0x7b /* INTD# */ 58 59/* 60 * Handle hypertransport & SMP interrupts. The interrupt lines are scarce. 61 * For interprocessor interrupts, the best thing to do is to use the INTMSG 62 * register. We use the same external interrupt line, i.e. INTB3 and monitor 63 * another status bit 64 */ 65static void ll_ht_smp_irq_handler(int irq) 66{ 67 u32 status = OCD_READ(RM9000x2_OCD_INTP0STATUS4); 68 69 /* Ack all the bits that correspond to the interrupt sources */ 70 if (status != 0) 71 OCD_WRITE(RM9000x2_OCD_INTP0STATUS4, IRQ_ACK_BITS); 72 73 status = OCD_READ(RM9000x2_OCD_INTP1STATUS4); 74 if (status != 0) 75 OCD_WRITE(RM9000x2_OCD_INTP1STATUS4, IRQ_ACK_BITS); 76 77#ifdef CONFIG_HT_LEVEL_TRIGGER 78 /* 79 * Level Trigger Mode only. Send the HT EOI message back to the source. 80 */ 81 switch (status) { 82 case 0x1000000: 83 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA); 84 break; 85 case 0x2000000: 86 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB); 87 break; 88 case 0x4000000: 89 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC); 90 break; 91 case 0x8000000: 92 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD); 93 break; 94 case 0x0000001: 95 /* PLX */ 96 OCD_WRITE(RM9000x2_OCD_HTEOI, 0x20); 97 OCD_WRITE(IRQ_CLEAR_REG, IRQ_ACK_BITS); 98 break; 99 case 0xf000000: 100 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTA); 101 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTB); 102 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTC); 103 OCD_WRITE(RM9000x2_OCD_HTEOI, HYPERTRANSPORT_INTD); 104 break; 105 } 106#endif /* CONFIG_HT_LEVEL_TRIGGER */ 107 108 do_IRQ(irq); 109} 110 111asmlinkage void plat_irq_dispatch(void) 112{ 113 unsigned int cause = read_c0_cause(); 114 unsigned int status = read_c0_status(); 115 unsigned int pending = cause & status; 116 117 if (pending & STATUSF_IP7) { 118 do_IRQ(7); 119 } else if (pending & STATUSF_IP2) { 120#ifdef CONFIG_HYPERTRANSPORT 121 ll_ht_smp_irq_handler(2); 122#else 123 do_IRQ(2); 124#endif 125 } else if (pending & STATUSF_IP3) { 126 do_IRQ(3); 127 } else if (pending & STATUSF_IP4) { 128 do_IRQ(4); 129 } else if (pending & STATUSF_IP5) { 130#ifdef CONFIG_SMP 131 titan_mailbox_irq(); 132#else 133 do_IRQ(5); 134#endif 135 } else if (pending & STATUSF_IP6) { 136 do_IRQ(4); 137 } 138} 139 140#ifdef CONFIG_KGDB 141extern void init_second_port(void); 142#endif 143 144/* 145 * Initialize the next level interrupt handler 146 */ 147void __init arch_init_irq(void) 148{ 149 clear_c0_status(ST0_IM); 150 151 mips_cpu_irq_init(); 152 rm7k_cpu_irq_init(); 153 rm9k_cpu_irq_init(); 154 155#ifdef CONFIG_KGDB 156 /* At this point, initialize the second serial port */ 157 init_second_port(); 158#endif 159 160#ifdef CONFIG_GDB_CONSOLE 161 register_gdb_console(); 162#endif 163} 164