aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2011-03-28 09:57:46 -0400
committerWill Deacon <will.deacon@arm.com>2011-05-11 11:04:17 -0400
commit6ac77e469e991e9dd91b28e503fa24b5609eedba (patch)
tree68c0b58456e2e5524624ca48a8f8c2a77b7d99c5 /arch/arm/common
parent1a01753ed90a4fb84357b9b592e50564c07737f7 (diff)
ARM: GIC: Convert GIC library to use the IO relaxed operations
The GIC register accesses today make use of readl()/writel() which prove to be very expensive when used along with mandatory barriers. This mandatory barriers also introduces an un-necessary and expensive l2x0_sync() operation. On Cortex-A9 MP cores, GIC IO accesses from CPU are direct and doesn't go through L2X0 write buffer. A DSB before writel_relaxed() in gic_raise_softirq() is added to be compliant with the Barrier Litmus document - the mailbox scenario. Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/gic.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index e9c2ff83909b..4ddd0a6ac7ff 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -89,7 +89,7 @@ static void gic_mask_irq(struct irq_data *d)
89 u32 mask = 1 << (d->irq % 32); 89 u32 mask = 1 << (d->irq % 32);
90 90
91 spin_lock(&irq_controller_lock); 91 spin_lock(&irq_controller_lock);
92 writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4); 92 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
93 if (gic_arch_extn.irq_mask) 93 if (gic_arch_extn.irq_mask)
94 gic_arch_extn.irq_mask(d); 94 gic_arch_extn.irq_mask(d);
95 spin_unlock(&irq_controller_lock); 95 spin_unlock(&irq_controller_lock);
@@ -102,7 +102,7 @@ static void gic_unmask_irq(struct irq_data *d)
102 spin_lock(&irq_controller_lock); 102 spin_lock(&irq_controller_lock);
103 if (gic_arch_extn.irq_unmask) 103 if (gic_arch_extn.irq_unmask)
104 gic_arch_extn.irq_unmask(d); 104 gic_arch_extn.irq_unmask(d);
105 writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4); 105 writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
106 spin_unlock(&irq_controller_lock); 106 spin_unlock(&irq_controller_lock);
107} 107}
108 108
@@ -114,7 +114,7 @@ static void gic_eoi_irq(struct irq_data *d)
114 spin_unlock(&irq_controller_lock); 114 spin_unlock(&irq_controller_lock);
115 } 115 }
116 116
117 writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); 117 writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
118} 118}
119 119
120static int gic_set_type(struct irq_data *d, unsigned int type) 120static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -140,7 +140,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
140 if (gic_arch_extn.irq_set_type) 140 if (gic_arch_extn.irq_set_type)
141 gic_arch_extn.irq_set_type(d, type); 141 gic_arch_extn.irq_set_type(d, type);
142 142
143 val = readl(base + GIC_DIST_CONFIG + confoff); 143 val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
144 if (type == IRQ_TYPE_LEVEL_HIGH) 144 if (type == IRQ_TYPE_LEVEL_HIGH)
145 val &= ~confmask; 145 val &= ~confmask;
146 else if (type == IRQ_TYPE_EDGE_RISING) 146 else if (type == IRQ_TYPE_EDGE_RISING)
@@ -150,15 +150,15 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
150 * As recommended by the spec, disable the interrupt before changing 150 * As recommended by the spec, disable the interrupt before changing
151 * the configuration 151 * the configuration
152 */ 152 */
153 if (readl(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) { 153 if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
154 writel(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff); 154 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
155 enabled = true; 155 enabled = true;
156 } 156 }
157 157
158 writel(val, base + GIC_DIST_CONFIG + confoff); 158 writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
159 159
160 if (enabled) 160 if (enabled)
161 writel(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); 161 writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
162 162
163 spin_unlock(&irq_controller_lock); 163 spin_unlock(&irq_controller_lock);
164 164
@@ -190,8 +190,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
190 190
191 spin_lock(&irq_controller_lock); 191 spin_lock(&irq_controller_lock);
192 d->node = cpu; 192 d->node = cpu;
193 val = readl(reg) & ~mask; 193 val = readl_relaxed(reg) & ~mask;
194 writel(val | bit, reg); 194 writel_relaxed(val | bit, reg);
195 spin_unlock(&irq_controller_lock); 195 spin_unlock(&irq_controller_lock);
196 196
197 return 0; 197 return 0;
@@ -223,7 +223,7 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
223 chained_irq_enter(chip, desc); 223 chained_irq_enter(chip, desc);
224 224
225 spin_lock(&irq_controller_lock); 225 spin_lock(&irq_controller_lock);
226 status = readl(chip_data->cpu_base + GIC_CPU_INTACK); 226 status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
227 spin_unlock(&irq_controller_lock); 227 spin_unlock(&irq_controller_lock);
228 228
229 gic_irq = (status & 0x3ff); 229 gic_irq = (status & 0x3ff);
@@ -272,13 +272,13 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
272 cpumask |= cpumask << 8; 272 cpumask |= cpumask << 8;
273 cpumask |= cpumask << 16; 273 cpumask |= cpumask << 16;
274 274
275 writel(0, base + GIC_DIST_CTRL); 275 writel_relaxed(0, base + GIC_DIST_CTRL);
276 276
277 /* 277 /*
278 * Find out how many interrupts are supported. 278 * Find out how many interrupts are supported.
279 * The GIC only supports up to 1020 interrupt sources. 279 * The GIC only supports up to 1020 interrupt sources.
280 */ 280 */
281 gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f; 281 gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
282 gic_irqs = (gic_irqs + 1) * 32; 282 gic_irqs = (gic_irqs + 1) * 32;
283 if (gic_irqs > 1020) 283 if (gic_irqs > 1020)
284 gic_irqs = 1020; 284 gic_irqs = 1020;
@@ -287,26 +287,26 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
287 * Set all global interrupts to be level triggered, active low. 287 * Set all global interrupts to be level triggered, active low.
288 */ 288 */
289 for (i = 32; i < gic_irqs; i += 16) 289 for (i = 32; i < gic_irqs; i += 16)
290 writel(0, base + GIC_DIST_CONFIG + i * 4 / 16); 290 writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
291 291
292 /* 292 /*
293 * Set all global interrupts to this CPU only. 293 * Set all global interrupts to this CPU only.
294 */ 294 */
295 for (i = 32; i < gic_irqs; i += 4) 295 for (i = 32; i < gic_irqs; i += 4)
296 writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4); 296 writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
297 297
298 /* 298 /*
299 * Set priority on all global interrupts. 299 * Set priority on all global interrupts.
300 */ 300 */
301 for (i = 32; i < gic_irqs; i += 4) 301 for (i = 32; i < gic_irqs; i += 4)
302 writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); 302 writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
303 303
304 /* 304 /*
305 * Disable all interrupts. Leave the PPI and SGIs alone 305 * Disable all interrupts. Leave the PPI and SGIs alone
306 * as these enables are banked registers. 306 * as these enables are banked registers.
307 */ 307 */
308 for (i = 32; i < gic_irqs; i += 32) 308 for (i = 32; i < gic_irqs; i += 32)
309 writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); 309 writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
310 310
311 /* 311 /*
312 * Limit number of interrupts registered to the platform maximum 312 * Limit number of interrupts registered to the platform maximum
@@ -324,7 +324,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
324 set_irq_flags(i, IRQF_VALID | IRQF_PROBE); 324 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
325 } 325 }
326 326
327 writel(1, base + GIC_DIST_CTRL); 327 writel_relaxed(1, base + GIC_DIST_CTRL);
328} 328}
329 329
330static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) 330static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
@@ -337,17 +337,17 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
337 * Deal with the banked PPI and SGI interrupts - disable all 337 * Deal with the banked PPI and SGI interrupts - disable all
338 * PPI interrupts, ensure all SGI interrupts are enabled. 338 * PPI interrupts, ensure all SGI interrupts are enabled.
339 */ 339 */
340 writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR); 340 writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
341 writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET); 341 writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
342 342
343 /* 343 /*
344 * Set priority on PPI and SGI interrupts 344 * Set priority on PPI and SGI interrupts
345 */ 345 */
346 for (i = 0; i < 32; i += 4) 346 for (i = 0; i < 32; i += 4)
347 writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); 347 writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
348 348
349 writel(0xf0, base + GIC_CPU_PRIMASK); 349 writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
350 writel(1, base + GIC_CPU_CTRL); 350 writel_relaxed(1, base + GIC_CPU_CTRL);
351} 351}
352 352
353void __init gic_init(unsigned int gic_nr, unsigned int irq_start, 353void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -391,7 +391,13 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
391{ 391{
392 unsigned long map = *cpus_addr(*mask); 392 unsigned long map = *cpus_addr(*mask);
393 393
394 /*
395 * Ensure that stores to Normal memory are visible to the
396 * other CPUs before issuing the IPI.
397 */
398 dsb();
399
394 /* this always happens on GIC0 */ 400 /* this always happens on GIC0 */
395 writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT); 401 writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
396} 402}
397#endif 403#endif