Commit 1198365625bf22294263267df3360cb2a4c76f2d
Committed by
Tony Lindgren
1 parent
33ca0be083
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
arm: omap: irq: switch over to intc_readl on omap_intc_handle_irq
an almost blind conversion from readl_relaxed to our newly introduced intc_readl(). While at that, also remove some hardcoded register addresses. Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Showing 1 changed file with 8 additions and 6 deletions Inline Diff
arch/arm/mach-omap2/irq.c
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap2/irq.c | 2 | * linux/arch/arm/mach-omap2/irq.c |
3 | * | 3 | * |
4 | * Interrupt handler for OMAP2 boards. | 4 | * Interrupt handler for OMAP2 boards. |
5 | * | 5 | * |
6 | * Copyright (C) 2005 Nokia Corporation | 6 | * Copyright (C) 2005 Nokia Corporation |
7 | * Author: Paul Mundt <paul.mundt@nokia.com> | 7 | * Author: Paul Mundt <paul.mundt@nokia.com> |
8 | * | 8 | * |
9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
10 | * License. See the file "COPYING" in the main directory of this archive | 10 | * License. See the file "COPYING" in the main directory of this archive |
11 | * for more details. | 11 | * for more details. |
12 | */ | 12 | */ |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include <asm/exception.h> | 19 | #include <asm/exception.h> |
20 | #include <asm/mach/irq.h> | 20 | #include <asm/mach/irq.h> |
21 | #include <linux/irqdomain.h> | 21 | #include <linux/irqdomain.h> |
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | 25 | ||
26 | #include "soc.h" | 26 | #include "soc.h" |
27 | #include "iomap.h" | 27 | #include "iomap.h" |
28 | #include "common.h" | 28 | #include "common.h" |
29 | 29 | ||
30 | /* selected INTC register offsets */ | 30 | /* selected INTC register offsets */ |
31 | 31 | ||
32 | #define INTC_REVISION 0x0000 | 32 | #define INTC_REVISION 0x0000 |
33 | #define INTC_SYSCONFIG 0x0010 | 33 | #define INTC_SYSCONFIG 0x0010 |
34 | #define INTC_SYSSTATUS 0x0014 | 34 | #define INTC_SYSSTATUS 0x0014 |
35 | #define INTC_SIR 0x0040 | 35 | #define INTC_SIR 0x0040 |
36 | #define INTC_CONTROL 0x0048 | 36 | #define INTC_CONTROL 0x0048 |
37 | #define INTC_PROTECTION 0x004C | 37 | #define INTC_PROTECTION 0x004C |
38 | #define INTC_IDLE 0x0050 | 38 | #define INTC_IDLE 0x0050 |
39 | #define INTC_THRESHOLD 0x0068 | 39 | #define INTC_THRESHOLD 0x0068 |
40 | #define INTC_MIR0 0x0084 | 40 | #define INTC_MIR0 0x0084 |
41 | #define INTC_MIR_CLEAR0 0x0088 | 41 | #define INTC_MIR_CLEAR0 0x0088 |
42 | #define INTC_MIR_SET0 0x008c | 42 | #define INTC_MIR_SET0 0x008c |
43 | #define INTC_PENDING_IRQ0 0x0098 | 43 | #define INTC_PENDING_IRQ0 0x0098 |
44 | #define INTC_PENDING_IRQ1 0x00b8 | ||
45 | #define INTC_PENDING_IRQ2 0x00d8 | ||
46 | #define INTC_PENDING_IRQ3 0x00f8 | ||
44 | #define INTC_ILR0 0x0100 | 47 | #define INTC_ILR0 0x0100 |
45 | 48 | ||
46 | #define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) | 49 | #define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) |
47 | #define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) | 50 | #define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) |
48 | #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* omap2/3 active interrupt offset */ | ||
49 | #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ | 51 | #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ |
50 | #define INTCPS_NR_ILR_REGS 128 | 52 | #define INTCPS_NR_ILR_REGS 128 |
51 | #define INTCPS_NR_MIR_REGS 3 | 53 | #define INTCPS_NR_MIR_REGS 3 |
52 | 54 | ||
53 | /* | 55 | /* |
54 | * OMAP2 has a number of different interrupt controllers, each interrupt | 56 | * OMAP2 has a number of different interrupt controllers, each interrupt |
55 | * controller is identified as its own "bank". Register definitions are | 57 | * controller is identified as its own "bank". Register definitions are |
56 | * fairly consistent for each bank, but not all registers are implemented | 58 | * fairly consistent for each bank, but not all registers are implemented |
57 | * for each bank.. when in doubt, consult the TRM. | 59 | * for each bank.. when in doubt, consult the TRM. |
58 | */ | 60 | */ |
59 | 61 | ||
60 | static struct irq_domain *domain; | 62 | static struct irq_domain *domain; |
61 | static void __iomem *omap_irq_base; | 63 | static void __iomem *omap_irq_base; |
62 | static int omap_nr_irqs = 96; | 64 | static int omap_nr_irqs = 96; |
63 | 65 | ||
64 | /* Structure to save interrupt controller context */ | 66 | /* Structure to save interrupt controller context */ |
65 | struct omap3_intc_regs { | 67 | struct omap3_intc_regs { |
66 | u32 sysconfig; | 68 | u32 sysconfig; |
67 | u32 protection; | 69 | u32 protection; |
68 | u32 idle; | 70 | u32 idle; |
69 | u32 threshold; | 71 | u32 threshold; |
70 | u32 ilr[INTCPS_NR_ILR_REGS]; | 72 | u32 ilr[INTCPS_NR_ILR_REGS]; |
71 | u32 mir[INTCPS_NR_MIR_REGS]; | 73 | u32 mir[INTCPS_NR_MIR_REGS]; |
72 | }; | 74 | }; |
73 | 75 | ||
74 | /* INTC bank register get/set */ | 76 | /* INTC bank register get/set */ |
75 | static void intc_writel(u32 reg, u32 val) | 77 | static void intc_writel(u32 reg, u32 val) |
76 | { | 78 | { |
77 | writel_relaxed(val, omap_irq_base + reg); | 79 | writel_relaxed(val, omap_irq_base + reg); |
78 | } | 80 | } |
79 | 81 | ||
80 | static u32 intc_readl(u32 reg) | 82 | static u32 intc_readl(u32 reg) |
81 | { | 83 | { |
82 | return readl_relaxed(omap_irq_base + reg); | 84 | return readl_relaxed(omap_irq_base + reg); |
83 | } | 85 | } |
84 | 86 | ||
85 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ | 87 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ |
86 | static void omap_ack_irq(struct irq_data *d) | 88 | static void omap_ack_irq(struct irq_data *d) |
87 | { | 89 | { |
88 | intc_writel(INTC_CONTROL, 0x1); | 90 | intc_writel(INTC_CONTROL, 0x1); |
89 | } | 91 | } |
90 | 92 | ||
91 | static void omap_mask_ack_irq(struct irq_data *d) | 93 | static void omap_mask_ack_irq(struct irq_data *d) |
92 | { | 94 | { |
93 | irq_gc_mask_disable_reg(d); | 95 | irq_gc_mask_disable_reg(d); |
94 | omap_ack_irq(d); | 96 | omap_ack_irq(d); |
95 | } | 97 | } |
96 | 98 | ||
97 | static void __init omap_irq_soft_reset(void) | 99 | static void __init omap_irq_soft_reset(void) |
98 | { | 100 | { |
99 | unsigned long tmp; | 101 | unsigned long tmp; |
100 | 102 | ||
101 | tmp = intc_readl(INTC_REVISION) & 0xff; | 103 | tmp = intc_readl(INTC_REVISION) & 0xff; |
102 | 104 | ||
103 | pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n", | 105 | pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n", |
104 | omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs); | 106 | omap_irq_base, tmp >> 4, tmp & 0xf, omap_nr_irqs); |
105 | 107 | ||
106 | tmp = intc_readl(INTC_SYSCONFIG); | 108 | tmp = intc_readl(INTC_SYSCONFIG); |
107 | tmp |= 1 << 1; /* soft reset */ | 109 | tmp |= 1 << 1; /* soft reset */ |
108 | intc_writel(INTC_SYSCONFIG, tmp); | 110 | intc_writel(INTC_SYSCONFIG, tmp); |
109 | 111 | ||
110 | while (!(intc_readl(INTC_SYSSTATUS) & 0x1)) | 112 | while (!(intc_readl(INTC_SYSSTATUS) & 0x1)) |
111 | /* Wait for reset to complete */; | 113 | /* Wait for reset to complete */; |
112 | 114 | ||
113 | /* Enable autoidle */ | 115 | /* Enable autoidle */ |
114 | intc_writel(INTC_SYSCONFIG, 1 << 0); | 116 | intc_writel(INTC_SYSCONFIG, 1 << 0); |
115 | } | 117 | } |
116 | 118 | ||
117 | int omap_irq_pending(void) | 119 | int omap_irq_pending(void) |
118 | { | 120 | { |
119 | int irq; | 121 | int irq; |
120 | 122 | ||
121 | for (irq = 0; irq < omap_nr_irqs; irq += 32) | 123 | for (irq = 0; irq < omap_nr_irqs; irq += 32) |
122 | if (intc_readl(INTC_PENDING_IRQ0 + | 124 | if (intc_readl(INTC_PENDING_IRQ0 + |
123 | ((irq >> 5) << 5))) | 125 | ((irq >> 5) << 5))) |
124 | return 1; | 126 | return 1; |
125 | return 0; | 127 | return 0; |
126 | } | 128 | } |
127 | 129 | ||
128 | static __init void | 130 | static __init void |
129 | omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | 131 | omap_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) |
130 | { | 132 | { |
131 | struct irq_chip_generic *gc; | 133 | struct irq_chip_generic *gc; |
132 | struct irq_chip_type *ct; | 134 | struct irq_chip_type *ct; |
133 | 135 | ||
134 | gc = irq_alloc_generic_chip("INTC", 1, irq_start, base, | 136 | gc = irq_alloc_generic_chip("INTC", 1, irq_start, base, |
135 | handle_level_irq); | 137 | handle_level_irq); |
136 | ct = gc->chip_types; | 138 | ct = gc->chip_types; |
137 | ct->chip.irq_ack = omap_mask_ack_irq; | 139 | ct->chip.irq_ack = omap_mask_ack_irq; |
138 | ct->chip.irq_mask = irq_gc_mask_disable_reg; | 140 | ct->chip.irq_mask = irq_gc_mask_disable_reg; |
139 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; | 141 | ct->chip.irq_unmask = irq_gc_unmask_enable_reg; |
140 | ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE; | 142 | ct->chip.flags |= IRQCHIP_SKIP_SET_WAKE; |
141 | 143 | ||
142 | ct->regs.enable = INTC_MIR_CLEAR0; | 144 | ct->regs.enable = INTC_MIR_CLEAR0; |
143 | ct->regs.disable = INTC_MIR_SET0; | 145 | ct->regs.disable = INTC_MIR_SET0; |
144 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | 146 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, |
145 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | 147 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); |
146 | } | 148 | } |
147 | 149 | ||
148 | static void __init omap_init_irq(u32 base, int nr_irqs, | 150 | static void __init omap_init_irq(u32 base, int nr_irqs, |
149 | struct device_node *node) | 151 | struct device_node *node) |
150 | { | 152 | { |
151 | int j, irq_base; | 153 | int j, irq_base; |
152 | 154 | ||
153 | omap_irq_base = ioremap(base, SZ_4K); | 155 | omap_irq_base = ioremap(base, SZ_4K); |
154 | if (WARN_ON(!omap_irq_base)) | 156 | if (WARN_ON(!omap_irq_base)) |
155 | return; | 157 | return; |
156 | 158 | ||
157 | omap_nr_irqs = nr_irqs; | 159 | omap_nr_irqs = nr_irqs; |
158 | 160 | ||
159 | irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); | 161 | irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); |
160 | if (irq_base < 0) { | 162 | if (irq_base < 0) { |
161 | pr_warn("Couldn't allocate IRQ numbers\n"); | 163 | pr_warn("Couldn't allocate IRQ numbers\n"); |
162 | irq_base = 0; | 164 | irq_base = 0; |
163 | } | 165 | } |
164 | 166 | ||
165 | domain = irq_domain_add_legacy(node, nr_irqs, irq_base, 0, | 167 | domain = irq_domain_add_legacy(node, nr_irqs, irq_base, 0, |
166 | &irq_domain_simple_ops, NULL); | 168 | &irq_domain_simple_ops, NULL); |
167 | 169 | ||
168 | omap_irq_soft_reset(); | 170 | omap_irq_soft_reset(); |
169 | 171 | ||
170 | for (j = 0; j < omap_nr_irqs; j += 32) | 172 | for (j = 0; j < omap_nr_irqs; j += 32) |
171 | omap_alloc_gc(omap_irq_base + j, j + irq_base, 32); | 173 | omap_alloc_gc(omap_irq_base + j, j + irq_base, 32); |
172 | } | 174 | } |
173 | 175 | ||
174 | void __init omap2_init_irq(void) | 176 | void __init omap2_init_irq(void) |
175 | { | 177 | { |
176 | omap_init_irq(OMAP24XX_IC_BASE, 96, NULL); | 178 | omap_init_irq(OMAP24XX_IC_BASE, 96, NULL); |
177 | } | 179 | } |
178 | 180 | ||
179 | void __init omap3_init_irq(void) | 181 | void __init omap3_init_irq(void) |
180 | { | 182 | { |
181 | omap_init_irq(OMAP34XX_IC_BASE, 96, NULL); | 183 | omap_init_irq(OMAP34XX_IC_BASE, 96, NULL); |
182 | } | 184 | } |
183 | 185 | ||
184 | void __init ti81xx_init_irq(void) | 186 | void __init ti81xx_init_irq(void) |
185 | { | 187 | { |
186 | omap_init_irq(OMAP34XX_IC_BASE, 128, NULL); | 188 | omap_init_irq(OMAP34XX_IC_BASE, 128, NULL); |
187 | } | 189 | } |
188 | 190 | ||
189 | static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) | 191 | static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) |
190 | { | 192 | { |
191 | u32 irqnr; | 193 | u32 irqnr; |
192 | int handled_irq = 0; | 194 | int handled_irq = 0; |
193 | 195 | ||
194 | do { | 196 | do { |
195 | irqnr = readl_relaxed(base_addr + 0x98); | 197 | irqnr = intc_readl(INTC_PENDING_IRQ0); |
196 | if (irqnr) | 198 | if (irqnr) |
197 | goto out; | 199 | goto out; |
198 | 200 | ||
199 | irqnr = readl_relaxed(base_addr + 0xb8); | 201 | irqnr = intc_readl(INTC_PENDING_IRQ1); |
200 | if (irqnr) | 202 | if (irqnr) |
201 | goto out; | 203 | goto out; |
202 | 204 | ||
203 | irqnr = readl_relaxed(base_addr + 0xd8); | 205 | irqnr = intc_readl(INTC_PENDING_IRQ2); |
204 | #if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX) | 206 | #if IS_ENABLED(CONFIG_SOC_TI81XX) || IS_ENABLED(CONFIG_SOC_AM33XX) |
205 | if (irqnr) | 207 | if (irqnr) |
206 | goto out; | 208 | goto out; |
207 | irqnr = readl_relaxed(base_addr + 0xf8); | 209 | irqnr = intc_readl(INTC_PENDING_IRQ3); |
208 | #endif | 210 | #endif |
209 | 211 | ||
210 | out: | 212 | out: |
211 | if (!irqnr) | 213 | if (!irqnr) |
212 | break; | 214 | break; |
213 | 215 | ||
214 | irqnr = readl_relaxed(base_addr + INTCPS_SIR_IRQ_OFFSET); | 216 | irqnr = intc_readl(INTC_SIR); |
215 | irqnr &= ACTIVEIRQ_MASK; | 217 | irqnr &= ACTIVEIRQ_MASK; |
216 | 218 | ||
217 | if (irqnr) { | 219 | if (irqnr) { |
218 | irqnr = irq_find_mapping(domain, irqnr); | 220 | irqnr = irq_find_mapping(domain, irqnr); |
219 | handle_IRQ(irqnr, regs); | 221 | handle_IRQ(irqnr, regs); |
220 | handled_irq = 1; | 222 | handled_irq = 1; |
221 | } | 223 | } |
222 | } while (irqnr); | 224 | } while (irqnr); |
223 | 225 | ||
224 | /* If an irq is masked or deasserted while active, we will | 226 | /* If an irq is masked or deasserted while active, we will |
225 | * keep ending up here with no irq handled. So remove it from | 227 | * keep ending up here with no irq handled. So remove it from |
226 | * the INTC with an ack.*/ | 228 | * the INTC with an ack.*/ |
227 | if (!handled_irq) | 229 | if (!handled_irq) |
228 | omap_ack_irq(NULL); | 230 | omap_ack_irq(NULL); |
229 | } | 231 | } |
230 | 232 | ||
231 | asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) | 233 | asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) |
232 | { | 234 | { |
233 | void __iomem *base_addr = OMAP2_IRQ_BASE; | 235 | void __iomem *base_addr = OMAP2_IRQ_BASE; |
234 | omap_intc_handle_irq(base_addr, regs); | 236 | omap_intc_handle_irq(base_addr, regs); |
235 | } | 237 | } |
236 | 238 | ||
237 | int __init intc_of_init(struct device_node *node, | 239 | int __init intc_of_init(struct device_node *node, |
238 | struct device_node *parent) | 240 | struct device_node *parent) |
239 | { | 241 | { |
240 | struct resource res; | 242 | struct resource res; |
241 | u32 nr_irq = 96; | 243 | u32 nr_irq = 96; |
242 | 244 | ||
243 | if (WARN_ON(!node)) | 245 | if (WARN_ON(!node)) |
244 | return -ENODEV; | 246 | return -ENODEV; |
245 | 247 | ||
246 | if (of_address_to_resource(node, 0, &res)) { | 248 | if (of_address_to_resource(node, 0, &res)) { |
247 | WARN(1, "unable to get intc registers\n"); | 249 | WARN(1, "unable to get intc registers\n"); |
248 | return -EINVAL; | 250 | return -EINVAL; |
249 | } | 251 | } |
250 | 252 | ||
251 | if (of_property_read_u32(node, "ti,intc-size", &nr_irq)) | 253 | if (of_property_read_u32(node, "ti,intc-size", &nr_irq)) |
252 | pr_warn("unable to get intc-size, default to %d\n", nr_irq); | 254 | pr_warn("unable to get intc-size, default to %d\n", nr_irq); |
253 | 255 | ||
254 | omap_init_irq(res.start, nr_irq, of_node_get(node)); | 256 | omap_init_irq(res.start, nr_irq, of_node_get(node)); |
255 | 257 | ||
256 | return 0; | 258 | return 0; |
257 | } | 259 | } |
258 | 260 | ||
259 | static const struct of_device_id irq_match[] __initconst = { | 261 | static const struct of_device_id irq_match[] __initconst = { |
260 | { .compatible = "ti,omap2-intc", .data = intc_of_init, }, | 262 | { .compatible = "ti,omap2-intc", .data = intc_of_init, }, |
261 | { } | 263 | { } |
262 | }; | 264 | }; |
263 | 265 | ||
264 | void __init omap_intc_of_init(void) | 266 | void __init omap_intc_of_init(void) |
265 | { | 267 | { |
266 | of_irq_init(irq_match); | 268 | of_irq_init(irq_match); |
267 | } | 269 | } |
268 | 270 | ||
269 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) | 271 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) |
270 | static struct omap3_intc_regs intc_context; | 272 | static struct omap3_intc_regs intc_context; |
271 | 273 | ||
272 | void omap_intc_save_context(void) | 274 | void omap_intc_save_context(void) |
273 | { | 275 | { |
274 | int i; | 276 | int i; |
275 | 277 | ||
276 | intc_context.sysconfig = | 278 | intc_context.sysconfig = |
277 | intc_readl(INTC_SYSCONFIG); | 279 | intc_readl(INTC_SYSCONFIG); |
278 | intc_context.protection = | 280 | intc_context.protection = |
279 | intc_readl(INTC_PROTECTION); | 281 | intc_readl(INTC_PROTECTION); |
280 | intc_context.idle = | 282 | intc_context.idle = |
281 | intc_readl(INTC_IDLE); | 283 | intc_readl(INTC_IDLE); |
282 | intc_context.threshold = | 284 | intc_context.threshold = |
283 | intc_readl(INTC_THRESHOLD); | 285 | intc_readl(INTC_THRESHOLD); |
284 | 286 | ||
285 | for (i = 0; i < omap_nr_irqs; i++) | 287 | for (i = 0; i < omap_nr_irqs; i++) |
286 | intc_context.ilr[i] = | 288 | intc_context.ilr[i] = |
287 | intc_readl((INTC_ILR0 + 0x4 * i)); | 289 | intc_readl((INTC_ILR0 + 0x4 * i)); |
288 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) | 290 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) |
289 | intc_context.mir[i] = | 291 | intc_context.mir[i] = |
290 | intc_readl(INTC_MIR0 + (0x20 * i)); | 292 | intc_readl(INTC_MIR0 + (0x20 * i)); |
291 | } | 293 | } |
292 | 294 | ||
293 | void omap_intc_restore_context(void) | 295 | void omap_intc_restore_context(void) |
294 | { | 296 | { |
295 | int i; | 297 | int i; |
296 | 298 | ||
297 | intc_writel(INTC_SYSCONFIG, intc_context.sysconfig); | 299 | intc_writel(INTC_SYSCONFIG, intc_context.sysconfig); |
298 | intc_writel(INTC_PROTECTION, intc_context.protection); | 300 | intc_writel(INTC_PROTECTION, intc_context.protection); |
299 | intc_writel(INTC_IDLE, intc_context.idle); | 301 | intc_writel(INTC_IDLE, intc_context.idle); |
300 | intc_writel(INTC_THRESHOLD, intc_context.threshold); | 302 | intc_writel(INTC_THRESHOLD, intc_context.threshold); |
301 | 303 | ||
302 | for (i = 0; i < omap_nr_irqs; i++) | 304 | for (i = 0; i < omap_nr_irqs; i++) |
303 | intc_writel(INTC_ILR0 + 0x4 * i, | 305 | intc_writel(INTC_ILR0 + 0x4 * i, |
304 | intc_context.ilr[i]); | 306 | intc_context.ilr[i]); |
305 | 307 | ||
306 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) | 308 | for (i = 0; i < INTCPS_NR_MIR_REGS; i++) |
307 | intc_writel(INTC_MIR0 + 0x20 * i, | 309 | intc_writel(INTC_MIR0 + 0x20 * i, |
308 | intc_context.mir[i]); | 310 | intc_context.mir[i]); |
309 | /* MIRs are saved and restore with other PRCM registers */ | 311 | /* MIRs are saved and restore with other PRCM registers */ |
310 | } | 312 | } |
311 | 313 | ||
312 | void omap3_intc_suspend(void) | 314 | void omap3_intc_suspend(void) |
313 | { | 315 | { |
314 | /* A pending interrupt would prevent OMAP from entering suspend */ | 316 | /* A pending interrupt would prevent OMAP from entering suspend */ |
315 | omap_ack_irq(NULL); | 317 | omap_ack_irq(NULL); |
316 | } | 318 | } |
317 | 319 | ||
318 | void omap3_intc_prepare_idle(void) | 320 | void omap3_intc_prepare_idle(void) |
319 | { | 321 | { |
320 | /* | 322 | /* |
321 | * Disable autoidle as it can stall interrupt controller, | 323 | * Disable autoidle as it can stall interrupt controller, |
322 | * cf. errata ID i540 for 3430 (all revisions up to 3.1.x) | 324 | * cf. errata ID i540 for 3430 (all revisions up to 3.1.x) |
323 | */ | 325 | */ |
324 | intc_writel(INTC_SYSCONFIG, 0); | 326 | intc_writel(INTC_SYSCONFIG, 0); |
325 | } | 327 | } |
326 | 328 | ||
327 | void omap3_intc_resume_idle(void) | 329 | void omap3_intc_resume_idle(void) |
328 | { | 330 | { |
329 | /* Re-enable autoidle */ | 331 | /* Re-enable autoidle */ |
330 | intc_writel(INTC_SYSCONFIG, 1); | 332 | intc_writel(INTC_SYSCONFIG, 1); |
331 | } | 333 | } |
332 | 334 | ||
333 | asmlinkage void __exception_irq_entry omap3_intc_handle_irq(struct pt_regs *regs) | 335 | asmlinkage void __exception_irq_entry omap3_intc_handle_irq(struct pt_regs *regs) |
334 | { | 336 | { |
335 | void __iomem *base_addr = OMAP3_IRQ_BASE; | 337 | void __iomem *base_addr = OMAP3_IRQ_BASE; |
336 | omap_intc_handle_irq(base_addr, regs); | 338 | omap_intc_handle_irq(base_addr, regs); |
337 | } | 339 | } |
338 | #endif /* CONFIG_ARCH_OMAP3 */ | 340 | #endif /* CONFIG_ARCH_OMAP3 */ |