1 /* 2 * linux/arch/xtensa/kernel/irq.c 3 * 4 * Xtensa built-in interrupt controller and some generic functions copied 5 * from i386. 6 * 7 * Copyright (C) 2002 - 2005 Tensilica, Inc. 8 * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar 9 * 10 * 11 * Chris Zankel <chris@zankel.net> 12 * Kevin Chea 13 * 14 */ 15 16 #include <linux/module.h> 17 #include <linux/seq_file.h> 18 #include <linux/interrupt.h> 19 #include <linux/irq.h> 20 #include <linux/kernel_stat.h> 21 22 #include <asm/uaccess.h> 23 #include <asm/platform.h> 24 25 static void enable_xtensa_irq(unsigned int irq); 26 static void disable_xtensa_irq(unsigned int irq); 27 static void mask_and_ack_xtensa(unsigned int irq); 28 static void end_xtensa_irq(unsigned int irq); 29 30 static unsigned int cached_irq_mask; 31 32 atomic_t irq_err_count; 33 34 /* 35 * 'what should we do if we get a hw irq event on an illegal vector'. 36 * each architecture has to answer this themselves. 37 */ 38 void ack_bad_irq(unsigned int irq) 39 { 40 printk("unexpected IRQ trap at vector %02x\n", irq); 41 } 42 43 /* 44 * do_IRQ handles all normal device IRQ's (the special 45 * SMP cross-CPU interrupts have their own specific 46 * handlers). 47 */ 48 49 unsigned int do_IRQ(int irq, struct pt_regs *regs) 50 { 51 irq_enter(); 52 53 #ifdef CONFIG_DEBUG_STACKOVERFLOW 54 /* Debugging check for stack overflow: is there less than 1KB free? */ 55 { 56 unsigned long sp; 57 58 __asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp)); 59 sp &= THREAD_SIZE - 1; 60 61 if (unlikely(sp < (sizeof(thread_info) + 1024))) 62 printk("Stack overflow in do_IRQ: %ld\n", 63 sp - sizeof(struct thread_info)); 64 } 65 #endif 66 67 __do_IRQ(irq, regs); 68 69 irq_exit(); 70 71 return 1; 72 } 73 74 /* 75 * Generic, controller-independent functions: 76 */ 77 78 int show_interrupts(struct seq_file *p, void *v) 79 { 80 int i = *(loff_t *) v, j; 81 struct irqaction * action; 82 unsigned long flags; 83 84 if (i == 0) { 85 seq_printf(p, " "); 86 for (j=0; j<NR_CPUS; j++) 87 if (cpu_online(j)) 88 seq_printf(p, "CPU%d ",j); 89 seq_putc(p, '\n'); 90 } 91 92 if (i < NR_IRQS) { 93 spin_lock_irqsave(&irq_desc[i].lock, flags); 94 action = irq_desc[i].action; 95 if (!action) 96 goto skip; 97 seq_printf(p, "%3d: ",i); 98 #ifndef CONFIG_SMP 99 seq_printf(p, "%10u ", kstat_irqs(i)); 100 #else 101 for (j = 0; j < NR_CPUS; j++) 102 if (cpu_online(j)) 103 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 104 #endif 105 seq_printf(p, " %14s", irq_desc[i].handler->typename); 106 seq_printf(p, " %s", action->name); 107 108 for (action=action->next; action; action = action->next) 109 seq_printf(p, ", %s", action->name); 110 111 seq_putc(p, '\n'); 112 skip: 113 spin_unlock_irqrestore(&irq_desc[i].lock, flags); 114 } else if (i == NR_IRQS) { 115 seq_printf(p, "NMI: "); 116 for (j = 0; j < NR_CPUS; j++) 117 if (cpu_online(j)) 118 seq_printf(p, "%10u ", nmi_count(j)); 119 seq_putc(p, '\n'); 120 seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); 121 } 122 return 0; 123 } 124 /* shutdown is same as "disable" */ 125 #define shutdown_xtensa_irq disable_xtensa_irq 126 127 static unsigned int startup_xtensa_irq(unsigned int irq) 128 { 129 enable_xtensa_irq(irq); 130 return 0; /* never anything pending */ 131 } 132 133 static struct hw_interrupt_type xtensa_irq_type = { 134 "Xtensa-IRQ", 135 startup_xtensa_irq, 136 shutdown_xtensa_irq, 137 enable_xtensa_irq, 138 disable_xtensa_irq, 139 mask_and_ack_xtensa, 140 end_xtensa_irq 141 }; 142 143 static inline void mask_irq(unsigned int irq) 144 { 145 cached_irq_mask &= ~(1 << irq); 146 set_sr (cached_irq_mask, INTENABLE); 147 } 148 149 static inline void unmask_irq(unsigned int irq) 150 { 151 cached_irq_mask |= 1 << irq; 152 set_sr (cached_irq_mask, INTENABLE); 153 } 154 155 static void disable_xtensa_irq(unsigned int irq) 156 { 157 unsigned long flags; 158 local_save_flags(flags); 159 mask_irq(irq); 160 local_irq_restore(flags); 161 } 162 163 static void enable_xtensa_irq(unsigned int irq) 164 { 165 unsigned long flags; 166 local_save_flags(flags); 167 unmask_irq(irq); 168 local_irq_restore(flags); 169 } 170 171 static void mask_and_ack_xtensa(unsigned int irq) 172 { 173 disable_xtensa_irq(irq); 174 } 175 176 static void end_xtensa_irq(unsigned int irq) 177 { 178 enable_xtensa_irq(irq); 179 } 180 181 182 void __init init_IRQ(void) 183 { 184 int i; 185 186 for (i=0; i < XTENSA_NR_IRQS; i++) 187 irq_desc[i].handler = &xtensa_irq_type; 188 189 cached_irq_mask = 0; 190 191 platform_init_irq(); 192 } 193