All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tero Kristo <t-kristo@ti.com>
To: linux-omap@vger.kernel.org, paul@pwsan.com, khilman@ti.com
Cc: linux-arm-kernel@lists.infradead.org,
	Colin Cross <ccross@android.com>, Sebastien Jan <s-jan@ti.com>
Subject: [PATCHv9 6/8] ARM: OMAP4: retrigger localtimers after re-enabling gic
Date: Thu, 18 Oct 2012 12:20:08 +0300	[thread overview]
Message-ID: <1350552010-28760-7-git-send-email-t-kristo@ti.com> (raw)
In-Reply-To: <1350552010-28760-1-git-send-email-t-kristo@ti.com>

From: Colin Cross <ccross@android.com>

'Workaround for ROM bug because of CA9 r2pX gic control'
register change disables the gic distributor while the secondary
cpu is being booted.  If a localtimer interrupt on the primary cpu
occurs when the distributor is turned off, the interrupt is lost,
and the localtimer never fires again.

Make the primary cpu wait for the secondary cpu to reenable the
gic distributor (with interrupts off for safety), and then
check if the pending bit is set in the localtimer but not the
gic.  If so, ack it in the localtimer, and reset the timer with
the minimum timeout to trigger a new timer interrupt.

Signed-off-by: Colin Cross <ccross@android.com>
[s-jan@ti.com: adapted to k3.4 + validated functionality]
Signed-off-by: Sebastien Jan <s-jan@ti.com>
[t-kristo@ti.com: dropped generic ARM kernel exports from the code, rebased
 to mainline]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/common.h       |    2 ++
 arch/arm/mach-omap2/omap-smp.c     |   13 ++++++++++++-
 arch/arm/mach-omap2/omap4-common.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 70993a9..d29dbaa 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -276,6 +276,8 @@ static inline void __iomem *omap4_get_scu_base(void)
 
 extern void __init gic_init_irq(void);
 extern void gic_dist_disable(void);
+extern bool gic_dist_disabled(void);
+extern void gic_timer_retrigger(void);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 7d9c0e3..49a08df 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -134,11 +134,22 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
 		 * 2) CPU1 must re-enable the GIC distributor on
 		 * it's wakeup path.
 		 */
-		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD))
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			local_irq_disable();
 			gic_dist_disable();
+		}
 
 		clkdm_wakeup(cpu1_clkdm);
 		clkdm_allow_idle(cpu1_clkdm);
+
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			while (gic_dist_disabled()) {
+				udelay(1);
+				cpu_relax();
+			}
+			gic_timer_retrigger();
+			local_irq_enable();
+		}
 	} else {
 		dsb_sev();
 		booted = true;
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 72cf396..6f94b4e 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
 #include <linux/of_irq.h>
@@ -24,6 +25,7 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
+#include <asm/smp_twd.h>
 
 #include <plat/sram.h>
 #include <plat/omap-secure.h>
@@ -42,6 +44,9 @@ static void __iomem *l2cache_base;
 
 static void __iomem *sar_ram_base;
 static void __iomem *gic_dist_base_addr;
+static void __iomem *twd_base;
+
+#define IRQ_LOCALTIMER		29
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 /* Used to implement memory barrier on DRAM path */
@@ -101,6 +106,9 @@ void __init gic_init_irq(void)
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
 
+	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_4K);
+	BUG_ON(!twd_base);
+
 	/* Static mapping, never released */
 	omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
 	BUG_ON(!omap_irq_base);
@@ -116,6 +124,32 @@ void gic_dist_disable(void)
 		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 }
 
+bool gic_dist_disabled(void)
+{
+	return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);
+}
+
+void gic_timer_retrigger(void)
+{
+	u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
+	u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET);
+	u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+	if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) {
+		/*
+		 * The local timer interrupt got lost while the distributor was
+		 * disabled.  Ack the pending interrupt, and retrigger it.
+		 */
+		pr_warn("%s: lost localtimer interrupt\n", __func__);
+		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+		if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) {
+			__raw_writel(1, twd_base + TWD_TIMER_COUNTER);
+			twd_ctrl |= TWD_TIMER_CONTROL_ENABLE;
+			__raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL);
+		}
+	}
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
-- 
1.7.4.1


