aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-pxa/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa/irq.c')
-rw-r--r--arch/arm/mach-pxa/irq.c129
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
38static int pxa_internal_irq_nr; 49static int pxa_internal_irq_nr;
39 50
51static inline int cpu_has_ipr(void)
52{
53 return !cpu_is_pxa25x();
54}
55
40static void pxa_mask_irq(unsigned int irq) 56static 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
45static void pxa_unmask_irq(unsigned int irq) 65static 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
50static struct irq_chip pxa_internal_irq_chip = { 74static struct irq_chip pxa_internal_irq_chip = {
@@ -86,12 +110,16 @@ static void pxa_ack_low_gpio(unsigned int irq)
86 110
87static void pxa_mask_low_gpio(unsigned int irq) 111static 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
92static void pxa_unmask_low_gpio(unsigned int irq) 118static 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
97static struct irq_chip pxa_low_gpio_chip = { 125static 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
151static 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
123void __init pxa_init_irq(int irq_nr, set_wake_t fn) 162void __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
159static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state) 199static 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
176static int pxa_irq_resume(struct sys_device *dev) 218static 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