Blame view
arch/arm/mach-at91/irq.c
4.37 KB
73a59c1c4 [ARM] 3240/2: AT9... |
1 |
/* |
9d0412680 [ARM] 4124/1: Ren... |
2 |
* linux/arch/arm/mach-at91/irq.c |
73a59c1c4 [ARM] 3240/2: AT9... |
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
* * Copyright (C) 2004 SAN People * Copyright (C) 2004 ATMEL * Copyright (C) Rick Bronson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
73a59c1c4 [ARM] 3240/2: AT9... |
22 23 24 25 |
#include <linux/init.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/types.h> |
a09e64fbc [ARM] Move includ... |
26 |
#include <mach/hardware.h> |
73a59c1c4 [ARM] 3240/2: AT9... |
27 |
#include <asm/irq.h> |
73a59c1c4 [ARM] 3240/2: AT9... |
28 29 30 31 32 |
#include <asm/setup.h> #include <asm/mach/arch.h> #include <asm/mach/irq.h> #include <asm/mach/map.h> |
be6d43217 ARM: at91: make a... |
33 |
void __iomem *at91_aic_base; |
73a59c1c4 [ARM] 3240/2: AT9... |
34 |
|
da0f9403d ARM: at91: irq_da... |
35 |
static void at91_aic_mask_irq(struct irq_data *d) |
73a59c1c4 [ARM] 3240/2: AT9... |
36 37 |
{ /* Disable interrupt on AIC */ |
be6d43217 ARM: at91: make a... |
38 |
at91_aic_write(AT91_AIC_IDCR, 1 << d->irq); |
73a59c1c4 [ARM] 3240/2: AT9... |
39 |
} |
da0f9403d ARM: at91: irq_da... |
40 |
static void at91_aic_unmask_irq(struct irq_data *d) |
73a59c1c4 [ARM] 3240/2: AT9... |
41 42 |
{ /* Enable interrupt on AIC */ |
be6d43217 ARM: at91: make a... |
43 |
at91_aic_write(AT91_AIC_IECR, 1 << d->irq); |
73a59c1c4 [ARM] 3240/2: AT9... |
44 |
} |
1f4fd0a0d [ARM] 3946/1: AT9... |
45 46 47 |
unsigned int at91_extern_irq; #define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) |
da0f9403d ARM: at91: irq_da... |
48 |
static int at91_aic_set_type(struct irq_data *d, unsigned type) |
73a59c1c4 [ARM] 3240/2: AT9... |
49 50 |
{ unsigned int smr, srctype; |
73a59c1c4 [ARM] 3240/2: AT9... |
51 |
switch (type) { |
6cab48602 [ARM] 5179/1: Rep... |
52 |
case IRQ_TYPE_LEVEL_HIGH: |
73a59c1c4 [ARM] 3240/2: AT9... |
53 54 |
srctype = AT91_AIC_SRCTYPE_HIGH; break; |
6cab48602 [ARM] 5179/1: Rep... |
55 |
case IRQ_TYPE_EDGE_RISING: |
73a59c1c4 [ARM] 3240/2: AT9... |
56 57 |
srctype = AT91_AIC_SRCTYPE_RISING; break; |
6cab48602 [ARM] 5179/1: Rep... |
58 |
case IRQ_TYPE_LEVEL_LOW: |
da0f9403d ARM: at91: irq_da... |
59 |
if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ |
1f4fd0a0d [ARM] 3946/1: AT9... |
60 61 |
srctype = AT91_AIC_SRCTYPE_LOW; else |
37f2e4bc1 [ARM] 3582/1: AT9... |
62 |
return -EINVAL; |
73a59c1c4 [ARM] 3240/2: AT9... |
63 |
break; |
6cab48602 [ARM] 5179/1: Rep... |
64 |
case IRQ_TYPE_EDGE_FALLING: |
da0f9403d ARM: at91: irq_da... |
65 |
if ((d->irq == AT91_ID_FIQ) || is_extern_irq(d->irq)) /* only supported on external interrupts */ |
1f4fd0a0d [ARM] 3946/1: AT9... |
66 67 |
srctype = AT91_AIC_SRCTYPE_FALLING; else |
37f2e4bc1 [ARM] 3582/1: AT9... |
68 |
return -EINVAL; |
73a59c1c4 [ARM] 3240/2: AT9... |
69 70 71 72 |
break; default: return -EINVAL; } |
be6d43217 ARM: at91: make a... |
73 74 |
smr = at91_aic_read(AT91_AIC_SMR(d->irq)) & ~AT91_AIC_SRCTYPE; at91_aic_write(AT91_AIC_SMR(d->irq), smr | srctype); |
73a59c1c4 [ARM] 3240/2: AT9... |
75 76 |
return 0; } |
683c66bf7 [ARM] 3583/1: AT9... |
77 78 79 80 |
#ifdef CONFIG_PM static u32 wakeups; static u32 backups; |
da0f9403d ARM: at91: irq_da... |
81 |
static int at91_aic_set_wake(struct irq_data *d, unsigned value) |
683c66bf7 [ARM] 3583/1: AT9... |
82 |
{ |
da0f9403d ARM: at91: irq_da... |
83 |
if (unlikely(d->irq >= 32)) |
683c66bf7 [ARM] 3583/1: AT9... |
84 85 86 |
return -EINVAL; if (value) |
da0f9403d ARM: at91: irq_da... |
87 |
wakeups |= (1 << d->irq); |
683c66bf7 [ARM] 3583/1: AT9... |
88 |
else |
da0f9403d ARM: at91: irq_da... |
89 |
wakeups &= ~(1 << d->irq); |
683c66bf7 [ARM] 3583/1: AT9... |
90 91 92 93 94 95 |
return 0; } void at91_irq_suspend(void) { |
be6d43217 ARM: at91: make a... |
96 97 98 |
backups = at91_aic_read(AT91_AIC_IMR); at91_aic_write(AT91_AIC_IDCR, backups); at91_aic_write(AT91_AIC_IECR, wakeups); |
683c66bf7 [ARM] 3583/1: AT9... |
99 100 101 102 |
} void at91_irq_resume(void) { |
be6d43217 ARM: at91: make a... |
103 104 |
at91_aic_write(AT91_AIC_IDCR, wakeups); at91_aic_write(AT91_AIC_IECR, backups); |
683c66bf7 [ARM] 3583/1: AT9... |
105 106 107 |
} #else |
ba854e184 [ARM] 3711/1: AT9... |
108 |
#define at91_aic_set_wake NULL |
683c66bf7 [ARM] 3583/1: AT9... |
109 |
#endif |
38c677cb9 [ARM] 3739/1: gen... |
110 111 |
static struct irq_chip at91_aic_chip = { .name = "AIC", |
da0f9403d ARM: at91: irq_da... |
112 113 114 115 116 |
.irq_ack = at91_aic_mask_irq, .irq_mask = at91_aic_mask_irq, .irq_unmask = at91_aic_unmask_irq, .irq_set_type = at91_aic_set_type, .irq_set_wake = at91_aic_set_wake, |
73a59c1c4 [ARM] 3240/2: AT9... |
117 118 119 120 121 |
}; /* * Initialize the AIC interrupt controller. */ |
ba854e184 [ARM] 3711/1: AT9... |
122 |
void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) |
73a59c1c4 [ARM] 3240/2: AT9... |
123 124 |
{ unsigned int i; |
be6d43217 ARM: at91: make a... |
125 126 127 128 129 |
at91_aic_base = ioremap(AT91_AIC, 512); if (!at91_aic_base) panic("Impossible to ioremap AT91_AIC "); |
73a59c1c4 [ARM] 3240/2: AT9... |
130 131 132 133 134 135 |
/* * The IVR is used by macro get_irqnr_and_base to read and verify. * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred. */ for (i = 0; i < NR_AIC_IRQS; i++) { /* Put irq number in Source Vector Register: */ |
be6d43217 ARM: at91: make a... |
136 |
at91_aic_write(AT91_AIC_SVR(i), i); |
ba854e184 [ARM] 3711/1: AT9... |
137 |
/* Active Low interrupt, with the specified priority */ |
be6d43217 ARM: at91: make a... |
138 |
at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); |
73a59c1c4 [ARM] 3240/2: AT9... |
139 |
|
f38c02f3b arm: Fold irq_set... |
140 |
irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq); |
73a59c1c4 [ARM] 3240/2: AT9... |
141 142 143 144 |
set_irq_flags(i, IRQF_VALID | IRQF_PROBE); /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ if (i < 8) |
be6d43217 ARM: at91: make a... |
145 |
at91_aic_write(AT91_AIC_EOICR, 0); |
73a59c1c4 [ARM] 3240/2: AT9... |
146 147 148 149 150 151 |
} /* * Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU */ |
be6d43217 ARM: at91: make a... |
152 |
at91_aic_write(AT91_AIC_SPU, NR_AIC_IRQS); |
73a59c1c4 [ARM] 3240/2: AT9... |
153 154 |
/* No debugging in AIC: Debug (Protect) Control Register */ |
be6d43217 ARM: at91: make a... |
155 |
at91_aic_write(AT91_AIC_DCR, 0); |
73a59c1c4 [ARM] 3240/2: AT9... |
156 157 |
/* Disable and clear all interrupts initially */ |
be6d43217 ARM: at91: make a... |
158 159 |
at91_aic_write(AT91_AIC_IDCR, 0xFFFFFFFF); at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF); |
73a59c1c4 [ARM] 3240/2: AT9... |
160 |
} |