diff options
author | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 12:57:02 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2010-12-22 12:57:02 -0500 |
commit | 4b7bd364700d9ac8372eff48832062b936d0793b (patch) | |
tree | 0dbf78c95456a0b02d07fcd473281f04a87e266d /arch/arm/common | |
parent | c0d8768af260e2cbb4bf659ae6094a262c86b085 (diff) | |
parent | 90a8a73c06cc32b609a880d48449d7083327e11a (diff) |
Merge branch 'master' into for-next
Conflicts:
MAINTAINERS
arch/arm/mach-omap2/pm24xx.c
drivers/scsi/bfa/bfa_fcpim.c
Needed to update to apply fixes for which the old branch was too
outdated.
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/gic.c | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index ada6359160eb..e6388dcd8cfa 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c | |||
@@ -146,9 +146,15 @@ static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val) | |||
146 | unsigned int shift = (irq % 4) * 8; | 146 | unsigned int shift = (irq % 4) * 8; |
147 | unsigned int cpu = cpumask_first(mask_val); | 147 | unsigned int cpu = cpumask_first(mask_val); |
148 | u32 val; | 148 | u32 val; |
149 | struct irq_desc *desc; | ||
149 | 150 | ||
150 | spin_lock(&irq_controller_lock); | 151 | spin_lock(&irq_controller_lock); |
151 | irq_desc[irq].node = cpu; | 152 | desc = irq_to_desc(irq); |
153 | if (desc == NULL) { | ||
154 | spin_unlock(&irq_controller_lock); | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | desc->node = cpu; | ||
152 | val = readl(reg) & ~(0xff << shift); | 158 | val = readl(reg) & ~(0xff << shift); |
153 | val |= 1 << (cpu + shift); | 159 | val |= 1 << (cpu + shift); |
154 | writel(val, reg); | 160 | writel(val, reg); |
@@ -210,7 +216,7 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) | |||
210 | void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | 216 | void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, |
211 | unsigned int irq_start) | 217 | unsigned int irq_start) |
212 | { | 218 | { |
213 | unsigned int max_irq, i; | 219 | unsigned int gic_irqs, irq_limit, i; |
214 | u32 cpumask = 1 << smp_processor_id(); | 220 | u32 cpumask = 1 << smp_processor_id(); |
215 | 221 | ||
216 | if (gic_nr >= MAX_GIC_NR) | 222 | if (gic_nr >= MAX_GIC_NR) |
@@ -226,46 +232,49 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | |||
226 | 232 | ||
227 | /* | 233 | /* |
228 | * Find out how many interrupts are supported. | 234 | * Find out how many interrupts are supported. |
229 | */ | ||
230 | max_irq = readl(base + GIC_DIST_CTR) & 0x1f; | ||
231 | max_irq = (max_irq + 1) * 32; | ||
232 | |||
233 | /* | ||
234 | * The GIC only supports up to 1020 interrupt sources. | 235 | * The GIC only supports up to 1020 interrupt sources. |
235 | * Limit this to either the architected maximum, or the | ||
236 | * platform maximum. | ||
237 | */ | 236 | */ |
238 | if (max_irq > max(1020, NR_IRQS)) | 237 | gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f; |
239 | max_irq = max(1020, NR_IRQS); | 238 | gic_irqs = (gic_irqs + 1) * 32; |
239 | if (gic_irqs > 1020) | ||
240 | gic_irqs = 1020; | ||
240 | 241 | ||
241 | /* | 242 | /* |
242 | * Set all global interrupts to be level triggered, active low. | 243 | * Set all global interrupts to be level triggered, active low. |
243 | */ | 244 | */ |
244 | for (i = 32; i < max_irq; i += 16) | 245 | for (i = 32; i < gic_irqs; i += 16) |
245 | writel(0, base + GIC_DIST_CONFIG + i * 4 / 16); | 246 | writel(0, base + GIC_DIST_CONFIG + i * 4 / 16); |
246 | 247 | ||
247 | /* | 248 | /* |
248 | * Set all global interrupts to this CPU only. | 249 | * Set all global interrupts to this CPU only. |
249 | */ | 250 | */ |
250 | for (i = 32; i < max_irq; i += 4) | 251 | for (i = 32; i < gic_irqs; i += 4) |
251 | writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); | 252 | writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); |
252 | 253 | ||
253 | /* | 254 | /* |
254 | * Set priority on all interrupts. | 255 | * Set priority on all global interrupts. |
255 | */ | 256 | */ |
256 | for (i = 0; i < max_irq; i += 4) | 257 | for (i = 32; i < gic_irqs; i += 4) |
257 | writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); | 258 | writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); |
258 | 259 | ||
259 | /* | 260 | /* |
260 | * Disable all interrupts. | 261 | * Disable all interrupts. Leave the PPI and SGIs alone |
262 | * as these enables are banked registers. | ||
261 | */ | 263 | */ |
262 | for (i = 0; i < max_irq; i += 32) | 264 | for (i = 32; i < gic_irqs; i += 32) |
263 | writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); | 265 | writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); |
264 | 266 | ||
265 | /* | 267 | /* |
268 | * Limit number of interrupts registered to the platform maximum | ||
269 | */ | ||
270 | irq_limit = gic_data[gic_nr].irq_offset + gic_irqs; | ||
271 | if (WARN_ON(irq_limit > NR_IRQS)) | ||
272 | irq_limit = NR_IRQS; | ||
273 | |||
274 | /* | ||
266 | * Setup the Linux IRQ subsystem. | 275 | * Setup the Linux IRQ subsystem. |
267 | */ | 276 | */ |
268 | for (i = irq_start; i < gic_data[gic_nr].irq_offset + max_irq; i++) { | 277 | for (i = irq_start; i < irq_limit; i++) { |
269 | set_irq_chip(i, &gic_chip); | 278 | set_irq_chip(i, &gic_chip); |
270 | set_irq_chip_data(i, &gic_data[gic_nr]); | 279 | set_irq_chip_data(i, &gic_data[gic_nr]); |
271 | set_irq_handler(i, handle_level_irq); | 280 | set_irq_handler(i, handle_level_irq); |
@@ -277,11 +286,30 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base, | |||
277 | 286 | ||
278 | void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) | 287 | void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base) |
279 | { | 288 | { |
289 | void __iomem *dist_base; | ||
290 | int i; | ||
291 | |||
280 | if (gic_nr >= MAX_GIC_NR) | 292 | if (gic_nr >= MAX_GIC_NR) |
281 | BUG(); | 293 | BUG(); |
282 | 294 | ||
295 | dist_base = gic_data[gic_nr].dist_base; | ||
296 | BUG_ON(!dist_base); | ||
297 | |||
283 | gic_data[gic_nr].cpu_base = base; | 298 | gic_data[gic_nr].cpu_base = base; |
284 | 299 | ||
300 | /* | ||
301 | * Deal with the banked PPI and SGI interrupts - disable all | ||
302 | * PPI interrupts, ensure all SGI interrupts are enabled. | ||
303 | */ | ||
304 | writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR); | ||
305 | writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET); | ||
306 | |||
307 | /* | ||
308 | * Set priority on PPI and SGI interrupts | ||
309 | */ | ||
310 | for (i = 0; i < 32; i += 4) | ||
311 | writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); | ||
312 | |||
285 | writel(0xf0, base + GIC_CPU_PRIMASK); | 313 | writel(0xf0, base + GIC_CPU_PRIMASK); |
286 | writel(1, base + GIC_CPU_CTRL); | 314 | writel(1, base + GIC_CPU_CTRL); |
287 | } | 315 | } |