Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfe3e2b6 authored by Trilok Soni's avatar Trilok Soni Committed by Stephen Boyd
Browse files

ARM: gic: Add flag to select 8625 QGIC2 back to back read/write workaround



MSM8625 v1.0 needs the s/w workaround for hready pin access problem
in QGIC2. The workaround is add the lock around every QGIC2 register's
read and write operation to avoid reading the incorrect value from the
QGIC2 registers when back to back read happens on another CPU.

Change-Id: If980c03d2c57b0b9c560b5a746db0535584841d9
Signed-off-by: default avatarTrilok Soni <tsoni@codeaurora.org>
parent a8182394
Loading
Loading
Loading
Loading
+34 −43
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@

#include "irqchip.h"

#include <mach/socinfo.h>

union gic_base {
	void __iomem *common_base;
	void __percpu __iomem **percpu_base;
@@ -58,6 +60,7 @@ struct gic_chip_data {
	unsigned int irq_offset;
	union gic_base dist_base;
	union gic_base cpu_base;
	bool need_access_lock;
#ifdef CONFIG_CPU_PM
	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
@@ -216,14 +219,8 @@ static int gic_suspend_one(struct gic_chip_data *gic)
{
	unsigned int i;
	void __iomem *base = gic_data_dist_base(gic);
#ifdef CONFIG_ARCH_MSM8625
	unsigned long flags;
#endif

	for (i = 0; i * 32 < gic->gic_irqs; i++) {
#ifdef CONFIG_ARCH_MSM8625
		raw_spin_lock_irqsave(&irq_controller_lock, flags);
#endif
		gic->enabled_irqs[i]
			= readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
		/* disable all of them */
@@ -231,9 +228,6 @@ static int gic_suspend_one(struct gic_chip_data *gic)
		/* enable the wakeup set */
		writel_relaxed(gic->wakeup_irqs[i],
			base + GIC_DIST_ENABLE_SET + i * 4);
#ifdef CONFIG_ARCH_MSM8625
		raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
#endif
	}
	mb();
	return 0;
@@ -314,18 +308,19 @@ arch_initcall(gic_init_sys);

static void gic_eoi_irq(struct irq_data *d)
{
	struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);

	if (gic_arch_extn.irq_eoi) {
		raw_spin_lock(&irq_controller_lock);
		gic_arch_extn.irq_eoi(d);
		raw_spin_unlock(&irq_controller_lock);
	}
#ifdef CONFIG_ARCH_MSM8625

	if (gic->need_access_lock)
		raw_spin_lock(&irq_controller_lock);
#endif
	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
#ifdef CONFIG_ARCH_MSM8625
	if (gic->need_access_lock)
		raw_spin_unlock(&irq_controller_lock);
#endif
}

static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -445,13 +440,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
	void __iomem *cpu_base = gic_data_cpu_base(gic);

	do {
#ifdef CONFIG_ARCH_MSM8625
		if (gic->need_access_lock)
			raw_spin_lock(&irq_controller_lock);
#endif
		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
#ifdef CONFIG_ARCH_MSM8625
		if (gic->need_access_lock)
			raw_spin_unlock(&irq_controller_lock);
#endif
		irqnr = irqstat & ~0x1c00;

		if (likely(irqnr > 15 && irqnr < 1021)) {
@@ -460,13 +453,11 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
			continue;
		}
		if (irqnr < 16) {
#ifdef CONFIG_ARCH_MSM8625
			if (gic->need_access_lock)
				raw_spin_lock(&irq_controller_lock);
#endif
			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
#ifdef CONFIG_ARCH_MSM8625
			if (gic->need_access_lock)
				raw_spin_unlock(&irq_controller_lock);
#endif
#ifdef CONFIG_SMP
			handle_IPI(irqnr, regs);
#endif
@@ -623,9 +614,8 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
	 * Deal with the banked PPI and SGI interrupts - disable all
	 * PPI interrupts, ensure all SGI interrupts are enabled.
	 */
#ifdef CONFIG_ARCH_MSM8625
	if (gic->need_access_lock)
		raw_spin_lock(&irq_controller_lock);
#endif
	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);

@@ -645,9 +635,8 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
		writel_relaxed(0xF, base + GIC_CPU_CTRL);
	else
		writel_relaxed(1, base + GIC_CPU_CTRL);
#ifdef CONFIG_ARCH_MSM8625
	if (gic->need_access_lock)
		raw_spin_unlock(&irq_controller_lock);
#endif
	mb();
}

@@ -875,9 +864,8 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
	int cpu;
	unsigned long sgir;
	unsigned long map = 0;
#ifdef CONFIG_ARCH_MSM8625
	unsigned long flags;
#endif
	unsigned long flags = 0;
	struct gic_chip_data *gic = &gic_data[0];

	/* Convert our logical CPU mask into a physical one. */
	for_each_cpu(cpu, mask)
@@ -886,20 +874,19 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
	sgir = (map << 16) | irq;
	if (is_cpu_secure())
		sgir |= (1 << 15);

	/*
	 * Ensure that stores to Normal memory are visible to the
	 * other CPUs before issuing the IPI.
	 */
	dsb();

#ifdef CONFIG_ARCH_MSM8625
	if (gic->need_access_lock)
		raw_spin_lock_irqsave(&irq_controller_lock, flags);
#endif
	/* this always happens on GIC0 */
	writel_relaxed(sgir, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
#ifdef CONFIG_ARCH_MSM8625
	writel_relaxed(sgir, gic_data_dist_base(gic) + GIC_DIST_SOFTINT);
	if (gic->need_access_lock)
		raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
#endif
	mb();
}
#endif
@@ -1006,6 +993,10 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
	BUG_ON(gic_nr >= MAX_GIC_NR);

	gic = &gic_data[gic_nr];
	if (cpu_is_msm8625() &&
			(SOCINFO_VERSION_MAJOR(socinfo_get_version()) <= 1))
		gic->need_access_lock = true;

#ifdef CONFIG_GIC_NON_BANKED
	if (percpu_offset) { /* Frankein-GIC without banked registers... */
		unsigned int cpu;