diff options
Diffstat (limited to 'drivers/irqchip/irq-gic.c')
-rw-r--r-- | drivers/irqchip/irq-gic.c | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 3826698b5890..38493ff28fa5 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -270,8 +270,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) | |||
270 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; | 270 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; |
271 | 271 | ||
272 | if (likely(irqnr > 15 && irqnr < 1021)) { | 272 | if (likely(irqnr > 15 && irqnr < 1021)) { |
273 | irqnr = irq_find_mapping(gic->domain, irqnr); | 273 | handle_domain_irq(gic->domain, irqnr, regs); |
274 | handle_IRQ(irqnr, regs); | ||
275 | continue; | 274 | continue; |
276 | } | 275 | } |
277 | if (irqnr < 16) { | 276 | if (irqnr < 16) { |
@@ -298,8 +297,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
298 | status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); | 297 | status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); |
299 | raw_spin_unlock(&irq_controller_lock); | 298 | raw_spin_unlock(&irq_controller_lock); |
300 | 299 | ||
301 | gic_irq = (status & 0x3ff); | 300 | gic_irq = (status & GICC_IAR_INT_ID_MASK); |
302 | if (gic_irq == 1023) | 301 | if (gic_irq == GICC_INT_SPURIOUS) |
303 | goto out; | 302 | goto out; |
304 | 303 | ||
305 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); | 304 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); |
@@ -353,6 +352,21 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic) | |||
353 | return mask; | 352 | return mask; |
354 | } | 353 | } |
355 | 354 | ||
355 | static void gic_cpu_if_up(void) | ||
356 | { | ||
357 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); | ||
358 | u32 bypass = 0; | ||
359 | |||
360 | /* | ||
361 | * Preserve bypass disable bits to be written back later | ||
362 | */ | ||
363 | bypass = readl(cpu_base + GIC_CPU_CTRL); | ||
364 | bypass &= GICC_DIS_BYPASS_MASK; | ||
365 | |||
366 | writel_relaxed(bypass | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); | ||
367 | } | ||
368 | |||
369 | |||
356 | static void __init gic_dist_init(struct gic_chip_data *gic) | 370 | static void __init gic_dist_init(struct gic_chip_data *gic) |
357 | { | 371 | { |
358 | unsigned int i; | 372 | unsigned int i; |
@@ -360,7 +374,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
360 | unsigned int gic_irqs = gic->gic_irqs; | 374 | unsigned int gic_irqs = gic->gic_irqs; |
361 | void __iomem *base = gic_data_dist_base(gic); | 375 | void __iomem *base = gic_data_dist_base(gic); |
362 | 376 | ||
363 | writel_relaxed(0, base + GIC_DIST_CTRL); | 377 | writel_relaxed(GICD_DISABLE, base + GIC_DIST_CTRL); |
364 | 378 | ||
365 | /* | 379 | /* |
366 | * Set all global interrupts to this CPU only. | 380 | * Set all global interrupts to this CPU only. |
@@ -373,7 +387,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
373 | 387 | ||
374 | gic_dist_config(base, gic_irqs, NULL); | 388 | gic_dist_config(base, gic_irqs, NULL); |
375 | 389 | ||
376 | writel_relaxed(1, base + GIC_DIST_CTRL); | 390 | writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL); |
377 | } | 391 | } |
378 | 392 | ||
379 | static void gic_cpu_init(struct gic_chip_data *gic) | 393 | static void gic_cpu_init(struct gic_chip_data *gic) |
@@ -400,14 +414,18 @@ static void gic_cpu_init(struct gic_chip_data *gic) | |||
400 | 414 | ||
401 | gic_cpu_config(dist_base, NULL); | 415 | gic_cpu_config(dist_base, NULL); |
402 | 416 | ||
403 | writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); | 417 | writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); |
404 | writel_relaxed(1, base + GIC_CPU_CTRL); | 418 | gic_cpu_if_up(); |
405 | } | 419 | } |
406 | 420 | ||
407 | void gic_cpu_if_down(void) | 421 | void gic_cpu_if_down(void) |
408 | { | 422 | { |
409 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); | 423 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); |
410 | writel_relaxed(0, cpu_base + GIC_CPU_CTRL); | 424 | u32 val = 0; |
425 | |||
426 | val = readl(cpu_base + GIC_CPU_CTRL); | ||
427 | val &= ~GICC_ENABLE; | ||
428 | writel_relaxed(val, cpu_base + GIC_CPU_CTRL); | ||
411 | } | 429 | } |
412 | 430 | ||
413 | #ifdef CONFIG_CPU_PM | 431 | #ifdef CONFIG_CPU_PM |
@@ -467,14 +485,14 @@ static void gic_dist_restore(unsigned int gic_nr) | |||
467 | if (!dist_base) | 485 | if (!dist_base) |
468 | return; | 486 | return; |
469 | 487 | ||
470 | writel_relaxed(0, dist_base + GIC_DIST_CTRL); | 488 | writel_relaxed(GICD_DISABLE, dist_base + GIC_DIST_CTRL); |
471 | 489 | ||
472 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) | 490 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) |
473 | writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], | 491 | writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], |
474 | dist_base + GIC_DIST_CONFIG + i * 4); | 492 | dist_base + GIC_DIST_CONFIG + i * 4); |
475 | 493 | ||
476 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) | 494 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) |
477 | writel_relaxed(0xa0a0a0a0, | 495 | writel_relaxed(GICD_INT_DEF_PRI_X4, |
478 | dist_base + GIC_DIST_PRI + i * 4); | 496 | dist_base + GIC_DIST_PRI + i * 4); |
479 | 497 | ||
480 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) | 498 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) |
@@ -485,7 +503,7 @@ static void gic_dist_restore(unsigned int gic_nr) | |||
485 | writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], | 503 | writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], |
486 | dist_base + GIC_DIST_ENABLE_SET + i * 4); | 504 | dist_base + GIC_DIST_ENABLE_SET + i * 4); |
487 | 505 | ||
488 | writel_relaxed(1, dist_base + GIC_DIST_CTRL); | 506 | writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL); |
489 | } | 507 | } |
490 | 508 | ||
491 | static void gic_cpu_save(unsigned int gic_nr) | 509 | static void gic_cpu_save(unsigned int gic_nr) |
@@ -539,10 +557,11 @@ static void gic_cpu_restore(unsigned int gic_nr) | |||
539 | writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); | 557 | writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); |
540 | 558 | ||
541 | for (i = 0; i < DIV_ROUND_UP(32, 4); i++) | 559 | for (i = 0; i < DIV_ROUND_UP(32, 4); i++) |
542 | writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); | 560 | writel_relaxed(GICD_INT_DEF_PRI_X4, |
561 | dist_base + GIC_DIST_PRI + i * 4); | ||
543 | 562 | ||
544 | writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); | 563 | writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK); |
545 | writel_relaxed(1, cpu_base + GIC_CPU_CTRL); | 564 | gic_cpu_if_up(); |
546 | } | 565 | } |
547 | 566 | ||
548 | static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) | 567 | static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) |
@@ -867,7 +886,7 @@ static int gic_routable_irq_domain_xlate(struct irq_domain *d, | |||
867 | return 0; | 886 | return 0; |
868 | } | 887 | } |
869 | 888 | ||
870 | const struct irq_domain_ops gic_default_routable_irq_domain_ops = { | 889 | static const struct irq_domain_ops gic_default_routable_irq_domain_ops = { |
871 | .map = gic_routable_irq_domain_map, | 890 | .map = gic_routable_irq_domain_map, |
872 | .unmap = gic_routable_irq_domain_unmap, | 891 | .unmap = gic_routable_irq_domain_unmap, |
873 | .xlate = gic_routable_irq_domain_xlate, | 892 | .xlate = gic_routable_irq_domain_xlate, |