diff options
Diffstat (limited to 'arch/arm/mach-pxa/irq.c')
-rw-r--r-- | arch/arm/mach-pxa/irq.c | 129 |
1 files changed, 86 insertions, 43 deletions
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 1beb40f692fc..54e91c9e71c8 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c | |||
@@ -16,20 +16,31 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/sysdev.h> | 18 | #include <linux/sysdev.h> |
19 | #include <linux/io.h> | ||
20 | #include <linux/irq.h> | ||
19 | 21 | ||
20 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
21 | #include <asm/irq.h> | 23 | #include <mach/irqs.h> |
22 | #include <asm/mach/irq.h> | ||
23 | #include <mach/gpio.h> | 24 | #include <mach/gpio.h> |
24 | #include <mach/regs-intc.h> | ||
25 | 25 | ||
26 | #include "generic.h" | 26 | #include "generic.h" |
27 | 27 | ||
28 | #define MAX_INTERNAL_IRQS 128 | 28 | #define IRQ_BASE (void __iomem *)io_p2v(0x40d00000) |
29 | |||
30 | #define ICIP (0x000) | ||
31 | #define ICMR (0x004) | ||
32 | #define ICLR (0x008) | ||
33 | #define ICFR (0x00c) | ||
34 | #define ICPR (0x010) | ||
35 | #define ICCR (0x014) | ||
36 | #define ICHP (0x018) | ||
37 | #define IPR(i) (((i) < 32) ? (0x01c + ((i) << 2)) : \ | ||
38 | ((i) < 64) ? (0x0b0 + (((i) - 32) << 2)) : \ | ||
39 | (0x144 + (((i) - 64) << 2))) | ||
40 | #define IPR_VALID (1 << 31) | ||
41 | #define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f) | ||
29 | 42 | ||
30 | #define IRQ_BIT(n) (((n) - PXA_IRQ(0)) & 0x1f) | 43 | #define MAX_INTERNAL_IRQS 128 |
31 | #define _ICMR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICMR2 : &ICMR)) | ||
32 | #define _ICLR(n) (*((((n) - PXA_IRQ(0)) & ~0x1f) ? &ICLR2 : &ICLR)) | ||
33 | 44 | ||
34 | /* | 45 | /* |
35 | * This is for peripheral IRQs internal to the PXA chip. | 46 | * This is for peripheral IRQs internal to the PXA chip. |
@@ -37,14 +48,27 @@ | |||
37 | 48 | ||
38 | static int pxa_internal_irq_nr; | 49 | static int pxa_internal_irq_nr; |
39 | 50 | ||
51 | static inline int cpu_has_ipr(void) | ||
52 | { | ||
53 | return !cpu_is_pxa25x(); | ||
54 | } | ||
55 | |||
40 | static void pxa_mask_irq(unsigned int irq) | 56 | static void pxa_mask_irq(unsigned int irq) |
41 | { | 57 | { |
42 | _ICMR(irq) &= ~(1 << IRQ_BIT(irq)); | 58 | void __iomem *base = get_irq_chip_data(irq); |
59 | uint32_t icmr = __raw_readl(base + ICMR); | ||
60 | |||
61 | icmr &= ~(1 << IRQ_BIT(irq)); | ||
62 | __raw_writel(icmr, base + ICMR); | ||
43 | } | 63 | } |
44 | 64 | ||
45 | static void pxa_unmask_irq(unsigned int irq) | 65 | static void pxa_unmask_irq(unsigned int irq) |
46 | { | 66 | { |
47 | _ICMR(irq) |= 1 << IRQ_BIT(irq); | 67 | void __iomem *base = get_irq_chip_data(irq); |
68 | uint32_t icmr = __raw_readl(base + ICMR); | ||
69 | |||
70 | icmr |= 1 << IRQ_BIT(irq); | ||
71 | __raw_writel(icmr, base + ICMR); | ||
48 | } | 72 | } |
49 | 73 | ||
50 | static struct irq_chip pxa_internal_irq_chip = { | 74 | static struct irq_chip pxa_internal_irq_chip = { |
@@ -86,12 +110,16 @@ static void pxa_ack_low_gpio(unsigned int irq) | |||
86 | 110 | ||
87 | static void pxa_mask_low_gpio(unsigned int irq) | 111 | static void pxa_mask_low_gpio(unsigned int irq) |
88 | { | 112 | { |
89 | ICMR &= ~(1 << (irq - PXA_IRQ(0))); | 113 | struct irq_desc *desc = irq_to_desc(irq); |
114 | |||
115 | desc->chip->mask(irq); | ||
90 | } | 116 | } |
91 | 117 | ||
92 | static void pxa_unmask_low_gpio(unsigned int irq) | 118 | static void pxa_unmask_low_gpio(unsigned int irq) |
93 | { | 119 | { |
94 | ICMR |= 1 << (irq - PXA_IRQ(0)); | 120 | struct irq_desc *desc = irq_to_desc(irq); |
121 | |||
122 | desc->chip->unmask(irq); | ||
95 | } | 123 | } |
96 | 124 | ||
97 | static struct irq_chip pxa_low_gpio_chip = { | 125 | static struct irq_chip pxa_low_gpio_chip = { |
@@ -120,33 +148,45 @@ static void __init pxa_init_low_gpio_irq(set_wake_t fn) | |||
120 | pxa_low_gpio_chip.set_wake = fn; | 148 | pxa_low_gpio_chip.set_wake = fn; |
121 | } | 149 | } |
122 | 150 | ||
151 | static inline void __iomem *irq_base(int i) | ||
152 | { | ||
153 | static unsigned long phys_base[] = { | ||
154 | 0x40d00000, | ||
155 | 0x40d0009c, | ||
156 | 0x40d00130, | ||
157 | }; | ||
158 | |||
159 | return (void __iomem *)io_p2v(phys_base[i >> 5]); | ||
160 | } | ||
161 | |||
123 | void __init pxa_init_irq(int irq_nr, set_wake_t fn) | 162 | void __init pxa_init_irq(int irq_nr, set_wake_t fn) |
124 | { | 163 | { |
125 | int irq, i; | 164 | int irq, i, n; |
126 | 165 | ||
127 | BUG_ON(irq_nr > MAX_INTERNAL_IRQS); | 166 | BUG_ON(irq_nr > MAX_INTERNAL_IRQS); |
128 | 167 | ||
129 | pxa_internal_irq_nr = irq_nr; | 168 | pxa_internal_irq_nr = irq_nr; |
130 | 169 | ||
131 | for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq += 32) { | 170 | for (n = 0; n < irq_nr; n += 32) { |
132 | _ICMR(irq) = 0; /* disable all IRQs */ | 171 | void __iomem *base = irq_base(n); |
133 | _ICLR(irq) = 0; /* all IRQs are IRQ, not FIQ */ | 172 | |
134 | } | 173 | __raw_writel(0, base + ICMR); /* disable all IRQs */ |
135 | 174 | __raw_writel(0, base + ICLR); /* all IRQs are IRQ, not FIQ */ | |
136 | /* initialize interrupt priority */ | 175 | for (i = n; (i < (n + 32)) && (i < irq_nr); i++) { |
137 | if (cpu_is_pxa27x() || cpu_is_pxa3xx()) { | 176 | /* initialize interrupt priority */ |
138 | for (i = 0; i < irq_nr; i++) | 177 | if (cpu_has_ipr()) |
139 | IPR(i) = i | (1 << 31); | 178 | __raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i)); |
179 | |||
180 | irq = PXA_IRQ(i); | ||
181 | set_irq_chip(irq, &pxa_internal_irq_chip); | ||
182 | set_irq_chip_data(irq, base); | ||
183 | set_irq_handler(irq, handle_level_irq); | ||
184 | set_irq_flags(irq, IRQF_VALID); | ||
185 | } | ||
140 | } | 186 | } |
141 | 187 | ||
142 | /* only unmasked interrupts kick us out of idle */ | 188 | /* only unmasked interrupts kick us out of idle */ |
143 | ICCR = 1; | 189 | __raw_writel(1, irq_base(0) + ICCR); |
144 | |||
145 | for (irq = PXA_IRQ(0); irq < PXA_IRQ(irq_nr); irq++) { | ||
146 | set_irq_chip(irq, &pxa_internal_irq_chip); | ||
147 | set_irq_handler(irq, handle_level_irq); | ||
148 | set_irq_flags(irq, IRQF_VALID); | ||
149 | } | ||
150 | 190 | ||
151 | pxa_internal_irq_chip.set_wake = fn; | 191 | pxa_internal_irq_chip.set_wake = fn; |
152 | pxa_init_low_gpio_irq(fn); | 192 | pxa_init_low_gpio_irq(fn); |
@@ -158,16 +198,18 @@ static unsigned long saved_ipr[MAX_INTERNAL_IRQS]; | |||
158 | 198 | ||
159 | static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) | 199 | static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) |
160 | { | 200 | { |
161 | int i, irq = PXA_IRQ(0); | 201 | int i; |
162 | 202 | ||
163 | for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) { | 203 | for (i = 0; i < pxa_internal_irq_nr; i += 32) { |
164 | saved_icmr[i] = _ICMR(irq); | 204 | void __iomem *base = irq_base(i); |
165 | _ICMR(irq) = 0; | 205 | |
206 | saved_icmr[i] = __raw_readl(base + ICMR); | ||
207 | __raw_writel(0, base + ICMR); | ||
166 | } | 208 | } |
167 | 209 | ||
168 | if (cpu_is_pxa27x() || cpu_is_pxa3xx()) { | 210 | if (cpu_has_ipr()) { |
169 | for (i = 0; i < pxa_internal_irq_nr; i++) | 211 | for (i = 0; i < pxa_internal_irq_nr; i++) |
170 | saved_ipr[i] = IPR(i); | 212 | saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i)); |
171 | } | 213 | } |
172 | 214 | ||
173 | return 0; | 215 | return 0; |
@@ -175,19 +217,20 @@ static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) | |||
175 | 217 | ||
176 | static int pxa_irq_resume(struct sys_device *dev) | 218 | static int pxa_irq_resume(struct sys_device *dev) |
177 | { | 219 | { |
178 | int i, irq = PXA_IRQ(0); | 220 | int i; |
179 | 221 | ||
180 | if (cpu_is_pxa27x() || cpu_is_pxa3xx()) { | 222 | for (i = 0; i < pxa_internal_irq_nr; i += 32) { |
181 | for (i = 0; i < pxa_internal_irq_nr; i++) | 223 | void __iomem *base = irq_base(i); |
182 | IPR(i) = saved_ipr[i]; | ||
183 | } | ||
184 | 224 | ||
185 | for (i = 0; irq < PXA_IRQ(pxa_internal_irq_nr); i++, irq += 32) { | 225 | __raw_writel(saved_icmr[i], base + ICMR); |
186 | _ICMR(irq) = saved_icmr[i]; | 226 | __raw_writel(0, base + ICLR); |
187 | _ICLR(irq) = 0; | ||
188 | } | 227 | } |
189 | 228 | ||
190 | ICCR = 1; | 229 | if (!cpu_is_pxa25x()) |
230 | for (i = 0; i < pxa_internal_irq_nr; i++) | ||
231 | __raw_writel(saved_ipr[i], IRQ_BASE + IPR(i)); | ||
232 | |||
233 | __raw_writel(1, IRQ_BASE + ICCR); | ||
191 | return 0; | 234 | return 0; |
192 | } | 235 | } |
193 | #else | 236 | #else |