diff options
author | Jason Cooper <jason@lakedaemon.net> | 2014-09-14 03:53:39 -0400 |
---|---|---|
committer | Jason Cooper <jason@lakedaemon.net> | 2014-09-14 03:53:39 -0400 |
commit | ce92bfe88ba38e76371feb93307125fac3f800f0 (patch) | |
tree | a10bca9849e16830a846dcabe6bcefcc4a8fbe36 | |
parent | cec9694af7ada37611eb41733065427c0e72cd6c (diff) | |
parent | 3228950621d92f0f212378f95a6998ef3a1be0bb (diff) |
Merge branch 'irqchip/gic' into irqchip/core
-rw-r--r-- | drivers/irqchip/irq-gic-common.c | 15 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 46 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic.h | 16 |
3 files changed, 58 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) |
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 45e2d8c15bd2..13eed92c7d24 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h | |||
@@ -21,7 +21,11 @@ | |||
21 | #define GIC_CPU_ACTIVEPRIO 0xd0 | 21 | #define GIC_CPU_ACTIVEPRIO 0xd0 |
22 | #define GIC_CPU_IDENT 0xfc | 22 | #define GIC_CPU_IDENT 0xfc |
23 | 23 | ||
24 | #define GICC_ENABLE 0x1 | ||
25 | #define GICC_INT_PRI_THRESHOLD 0xf0 | ||
24 | #define GICC_IAR_INT_ID_MASK 0x3ff | 26 | #define GICC_IAR_INT_ID_MASK 0x3ff |
27 | #define GICC_INT_SPURIOUS 1023 | ||
28 | #define GICC_DIS_BYPASS_MASK 0x1e0 | ||
25 | 29 | ||
26 | #define GIC_DIST_CTRL 0x000 | 30 | #define GIC_DIST_CTRL 0x000 |
27 | #define GIC_DIST_CTR 0x004 | 31 | #define GIC_DIST_CTR 0x004 |
@@ -39,6 +43,18 @@ | |||
39 | #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 | 43 | #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 |
40 | #define GIC_DIST_SGI_PENDING_SET 0xf20 | 44 | #define GIC_DIST_SGI_PENDING_SET 0xf20 |
41 | 45 | ||
46 | #define GICD_ENABLE 0x1 | ||
47 | #define GICD_DISABLE 0x0 | ||
48 | #define GICD_INT_ACTLOW_LVLTRIG 0x0 | ||
49 | #define GICD_INT_EN_CLR_X32 0xffffffff | ||
50 | #define GICD_INT_EN_SET_SGI 0x0000ffff | ||
51 | #define GICD_INT_EN_CLR_PPI 0xffff0000 | ||
52 | #define GICD_INT_DEF_PRI 0xa0 | ||
53 | #define GICD_INT_DEF_PRI_X4 ((GICD_INT_DEF_PRI << 24) |\ | ||
54 | (GICD_INT_DEF_PRI << 16) |\ | ||
55 | (GICD_INT_DEF_PRI << 8) |\ | ||
56 | GICD_INT_DEF_PRI) | ||
57 | |||
42 | #define GICH_HCR 0x0 | 58 | #define GICH_HCR 0x0 |
43 | #define GICH_VTR 0x4 | 59 | #define GICH_VTR 0x4 |
44 | #define GICH_VMCR 0x8 | 60 | #define GICH_VMCR 0x8 |