1/* irq.c: FRV IRQ handling 2 * 3 * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12#include <linux/ptrace.h> 13#include <linux/errno.h> 14#include <linux/signal.h> 15#include <linux/sched.h> 16#include <linux/ioport.h> 17#include <linux/interrupt.h> 18#include <linux/timex.h> 19#include <linux/random.h> 20#include <linux/init.h> 21#include <linux/kernel_stat.h> 22#include <linux/irq.h> 23#include <linux/proc_fs.h> 24#include <linux/seq_file.h> 25#include <linux/module.h> 26#include <linux/bitops.h> 27 28#include <linux/atomic.h> 29#include <asm/io.h> 30#include <asm/smp.h> 31#include <asm/uaccess.h> 32#include <asm/pgalloc.h> 33#include <asm/delay.h> 34#include <asm/irq.h> 35#include <asm/irc-regs.h> 36#include <asm/gdb-stub.h> 37 38#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16)) 39 40extern void __init fpga_init(void); 41#ifdef CONFIG_FUJITSU_MB93493 42extern void __init mb93493_init(void); 43#endif 44 45#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) 46 47atomic_t irq_err_count; 48 49int arch_show_interrupts(struct seq_file *p, int prec) 50{ 51 seq_printf(p, "%*s: ", prec, "ERR"); 52 seq_printf(p, "%10u\n", atomic_read(&irq_err_count)); 53 return 0; 54} 55 56/* 57 * on-CPU PIC operations 58 */ 59static void frv_cpupic_ack(struct irq_data *d) 60{ 61 __clr_RC(d->irq); 62 __clr_IRL(); 63} 64 65static void frv_cpupic_mask(struct irq_data *d) 66{ 67 __set_MASK(d->irq); 68} 69 70static void frv_cpupic_mask_ack(struct irq_data *d) 71{ 72 __set_MASK(d->irq); 73 __clr_RC(d->irq); 74 __clr_IRL(); 75} 76 77static void frv_cpupic_unmask(struct irq_data *d) 78{ 79 __clr_MASK(d->irq); 80} 81 82static struct irq_chip frv_cpu_pic = { 83 .name = "cpu", 84 .irq_ack = frv_cpupic_ack, 85 .irq_mask = frv_cpupic_mask, 86 .irq_mask_ack = frv_cpupic_mask_ack, 87 .irq_unmask = frv_cpupic_unmask, 88}; 89 90/* 91 * handles all normal device IRQs 92 * - registers are referred to by the __frame variable (GR28) 93 * - IRQ distribution is complicated in this arch because of the many PICs, the 94 * way they work and the way they cascade 95 */ 96asmlinkage void do_IRQ(void) 97{ 98 irq_enter(); 99 generic_handle_irq(__get_IRL()); 100 irq_exit(); 101} 102 103/* 104 * handles all NMIs when not co-opted by the debugger 105 * - registers are referred to by the __frame variable (GR28) 106 */ 107asmlinkage void do_NMI(void) 108{ 109} 110 111/* 112 * initialise the interrupt system 113 */ 114void __init init_IRQ(void) 115{ 116 int level; 117 118 for (level = 1; level <= 14; level++) 119 irq_set_chip_and_handler(level, &frv_cpu_pic, 120 handle_level_irq); 121 122 irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq); 123 124 /* set the trigger levels for internal interrupt sources 125 * - timers all falling-edge 126 * - ERR0 is rising-edge 127 * - all others are high-level 128 */ 129 __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */ 130 __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */ 131 132 /* route internal interrupts */ 133 set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, 134 IRQ_DMA0_LEVEL); 135 set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL); 136 set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, 137 IRQ_UART1_LEVEL, IRQ_UART0_LEVEL); 138 set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, 139 IRQ_DMA4_LEVEL); 140 141 /* route external interrupts */ 142 set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, 143 IRQ_XIRQ4_LEVEL); 144 set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, 145 IRQ_XIRQ0_LEVEL); 146 147#if defined(CONFIG_MB93091_VDK) 148 __set_TM1(0x55550000); /* XIRQ7-0 all active low */ 149#elif defined(CONFIG_MB93093_PDK) 150 __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */ 151#else 152#error dont know external IRQ trigger levels for this setup 153#endif 154 155 fpga_init(); 156#ifdef CONFIG_FUJITSU_MB93493 157 mb93493_init(); 158#endif 159} 160