Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/vr41xx/common/irq.c
10820 views
1
/*
2
* Interrupt handing routines for NEC VR4100 series.
3
*
4
* Copyright (C) 2005-2007 Yoichi Yuasa <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
*/
20
#include <linux/interrupt.h>
21
#include <linux/module.h>
22
#include <linux/irq.h>
23
24
#include <asm/irq_cpu.h>
25
#include <asm/system.h>
26
#include <asm/vr41xx/irq.h>
27
28
typedef struct irq_cascade {
29
int (*get_irq)(unsigned int);
30
} irq_cascade_t;
31
32
static irq_cascade_t irq_cascade[NR_IRQS] __cacheline_aligned;
33
34
static struct irqaction cascade_irqaction = {
35
.handler = no_action,
36
.name = "cascade",
37
};
38
39
int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int))
40
{
41
int retval = 0;
42
43
if (irq >= NR_IRQS)
44
return -EINVAL;
45
46
if (irq_cascade[irq].get_irq != NULL)
47
free_irq(irq, NULL);
48
49
irq_cascade[irq].get_irq = get_irq;
50
51
if (get_irq != NULL) {
52
retval = setup_irq(irq, &cascade_irqaction);
53
if (retval < 0)
54
irq_cascade[irq].get_irq = NULL;
55
}
56
57
return retval;
58
}
59
60
EXPORT_SYMBOL_GPL(cascade_irq);
61
62
static void irq_dispatch(unsigned int irq)
63
{
64
irq_cascade_t *cascade;
65
66
if (irq >= NR_IRQS) {
67
atomic_inc(&irq_err_count);
68
return;
69
}
70
71
cascade = irq_cascade + irq;
72
if (cascade->get_irq != NULL) {
73
struct irq_desc *desc = irq_to_desc(irq);
74
struct irq_data *idata = irq_desc_get_irq_data(desc);
75
struct irq_chip *chip = irq_desc_get_chip(desc);
76
int ret;
77
78
if (chip->irq_mask_ack)
79
chip->irq_mask_ack(idata);
80
else {
81
chip->irq_mask(idata);
82
chip->irq_ack(idata);
83
}
84
ret = cascade->get_irq(irq);
85
irq = ret;
86
if (ret < 0)
87
atomic_inc(&irq_err_count);
88
else
89
irq_dispatch(irq);
90
if (!irqd_irq_disabled(idata) && chip->irq_unmask)
91
chip->irq_unmask(idata);
92
} else
93
do_IRQ(irq);
94
}
95
96
asmlinkage void plat_irq_dispatch(void)
97
{
98
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
99
100
if (pending & CAUSEF_IP7)
101
do_IRQ(TIMER_IRQ);
102
else if (pending & 0x7800) {
103
if (pending & CAUSEF_IP3)
104
irq_dispatch(INT1_IRQ);
105
else if (pending & CAUSEF_IP4)
106
irq_dispatch(INT2_IRQ);
107
else if (pending & CAUSEF_IP5)
108
irq_dispatch(INT3_IRQ);
109
else if (pending & CAUSEF_IP6)
110
irq_dispatch(INT4_IRQ);
111
} else if (pending & CAUSEF_IP2)
112
irq_dispatch(INT0_IRQ);
113
else if (pending & CAUSEF_IP0)
114
do_IRQ(MIPS_SOFTINT0_IRQ);
115
else if (pending & CAUSEF_IP1)
116
do_IRQ(MIPS_SOFTINT1_IRQ);
117
else
118
spurious_interrupt();
119
}
120
121
void __init arch_init_irq(void)
122
{
123
mips_cpu_irq_init();
124
}
125
126