WARNING: multiple messages have this Message-ID (diff)
From: t-kristo@ti.com (Tero Kristo)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv9 6/8] ARM: OMAP4: retrigger localtimers after re-enabling gic
Date: Thu, 18 Oct 2012 12:20:08 +0300	[thread overview]
Message-ID: <1350552010-28760-7-git-send-email-t-kristo@ti.com> (raw)
In-Reply-To: <1350552010-28760-1-git-send-email-t-kristo@ti.com>

From: Colin Cross <ccross@android.com>

'Workaround for ROM bug because of CA9 r2pX gic control'
register change disables the gic distributor while the secondary
cpu is being booted.  If a localtimer interrupt on the primary cpu
occurs when the distributor is turned off, the interrupt is lost,
and the localtimer never fires again.

Make the primary cpu wait for the secondary cpu to reenable the
gic distributor (with interrupts off for safety), and then
check if the pending bit is set in the localtimer but not the
gic.  If so, ack it in the localtimer, and reset the timer with
the minimum timeout to trigger a new timer interrupt.

Signed-off-by: Colin Cross <ccross@android.com>
[s-jan at ti.com: adapted to k3.4 + validated functionality]
Signed-off-by: Sebastien Jan <s-jan@ti.com>
[t-kristo at ti.com: dropped generic ARM kernel exports from the code, rebased
 to mainline]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/common.h       |    2 ++
 arch/arm/mach-omap2/omap-smp.c     |   13 ++++++++++++-
 arch/arm/mach-omap2/omap4-common.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 70993a9..d29dbaa 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -276,6 +276,8 @@ static inline void __iomem *omap4_get_scu_base(void)
 
 extern void __init gic_init_irq(void);
 extern void gic_dist_disable(void);
+extern bool gic_dist_disabled(void);
+extern void gic_timer_retrigger(void);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 7d9c0e3..49a08df 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -134,11 +134,22 @@ static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *
 		 * 2) CPU1 must re-enable the GIC distributor on
 		 * it's wakeup path.
 		 */
-		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD))
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			local_irq_disable();
 			gic_dist_disable();
+		}
 
 		clkdm_wakeup(cpu1_clkdm);
 		clkdm_allow_idle(cpu1_clkdm);
+
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD)) {
+			while (gic_dist_disabled()) {
+				udelay(1);
+				cpu_relax();
+			}
+			gic_timer_retrigger();
+			local_irq_enable();
+		}
 	} else {
 		dsb_sev();
 		booted = true;
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 72cf396..6f94b4e 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
 #include <linux/of_irq.h>
@@ -24,6 +25,7 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
+#include <asm/smp_twd.h>
 
 #include <plat/sram.h>
 #include <plat/omap-secure.h>
@@ -42,6 +44,9 @@ static void __iomem *l2cache_base;
 
 static void __iomem *sar_ram_base;
 static void __iomem *gic_dist_base_addr;
+static void __iomem *twd_base;
+
+#define IRQ_LOCALTIMER		29
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 /* Used to implement memory barrier on DRAM path */
@@ -101,6 +106,9 @@ void __init gic_init_irq(void)
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 	BUG_ON(!gic_dist_base_addr);
 
+	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_4K);
+	BUG_ON(!twd_base);
+
 	/* Static mapping, never released */
 	omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
 	BUG_ON(!omap_irq_base);
@@ -116,6 +124,32 @@ void gic_dist_disable(void)
 		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 }
 
