Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-lpc32xx/irq.c
10817 views
1
/*
2
* arch/arm/mach-lpc32xx/irq.c
3
*
4
* Author: Kevin Wells <[email protected]>
5
*
6
* Copyright (C) 2010 NXP Semiconductors
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
19
#include <linux/kernel.h>
20
#include <linux/types.h>
21
#include <linux/interrupt.h>
22
#include <linux/irq.h>
23
#include <linux/err.h>
24
#include <linux/io.h>
25
26
#include <mach/irqs.h>
27
#include <mach/hardware.h>
28
#include <mach/platform.h>
29
#include "common.h"
30
31
/*
32
* Default value representing the Activation polarity of all internal
33
* interrupt sources
34
*/
35
#define MIC_APR_DEFAULT 0x3FF0EFE0
36
#define SIC1_APR_DEFAULT 0xFBD27186
37
#define SIC2_APR_DEFAULT 0x801810C0
38
39
/*
40
* Default value representing the Activation Type of all internal
41
* interrupt sources. All are level sensitive.
42
*/
43
#define MIC_ATR_DEFAULT 0x00000000
44
#define SIC1_ATR_DEFAULT 0x00026000
45
#define SIC2_ATR_DEFAULT 0x00000000
46
47
struct lpc32xx_event_group_regs {
48
void __iomem *enab_reg;
49
void __iomem *edge_reg;
50
void __iomem *maskstat_reg;
51
void __iomem *rawstat_reg;
52
};
53
54
static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
55
.enab_reg = LPC32XX_CLKPWR_INT_ER,
56
.edge_reg = LPC32XX_CLKPWR_INT_AP,
57
.maskstat_reg = LPC32XX_CLKPWR_INT_SR,
58
.rawstat_reg = LPC32XX_CLKPWR_INT_RS,
59
};
60
61
static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
62
.enab_reg = LPC32XX_CLKPWR_PIN_ER,
63
.edge_reg = LPC32XX_CLKPWR_PIN_AP,
64
.maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
65
.rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
66
};
67
68
struct lpc32xx_event_info {
69
const struct lpc32xx_event_group_regs *event_group;
70
u32 mask;
71
};
72
73
/*
74
* Maps an IRQ number to and event mask and register
75
*/
76
static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
77
[IRQ_LPC32XX_GPI_08] = {
78
.event_group = &lpc32xx_event_pin_regs,
79
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
80
},
81
[IRQ_LPC32XX_GPI_09] = {
82
.event_group = &lpc32xx_event_pin_regs,
83
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
84
},
85
[IRQ_LPC32XX_GPI_19] = {
86
.event_group = &lpc32xx_event_pin_regs,
87
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
88
},
89
[IRQ_LPC32XX_GPI_07] = {
90
.event_group = &lpc32xx_event_pin_regs,
91
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
92
},
93
[IRQ_LPC32XX_GPI_00] = {
94
.event_group = &lpc32xx_event_pin_regs,
95
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
96
},
97
[IRQ_LPC32XX_GPI_01] = {
98
.event_group = &lpc32xx_event_pin_regs,
99
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
100
},
101
[IRQ_LPC32XX_GPI_02] = {
102
.event_group = &lpc32xx_event_pin_regs,
103
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
104
},
105
[IRQ_LPC32XX_GPI_03] = {
106
.event_group = &lpc32xx_event_pin_regs,
107
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
108
},
109
[IRQ_LPC32XX_GPI_04] = {
110
.event_group = &lpc32xx_event_pin_regs,
111
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
112
},
113
[IRQ_LPC32XX_GPI_05] = {
114
.event_group = &lpc32xx_event_pin_regs,
115
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
116
},
117
[IRQ_LPC32XX_GPI_06] = {
118
.event_group = &lpc32xx_event_pin_regs,
119
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
120
},
121
[IRQ_LPC32XX_GPIO_00] = {
122
.event_group = &lpc32xx_event_int_regs,
123
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
124
},
125
[IRQ_LPC32XX_GPIO_01] = {
126
.event_group = &lpc32xx_event_int_regs,
127
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
128
},
129
[IRQ_LPC32XX_GPIO_02] = {
130
.event_group = &lpc32xx_event_int_regs,
131
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
132
},
133
[IRQ_LPC32XX_GPIO_03] = {
134
.event_group = &lpc32xx_event_int_regs,
135
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
136
},
137
[IRQ_LPC32XX_GPIO_04] = {
138
.event_group = &lpc32xx_event_int_regs,
139
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
140
},
141
[IRQ_LPC32XX_GPIO_05] = {
142
.event_group = &lpc32xx_event_int_regs,
143
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
144
},
145
[IRQ_LPC32XX_KEY] = {
146
.event_group = &lpc32xx_event_int_regs,
147
.mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
148
},
149
[IRQ_LPC32XX_USB_OTG_ATX] = {
150
.event_group = &lpc32xx_event_int_regs,
151
.mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
152
},
153
[IRQ_LPC32XX_USB_HOST] = {
154
.event_group = &lpc32xx_event_int_regs,
155
.mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
156
},
157
[IRQ_LPC32XX_RTC] = {
158
.event_group = &lpc32xx_event_int_regs,
159
.mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
160
},
161
[IRQ_LPC32XX_MSTIMER] = {
162
.event_group = &lpc32xx_event_int_regs,
163
.mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
164
},
165
[IRQ_LPC32XX_TS_AUX] = {
166
.event_group = &lpc32xx_event_int_regs,
167
.mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
168
},
169
[IRQ_LPC32XX_TS_P] = {
170
.event_group = &lpc32xx_event_int_regs,
171
.mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
172
},
173
[IRQ_LPC32XX_TS_IRQ] = {
174
.event_group = &lpc32xx_event_int_regs,
175
.mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
176
},
177
};
178
179
static void get_controller(unsigned int irq, unsigned int *base,
180
unsigned int *irqbit)
181
{
182
if (irq < 32) {
183
*base = LPC32XX_MIC_BASE;
184
*irqbit = 1 << irq;
185
} else if (irq < 64) {
186
*base = LPC32XX_SIC1_BASE;
187
*irqbit = 1 << (irq - 32);
188
} else {
189
*base = LPC32XX_SIC2_BASE;
190
*irqbit = 1 << (irq - 64);
191
}
192
}
193
194
static void lpc32xx_mask_irq(struct irq_data *d)
195
{
196
unsigned int reg, ctrl, mask;
197
198
get_controller(d->irq, &ctrl, &mask);
199
200
reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
201
__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
202
}
203
204
static void lpc32xx_unmask_irq(struct irq_data *d)
205
{
206
unsigned int reg, ctrl, mask;
207
208
get_controller(d->irq, &ctrl, &mask);
209
210
reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
211
__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
212
}
213
214
static void lpc32xx_ack_irq(struct irq_data *d)
215
{
216
unsigned int ctrl, mask;
217
218
get_controller(d->irq, &ctrl, &mask);
219
220
__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
221
222
/* Also need to clear pending wake event */
223
if (lpc32xx_events[d->irq].mask != 0)
224
__raw_writel(lpc32xx_events[d->irq].mask,
225
lpc32xx_events[d->irq].event_group->rawstat_reg);
226
}
227
228
static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
229
int use_edge)
230
{
231
unsigned int reg, ctrl, mask;
232
233
get_controller(irq, &ctrl, &mask);
234
235
/* Activation level, high or low */
236
reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
237
if (use_high_level)
238
reg |= mask;
239
else
240
reg &= ~mask;
241
__raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
242
243
/* Activation type, edge or level */
244
reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
245
if (use_edge)
246
reg |= mask;
247
else
248
reg &= ~mask;
249
__raw_writel(reg, LPC32XX_INTC_ACT_TYPE(ctrl));
250
251
/* Use same polarity for the wake events */
252
if (lpc32xx_events[irq].mask != 0) {
253
reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
254
255
if (use_high_level)
256
reg |= lpc32xx_events[irq].mask;
257
else
258
reg &= ~lpc32xx_events[irq].mask;
259
260
__raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
261
}
262
}
263
264
static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
265
{
266
switch (type) {
267
case IRQ_TYPE_EDGE_RISING:
268
/* Rising edge sensitive */
269
__lpc32xx_set_irq_type(d->irq, 1, 1);
270
break;
271
272
case IRQ_TYPE_EDGE_FALLING:
273
/* Falling edge sensitive */
274
__lpc32xx_set_irq_type(d->irq, 0, 1);
275
break;
276
277
case IRQ_TYPE_LEVEL_LOW:
278
/* Low level sensitive */
279
__lpc32xx_set_irq_type(d->irq, 0, 0);
280
break;
281
282
case IRQ_TYPE_LEVEL_HIGH:
283
/* High level sensitive */
284
__lpc32xx_set_irq_type(d->irq, 1, 0);
285
break;
286
287
/* Other modes are not supported */
288
default:
289
return -EINVAL;
290
}
291
292
/* Ok to use the level handler for all types */
293
irq_set_handler(d->irq, handle_level_irq);
294
295
return 0;
296
}
297
298
static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
299
{
300
unsigned long eventreg;
301
302
if (lpc32xx_events[d->irq].mask != 0) {
303
eventreg = __raw_readl(lpc32xx_events[d->irq].
304
event_group->enab_reg);
305
306
if (state)
307
eventreg |= lpc32xx_events[d->irq].mask;
308
else
309
eventreg &= ~lpc32xx_events[d->irq].mask;
310
311
__raw_writel(eventreg,
312
lpc32xx_events[d->irq].event_group->enab_reg);
313
314
return 0;
315
}
316
317
/* Clear event */
318
__raw_writel(lpc32xx_events[d->irq].mask,
319
lpc32xx_events[d->irq].event_group->rawstat_reg);
320
321
return -ENODEV;
322
}
323
324
static void __init lpc32xx_set_default_mappings(unsigned int apr,
325
unsigned int atr, unsigned int offset)
326
{
327
unsigned int i;
328
329
/* Set activation levels for each interrupt */
330
i = 0;
331
while (i < 32) {
332
__lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
333
((atr >> i) & 0x1));
334
i++;
335
}
336
}
337
338
static struct irq_chip lpc32xx_irq_chip = {
339
.irq_ack = lpc32xx_ack_irq,
340
.irq_mask = lpc32xx_mask_irq,
341
.irq_unmask = lpc32xx_unmask_irq,
342
.irq_set_type = lpc32xx_set_irq_type,
343
.irq_set_wake = lpc32xx_irq_wake
344
};
345
346
static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
347
{
348
unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
349
350
while (ints != 0) {
351
int irqno = fls(ints) - 1;
352
353
ints &= ~(1 << irqno);
354
355
generic_handle_irq(LPC32XX_SIC1_IRQ(irqno));
356
}
357
}
358
359
static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
360
{
361
unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
362
363
while (ints != 0) {
364
int irqno = fls(ints) - 1;
365
366
ints &= ~(1 << irqno);
367
368
generic_handle_irq(LPC32XX_SIC2_IRQ(irqno));
369
}
370
}
371
372
void __init lpc32xx_init_irq(void)
373
{
374
unsigned int i;
375
376
/* Setup MIC */
377
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
378
__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
379
__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
380
381
/* Setup SIC1 */
382
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
383
__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
384
__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
385
386
/* Setup SIC2 */
387
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
388
__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
389
__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
390
391
/* Configure supported IRQ's */
392
for (i = 0; i < NR_IRQS; i++) {
393
irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
394
handle_level_irq);
395
set_irq_flags(i, IRQF_VALID);
396
}
397
398
/* Set default mappings */
399
lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
400
lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
401
lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
402
403
/* mask all interrupts except SUBIRQ */
404
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
405
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
406
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
407
408
/* MIC SUBIRQx interrupts will route handling to the chain handlers */
409
irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
410
irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
411
412
/* Initially disable all wake events */
413
__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
414
__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
415
__raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
416
417
/*
418
* Default wake activation polarities, all pin sources are low edge
419
* triggered
420
*/
421
__raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
422
LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
423
LPC32XX_CLKPWR_INTSRC_RTC_BIT,
424
LPC32XX_CLKPWR_INT_AP);
425
__raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
426
427
/* Clear latched wake event states */
428
__raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
429
LPC32XX_CLKPWR_PIN_RS);
430
__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
431
LPC32XX_CLKPWR_INT_RS);
432
}
433
434