Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/emma/markeins/irq.c
10818 views
1
/*
2
* Copyright (C) NEC Electronics Corporation 2004-2006
3
*
4
* This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
5
*
6
* Copyright 2001 MontaVista Software Inc.
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*/
22
#include <linux/init.h>
23
#include <linux/interrupt.h>
24
#include <linux/irq.h>
25
#include <linux/types.h>
26
#include <linux/ptrace.h>
27
#include <linux/delay.h>
28
29
#include <asm/irq_cpu.h>
30
#include <asm/system.h>
31
#include <asm/mipsregs.h>
32
#include <asm/addrspace.h>
33
#include <asm/bootinfo.h>
34
35
#include <asm/emma/emma2rh.h>
36
37
static void emma2rh_irq_enable(struct irq_data *d)
38
{
39
unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
40
u32 reg_value, reg_bitmask, reg_index;
41
42
reg_index = EMMA2RH_BHIF_INT_EN_0 +
43
(EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
44
reg_value = emma2rh_in32(reg_index);
45
reg_bitmask = 0x1 << (irq % 32);
46
emma2rh_out32(reg_index, reg_value | reg_bitmask);
47
}
48
49
static void emma2rh_irq_disable(struct irq_data *d)
50
{
51
unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
52
u32 reg_value, reg_bitmask, reg_index;
53
54
reg_index = EMMA2RH_BHIF_INT_EN_0 +
55
(EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
56
reg_value = emma2rh_in32(reg_index);
57
reg_bitmask = 0x1 << (irq % 32);
58
emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
59
}
60
61
struct irq_chip emma2rh_irq_controller = {
62
.name = "emma2rh_irq",
63
.irq_mask = emma2rh_irq_disable,
64
.irq_unmask = emma2rh_irq_enable,
65
};
66
67
void emma2rh_irq_init(void)
68
{
69
u32 i;
70
71
for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
72
irq_set_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
73
&emma2rh_irq_controller,
74
handle_level_irq, "level");
75
}
76
77
static void emma2rh_sw_irq_enable(struct irq_data *d)
78
{
79
unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
80
u32 reg;
81
82
reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
83
reg |= 1 << irq;
84
emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
85
}
86
87
static void emma2rh_sw_irq_disable(struct irq_data *d)
88
{
89
unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
90
u32 reg;
91
92
reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
93
reg &= ~(1 << irq);
94
emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
95
}
96
97
struct irq_chip emma2rh_sw_irq_controller = {
98
.name = "emma2rh_sw_irq",
99
.irq_mask = emma2rh_sw_irq_disable,
100
.irq_unmask = emma2rh_sw_irq_enable,
101
};
102
103
void emma2rh_sw_irq_init(void)
104
{
105
u32 i;
106
107
for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
108
irq_set_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
109
&emma2rh_sw_irq_controller,
110
handle_level_irq, "level");
111
}
112
113
static void emma2rh_gpio_irq_enable(struct irq_data *d)
114
{
115
unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
116
u32 reg;
117
118
reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
119
reg |= 1 << irq;
120
emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
121
}
122
123
static void emma2rh_gpio_irq_disable(struct irq_data *d)
124
{
125
unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
126
u32 reg;
127
128
reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
129
reg &= ~(1 << irq);
130
emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
131
}
132
133
static void emma2rh_gpio_irq_ack(struct irq_data *d)
134
{
135
unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
136
137
emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
138
}
139
140
static void emma2rh_gpio_irq_mask_ack(struct irq_data *d)
141
{
142
unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
143
u32 reg;
144
145
emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
146
147
reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
148
reg &= ~(1 << irq);
149
emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
150
}
151
152
struct irq_chip emma2rh_gpio_irq_controller = {
153
.name = "emma2rh_gpio_irq",
154
.irq_ack = emma2rh_gpio_irq_ack,
155
.irq_mask = emma2rh_gpio_irq_disable,
156
.irq_mask_ack = emma2rh_gpio_irq_mask_ack,
157
.irq_unmask = emma2rh_gpio_irq_enable,
158
};
159
160
void emma2rh_gpio_irq_init(void)
161
{
162
u32 i;
163
164
for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
165
irq_set_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
166
&emma2rh_gpio_irq_controller,
167
handle_edge_irq, "edge");
168
}
169
170
static struct irqaction irq_cascade = {
171
.handler = no_action,
172
.flags = 0,
173
.name = "cascade",
174
.dev_id = NULL,
175
.next = NULL,
176
};
177
178
/*
179
* the first level int-handler will jump here if it is a emma2rh irq
180
*/
181
void emma2rh_irq_dispatch(void)
182
{
183
u32 intStatus;
184
u32 bitmask;
185
u32 i;
186
187
intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) &
188
emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
189
190
#ifdef EMMA2RH_SW_CASCADE
191
if (intStatus & (1UL << EMMA2RH_SW_CASCADE)) {
192
u32 swIntStatus;
193
swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
194
& emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
195
for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
196
if (swIntStatus & bitmask) {
197
do_IRQ(EMMA2RH_SW_IRQ_BASE + i);
198
return;
199
}
200
}
201
}
202
/* Skip S/W interrupt */
203
intStatus &= ~(1UL << EMMA2RH_SW_CASCADE);
204
#endif
205
206
for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
207
if (intStatus & bitmask) {
208
do_IRQ(EMMA2RH_IRQ_BASE + i);
209
return;
210
}
211
}
212
213
intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) &
214
emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
215
216
#ifdef EMMA2RH_GPIO_CASCADE
217
if (intStatus & (1UL << (EMMA2RH_GPIO_CASCADE % 32))) {
218
u32 gpioIntStatus;
219
gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
220
& emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
221
for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
222
if (gpioIntStatus & bitmask) {
223
do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i);
224
return;
225
}
226
}
227
}
228
/* Skip GPIO interrupt */
229
intStatus &= ~(1UL << (EMMA2RH_GPIO_CASCADE % 32));
230
#endif
231
232
for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
233
if (intStatus & bitmask) {
234
do_IRQ(EMMA2RH_IRQ_BASE + i);
235
return;
236
}
237
}
238
239
intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) &
240
emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
241
242
for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
243
if (intStatus & bitmask) {
244
do_IRQ(EMMA2RH_IRQ_BASE + i);
245
return;
246
}
247
}
248
}
249
250
void __init arch_init_irq(void)
251
{
252
u32 reg;
253
254
/* by default, interrupts are disabled. */
255
emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
256
emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
257
emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
258
emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
259
emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
260
emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
261
emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
262
263
clear_c0_status(0xff00);
264
set_c0_status(0x0400);
265
266
#define GPIO_PCI (0xf<<15)
267
/* setup GPIO interrupt for PCI interface */
268
/* direction input */
269
reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
270
emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
271
/* disable interrupt */
272
reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
273
emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
274
/* level triggerd */
275
reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
276
emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
277
reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
278
emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
279
/* interrupt clear */
280
emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
281
282
/* init all controllers */
283
emma2rh_irq_init();
284
emma2rh_sw_irq_init();
285
emma2rh_gpio_irq_init();
286
mips_cpu_irq_init();
287
288
/* setup cascade interrupts */
289
setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
290
setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
291
setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade);
292
}
293
294
asmlinkage void plat_irq_dispatch(void)
295
{
296
unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
297
298
if (pending & STATUSF_IP7)
299
do_IRQ(MIPS_CPU_IRQ_BASE + 7);
300
else if (pending & STATUSF_IP2)
301
emma2rh_irq_dispatch();
302
else if (pending & STATUSF_IP1)
303
do_IRQ(MIPS_CPU_IRQ_BASE + 1);
304
else if (pending & STATUSF_IP0)
305
do_IRQ(MIPS_CPU_IRQ_BASE + 0);
306
else
307
spurious_interrupt();
308
}
309
310