Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/xtensa/kernel/irq.c
10817 views
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 - 2006 Tensilica, Inc.
8
* Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
9
*
10
*
11
* Chris Zankel <[email protected]>
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 unsigned int cached_irq_mask;
26
27
atomic_t irq_err_count;
28
29
/*
30
* do_IRQ handles all normal device IRQ's (the special
31
* SMP cross-CPU interrupts have their own specific
32
* handlers).
33
*/
34
35
asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
36
{
37
struct pt_regs *old_regs = set_irq_regs(regs);
38
39
if (irq >= NR_IRQS) {
40
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
41
__func__, irq);
42
}
43
44
irq_enter();
45
46
#ifdef CONFIG_DEBUG_STACKOVERFLOW
47
/* Debugging check for stack overflow: is there less than 1KB free? */
48
{
49
unsigned long sp;
50
51
__asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp));
52
sp &= THREAD_SIZE - 1;
53
54
if (unlikely(sp < (sizeof(thread_info) + 1024)))
55
printk("Stack overflow in do_IRQ: %ld\n",
56
sp - sizeof(struct thread_info));
57
}
58
#endif
59
generic_handle_irq(irq);
60
61
irq_exit();
62
set_irq_regs(old_regs);
63
}
64
65
int arch_show_interrupts(struct seq_file *p, int prec)
66
{
67
seq_printf(p, "%*s: ", prec, "ERR");
68
seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
69
return 0;
70
}
71
72
static void xtensa_irq_mask(struct irq_data *d)
73
{
74
cached_irq_mask &= ~(1 << d->irq);
75
set_sr (cached_irq_mask, INTENABLE);
76
}
77
78
static void xtensa_irq_unmask(struct irq_data *d)
79
{
80
cached_irq_mask |= 1 << d->irq;
81
set_sr (cached_irq_mask, INTENABLE);
82
}
83
84
static void xtensa_irq_enable(struct irq_data *d)
85
{
86
variant_irq_enable(d->irq);
87
xtensa_irq_unmask(d->irq);
88
}
89
90
static void xtensa_irq_disable(struct irq_data *d)
91
{
92
xtensa_irq_mask(d->irq);
93
variant_irq_disable(d->irq);
94
}
95
96
static void xtensa_irq_ack(struct irq_data *d)
97
{
98
set_sr(1 << d->irq, INTCLEAR);
99
}
100
101
static int xtensa_irq_retrigger(struct irq_data *d)
102
{
103
set_sr (1 << d->irq, INTSET);
104
return 1;
105
}
106
107
108
static struct irq_chip xtensa_irq_chip = {
109
.name = "xtensa",
110
.irq_enable = xtensa_irq_enable,
111
.irq_disable = xtensa_irq_disable,
112
.irq_mask = xtensa_irq_mask,
113
.irq_unmask = xtensa_irq_unmask,
114
.irq_ack = xtensa_irq_ack,
115
.irq_retrigger = xtensa_irq_retrigger,
116
};
117
118
void __init init_IRQ(void)
119
{
120
int index;
121
122
for (index = 0; index < XTENSA_NR_IRQS; index++) {
123
int mask = 1 << index;
124
125
if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
126
irq_set_chip_and_handler(index, &xtensa_irq_chip,
127
handle_simple_irq);
128
129
else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
130
irq_set_chip_and_handler(index, &xtensa_irq_chip,
131
handle_edge_irq);
132
133
else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
134
irq_set_chip_and_handler(index, &xtensa_irq_chip,
135
handle_level_irq);
136
137
else if (mask & XCHAL_INTTYPE_MASK_TIMER)
138
irq_set_chip_and_handler(index, &xtensa_irq_chip,
139
handle_edge_irq);
140
141
else /* XCHAL_INTTYPE_MASK_WRITE_ERROR */
142
/* XCHAL_INTTYPE_MASK_NMI */
143
144
irq_set_chip_and_handler(index, &xtensa_irq_chip,
145
handle_level_irq);
146
}
147
148
cached_irq_mask = 0;
149
150
variant_init_irq();
151
}
152
153