diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/irqchip/irq-gic-common.c | 15 | ||||
| -rw-r--r-- | drivers/irqchip/irq-gic.c | 46 |
2 files changed, 42 insertions, 19 deletions
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index 60ac704d2090..61541ff24397 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c | |||
| @@ -74,20 +74,22 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs, | |||
| 74 | * Set all global interrupts to be level triggered, active low. | 74 | * Set all global interrupts to be level triggered, active low. |
| 75 | */ | 75 | */ |
| 76 | for (i = 32; i < gic_irqs; i += 16) | 76 | for (i = 32; i < gic_irqs; i += 16) |
| 77 | writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4); | 77 | writel_relaxed(GICD_INT_ACTLOW_LVLTRIG, |
| 78 | base + GIC_DIST_CONFIG + i / 4); | ||
| 78 | 79 | ||
| 79 | /* | 80 | /* |
| 80 | * Set priority on all global interrupts. | 81 | * Set priority on all global interrupts. |
| 81 | */ | 82 | */ |
| 82 | for (i = 32; i < gic_irqs; i += 4) | 83 | for (i = 32; i < gic_irqs; i += 4) |
| 83 | writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i); | 84 | writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i); |
| 84 | 85 | ||
| 85 | /* | 86 | /* |
| 86 | * Disable all interrupts. Leave the PPI and SGIs alone | 87 | * Disable all interrupts. Leave the PPI and SGIs alone |
| 87 | * as they are enabled by redistributor registers. | 88 | * as they are enabled by redistributor registers. |
| 88 | */ | 89 | */ |
| 89 | for (i = 32; i < gic_irqs; i += 32) | 90 | for (i = 32; i < gic_irqs; i += 32) |
| 90 | writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8); | 91 | writel_relaxed(GICD_INT_EN_CLR_X32, |
| 92 | base + GIC_DIST_ENABLE_CLEAR + i / 8); | ||
| 91 | 93 | ||
| 92 | if (sync_access) | 94 | if (sync_access) |
| 93 | sync_access(); | 95 | sync_access(); |
| @@ -101,14 +103,15 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void)) | |||
| 101 | * Deal with the banked PPI and SGI interrupts - disable all | 103 | * Deal with the banked PPI and SGI interrupts - disable all |
| 102 | * PPI interrupts, ensure all SGI interrupts are enabled. | 104 | * PPI interrupts, ensure all SGI interrupts are enabled. |
| 103 | */ | 105 | */ |
| 104 | writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR); | 106 | writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR); |
| 105 | writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET); | 107 | writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET); |
| 106 | 108 | ||
| 107 | /* | 109 | /* |
| 108 | * Set priority on PPI and SGI interrupts | 110 | * Set priority on PPI and SGI interrupts |
| 109 | */ | 111 | */ |
| 110 | for (i = 0; i < 32; i += 4) | 112 | for (i = 0; i < 32; i += 4) |
| 111 | writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); | 113 | writel_relaxed(GICD_INT_DEF_PRI_X4, |
| 114 | base + GIC_DIST_PRI + i * 4 / 4); | ||
| 112 | 115 | ||
| 113 | if (sync_access) | 116 | if (sync_access) |
| 114 | sync_access(); | 117 | sync_access(); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 4b959e606fe8..2500f6ba29e1 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
| @@ -298,8 +298,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); | 298 | status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); |
| 299 | raw_spin_unlock(&irq_controller_lock); | 299 | raw_spin_unlock(&irq_controller_lock); |
| 300 | 300 | ||
| 301 | gic_irq = (status & 0x3ff); | 301 | gic_irq = (status & GICC_IAR_INT_ID_MASK); |
| 302 | if (gic_irq == 1023) | 302 | if (gic_irq == GICC_INT_SPURIOUS) |
| 303 | goto out; | 303 | goto out; |
| 304 | 304 | ||
| 305 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); | 305 | cascade_irq = irq_find_mapping(chip_data->domain, gic_irq); |
| @@ -353,6 +353,21 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic) | |||
| 353 | return mask; | 353 | return mask; |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static void gic_cpu_if_up(void) | ||
| 357 | { | ||
| 358 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); | ||
| 359 | u32 bypass = 0; | ||
| 360 | |||
| 361 | /* | ||
| 362 | * Preserve bypass disable bits to be written back later | ||
| 363 | */ | ||
| 364 | bypass = readl(cpu_base + GIC_CPU_CTRL); | ||
| 365 | bypass &= GICC_DIS_BYPASS_MASK; | ||
| 366 | |||
| 367 | writel_relaxed(bypass | GICC_ENABLE, cpu_base + GIC_CPU_CTRL); | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 356 | static void __init gic_dist_init(struct gic_chip_data *gic) | 371 | static void __init gic_dist_init(struct gic_chip_data *gic) |
| 357 | { | 372 | { |
| 358 | unsigned int i; | 373 | unsigned int i; |
| @@ -360,7 +375,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
| 360 | unsigned int gic_irqs = gic->gic_irqs; | 375 | unsigned int gic_irqs = gic->gic_irqs; |
| 361 | void __iomem *base = gic_data_dist_base(gic); | 376 | void __iomem *base = gic_data_dist_base(gic); |
| 362 | 377 | ||
| 363 | writel_relaxed(0, base + GIC_DIST_CTRL); | 378 | writel_relaxed(GICD_DISABLE, base + GIC_DIST_CTRL); |
| 364 | 379 | ||
| 365 | /* | 380 | /* |
| 366 | * Set all global interrupts to this CPU only. | 381 | * Set all global interrupts to this CPU only. |
| @@ -373,7 +388,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) | |||
| 373 | 388 | ||
| 374 | gic_dist_config(base, gic_irqs, NULL); | 389 | gic_dist_config(base, gic_irqs, NULL); |
| 375 | 390 | ||
| 376 | writel_relaxed(1, base + GIC_DIST_CTRL); | 391 | writel_relaxed(GICD_ENABLE, base + GIC_DIST_CTRL); |
| 377 | } | 392 | } |
| 378 | 393 | ||
| 379 | static void gic_cpu_init(struct gic_chip_data *gic) | 394 | static void gic_cpu_init(struct gic_chip_data *gic) |
| @@ -400,14 +415,18 @@ static void gic_cpu_init(struct gic_chip_data *gic) | |||
| 400 | 415 | ||
| 401 | gic_cpu_config(dist_base, NULL); | 416 | gic_cpu_config(dist_base, NULL); |
| 402 | 417 | ||
| 403 | writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); | 418 | writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); |
| 404 | writel_relaxed(1, base + GIC_CPU_CTRL); | 419 | gic_cpu_if_up(); |
| 405 | } | 420 | } |
| 406 | 421 | ||
| 407 | void gic_cpu_if_down(void) | 422 | void gic_cpu_if_down(void) |
| 408 | { | 423 | { |
| 409 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); | 424 | void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); |
| 410 | writel_relaxed(0, cpu_base + GIC_CPU_CTRL); | 425 | u32 val = 0; |
| 426 | |||
| 427 | val = readl(cpu_base + GIC_CPU_CTRL); | ||
| 428 | val &= ~GICC_ENABLE; | ||
| 429 | writel_relaxed(val, cpu_base + GIC_CPU_CTRL); | ||
| 411 | } | 430 | } |
| 412 | 431 | ||
| 413 | #ifdef CONFIG_CPU_PM | 432 | #ifdef CONFIG_CPU_PM |
| @@ -467,14 +486,14 @@ static void gic_dist_restore(unsigned int gic_nr) | |||
| 467 | if (!dist_base) | 486 | if (!dist_base) |
| 468 | return; | 487 | return; |
| 469 | 488 | ||
| 470 | writel_relaxed(0, dist_base + GIC_DIST_CTRL); | 489 | writel_relaxed(GICD_DISABLE, dist_base + GIC_DIST_CTRL); |
| 471 | 490 | ||
| 472 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) | 491 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++) |
| 473 | writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], | 492 | writel_relaxed(gic_data[gic_nr].saved_spi_conf[i], |
| 474 | dist_base + GIC_DIST_CONFIG + i * 4); | 493 | dist_base + GIC_DIST_CONFIG + i * 4); |
| 475 | 494 | ||
| 476 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) | 495 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) |
| 477 | writel_relaxed(0xa0a0a0a0, | 496 | writel_relaxed(GICD_INT_DEF_PRI_X4, |
| 478 | dist_base + GIC_DIST_PRI + i * 4); | 497 | dist_base + GIC_DIST_PRI + i * 4); |
| 479 | 498 | ||
| 480 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) | 499 | for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++) |
| @@ -485,7 +504,7 @@ static void gic_dist_restore(unsigned int gic_nr) | |||
| 485 | writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], | 504 | writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], |
| 486 | dist_base + GIC_DIST_ENABLE_SET + i * 4); | 505 | dist_base + GIC_DIST_ENABLE_SET + i * 4); |
| 487 | 506 | ||
| 488 | writel_relaxed(1, dist_base + GIC_DIST_CTRL); | 507 | writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL); |
| 489 | } | 508 | } |
| 490 | 509 | ||
| 491 | static void gic_cpu_save(unsigned int gic_nr) | 510 | static void gic_cpu_save(unsigned int gic_nr) |
| @@ -539,10 +558,11 @@ static void gic_cpu_restore(unsigned int gic_nr) | |||
| 539 | writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); | 558 | writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4); |
| 540 | 559 | ||
| 541 | for (i = 0; i < DIV_ROUND_UP(32, 4); i++) | 560 | for (i = 0; i < DIV_ROUND_UP(32, 4); i++) |
| 542 | writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); | 561 | writel_relaxed(GICD_INT_DEF_PRI_X4, |
| 562 | dist_base + GIC_DIST_PRI + i * 4); | ||
| 543 | 563 | ||
| 544 | writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); | 564 | writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK); |
| 545 | writel_relaxed(1, cpu_base + GIC_CPU_CTRL); | 565 | gic_cpu_if_up(); |
| 546 | } | 566 | } |
| 547 | 567 | ||
| 548 | static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) | 568 | static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) |
