1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include <linux/kernel_stat.h>
31#include <linux/module.h>
32#include <linux/random.h>
33#include <linux/seq_file.h>
34#include <linux/kallsyms.h>
35#include <linux/interrupt.h>
36#include <linux/irq.h>
37#include <asm/trace.h>
38
39static unsigned long irq_err_count;
40static spinlock_t irq_controller_lock;
41
42
43
44
45void dummy_mask_unmask_irq(unsigned int irq)
46{
47}
48
49void ack_bad_irq(unsigned int irq)
50{
51 irq_err_count += 1;
52 printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
53}
54EXPORT_SYMBOL(ack_bad_irq);
55
56static struct irq_chip bad_chip = {
57 .ack = dummy_mask_unmask_irq,
58 .mask = dummy_mask_unmask_irq,
59 .unmask = dummy_mask_unmask_irq,
60};
61
62static struct irq_desc bad_irq_desc = {
63 .status = IRQ_DISABLED,
64 .chip = &bad_chip,
65 .handle_irq = handle_bad_irq,
66 .depth = 1,
67 .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock),
68#ifdef CONFIG_SMP
69 .affinity = CPU_MASK_ALL
70#endif
71};
72
73int show_interrupts(struct seq_file *p, void *v)
74{
75 int i = *(loff_t *) v;
76 struct irqaction *action;
77 unsigned long flags;
78
79 if (i < NR_IRQS) {
80 spin_lock_irqsave(&irq_desc[i].lock, flags);
81 action = irq_desc[i].action;
82 if (!action)
83 goto unlock;
84
85 seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
86 seq_printf(p, " %s", action->name);
87 for (action = action->next; action; action = action->next)
88 seq_printf(p, ", %s", action->name);
89
90 seq_putc(p, '\n');
91 unlock:
92 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
93 } else if (i == NR_IRQS) {
94 seq_printf(p, "Err: %10lu\n", irq_err_count);
95 }
96 return 0;
97}
98
99
100
101
102
103
104
105#ifdef CONFIG_DO_IRQ_L1
106__attribute__((l1_text))
107#endif
108asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
109{
110 struct pt_regs *old_regs;
111 struct irq_desc *desc = irq_desc + irq;
112 unsigned short pending, other_ints;
113
114 old_regs = set_irq_regs(regs);
115
116
117
118
119
120 if (irq >= NR_IRQS)
121 desc = &bad_irq_desc;
122
123 irq_enter();
124
125 generic_handle_irq(irq);
126
127
128
129
130
131 CSYNC();
132 pending = bfin_read_IPEND() & ~0x8000;
133 other_ints = pending & (pending - 1);
134 if (other_ints == 0)
135 lower_to_irq14();
136 irq_exit();
137
138 set_irq_regs(old_regs);
139}
140
141void __init init_IRQ(void)
142{
143 struct irq_desc *desc;
144 int irq;
145
146 spin_lock_init(&irq_controller_lock);
147 for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
148 *desc = bad_irq_desc;
149 }
150
151 init_arch_irq();
152
153#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
154
155 trace_buff_offset = 0;
156 bfin_write_TBUFCTL(BFIN_TRACE_ON);
157 printk(KERN_INFO "Hardware Trace expanded to %ik\n",
158 1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN);
159#endif
160}
161