aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Cooper <jason@lakedaemon.net>2014-09-14 03:53:39 -0400
committerJason Cooper <jason@lakedaemon.net>2014-09-14 03:53:39 -0400
commitce92bfe88ba38e76371feb93307125fac3f800f0 (patch)
treea10bca9849e16830a846dcabe6bcefcc4a8fbe36
parentcec9694af7ada37611eb41733065427c0e72cd6c (diff)
parent3228950621d92f0f212378f95a6998ef3a1be0bb (diff)
Merge branch 'irqchip/gic' into irqchip/core
-rw-r--r--drivers/irqchip/irq-gic-common.c15
-rw-r--r--drivers/irqchip/irq-gic.c46
-rw-r--r--include/linux/irqchip/arm-gic.h16
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
356static 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
356static void __init gic_dist_init(struct gic_chip_data *gic) 371static 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
379static void gic_cpu_init(struct gic_chip_data *gic) 394static 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
407void gic_cpu_if_down(void) 422void 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
491static void gic_cpu_save(unsigned int gic_nr) 510static 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
548static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) 568static 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