+bool gic_dist_disabled(void)
+{
+	return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);
+}
+
+void gic_timer_retrigger(void)
+{
+	u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
+	u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET);
+	u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
+
+	if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) {
+		/*
+		 * The local timer interrupt got lost while the distributor was
+		 * disabled.  Ack the pending interrupt, and retrigger it.
+		 */
+		pr_warn("%s: lost localtimer interrupt\n", __func__);
+		__raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
+		if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) {
+			__raw_writel(1, twd_base + TWD_TIMER_COUNTER);
+			twd_ctrl |= TWD_TIMER_CONTROL_ENABLE;
+			__raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL);
+		}
+	}
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
-- 
1.7.4.1

  parent reply	other threads:[~2012-10-18  9:20 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-18  9:20 [PATCHv9 0/8] ARM: OMAP4: core retention support Tero Kristo
2012-10-18  9:20 ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 1/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-27  3:00   ` Paul Walmsley
2012-10-27  3:00     ` Paul Walmsley
2012-11-21 23:05   ` Paul Walmsley
2012-11-21 23:05     ` Paul Walmsley
2012-10-18  9:20 ` [PATCHv9 2/8] ARM: OMAP4: PM: add errata support Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-11-05 22:36   ` Kevin Hilman
2012-11-05 22:36     ` Kevin Hilman
2012-11-06 21:52     ` Kevin Hilman
2012-11-06 21:52       ` Kevin Hilman
2012-11-07 10:11       ` Tero Kristo
2012-11-07 10:11         ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX GIC control register change Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 4/8] ARM: OMAP4: suspend: Program all domains to retention Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 5/8] ARM: OMAP4: PM: put all domains to OSWR during suspend Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-18  9:20 ` Tero Kristo [this message]
2012-10-18  9:20   ` [PATCHv9 6/8] ARM: OMAP4: retrigger localtimers after re-enabling gic Tero Kristo
2012-10-27  2:51   ` Paul Walmsley
2012-10-27  2:51     ` Paul Walmsley
2012-11-05 22:25   ` Kevin Hilman
2012-11-05 22:25     ` Kevin Hilman
2012-11-06  9:15     ` Tero Kristo
2012-11-06  9:15       ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 7/8] ARM: OMAP: PM: update target fpwrst to what pwrdm can reach Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-18  9:20 ` [PATCHv9 8/8] ARM: OMAP4: USB: power down MUSB PHY if not used Tero Kristo
2012-10-18  9:20   ` Tero Kristo
2012-10-18 10:33   ` Felipe Balbi
2012-10-18 10:33     ` Felipe Balbi
2012-10-18 12:18     ` Tero Kristo
2012-10-18 12:18       ` Tero Kristo
2012-10-18 13:53       ` Felipe Balbi
2012-10-18 13:53         ` Felipe Balbi
2012-10-18 14:39         ` Tero Kristo
2012-10-18 14:39           ` Tero Kristo
2012-10-18 14:41           ` Felipe Balbi
2012-10-18 14:41             ` Felipe Balbi
2012-10-22  8:54           ` kishon
2012-10-22  8:54             ` kishon
2012-10-22  9:07             ` Felipe Balbi
2012-10-22  9:07               ` Felipe Balbi
2012-10-22  9:25               ` kishon
2012-10-22  9:25                 ` kishon
2012-10-27  2:52   ` Paul Walmsley
2012-10-27  2:52     ` Paul Walmsley
2012-10-27  3:02 ` [PATCHv9 0/8] ARM: OMAP4: core retention support Paul Walmsley
2012-10-27  3:02   ` Paul Walmsley
2012-11-05 22:23 ` Kevin Hilman
2012-11-05 22:23   ` Kevin Hilman
2012-11-06  9:18   ` Tero Kristo
2012-11-06  9:18     ` Tero Kristo
2012-11-06 21:19     ` Kevin Hilman
2012-11-06 21:19       ` Kevin Hilman
2012-11-07 10:17       ` Tero Kristo
2012-11-07 10:17         ` Tero Kristo
2012-11-12 14:41       ` Tero Kristo
2012-11-12 14:41         ` Tero Kristo
2012-11-13 19:18         ` Kevin Hilman
2012-11-13 19:18           ` Kevin Hilman
2012-11-07 18:35   ` Paul Walmsley
2012-11-07 18:35     ` Paul Walmsley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1350552010-28760-7-git-send-email-t-kristo@ti.com \
    --to=t-kristo@ti.com \
    --cc=ccross@android.com \
    --cc=khilman@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=paul@pwsan.com \
    --cc=s-jan@ti.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.