All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv5 0/8] ARM: OMAP4: core retention support
@ 2012-05-14 10:03 ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

Hi,

Changes compared to previous version:

- Patch 6 now adds support for reading prev logic and mem states
  instead of tweaking the _update_logic_membank_counters function
  directly.

- Some version of "[PATCH] OMAP2+: UART: Add mechanism to probe uart
  pins and configure rx wakeup" from Govindraj is needed, otherwise
  UART can't wake up the device from suspend.

Tested with omap4460 GP panda + omap4430 EMU blaze devices.

Patches also available here:
tree: git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: mainline-3.4-omap4-ret-v5

-Tero


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 0/8] ARM: OMAP4: core retention support
@ 2012-05-14 10:03 ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Changes compared to previous version:

- Patch 6 now adds support for reading prev logic and mem states
  instead of tweaking the _update_logic_membank_counters function
  directly.

- Some version of "[PATCH] OMAP2+: UART: Add mechanism to probe uart
  pins and configure rx wakeup" from Govindraj is needed, otherwise
  UART can't wake up the device from suspend.

Tested with omap4460 GP panda + omap4430 EMU blaze devices.

Patches also available here:
tree: git://gitorious.org/~kristo/omap-pm/omap-pm-work.git
branch: mainline-3.4-omap4-ret-v5

-Tero

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel, Rajendra Nayak

From: Rajendra Nayak <rnayak@ti.com>

Remove the FIXME's in the suspend sequence since
we now intend to support system level RET support.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/pm44xx.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 8856253..31990d5 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!strncmp(pwrdm->name, "cpu", 3))
 		return 0;
 
-	/*
-	 * FIXME: Remove this check when core retention is supported
-	 * Only MPUSS power domain is added in the list.
-	 */
-	if (strcmp(pwrdm->name, "mpu_pwrdm"))
-		return 0;
 
 	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
 	if (!pwrst)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@ti.com>

Remove the FIXME's in the suspend sequence since
we now intend to support system level RET support.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
 arch/arm/mach-omap2/pm44xx.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 8856253..31990d5 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!strncmp(pwrdm->name, "cpu", 3))
 		return 0;
 
-	/*
-	 * FIXME: Remove this check when core retention is supported
-	 * Only MPUSS power domain is added in the list.
-	 */
-	if (strcmp(pwrdm->name, "mpu_pwrdm"))
-		return 0;
 
 	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
 	if (!pwrst)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 2/8] TEMP: ARM: OMAP4: hwmod_data: Do not get DSP out of reset at boot time
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel, Rajendra Nayak

From: Rajendra Nayak <rnayak@ti.com>

With no driver handling DSP, if brought out of reset, it stays
active and does not assert standby. This leads to IVAHD powerdomain not
transitioning and hence preventing chip retention.

This patch is no longer needed once Paul's powerdomain fixes are merged:
   http://marc.info/?l=linux-omap&m=133040749621183&w=2

Just provided for testing purposes.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6abc757..fd305bc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1160,6 +1160,7 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.name		= "dsp",
 	.class		= &omap44xx_dsp_hwmod_class,
 	.clkdm_name	= "tesla_clkdm",
+	.flags		= HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_dsp_irqs,
 	.rst_lines	= omap44xx_dsp_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 2/8] TEMP: ARM: OMAP4: hwmod_data: Do not get DSP out of reset at boot time
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@ti.com>

With no driver handling DSP, if brought out of reset, it stays
active and does not assert standby. This leads to IVAHD powerdomain not
transitioning and hence preventing chip retention.

This patch is no longer needed once Paul's powerdomain fixes are merged:
   http://marc.info/?l=linux-omap&m=133040749621183&w=2

Just provided for testing purposes.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 6abc757..fd305bc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1160,6 +1160,7 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.name		= "dsp",
 	.class		= &omap44xx_dsp_hwmod_class,
 	.clkdm_name	= "tesla_clkdm",
+	.flags		= HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_dsp_irqs,
 	.rst_lines	= omap44xx_dsp_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel, Santosh Shilimkar

From: Santosh Shilimkar <santosh.shilimkar@ti.com>

GIC distributor control register has changed between CortexA9 r1pX and
r2pX. The Control Register secure banked version is now composed of 2
bits:
     bit 0 == Secure Enable
     bit 1 == Non-Secure Enable
The Non-Secure banked register has not changed. Since the ROM Code is
based on the r1pX GIC, the CPU1 GIC restoration will cause a problem
to CPU0 Non-Secure SW.
The workaround must be:
     1) Before doing the CPU1 wakeup, CPU0 must disable
        the GIC distributor
     2) CPU1 must re-enable the GIC distributor on
        it's wakeup path.

With this procedure, the GIC configuration done between the
CPU0 wakeup and CPU1 wakeup will not be lost but during this
short windows, the CPU0 will not receive interrupts

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/common.h              |    2 +
 arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
 arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
 arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 57da7f4..48d1ebe 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
 #endif
 
 extern void __init gic_init_irq(void);
+extern void gic_dist_disable(void);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
@@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
+extern void omap_secondary_startup_4460(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 503ac77..d602555 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
+ENTRY(omap_secondary_startup_4460)
+hold_2:	ldr	r12,=0x103
+	dsb
+	smc	#0			@ read from AuxCoreBoot0
+	mov	r0, r0, lsr #9
+	mrc	p15, 0, r4, c0, c0, 5
+	and	r4, r4, #0x0f
+	cmp	r0, r4
+	bne	hold_2
+
+	/*
+	 * GIC distributor control register has changed between
+	 * CortexA9 r1pX and r2pX. The Control Register secure
+	 * banked version is now composed of 2 bits:
+	 * bit 0 == Secure Enable
+	 * bit 1 == Non-Secure Enable
+	 * The Non-Secure banked register has not changed
+	 * Because the ROM Code is based on the r1pX GIC, the CPU1
+	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+	 * The workaround must be:
+	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+	 * the GIC distributor
+	 * 2) CPU1 must re-enable the GIC distributor on
+	 * it's wakeup path.
+	 */
+	ldr	r1, =0x48241000
+	ldr	r0, [r1]
+	orr	r0, #1
+	str	r0, [r1]
+
+	/*
+	 * we've been released from the wait loop,secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+ENDPROC(omap_secondary_startup_4460)
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 13670aa..e02c082 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
 	void __iomem *scu_sar_addr;
 	void __iomem *wkup_sar_addr;
 	void __iomem *l2x0_sar_addr;
+	void (*secondary_startup)(void);
 };
 
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
@@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int cpu_state = 0;
+	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 
 	clear_cpu_prev_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
-	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
+	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
 	/*
@@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
 	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
 	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
+	if (cpu_is_omap446x())
+		pm_info->secondary_startup = omap_secondary_startup_4460;
+	else
+		pm_info->secondary_startup = omap_secondary_startup;
+
 	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
 	if (!pm_info->pwrdm) {
 		pr_err("Lookup failed for CPU1 pwrdm\n");
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index deffbf1..c3eb9e8 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -33,6 +33,7 @@
 
 /* SCU base address */
 static void __iomem *scu_base;
+bool omap4_smp_romcode_errata;
 
 static DEFINE_SPINLOCK(boot_lock);
 
@@ -104,6 +105,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 *	4.3.4.2 Power States of CPU0 and CPU1
 	 */
 	if (booted) {
+		/*
+		 * GIC distributor control register has changed between
+		 * CortexA9 r1pX and r2pX. The Control Register secure
+		 * banked version is now composed of 2 bits:
+		 * bit 0 == Secure Enable
+		 * bit 1 == Non-Secure Enable
+		 * The Non-Secure banked register has not changed
+		 * Because the ROM Code is based on the r1pX GIC, the CPU1
+		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+		 * The workaround must be:
+		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+		 * the GIC distributor
+		 * 2) CPU1 must re-enable the GIC distributor on
+		 * it's wakeup path.
+		 */
+		if (omap4_smp_romcode_errata)
+			gic_dist_disable();
+
 		clkdm_wakeup(cpu1_clkdm);
 		clkdm_allow_idle(cpu1_clkdm);
 	} else {
@@ -124,13 +143,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
+	void *startup_addr = omap_secondary_startup;
+
 	/*
 	 * Write the address of secondary startup routine into the
 	 * AuxCoreBoot1 where ROM code will jump and start executing
 	 * on secondary core once out of WFE
 	 * A barrier is added to ensure that write buffer is drained
 	 */
-	omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+	if (cpu_is_omap446x()) {
+		startup_addr = omap_secondary_startup_4460;
+		omap4_smp_romcode_errata = true;
+	}
+
+	omap_auxcoreboot_addr(virt_to_phys(startup_addr));
 	smp_wmb();
 
 	/*
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 70de277..cc6a915 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -38,6 +38,7 @@ static void __iomem *l2cache_base;
 #endif
 
 static void __iomem *sar_ram_base;
+static void __iomem *gic_dist_base_addr;
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 /* Used to implement memory barrier on DRAM path */
@@ -92,7 +93,6 @@ void __init omap_barriers_init(void)
 void __init gic_init_irq(void)
 {
 	void __iomem *omap_irq_base;
-	void __iomem *gic_dist_base_addr;
 
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
@@ -107,6 +107,12 @@ void __init gic_init_irq(void)
 	gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
 }
 
+void gic_dist_disable(void)
+{
+	if (gic_dist_base_addr)
+		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Santosh Shilimkar <santosh.shilimkar@ti.com>

GIC distributor control register has changed between CortexA9 r1pX and
r2pX. The Control Register secure banked version is now composed of 2
bits:
     bit 0 == Secure Enable
     bit 1 == Non-Secure Enable
The Non-Secure banked register has not changed. Since the ROM Code is
based on the r1pX GIC, the CPU1 GIC restoration will cause a problem
to CPU0 Non-Secure SW.
The workaround must be:
     1) Before doing the CPU1 wakeup, CPU0 must disable
        the GIC distributor
     2) CPU1 must re-enable the GIC distributor on
        it's wakeup path.

With this procedure, the GIC configuration done between the
CPU0 wakeup and CPU1 wakeup will not be lost but during this
short windows, the CPU0 will not receive interrupts

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/common.h              |    2 +
 arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
 arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
 arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
 5 files changed, 80 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 57da7f4..48d1ebe 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
 #endif
 
 extern void __init gic_init_irq(void);
+extern void gic_dist_disable(void);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
@@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
+extern void omap_secondary_startup_4460(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 503ac77..d602555 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
+ENTRY(omap_secondary_startup_4460)
+hold_2:	ldr	r12,=0x103
+	dsb
+	smc	#0			@ read from AuxCoreBoot0
+	mov	r0, r0, lsr #9
+	mrc	p15, 0, r4, c0, c0, 5
+	and	r4, r4, #0x0f
+	cmp	r0, r4
+	bne	hold_2
+
+	/*
+	 * GIC distributor control register has changed between
+	 * CortexA9 r1pX and r2pX. The Control Register secure
+	 * banked version is now composed of 2 bits:
+	 * bit 0 == Secure Enable
+	 * bit 1 == Non-Secure Enable
+	 * The Non-Secure banked register has not changed
+	 * Because the ROM Code is based on the r1pX GIC, the CPU1
+	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+	 * The workaround must be:
+	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+	 * the GIC distributor
+	 * 2) CPU1 must re-enable the GIC distributor on
+	 * it's wakeup path.
+	 */
+	ldr	r1, =0x48241000
+	ldr	r0, [r1]
+	orr	r0, #1
+	str	r0, [r1]
+
+	/*
+	 * we've been released from the wait loop,secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+ENDPROC(omap_secondary_startup_4460)
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 13670aa..e02c082 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
 	void __iomem *scu_sar_addr;
 	void __iomem *wkup_sar_addr;
 	void __iomem *l2x0_sar_addr;
+	void (*secondary_startup)(void);
 };
 
 static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
@@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int cpu_state = 0;
+	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 
 	clear_cpu_prev_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
-	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
+	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
 	/*
@@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
 	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
 	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
+	if (cpu_is_omap446x())
+		pm_info->secondary_startup = omap_secondary_startup_4460;
+	else
+		pm_info->secondary_startup = omap_secondary_startup;
+
 	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
 	if (!pm_info->pwrdm) {
 		pr_err("Lookup failed for CPU1 pwrdm\n");
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index deffbf1..c3eb9e8 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -33,6 +33,7 @@
 
 /* SCU base address */
 static void __iomem *scu_base;
+bool omap4_smp_romcode_errata;
 
 static DEFINE_SPINLOCK(boot_lock);
 
@@ -104,6 +105,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 *	4.3.4.2 Power States of CPU0 and CPU1
 	 */
 	if (booted) {
+		/*
+		 * GIC distributor control register has changed between
+		 * CortexA9 r1pX and r2pX. The Control Register secure
+		 * banked version is now composed of 2 bits:
+		 * bit 0 == Secure Enable
+		 * bit 1 == Non-Secure Enable
+		 * The Non-Secure banked register has not changed
+		 * Because the ROM Code is based on the r1pX GIC, the CPU1
+		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
+		 * The workaround must be:
+		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
+		 * the GIC distributor
+		 * 2) CPU1 must re-enable the GIC distributor on
+		 * it's wakeup path.
+		 */
+		if (omap4_smp_romcode_errata)
+			gic_dist_disable();
+
 		clkdm_wakeup(cpu1_clkdm);
 		clkdm_allow_idle(cpu1_clkdm);
 	} else {
@@ -124,13 +143,20 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
+	void *startup_addr = omap_secondary_startup;
+
 	/*
 	 * Write the address of secondary startup routine into the
 	 * AuxCoreBoot1 where ROM code will jump and start executing
 	 * on secondary core once out of WFE
 	 * A barrier is added to ensure that write buffer is drained
 	 */
-	omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+	if (cpu_is_omap446x()) {
+		startup_addr = omap_secondary_startup_4460;
+		omap4_smp_romcode_errata = true;
+	}
+
+	omap_auxcoreboot_addr(virt_to_phys(startup_addr));
 	smp_wmb();
 
 	/*
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 70de277..cc6a915 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -38,6 +38,7 @@ static void __iomem *l2cache_base;
 #endif
 
 static void __iomem *sar_ram_base;
+static void __iomem *gic_dist_base_addr;
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 /* Used to implement memory barrier on DRAM path */
@@ -92,7 +93,6 @@ void __init omap_barriers_init(void)
 void __init gic_init_irq(void)
 {
 	void __iomem *omap_irq_base;
-	void __iomem *gic_dist_base_addr;
 
 	/* Static mapping, never released */
 	gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
@@ -107,6 +107,12 @@ void __init gic_init_irq(void)
 	gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
 }
 
+void gic_dist_disable(void)
+{
+	if (gic_dist_base_addr)
+		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 4/8] ARM: OMAP4: hwmod: flag hwmods/modules supporting module level context status
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel, Rajendra Nayak

From: Rajendra Nayak <rnayak@ti.com>

On OMAP4 most modules/hwmods support module level context status. On
OMAP3 and earlier, we relyed on the power domain level context status.
Identify all such modules using a 'HWMOD_CONTEXT_REG' flag, all such
hwmods already have a valid 'context_offs' populated in .prcm structure.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c   |  104 ++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 +
 2 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index fd305bc..16836ca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -128,6 +128,7 @@ static struct omap_hwmod omap44xx_dmm_hwmod = {
 	.name		= "dmm",
 	.class		= &omap44xx_dmm_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
@@ -184,6 +185,7 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = {
 	.name		= "emif_fw",
 	.class		= &omap44xx_emif_fw_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET,
@@ -229,6 +231,7 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = {
 	.name		= "l3_instr",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET,
@@ -328,6 +331,7 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_1_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_l3_main_1_irqs,
 	.prcm = {
 		.omap4 = {
@@ -430,6 +434,7 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
 	.name		= "l3_main_2",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_2_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET,
@@ -486,6 +491,7 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
 	.name		= "l3_main_3",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET,
@@ -577,6 +583,7 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
 	.name		= "l4_cfg",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET,
@@ -605,6 +612,7 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET,
@@ -633,6 +641,7 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
@@ -807,6 +816,7 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
 	.name		= "aess",
 	.class		= &omap44xx_aess_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_aess_irqs,
 	.sdma_reqs	= omap44xx_aess_sdma_reqs,
 	.main_clk	= "aess_fck",
@@ -898,7 +908,7 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = {
 	.name		= "counter_32k",
 	.class		= &omap44xx_counter_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_SWSUP_SIDLE,
 	.main_clk	= "sys_32k_ck",
 	.prcm = {
 		.omap4 = {
@@ -982,6 +992,7 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
 	.name		= "dma_system",
 	.class		= &omap44xx_dma_hwmod_class,
 	.clkdm_name	= "l3_dma_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dma_system_irqs,
 	.main_clk	= "l3_div_ck",
 	.prcm = {
@@ -1077,6 +1088,7 @@ static struct omap_hwmod omap44xx_dmic_hwmod = {
 	.name		= "dmic",
 	.class		= &omap44xx_dmic_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dmic_irqs,
 	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
 	.main_clk	= "dmic_fck",
@@ -1160,7 +1172,7 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.name		= "dsp",
 	.class		= &omap44xx_dsp_hwmod_class,
 	.clkdm_name	= "tesla_clkdm",
-	.flags		= HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_RESET | HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dsp_irqs,
 	.rst_lines	= omap44xx_dsp_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
@@ -1252,7 +1264,8 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap44xx_dss_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
 	.main_clk	= "dss_dss_clk",
@@ -1356,6 +1369,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dispc_irqs,
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1453,6 +1467,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap44xx_dsi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dsi1_irqs,
 	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1530,6 +1545,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.name		= "dss_dsi2",
 	.class		= &omap44xx_dsi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dsi2_irqs,
 	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1627,6 +1643,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.name		= "dss_hdmi",
 	.class		= &omap44xx_hdmi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
 	.main_clk	= "dss_48mhz_clk",
@@ -1719,6 +1736,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap44xx_rfbi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
 	.prcm = {
@@ -1790,6 +1808,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "dss_tv_clk",
 	.prcm = {
 		.omap4 = {
@@ -1868,6 +1887,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
 	.name		= "gpio1",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_gpio1_irqs,
 	.main_clk	= "gpio1_ick",
 	.prcm = {
@@ -1922,7 +1942,8 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
 	.name		= "gpio2",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio2_irqs,
 	.main_clk	= "gpio2_ick",
 	.prcm = {
@@ -1977,7 +1998,8 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
 	.name		= "gpio3",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio3_irqs,
 	.main_clk	= "gpio3_ick",
 	.prcm = {
@@ -2032,7 +2054,8 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
 	.name		= "gpio4",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio4_irqs,
 	.main_clk	= "gpio4_ick",
 	.prcm = {
@@ -2087,7 +2110,8 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
 	.name		= "gpio5",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio5_irqs,
 	.main_clk	= "gpio5_ick",
 	.prcm = {
@@ -2142,7 +2166,8 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
 	.name		= "gpio6",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio6_irqs,
 	.main_clk	= "gpio6_ick",
 	.prcm = {
@@ -2223,6 +2248,7 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
 	.name		= "hsi",
 	.class		= &omap44xx_hsi_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_hsi_irqs,
 	.main_clk	= "hsi_fck",
 	.prcm = {
@@ -2306,7 +2332,8 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
 	.name		= "i2c1",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c1_irqs,
 	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
 	.main_clk	= "i2c1_fck",
@@ -2362,7 +2389,8 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
 	.name		= "i2c2",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c2_irqs,
 	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
 	.main_clk	= "i2c2_fck",
@@ -2418,7 +2446,8 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
 	.name		= "i2c3",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c3_irqs,
 	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
 	.main_clk	= "i2c3_fck",
@@ -2474,7 +2503,8 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = {
 	.name		= "i2c4",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c4_irqs,
 	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
 	.main_clk	= "i2c4_fck",
@@ -2569,6 +2599,7 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
 	.name		= "ipu",
 	.class		= &omap44xx_ipu_hwmod_class,
 	.clkdm_name	= "ducati_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_ipu_irqs,
 	.rst_lines	= omap44xx_ipu_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_resets),
@@ -2667,6 +2698,7 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
 	.name		= "iss",
 	.class		= &omap44xx_iss_hwmod_class,
 	.clkdm_name	= "iss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_iss_irqs,
 	.sdma_reqs	= omap44xx_iss_sdma_reqs,
 	.main_clk	= "iss_fck",
@@ -2778,6 +2810,7 @@ static struct omap_hwmod omap44xx_iva_hwmod = {
 	.name		= "iva",
 	.class		= &omap44xx_iva_hwmod_class,
 	.clkdm_name	= "ivahd_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_iva_irqs,
 	.rst_lines	= omap44xx_iva_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
@@ -2852,6 +2885,7 @@ static struct omap_hwmod omap44xx_kbd_hwmod = {
 	.name		= "kbd",
 	.class		= &omap44xx_kbd_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_kbd_irqs,
 	.main_clk	= "kbd_fck",
 	.prcm = {
@@ -2919,6 +2953,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap44xx_mailbox_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mailbox_irqs,
 	.prcm = {
 		.omap4 = {
@@ -3015,6 +3050,7 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp1_irqs,
 	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
@@ -3097,6 +3133,7 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp2_irqs,
 	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
@@ -3179,6 +3216,7 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp3_irqs,
 	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
 	.main_clk	= "mcbsp3_fck",
@@ -3240,6 +3278,7 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp4_irqs,
 	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
 	.main_clk	= "mcbsp4_fck",
@@ -3336,6 +3375,7 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
 	.name		= "mcpdm",
 	.class		= &omap44xx_mcpdm_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcpdm_irqs,
 	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
 	.main_clk	= "mcpdm_fck",
@@ -3423,6 +3463,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
 	.name		= "mcspi1",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi1_irqs,
 	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
@@ -3485,6 +3526,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
 	.name		= "mcspi2",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi2_irqs,
 	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
@@ -3547,6 +3589,7 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
 	.name		= "mcspi3",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi3_irqs,
 	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
 	.main_clk	= "mcspi3_fck",
@@ -3607,6 +3650,7 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = {
 	.name		= "mcspi4",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi4_irqs,
 	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
 	.main_clk	= "mcspi4_fck",
@@ -3693,6 +3737,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
 	.name		= "mmc1",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc1_irqs,
 	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
 	.main_clk	= "mmc1_fck",
@@ -3754,6 +3799,7 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
 	.name		= "mmc2",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc2_irqs,
 	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
 	.main_clk	= "mmc2_fck",
@@ -3810,6 +3856,7 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
 	.name		= "mmc3",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc3_irqs,
 	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
 	.main_clk	= "mmc3_fck",
@@ -3864,6 +3911,7 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
 	.name		= "mmc4",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc4_irqs,
 
 	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
@@ -3919,6 +3967,7 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
 	.name		= "mmc5",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc5_irqs,
 	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
 	.main_clk	= "mmc5_fck",
@@ -3961,7 +4010,8 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
 	.name		= "mpu",
 	.class		= &omap44xx_mpu_hwmod_class,
 	.clkdm_name	= "mpuss_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_INIT_NO_IDLE |
+			  HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_mpu_irqs,
 	.main_clk	= "dpll_mpu_m2_ck",
 	.prcm = {
@@ -4038,6 +4088,7 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
 	.name		= "smartreflex_core",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
 
 	.main_clk	= "smartreflex_core_fck",
@@ -4091,6 +4142,7 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
 	.name		= "smartreflex_iva",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
 	.main_clk	= "smartreflex_iva_fck",
 	.prcm = {
@@ -4143,6 +4195,7 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
 	.name		= "smartreflex_mpu",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
 	.main_clk	= "smartreflex_mpu_fck",
 	.prcm = {
@@ -4209,6 +4262,7 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = {
 	.name		= "spinlock",
 	.class		= &omap44xx_spinlock_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET,
@@ -4301,6 +4355,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 	.name		= "timer1",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer1_irqs,
 	.main_clk	= "timer1_fck",
 	.prcm = {
@@ -4349,6 +4404,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 	.name		= "timer2",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer2_irqs,
 	.main_clk	= "timer2_fck",
 	.prcm = {
@@ -4397,6 +4453,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 	.name		= "timer3",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer3_irqs,
 	.main_clk	= "timer3_fck",
 	.prcm = {
@@ -4445,6 +4502,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 	.name		= "timer4",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer4_irqs,
 	.main_clk	= "timer4_fck",
 	.prcm = {
@@ -4512,6 +4570,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 	.name		= "timer5",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer5_irqs,
 	.main_clk	= "timer5_fck",
 	.prcm = {
@@ -4579,6 +4638,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 	.name		= "timer6",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer6_irqs,
 
 	.main_clk	= "timer6_fck",
@@ -4647,6 +4707,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 	.name		= "timer7",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer7_irqs,
 	.main_clk	= "timer7_fck",
 	.prcm = {
@@ -4714,6 +4775,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 	.name		= "timer8",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer8_irqs,
 	.main_clk	= "timer8_fck",
 	.prcm = {
@@ -4762,6 +4824,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 	.name		= "timer9",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer9_irqs,
 	.main_clk	= "timer9_fck",
 	.prcm = {
@@ -4810,6 +4873,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 	.name		= "timer10",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer10_irqs,
 	.main_clk	= "timer10_fck",
 	.prcm = {
@@ -4858,6 +4922,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
 	.name		= "timer11",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer11_irqs,
 	.main_clk	= "timer11_fck",
 	.prcm = {
@@ -4934,6 +4999,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
 	.name		= "uart1",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart1_irqs,
 	.sdma_reqs	= omap44xx_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
@@ -4988,6 +5054,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
 	.name		= "uart2",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart2_irqs,
 	.sdma_reqs	= omap44xx_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
@@ -5042,7 +5109,8 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
 	.name		= "uart3",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_INIT_NO_IDLE |
+			  HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_uart3_irqs,
 	.sdma_reqs	= omap44xx_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
@@ -5097,6 +5165,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.name		= "uart4",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart4_irqs,
 	.sdma_reqs	= omap44xx_uart4_sdma_reqs,
 	.main_clk	= "uart4_fck",
@@ -5177,7 +5246,8 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
 	.name		= "usb_otg_hs",
 	.class		= &omap44xx_usb_otg_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_SWSUP_SIDLE |
+			  HWMOD_SWSUP_MSTANDBY,
 	.mpu_irqs	= omap44xx_usb_otg_hs_irqs,
 	.main_clk	= "usb_otg_hs_ick",
 	.prcm = {
@@ -5252,6 +5322,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_wd_timer2_irqs,
 	.main_clk	= "wd_timer2_fck",
 	.prcm = {
@@ -5318,6 +5389,7 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
 	.name		= "wd_timer3",
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_wd_timer3_irqs,
 	.main_clk	= "wd_timer3_fck",
 	.prcm = {
@@ -5405,6 +5477,7 @@ static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
 	.name		= "usb_host_hs",
 	.class		= &omap44xx_usb_host_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "usb_host_hs_fck",
 	.prcm = {
 		.omap4 = {
@@ -5519,6 +5592,7 @@ static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
 	.name		= "usb_tll_hs",
 	.class		= &omap44xx_usb_tll_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "usb_tll_hs_ick",
 	.prcm = {
 		.omap4 = {
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 3f26db4..f247dee 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -401,6 +401,7 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_CONTEXT_REG: Module has a valid context register
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -411,6 +412,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST				(1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
 #define HWMOD_16BIT_REG				(1 << 8)
+#define HWMOD_CONTEXT_REG			(1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 4/8] ARM: OMAP4: hwmod: flag hwmods/modules supporting module level context status
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@ti.com>

On OMAP4 most modules/hwmods support module level context status. On
OMAP3 and earlier, we relyed on the power domain level context status.
Identify all such modules using a 'HWMOD_CONTEXT_REG' flag, all such
hwmods already have a valid 'context_offs' populated in .prcm structure.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod_44xx_data.c   |  104 ++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    2 +
 2 files changed, 91 insertions(+), 15 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index fd305bc..16836ca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -128,6 +128,7 @@ static struct omap_hwmod omap44xx_dmm_hwmod = {
 	.name		= "dmm",
 	.class		= &omap44xx_dmm_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET,
@@ -184,6 +185,7 @@ static struct omap_hwmod omap44xx_emif_fw_hwmod = {
 	.name		= "emif_fw",
 	.class		= &omap44xx_emif_fw_hwmod_class,
 	.clkdm_name	= "l3_emif_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET,
@@ -229,6 +231,7 @@ static struct omap_hwmod omap44xx_l3_instr_hwmod = {
 	.name		= "l3_instr",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET,
@@ -328,6 +331,7 @@ static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_1_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_l3_main_1_irqs,
 	.prcm = {
 		.omap4 = {
@@ -430,6 +434,7 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
 	.name		= "l3_main_2",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_2_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET,
@@ -486,6 +491,7 @@ static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
 	.name		= "l3_main_3",
 	.class		= &omap44xx_l3_hwmod_class,
 	.clkdm_name	= "l3_instr_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET,
@@ -577,6 +583,7 @@ static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
 	.name		= "l4_cfg",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET,
@@ -605,6 +612,7 @@ static struct omap_hwmod omap44xx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET,
@@ -633,6 +641,7 @@ static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &omap44xx_l4_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
@@ -807,6 +816,7 @@ static struct omap_hwmod omap44xx_aess_hwmod = {
 	.name		= "aess",
 	.class		= &omap44xx_aess_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_aess_irqs,
 	.sdma_reqs	= omap44xx_aess_sdma_reqs,
 	.main_clk	= "aess_fck",
@@ -898,7 +908,7 @@ static struct omap_hwmod omap44xx_counter_32k_hwmod = {
 	.name		= "counter_32k",
 	.class		= &omap44xx_counter_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_SWSUP_SIDLE,
 	.main_clk	= "sys_32k_ck",
 	.prcm = {
 		.omap4 = {
@@ -982,6 +992,7 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
 	.name		= "dma_system",
 	.class		= &omap44xx_dma_hwmod_class,
 	.clkdm_name	= "l3_dma_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dma_system_irqs,
 	.main_clk	= "l3_div_ck",
 	.prcm = {
@@ -1077,6 +1088,7 @@ static struct omap_hwmod omap44xx_dmic_hwmod = {
 	.name		= "dmic",
 	.class		= &omap44xx_dmic_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dmic_irqs,
 	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
 	.main_clk	= "dmic_fck",
@@ -1160,7 +1172,7 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 	.name		= "dsp",
 	.class		= &omap44xx_dsp_hwmod_class,
 	.clkdm_name	= "tesla_clkdm",
-	.flags		= HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_INIT_NO_RESET | HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dsp_irqs,
 	.rst_lines	= omap44xx_dsp_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_dsp_resets),
@@ -1252,7 +1264,8 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = {
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
 	.name		= "dss_core",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.class		= &omap44xx_dss_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
 	.main_clk	= "dss_dss_clk",
@@ -1356,6 +1369,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap44xx_dispc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dispc_irqs,
 	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1453,6 +1467,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap44xx_dsi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dsi1_irqs,
 	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1530,6 +1545,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
 	.name		= "dss_dsi2",
 	.class		= &omap44xx_dsi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_dsi2_irqs,
 	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
@@ -1627,6 +1643,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
 	.name		= "dss_hdmi",
 	.class		= &omap44xx_hdmi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
 	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
 	.main_clk	= "dss_48mhz_clk",
@@ -1719,6 +1736,7 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
 	.name		= "dss_rfbi",
 	.class		= &omap44xx_rfbi_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
 	.main_clk	= "dss_dss_clk",
 	.prcm = {
@@ -1790,6 +1808,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
 	.name		= "dss_venc",
 	.class		= &omap44xx_venc_hwmod_class,
 	.clkdm_name	= "l3_dss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "dss_tv_clk",
 	.prcm = {
 		.omap4 = {
@@ -1868,6 +1887,7 @@ static struct omap_hwmod omap44xx_gpio1_hwmod = {
 	.name		= "gpio1",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_gpio1_irqs,
 	.main_clk	= "gpio1_ick",
 	.prcm = {
@@ -1922,7 +1942,8 @@ static struct omap_hwmod omap44xx_gpio2_hwmod = {
 	.name		= "gpio2",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio2_irqs,
 	.main_clk	= "gpio2_ick",
 	.prcm = {
@@ -1977,7 +1998,8 @@ static struct omap_hwmod omap44xx_gpio3_hwmod = {
 	.name		= "gpio3",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio3_irqs,
 	.main_clk	= "gpio3_ick",
 	.prcm = {
@@ -2032,7 +2054,8 @@ static struct omap_hwmod omap44xx_gpio4_hwmod = {
 	.name		= "gpio4",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio4_irqs,
 	.main_clk	= "gpio4_ick",
 	.prcm = {
@@ -2087,7 +2110,8 @@ static struct omap_hwmod omap44xx_gpio5_hwmod = {
 	.name		= "gpio5",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio5_irqs,
 	.main_clk	= "gpio5_ick",
 	.prcm = {
@@ -2142,7 +2166,8 @@ static struct omap_hwmod omap44xx_gpio6_hwmod = {
 	.name		= "gpio6",
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.flags		= HWMOD_CONTEXT_REG |
+			  HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio6_irqs,
 	.main_clk	= "gpio6_ick",
 	.prcm = {
@@ -2223,6 +2248,7 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
 	.name		= "hsi",
 	.class		= &omap44xx_hsi_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_hsi_irqs,
 	.main_clk	= "hsi_fck",
 	.prcm = {
@@ -2306,7 +2332,8 @@ static struct omap_hwmod omap44xx_i2c1_hwmod = {
 	.name		= "i2c1",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c1_irqs,
 	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
 	.main_clk	= "i2c1_fck",
@@ -2362,7 +2389,8 @@ static struct omap_hwmod omap44xx_i2c2_hwmod = {
 	.name		= "i2c2",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c2_irqs,
 	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
 	.main_clk	= "i2c2_fck",
@@ -2418,7 +2446,8 @@ static struct omap_hwmod omap44xx_i2c3_hwmod = {
 	.name		= "i2c3",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c3_irqs,
 	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
 	.main_clk	= "i2c3_fck",
@@ -2474,7 +2503,8 @@ static struct omap_hwmod omap44xx_i2c4_hwmod = {
 	.name		= "i2c4",
 	.class		= &omap44xx_i2c_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_16BIT_REG |
+			  HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c4_irqs,
 	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
 	.main_clk	= "i2c4_fck",
@@ -2569,6 +2599,7 @@ static struct omap_hwmod omap44xx_ipu_hwmod = {
 	.name		= "ipu",
 	.class		= &omap44xx_ipu_hwmod_class,
 	.clkdm_name	= "ducati_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_ipu_irqs,
 	.rst_lines	= omap44xx_ipu_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_resets),
@@ -2667,6 +2698,7 @@ static struct omap_hwmod omap44xx_iss_hwmod = {
 	.name		= "iss",
 	.class		= &omap44xx_iss_hwmod_class,
 	.clkdm_name	= "iss_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_iss_irqs,
 	.sdma_reqs	= omap44xx_iss_sdma_reqs,
 	.main_clk	= "iss_fck",
@@ -2778,6 +2810,7 @@ static struct omap_hwmod omap44xx_iva_hwmod = {
 	.name		= "iva",
 	.class		= &omap44xx_iva_hwmod_class,
 	.clkdm_name	= "ivahd_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_iva_irqs,
 	.rst_lines	= omap44xx_iva_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
@@ -2852,6 +2885,7 @@ static struct omap_hwmod omap44xx_kbd_hwmod = {
 	.name		= "kbd",
 	.class		= &omap44xx_kbd_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_kbd_irqs,
 	.main_clk	= "kbd_fck",
 	.prcm = {
@@ -2919,6 +2953,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
 	.name		= "mailbox",
 	.class		= &omap44xx_mailbox_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mailbox_irqs,
 	.prcm = {
 		.omap4 = {
@@ -3015,6 +3050,7 @@ static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp1_irqs,
 	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
@@ -3097,6 +3133,7 @@ static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp2_irqs,
 	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
@@ -3179,6 +3216,7 @@ static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp3_irqs,
 	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
 	.main_clk	= "mcbsp3_fck",
@@ -3240,6 +3278,7 @@ static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap44xx_mcbsp_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcbsp4_irqs,
 	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
 	.main_clk	= "mcbsp4_fck",
@@ -3336,6 +3375,7 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
 	.name		= "mcpdm",
 	.class		= &omap44xx_mcpdm_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcpdm_irqs,
 	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
 	.main_clk	= "mcpdm_fck",
@@ -3423,6 +3463,7 @@ static struct omap_hwmod omap44xx_mcspi1_hwmod = {
 	.name		= "mcspi1",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi1_irqs,
 	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
@@ -3485,6 +3526,7 @@ static struct omap_hwmod omap44xx_mcspi2_hwmod = {
 	.name		= "mcspi2",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi2_irqs,
 	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
@@ -3547,6 +3589,7 @@ static struct omap_hwmod omap44xx_mcspi3_hwmod = {
 	.name		= "mcspi3",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi3_irqs,
 	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
 	.main_clk	= "mcspi3_fck",
@@ -3607,6 +3650,7 @@ static struct omap_hwmod omap44xx_mcspi4_hwmod = {
 	.name		= "mcspi4",
 	.class		= &omap44xx_mcspi_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mcspi4_irqs,
 	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
 	.main_clk	= "mcspi4_fck",
@@ -3693,6 +3737,7 @@ static struct omap_hwmod omap44xx_mmc1_hwmod = {
 	.name		= "mmc1",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc1_irqs,
 	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
 	.main_clk	= "mmc1_fck",
@@ -3754,6 +3799,7 @@ static struct omap_hwmod omap44xx_mmc2_hwmod = {
 	.name		= "mmc2",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc2_irqs,
 	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
 	.main_clk	= "mmc2_fck",
@@ -3810,6 +3856,7 @@ static struct omap_hwmod omap44xx_mmc3_hwmod = {
 	.name		= "mmc3",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc3_irqs,
 	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
 	.main_clk	= "mmc3_fck",
@@ -3864,6 +3911,7 @@ static struct omap_hwmod omap44xx_mmc4_hwmod = {
 	.name		= "mmc4",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc4_irqs,
 
 	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
@@ -3919,6 +3967,7 @@ static struct omap_hwmod omap44xx_mmc5_hwmod = {
 	.name		= "mmc5",
 	.class		= &omap44xx_mmc_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_mmc5_irqs,
 	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
 	.main_clk	= "mmc5_fck",
@@ -3961,7 +4010,8 @@ static struct omap_hwmod omap44xx_mpu_hwmod = {
 	.name		= "mpu",
 	.class		= &omap44xx_mpu_hwmod_class,
 	.clkdm_name	= "mpuss_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_INIT_NO_IDLE |
+			  HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_mpu_irqs,
 	.main_clk	= "dpll_mpu_m2_ck",
 	.prcm = {
@@ -4038,6 +4088,7 @@ static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
 	.name		= "smartreflex_core",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
 
 	.main_clk	= "smartreflex_core_fck",
@@ -4091,6 +4142,7 @@ static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
 	.name		= "smartreflex_iva",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
 	.main_clk	= "smartreflex_iva_fck",
 	.prcm = {
@@ -4143,6 +4195,7 @@ static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
 	.name		= "smartreflex_mpu",
 	.class		= &omap44xx_smartreflex_hwmod_class,
 	.clkdm_name	= "l4_ao_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
 	.main_clk	= "smartreflex_mpu_fck",
 	.prcm = {
@@ -4209,6 +4262,7 @@ static struct omap_hwmod omap44xx_spinlock_hwmod = {
 	.name		= "spinlock",
 	.class		= &omap44xx_spinlock_hwmod_class,
 	.clkdm_name	= "l4_cfg_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET,
@@ -4301,6 +4355,7 @@ static struct omap_hwmod omap44xx_timer1_hwmod = {
 	.name		= "timer1",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer1_irqs,
 	.main_clk	= "timer1_fck",
 	.prcm = {
@@ -4349,6 +4404,7 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
 	.name		= "timer2",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer2_irqs,
 	.main_clk	= "timer2_fck",
 	.prcm = {
@@ -4397,6 +4453,7 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
 	.name		= "timer3",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer3_irqs,
 	.main_clk	= "timer3_fck",
 	.prcm = {
@@ -4445,6 +4502,7 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
 	.name		= "timer4",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer4_irqs,
 	.main_clk	= "timer4_fck",
 	.prcm = {
@@ -4512,6 +4570,7 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
 	.name		= "timer5",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer5_irqs,
 	.main_clk	= "timer5_fck",
 	.prcm = {
@@ -4579,6 +4638,7 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
 	.name		= "timer6",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer6_irqs,
 
 	.main_clk	= "timer6_fck",
@@ -4647,6 +4707,7 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
 	.name		= "timer7",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer7_irqs,
 	.main_clk	= "timer7_fck",
 	.prcm = {
@@ -4714,6 +4775,7 @@ static struct omap_hwmod omap44xx_timer8_hwmod = {
 	.name		= "timer8",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer8_irqs,
 	.main_clk	= "timer8_fck",
 	.prcm = {
@@ -4762,6 +4824,7 @@ static struct omap_hwmod omap44xx_timer9_hwmod = {
 	.name		= "timer9",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer9_irqs,
 	.main_clk	= "timer9_fck",
 	.prcm = {
@@ -4810,6 +4873,7 @@ static struct omap_hwmod omap44xx_timer10_hwmod = {
 	.name		= "timer10",
 	.class		= &omap44xx_timer_1ms_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer10_irqs,
 	.main_clk	= "timer10_fck",
 	.prcm = {
@@ -4858,6 +4922,7 @@ static struct omap_hwmod omap44xx_timer11_hwmod = {
 	.name		= "timer11",
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_timer11_irqs,
 	.main_clk	= "timer11_fck",
 	.prcm = {
@@ -4934,6 +4999,7 @@ static struct omap_hwmod omap44xx_uart1_hwmod = {
 	.name		= "uart1",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart1_irqs,
 	.sdma_reqs	= omap44xx_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
@@ -4988,6 +5054,7 @@ static struct omap_hwmod omap44xx_uart2_hwmod = {
 	.name		= "uart2",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart2_irqs,
 	.sdma_reqs	= omap44xx_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
@@ -5042,7 +5109,8 @@ static struct omap_hwmod omap44xx_uart3_hwmod = {
 	.name		= "uart3",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
-	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_INIT_NO_IDLE |
+			  HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_uart3_irqs,
 	.sdma_reqs	= omap44xx_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
@@ -5097,6 +5165,7 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 	.name		= "uart4",
 	.class		= &omap44xx_uart_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_uart4_irqs,
 	.sdma_reqs	= omap44xx_uart4_sdma_reqs,
 	.main_clk	= "uart4_fck",
@@ -5177,7 +5246,8 @@ static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
 	.name		= "usb_otg_hs",
 	.class		= &omap44xx_usb_otg_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.flags		= HWMOD_CONTEXT_REG | HWMOD_SWSUP_SIDLE |
+			  HWMOD_SWSUP_MSTANDBY,
 	.mpu_irqs	= omap44xx_usb_otg_hs_irqs,
 	.main_clk	= "usb_otg_hs_ick",
 	.prcm = {
@@ -5252,6 +5322,7 @@ static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
 	.name		= "wd_timer2",
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_wd_timer2_irqs,
 	.main_clk	= "wd_timer2_fck",
 	.prcm = {
@@ -5318,6 +5389,7 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
 	.name		= "wd_timer3",
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.mpu_irqs	= omap44xx_wd_timer3_irqs,
 	.main_clk	= "wd_timer3_fck",
 	.prcm = {
@@ -5405,6 +5477,7 @@ static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
 	.name		= "usb_host_hs",
 	.class		= &omap44xx_usb_host_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "usb_host_hs_fck",
 	.prcm = {
 		.omap4 = {
@@ -5519,6 +5592,7 @@ static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
 	.name		= "usb_tll_hs",
 	.class		= &omap44xx_usb_tll_hs_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
+	.flags		= HWMOD_CONTEXT_REG,
 	.main_clk	= "usb_tll_hs_ick",
 	.prcm = {
 		.omap4 = {
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 3f26db4..f247dee 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -401,6 +401,7 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_CONTEXT_REG: Module has a valid context register
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -411,6 +412,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST				(1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
 #define HWMOD_16BIT_REG				(1 << 8)
+#define HWMOD_CONTEXT_REG			(1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel, Rajendra Nayak

From: Rajendra Nayak <rnayak@ti.com>

OMAP4 has module specific context lost registers which makes it now
possible to have module level context loss count, instead of relying
on the powerdomain level context count.

Add 2 private hwmod api's to update/clear the hwmod/module specific
context lost counters/register.

Update the module specific context_lost_counter and clear the hardware
bits just after enabling the module.

omap_hwmod_get_context_loss_count() now returns the hwmod context loss
count them on platforms where they exist (OMAP4), else fall back on
the pwrdm level counters for older platforms.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[paul@pwsan.com: added function kerneldoc, fixed structure kerneldoc,
 rearranged structure to avoid memory waste, marked fns as OMAP4-specific,
 prevent fn entry on non-OMAP4 chips, reduced indentation, merged update
 and clear, merged patches]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c             |   44 +++++++++++++++++++++++--
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    8 +++-
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 8683d6f..601f5a5f 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1520,6 +1520,36 @@ static void _reconfigure_io_chain(void)
 }
 
 /**
+ * _omap4_update_context_lost - increment hwmod context loss counter if
+ * hwmod context was lost, and clear hardware context loss reg
+ * @oh: hwmod to check for context loss
+ *
+ * If the PRCM indicates that the hwmod @oh lost context, increment
+ * our in-memory context loss counter, and clear the RM_*_CONTEXT
+ * bits. No return value.
+ */
+static void _omap4_update_context_lost(struct omap_hwmod *oh)
+{
+	u32 r;
+
+	if (!(oh->flags & HWMOD_CONTEXT_REG))
+		return;
+
+	r = omap4_prminst_read_inst_reg(oh->clkdm->pwrdm.ptr->prcm_partition,
+					oh->clkdm->pwrdm.ptr->prcm_offs,
+					oh->prcm.omap4.context_offs);
+
+	if (!r)
+		return;
+
+	oh->prcm.omap4.context_lost_counter++;
+
+	omap4_prminst_write_inst_reg(r, oh->clkdm->pwrdm.ptr->prcm_partition,
+				     oh->clkdm->pwrdm.ptr->prcm_offs,
+				     oh->prcm.omap4.context_offs);
+}
+
+/**
  * _enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
 	_enable_clocks(oh);
 	_enable_module(oh);
 
+	_omap4_update_context_lost(oh);
+
 	r = _wait_target_ready(oh);
 	if (!r) {
 		/*
@@ -2724,17 +2756,21 @@ ohsps_unlock:
  * omap_hwmod_get_context_loss_count - get lost context count
  * @oh: struct omap_hwmod *
  *
- * Query the powerdomain of of @oh to get the context loss
- * count for this device.
+ * Returns the context loss count of associated @oh
+ * upon success, or zero if no context loss data is available.
  *
- * Returns the context loss count of the powerdomain assocated with @oh
- * upon success, or zero if no powerdomain exists for @oh.
+ * On OMAP4, this queries the per-hwmod context loss register,
+ * assuming one exists.  If not, or on OMAP2/3, this queries the
+ * enclosing powerdomain context loss count.
  */
 int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
 
+	if (oh->flags & HWMOD_CONTEXT_REG)
+		return oh->prcm.omap4.context_lost_counter;
+
 	pwrdm = omap_hwmod_get_pwrdm(oh);
 	if (pwrdm)
 		ret = pwrdm_get_context_loss_count(pwrdm);
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index f247dee..8f5510b 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -364,9 +364,12 @@ struct omap_hwmod_omap2_prcm {
 
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
- * @clkctrl_reg: PRCM address of the clock control register
- * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @clkctrl_offs: offset of the PRCM clock control register
+ * @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM
+ * @context_offs: offset of the RM_*_CONTEXT register
  * @submodule_wkdep_bit: bit shift of the WKDEP range
+ * @modulemode: allowable modulemodes
+ * @context_lost_counter: Count of module level context lost
  */
 struct omap_hwmod_omap4_prcm {
 	u16		clkctrl_offs;
@@ -374,6 +377,7 @@ struct omap_hwmod_omap4_prcm {
 	u16		context_offs;
 	u8		submodule_wkdep_bit;
 	u8		modulemode;
+	unsigned	context_lost_counter;
 };
 
 
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rajendra Nayak <rnayak@ti.com>

OMAP4 has module specific context lost registers which makes it now
possible to have module level context loss count, instead of relying
on the powerdomain level context count.

Add 2 private hwmod api's to update/clear the hwmod/module specific
context lost counters/register.

Update the module specific context_lost_counter and clear the hardware
bits just after enabling the module.

omap_hwmod_get_context_loss_count() now returns the hwmod context loss
count them on platforms where they exist (OMAP4), else fall back on
the pwrdm level counters for older platforms.

Signed-off-by: Rajendra Nayak <rnayak@ti.com>
[paul at pwsan.com: added function kerneldoc, fixed structure kerneldoc,
 rearranged structure to avoid memory waste, marked fns as OMAP4-specific,
 prevent fn entry on non-OMAP4 chips, reduced indentation, merged update
 and clear, merged patches]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_hwmod.c             |   44 +++++++++++++++++++++++--
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    8 +++-
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 8683d6f..601f5a5f 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1520,6 +1520,36 @@ static void _reconfigure_io_chain(void)
 }
 
 /**
+ * _omap4_update_context_lost - increment hwmod context loss counter if
+ * hwmod context was lost, and clear hardware context loss reg
+ * @oh: hwmod to check for context loss
+ *
+ * If the PRCM indicates that the hwmod @oh lost context, increment
+ * our in-memory context loss counter, and clear the RM_*_CONTEXT
+ * bits. No return value.
+ */
+static void _omap4_update_context_lost(struct omap_hwmod *oh)
+{
+	u32 r;
+
+	if (!(oh->flags & HWMOD_CONTEXT_REG))
+		return;
+
+	r = omap4_prminst_read_inst_reg(oh->clkdm->pwrdm.ptr->prcm_partition,
+					oh->clkdm->pwrdm.ptr->prcm_offs,
+					oh->prcm.omap4.context_offs);
+
+	if (!r)
+		return;
+
+	oh->prcm.omap4.context_lost_counter++;
+
+	omap4_prminst_write_inst_reg(r, oh->clkdm->pwrdm.ptr->prcm_partition,
+				     oh->clkdm->pwrdm.ptr->prcm_offs,
+				     oh->prcm.omap4.context_offs);
+}
+
+/**
  * _enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
 	_enable_clocks(oh);
 	_enable_module(oh);
 
+	_omap4_update_context_lost(oh);
+
 	r = _wait_target_ready(oh);
 	if (!r) {
 		/*
@@ -2724,17 +2756,21 @@ ohsps_unlock:
  * omap_hwmod_get_context_loss_count - get lost context count
  * @oh: struct omap_hwmod *
  *
- * Query the powerdomain of of @oh to get the context loss
- * count for this device.
+ * Returns the context loss count of associated @oh
+ * upon success, or zero if no context loss data is available.
  *
- * Returns the context loss count of the powerdomain assocated with @oh
- * upon success, or zero if no powerdomain exists for @oh.
+ * On OMAP4, this queries the per-hwmod context loss register,
+ * assuming one exists.  If not, or on OMAP2/3, this queries the
+ * enclosing powerdomain context loss count.
  */
 int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 {
 	struct powerdomain *pwrdm;
 	int ret = 0;
 
+	if (oh->flags & HWMOD_CONTEXT_REG)
+		return oh->prcm.omap4.context_lost_counter;
+
 	pwrdm = omap_hwmod_get_pwrdm(oh);
 	if (pwrdm)
 		ret = pwrdm_get_context_loss_count(pwrdm);
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index f247dee..8f5510b 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -364,9 +364,12 @@ struct omap_hwmod_omap2_prcm {
 
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
- * @clkctrl_reg: PRCM address of the clock control register
- * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @clkctrl_offs: offset of the PRCM clock control register
+ * @rstctrl_offs: offset of the XXX_RSTCTRL register located in the PRM
+ * @context_offs: offset of the RM_*_CONTEXT register
  * @submodule_wkdep_bit: bit shift of the WKDEP range
+ * @modulemode: allowable modulemodes
+ * @context_lost_counter: Count of module level context lost
  */
 struct omap_hwmod_omap4_prcm {
 	u16		clkctrl_offs;
@@ -374,6 +377,7 @@ struct omap_hwmod_omap4_prcm {
 	u16		context_offs;
 	u8		submodule_wkdep_bit;
 	u8		modulemode;
+	unsigned	context_lost_counter;
 };
 
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

On OMAP4, there is no support to read previous logic state
or previous memory state achieved when a power domain transitions
to RET. Instead there are module level context registers.

In order to support the powerdomain level logic/mem_off_counters
on OMAP4, instead use the previous power state achieved (RET) and
the *programmed* logic/mem RET state to derive if a powerdomain lost
logic or did not.

If the powerdomain is programmed to enter RET state and lose logic
in RET state, knowing that the powerdomain entered RET is good enough
to derive that the logic was lost as well, in such cases.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 601325b..ab00736 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
 	return v;
 }
 
+static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_ON;
+
+	return omap4_pwrdm_read_logic_retst(pwrdm);
+}
+
 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
 	u32 m, v;
@@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
 	return v;
 }
 
+static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_ON;
+
+	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
+}
+
 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 {
 	u32 c = 0;
@@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
 	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
 	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
+	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
 	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
 	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
 	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
+	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
 	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
 	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
 	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

On OMAP4, there is no support to read previous logic state
or previous memory state achieved when a power domain transitions
to RET. Instead there are module level context registers.

In order to support the powerdomain level logic/mem_off_counters
on OMAP4, instead use the previous power state achieved (RET) and
the *programmed* logic/mem RET state to derive if a powerdomain lost
logic or did not.

If the powerdomain is programmed to enter RET state and lose logic
in RET state, knowing that the powerdomain entered RET is good enough
to derive that the logic was lost as well, in such cases.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 601325b..ab00736 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
 	return v;
 }
 
+static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_ON;
+
+	return omap4_pwrdm_read_logic_retst(pwrdm);
+}
+
 static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
 {
 	u32 m, v;
@@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
 	return v;
 }
 
+static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+	int state;
+
+	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
+
+	if (state == PWRDM_POWER_OFF)
+		return PWRDM_POWER_OFF;
+
+	if (state != PWRDM_POWER_RET)
+		return PWRDM_POWER_ON;
+
+	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
+}
+
 static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 {
 	u32 c = 0;
@@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
 	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
 	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
+	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
 	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
 	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
 	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
+	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
 	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
 	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
 	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 7/8] ARM: OMAP4: PM: Add next_logic_state param to power_state
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

This will make it easier to handle next logic states for power domains
during suspend. With this patch, the parameter is also programmed to
retention for every powerdomain, thus all powerdomains enter CSWR
state after this patch.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm44xx.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 31990d5..cc85576 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -26,6 +26,7 @@
 struct power_state {
 	struct powerdomain *pwrdm;
 	u32 next_state;
+	u32 next_logic_state;
 #ifdef CONFIG_SUSPEND
 	u32 saved_state;
 	u32 saved_logic_state;
@@ -51,7 +52,7 @@ static int omap4_pm_suspend(void)
 	/* Set targeted power domain states by suspend */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF);
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
 	}
 
 	/*
@@ -108,6 +109,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 
 	pwrst->pwrdm = pwrdm;
 	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_logic_state = PWRDM_POWER_RET;
 	list_add(&pwrst->node, &pwrst_list);
 
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 7/8] ARM: OMAP4: PM: Add next_logic_state param to power_state
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

This will make it easier to handle next logic states for power domains
during suspend. With this patch, the parameter is also programmed to
retention for every powerdomain, thus all powerdomains enter CSWR
state after this patch.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm44xx.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 31990d5..cc85576 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -26,6 +26,7 @@
 struct power_state {
 	struct powerdomain *pwrdm;
 	u32 next_state;
+	u32 next_logic_state;
 #ifdef CONFIG_SUSPEND
 	u32 saved_state;
 	u32 saved_logic_state;
@@ -51,7 +52,7 @@ static int omap4_pm_suspend(void)
 	/* Set targeted power domain states by suspend */
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-		pwrdm_set_logic_retst(pwrst->pwrdm, PWRDM_POWER_OFF);
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
 	}
 
 	/*
@@ -108,6 +109,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 
 	pwrst->pwrdm = pwrdm;
 	pwrst->next_state = PWRDM_POWER_RET;
+	pwrst->next_logic_state = PWRDM_POWER_RET;
 	list_add(&pwrst->node, &pwrst_list);
 
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
  2012-05-14 10:03 ` Tero Kristo
@ 2012-05-14 10:03   ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-omap, khilman, paul; +Cc: linux-arm-kernel

PM debug now contains a file that can be used to control OSWR support
enable / disable on OMAP4. Also removed the off_mode_enable file for
the same platform as it is unsupported.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
 arch/arm/mach-omap2/pm.h       |    1 +
 arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..d9a8e42 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -39,6 +39,7 @@
 #include "pm.h"
 
 u32 enable_off_mode;
+static u32 enable_oswr_mode;
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
 			omap_pm_enable_off_mode();
 		else
 			omap_pm_disable_off_mode();
-		if (cpu_is_omap34xx())
-			omap3_pm_off_mode_enable(val);
+
+		omap3_pm_off_mode_enable(val);
 	}
 
+	if (option == &enable_oswr_mode)
+		omap4_pm_oswr_mode_enable(val);
+
 	return 0;
 }
 
@@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
-				   &enable_off_mode, &pm_dbg_option_fops);
+	if (cpu_is_omap34xx())
+		(void) debugfs_create_file("enable_off_mode",
+			S_IRUGO | S_IWUSR, d, &enable_off_mode,
+			&pm_dbg_option_fops);
+
+	if (cpu_is_omap44xx())
+		(void) debugfs_create_file("enable_oswr_mode",
+			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
+			&pm_dbg_option_fops);
+
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 36fa90b..c36ab63 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -17,6 +17,7 @@
 
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
+extern void omap4_pm_oswr_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index cc85576..07ac0d3 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
+void omap4_pm_oswr_mode_enable(int enable)
+{
+	u32 next_logic_state;
+	struct power_state *pwrst;
+
+	if (enable)
+		next_logic_state = PWRDM_POWER_OFF;
+	else
+		next_logic_state = PWRDM_POWER_RET;
+
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		pwrst->next_logic_state = next_logic_state;
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
+	}
+}
+
 /**
  * omap_default_idle - OMAP4 default ilde routine.'
  *
-- 
1.7.4.1


^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
@ 2012-05-14 10:03   ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-14 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

PM debug now contains a file that can be used to control OSWR support
enable / disable on OMAP4. Also removed the off_mode_enable file for
the same platform as it is unsupported.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
 arch/arm/mach-omap2/pm.h       |    1 +
 arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..d9a8e42 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -39,6 +39,7 @@
 #include "pm.h"
 
 u32 enable_off_mode;
+static u32 enable_oswr_mode;
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
 			omap_pm_enable_off_mode();
 		else
 			omap_pm_disable_off_mode();
-		if (cpu_is_omap34xx())
-			omap3_pm_off_mode_enable(val);
+
+		omap3_pm_off_mode_enable(val);
 	}
 
+	if (option == &enable_oswr_mode)
+		omap4_pm_oswr_mode_enable(val);
+
 	return 0;
 }
 
@@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
-				   &enable_off_mode, &pm_dbg_option_fops);
+	if (cpu_is_omap34xx())
+		(void) debugfs_create_file("enable_off_mode",
+			S_IRUGO | S_IWUSR, d, &enable_off_mode,
+			&pm_dbg_option_fops);
+
+	if (cpu_is_omap44xx())
+		(void) debugfs_create_file("enable_oswr_mode",
+			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
+			&pm_dbg_option_fops);
+
 	pm_dbg_init_done = 1;
 
 	return 0;
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 36fa90b..c36ab63 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -17,6 +17,7 @@
 
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
+extern void omap4_pm_oswr_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index cc85576..07ac0d3 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
+void omap4_pm_oswr_mode_enable(int enable)
+{
+	u32 next_logic_state;
+	struct power_state *pwrst;
+
+	if (enable)
+		next_logic_state = PWRDM_POWER_OFF;
+	else
+		next_logic_state = PWRDM_POWER_RET;
+
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		pwrst->next_logic_state = next_logic_state;
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
+	}
+}
+
 /**
  * omap_default_idle - OMAP4 default ilde routine.'
  *
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-15 19:52     ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 19:52 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, paul, linux-arm-kernel, Rajendra Nayak

Tero Kristo <t-kristo@ti.com> writes:

> From: Rajendra Nayak <rnayak@ti.com>
>
> Remove the FIXME's in the suspend sequence since
> we now intend to support system level RET support.

minor: this should probably go at the end of the series, after retention
is supported.  Otherwise, ending up with only this patch applied
(e.g. during a git bisect) will lead to a broken boot I suspect.

Kevin

> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  arch/arm/mach-omap2/pm44xx.c |    6 ------
>  1 files changed, 0 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 8856253..31990d5 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  	if (!strncmp(pwrdm->name, "cpu", 3))
>  		return 0;
>  
> -	/*
> -	 * FIXME: Remove this check when core retention is supported
> -	 * Only MPUSS power domain is added in the list.
> -	 */
> -	if (strcmp(pwrdm->name, "mpu_pwrdm"))
> -		return 0;
>  
>  	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
>  	if (!pwrst)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
@ 2012-05-15 19:52     ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> From: Rajendra Nayak <rnayak@ti.com>
>
> Remove the FIXME's in the suspend sequence since
> we now intend to support system level RET support.

minor: this should probably go at the end of the series, after retention
is supported.  Otherwise, ending up with only this patch applied
(e.g. during a git bisect) will lead to a broken boot I suspect.

Kevin

> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> ---
>  arch/arm/mach-omap2/pm44xx.c |    6 ------
>  1 files changed, 0 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index 8856253..31990d5 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  	if (!strncmp(pwrdm->name, "cpu", 3))
>  		return 0;
>  
> -	/*
> -	 * FIXME: Remove this check when core retention is supported
> -	 * Only MPUSS power domain is added in the list.
> -	 */
> -	if (strcmp(pwrdm->name, "mpu_pwrdm"))
> -		return 0;
>  
>  	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
>  	if (!pwrst)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-15 21:44     ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 21:44 UTC (permalink / raw)
  To: Tero Kristo, Santosh Shilimkar; +Cc: paul, linux-omap, linux-arm-kernel

Santosh,

Tero Kristo <t-kristo@ti.com> writes:

> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits:
>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable
> The Non-Secure banked register has not changed. 

For those without the r1pX TRM handy, please include what this look like
before (presumably 1 bit?)  The changelog and in-code comments should
both be enhanced.

> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
> will cause a problem to CPU0 Non-Secure SW.

Please describe the problem, so we can better understand the specifics
of the workaround.

Also, is there an erratum number for this?

> The workaround must be:
>      1) Before doing the CPU1 wakeup, CPU0 must disable
>         the GIC distributor
>      2) CPU1 must re-enable the GIC distributor on
>         it's wakeup path.

Again, because the problem was not described, I am not entirely sure why
the workaround "must" be this, and how it fixes the problem.  Remember
to put yourself in the shoes of a reviewer who has not been deeply
involved in the code, so what seems obvious to you will not be obvious
to the reviewer without having to study the code and dig in to the TRMs.

> With this procedure, the GIC configuration done between the
> CPU0 wakeup and CPU1 wakeup will not be lost but during this
> short windows, the CPU0 will not receive interrupts

Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
devices? 

Also, the changelog doesn't describe what power states this affects, and
whether it's an idle problem or just a supend problem.  A quick glance
at the code suggests that only suspend is being addressed by this patch.
However, with the addition of coupled CPUidle (coming very soon now),
won't we have this same problem in idle?  IMO, this patch should address
both.

This workaround also assumes that you always want CPU1 to wakeup
immediately after CPU0.  I guess that will be the case for the coupled
states that would be affected by this bug, but the changelog should
describe that as well

Some minor comments below...

> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/common.h              |    2 +
>  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
>  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
>  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
>  5 files changed, 80 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index 57da7f4..48d1ebe 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
>  #endif
>  
>  extern void __init gic_init_irq(void);
> +extern void gic_dist_disable(void);
>  extern void omap_smc1(u32 fn, u32 arg);
>  extern void __iomem *omap4_get_sar_ram_base(void);
>  extern void omap_do_wfi(void);
> @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
>  #ifdef CONFIG_SMP
>  /* Needed for secondary core boot */
>  extern void omap_secondary_startup(void);
> +extern void omap_secondary_startup_4460(void);
>  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
>  extern void omap_auxcoreboot_addr(u32 cpu_addr);
>  extern u32 omap_read_auxcoreboot0(void);
> diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
> index 503ac77..d602555 100644
> --- a/arch/arm/mach-omap2/omap-headsmp.S
> +++ b/arch/arm/mach-omap2/omap-headsmp.S
> @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
>  	b	secondary_startup
>  ENDPROC(omap_secondary_startup)
>  
> +ENTRY(omap_secondary_startup_4460)
> +hold_2:	ldr	r12,=0x103
> +	dsb
> +	smc	#0			@ read from AuxCoreBoot0
> +	mov	r0, r0, lsr #9
> +	mrc	p15, 0, r4, c0, c0, 5
> +	and	r4, r4, #0x0f
> +	cmp	r0, r4
> +	bne	hold_2
> +
> +	/*
> +	 * GIC distributor control register has changed between
> +	 * CortexA9 r1pX and r2pX. The Control Register secure
> +	 * banked version is now composed of 2 bits:
> +	 * bit 0 == Secure Enable
> +	 * bit 1 == Non-Secure Enable
> +	 * The Non-Secure banked register has not changed
> +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
> +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> +	 * The workaround must be:
> +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> +	 * the GIC distributor
> +	 * 2) CPU1 must re-enable the GIC distributor on
> +	 * it's wakeup path.
> +	 */
> +	ldr	r1, =0x48241000

Why not OMAP44XX_GIC_DIST_BASE for readability sake?

> +	ldr	r0, [r1]
> +	orr	r0, #1
> +	str	r0, [r1]
> +
> +	/*
> +	 * we've been released from the wait loop,secondary_stack
> +	 * should now contain the SVC stack for this core
> +	 */
> +	b	secondary_startup
> +ENDPROC(omap_secondary_startup_4460)
> diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> index 13670aa..e02c082 100644
> --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
>  	void __iomem *scu_sar_addr;
>  	void __iomem *wkup_sar_addr;
>  	void __iomem *l2x0_sar_addr;
> +	void (*secondary_startup)(void);
>  };
>  
>  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
>  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>  {
>  	unsigned int cpu_state = 0;
> +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
>  
>  	if (omap_rev() == OMAP4430_REV_ES1_0)
>  		return -ENXIO;
> @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>  
>  	clear_cpu_prev_pwrst(cpu);
>  	set_cpu_next_pwrst(cpu, power_state);
> -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
> +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
>  	scu_pwrst_prepare(cpu, power_state);
>  
>  	/*
> @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
>  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
>  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
>  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
> +	if (cpu_is_omap446x())
> +		pm_info->secondary_startup = omap_secondary_startup_4460;
> +	else
> +		pm_info->secondary_startup = omap_secondary_startup;

Does this exist on 4470 too?

Using a PM erratum check here instead of cpu_is* would make this more
scalable.  

Same comment for the cpu_is* check in wakeup_secondary()

Then, where the erratum is defined, it should state clearly why this
affects 446x and not before (presumably because 4430 has r1pX and 4460
has r2pX.)

>  	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
>  	if (!pm_info->pwrdm) {
>  		pr_err("Lookup failed for CPU1 pwrdm\n");
> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index deffbf1..c3eb9e8 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -33,6 +33,7 @@
>  
>  /* SCU base address */
>  static void __iomem *scu_base;
> +bool omap4_smp_romcode_errata;

static?

Kevin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-15 21:44     ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 21:44 UTC (permalink / raw)
  To: linux-arm-kernel

Santosh,

Tero Kristo <t-kristo@ti.com> writes:

> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>
> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits:
>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable
> The Non-Secure banked register has not changed. 

For those without the r1pX TRM handy, please include what this look like
before (presumably 1 bit?)  The changelog and in-code comments should
both be enhanced.

> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
> will cause a problem to CPU0 Non-Secure SW.

Please describe the problem, so we can better understand the specifics
of the workaround.

Also, is there an erratum number for this?

> The workaround must be:
>      1) Before doing the CPU1 wakeup, CPU0 must disable
>         the GIC distributor
>      2) CPU1 must re-enable the GIC distributor on
>         it's wakeup path.

Again, because the problem was not described, I am not entirely sure why
the workaround "must" be this, and how it fixes the problem.  Remember
to put yourself in the shoes of a reviewer who has not been deeply
involved in the code, so what seems obvious to you will not be obvious
to the reviewer without having to study the code and dig in to the TRMs.

> With this procedure, the GIC configuration done between the
> CPU0 wakeup and CPU1 wakeup will not be lost but during this
> short windows, the CPU0 will not receive interrupts

Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
devices? 

Also, the changelog doesn't describe what power states this affects, and
whether it's an idle problem or just a supend problem.  A quick glance
at the code suggests that only suspend is being addressed by this patch.
However, with the addition of coupled CPUidle (coming very soon now),
won't we have this same problem in idle?  IMO, this patch should address
both.

This workaround also assumes that you always want CPU1 to wakeup
immediately after CPU0.  I guess that will be the case for the coupled
states that would be affected by this bug, but the changelog should
describe that as well

Some minor comments below...

> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>
> ---
>  arch/arm/mach-omap2/common.h              |    2 +
>  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
>  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
>  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
>  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
>  5 files changed, 80 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> index 57da7f4..48d1ebe 100644
> --- a/arch/arm/mach-omap2/common.h
> +++ b/arch/arm/mach-omap2/common.h
> @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
>  #endif
>  
>  extern void __init gic_init_irq(void);
> +extern void gic_dist_disable(void);
>  extern void omap_smc1(u32 fn, u32 arg);
>  extern void __iomem *omap4_get_sar_ram_base(void);
>  extern void omap_do_wfi(void);
> @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
>  #ifdef CONFIG_SMP
>  /* Needed for secondary core boot */
>  extern void omap_secondary_startup(void);
> +extern void omap_secondary_startup_4460(void);
>  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
>  extern void omap_auxcoreboot_addr(u32 cpu_addr);
>  extern u32 omap_read_auxcoreboot0(void);
> diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
> index 503ac77..d602555 100644
> --- a/arch/arm/mach-omap2/omap-headsmp.S
> +++ b/arch/arm/mach-omap2/omap-headsmp.S
> @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
>  	b	secondary_startup
>  ENDPROC(omap_secondary_startup)
>  
> +ENTRY(omap_secondary_startup_4460)
> +hold_2:	ldr	r12,=0x103
> +	dsb
> +	smc	#0			@ read from AuxCoreBoot0
> +	mov	r0, r0, lsr #9
> +	mrc	p15, 0, r4, c0, c0, 5
> +	and	r4, r4, #0x0f
> +	cmp	r0, r4
> +	bne	hold_2
> +
> +	/*
> +	 * GIC distributor control register has changed between
> +	 * CortexA9 r1pX and r2pX. The Control Register secure
> +	 * banked version is now composed of 2 bits:
> +	 * bit 0 == Secure Enable
> +	 * bit 1 == Non-Secure Enable
> +	 * The Non-Secure banked register has not changed
> +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
> +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> +	 * The workaround must be:
> +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> +	 * the GIC distributor
> +	 * 2) CPU1 must re-enable the GIC distributor on
> +	 * it's wakeup path.
> +	 */
> +	ldr	r1, =0x48241000

Why not OMAP44XX_GIC_DIST_BASE for readability sake?

> +	ldr	r0, [r1]
> +	orr	r0, #1
> +	str	r0, [r1]
> +
> +	/*
> +	 * we've been released from the wait loop,secondary_stack
> +	 * should now contain the SVC stack for this core
> +	 */
> +	b	secondary_startup
> +ENDPROC(omap_secondary_startup_4460)
> diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> index 13670aa..e02c082 100644
> --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
>  	void __iomem *scu_sar_addr;
>  	void __iomem *wkup_sar_addr;
>  	void __iomem *l2x0_sar_addr;
> +	void (*secondary_startup)(void);
>  };
>  
>  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
>  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>  {
>  	unsigned int cpu_state = 0;
> +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
>  
>  	if (omap_rev() == OMAP4430_REV_ES1_0)
>  		return -ENXIO;
> @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>  
>  	clear_cpu_prev_pwrst(cpu);
>  	set_cpu_next_pwrst(cpu, power_state);
> -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
> +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
>  	scu_pwrst_prepare(cpu, power_state);
>  
>  	/*
> @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
>  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
>  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
>  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
> +	if (cpu_is_omap446x())
> +		pm_info->secondary_startup = omap_secondary_startup_4460;
> +	else
> +		pm_info->secondary_startup = omap_secondary_startup;

Does this exist on 4470 too?

Using a PM erratum check here instead of cpu_is* would make this more
scalable.  

Same comment for the cpu_is* check in wakeup_secondary()

Then, where the erratum is defined, it should state clearly why this
affects 446x and not before (presumably because 4430 has r1pX and 4460
has r2pX.)

>  	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
>  	if (!pm_info->pwrdm) {
>  		pr_err("Lookup failed for CPU1 pwrdm\n");
> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index deffbf1..c3eb9e8 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -33,6 +33,7 @@
>  
>  /* SCU base address */
>  static void __iomem *scu_base;
> +bool omap4_smp_romcode_errata;

static?

Kevin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-15 22:36     ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 22:36 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, paul, linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> On OMAP4, there is no support to read previous logic state
> or previous memory state achieved when a power domain transitions
> to RET. Instead there are module level context registers.
>
> In order to support the powerdomain level logic/mem_off_counters
> on OMAP4, instead use the previous power state achieved (RET) and
> the *programmed* logic/mem RET state to derive if a powerdomain lost
> logic or did not.
>
> If the powerdomain is programmed to enter RET state and lose logic
> in RET state, knowing that the powerdomain entered RET is good enough
> to derive that the logic was lost as well, in such cases.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Looks OK, but these new functions need some kerneldoc to describe the
decision making.

Kevin

> ---
>  arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
>  1 files changed, 32 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..ab00736 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
>  	return v;
>  }
>  
> +static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
> +{
> +	int state;
> +
> +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> +
> +	if (state == PWRDM_POWER_OFF)
> +		return PWRDM_POWER_OFF;
> +
> +	if (state != PWRDM_POWER_RET)
> +		return PWRDM_POWER_ON;
> +
> +	return omap4_pwrdm_read_logic_retst(pwrdm);
> +}
> +
>  static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
>  {
>  	u32 m, v;
> @@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
>  	return v;
>  }
>  
> +static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> +{
> +	int state;
> +
> +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> +
> +	if (state == PWRDM_POWER_OFF)
> +		return PWRDM_POWER_OFF;
> +
> +	if (state != PWRDM_POWER_RET)
> +		return PWRDM_POWER_ON;
> +
> +	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
> +}
> +
>  static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>  {
>  	u32 c = 0;
> @@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
>  	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
>  	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
>  	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
> +	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
>  	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
>  	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
>  	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
> +	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
>  	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
>  	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
>  	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
@ 2012-05-15 22:36     ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 22:36 UTC (permalink / raw)
  To: linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> On OMAP4, there is no support to read previous logic state
> or previous memory state achieved when a power domain transitions
> to RET. Instead there are module level context registers.
>
> In order to support the powerdomain level logic/mem_off_counters
> on OMAP4, instead use the previous power state achieved (RET) and
> the *programmed* logic/mem RET state to derive if a powerdomain lost
> logic or did not.
>
> If the powerdomain is programmed to enter RET state and lose logic
> in RET state, knowing that the powerdomain entered RET is good enough
> to derive that the logic was lost as well, in such cases.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

Looks OK, but these new functions need some kerneldoc to describe the
decision making.

Kevin

> ---
>  arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
>  1 files changed, 32 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> index 601325b..ab00736 100644
> --- a/arch/arm/mach-omap2/powerdomain44xx.c
> +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> @@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
>  	return v;
>  }
>  
> +static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
> +{
> +	int state;
> +
> +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> +
> +	if (state == PWRDM_POWER_OFF)
> +		return PWRDM_POWER_OFF;
> +
> +	if (state != PWRDM_POWER_RET)
> +		return PWRDM_POWER_ON;
> +
> +	return omap4_pwrdm_read_logic_retst(pwrdm);
> +}
> +
>  static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
>  {
>  	u32 m, v;
> @@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
>  	return v;
>  }
>  
> +static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> +{
> +	int state;
> +
> +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> +
> +	if (state == PWRDM_POWER_OFF)
> +		return PWRDM_POWER_OFF;
> +
> +	if (state != PWRDM_POWER_RET)
> +		return PWRDM_POWER_ON;
> +
> +	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
> +}
> +
>  static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
>  {
>  	u32 c = 0;
> @@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
>  	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
>  	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
>  	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
> +	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
>  	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
>  	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
>  	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
> +	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
>  	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
>  	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
>  	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-15 22:41     ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 22:41 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, paul, linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> PM debug now contains a file that can be used to control OSWR support
> enable / disable on OMAP4. Also removed the off_mode_enable file for
> the same platform as it is unsupported.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
not interested managing another new flag for OSWR.

For OMAP4, this should just be the default, and any drivers that are
broken just need to be fixed either by implementing context save/restore
or by using constraints.

Kevin

> ---
>  arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
>  arch/arm/mach-omap2/pm.h       |    1 +
>  arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
>  3 files changed, 33 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index 814bcd9..d9a8e42 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -39,6 +39,7 @@
>  #include "pm.h"
>  
>  u32 enable_off_mode;
> +static u32 enable_oswr_mode;
>  
>  #ifdef CONFIG_DEBUG_FS
>  #include <linux/debugfs.h>
> @@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
>  			omap_pm_enable_off_mode();
>  		else
>  			omap_pm_disable_off_mode();
> -		if (cpu_is_omap34xx())
> -			omap3_pm_off_mode_enable(val);
> +
> +		omap3_pm_off_mode_enable(val);
>  	}
>  
> +	if (option == &enable_oswr_mode)
> +		omap4_pm_oswr_mode_enable(val);
> +
>  	return 0;
>  }
>  
> @@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
>  
>  	pwrdm_for_each(pwrdms_setup, (void *)d);
>  
> -	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
> -				   &enable_off_mode, &pm_dbg_option_fops);
> +	if (cpu_is_omap34xx())
> +		(void) debugfs_create_file("enable_off_mode",
> +			S_IRUGO | S_IWUSR, d, &enable_off_mode,
> +			&pm_dbg_option_fops);
> +
> +	if (cpu_is_omap44xx())
> +		(void) debugfs_create_file("enable_oswr_mode",
> +			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
> +			&pm_dbg_option_fops);
> +
>  	pm_dbg_init_done = 1;
>  
>  	return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 36fa90b..c36ab63 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -17,6 +17,7 @@
>  
>  extern void *omap3_secure_ram_storage;
>  extern void omap3_pm_off_mode_enable(int);
> +extern void omap4_pm_oswr_mode_enable(int);
>  extern void omap_sram_idle(void);
>  extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
>  extern int omap3_idle_init(void);
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index cc85576..07ac0d3 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
>  }
>  
> +void omap4_pm_oswr_mode_enable(int enable)
> +{
> +	u32 next_logic_state;
> +	struct power_state *pwrst;
> +
> +	if (enable)
> +		next_logic_state = PWRDM_POWER_OFF;
> +	else
> +		next_logic_state = PWRDM_POWER_RET;
> +
> +	list_for_each_entry(pwrst, &pwrst_list, node) {
> +		pwrst->next_logic_state = next_logic_state;
> +		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
> +	}
> +}
> +
>  /**
>   * omap_default_idle - OMAP4 default ilde routine.'
>   *

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
@ 2012-05-15 22:41     ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-15 22:41 UTC (permalink / raw)
  To: linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> PM debug now contains a file that can be used to control OSWR support
> enable / disable on OMAP4. Also removed the off_mode_enable file for
> the same platform as it is unsupported.
>
> Signed-off-by: Tero Kristo <t-kristo@ti.com>

I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
not interested managing another new flag for OSWR.

For OMAP4, this should just be the default, and any drivers that are
broken just need to be fixed either by implementing context save/restore
or by using constraints.

Kevin

> ---
>  arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
>  arch/arm/mach-omap2/pm.h       |    1 +
>  arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
>  3 files changed, 33 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> index 814bcd9..d9a8e42 100644
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -39,6 +39,7 @@
>  #include "pm.h"
>  
>  u32 enable_off_mode;
> +static u32 enable_oswr_mode;
>  
>  #ifdef CONFIG_DEBUG_FS
>  #include <linux/debugfs.h>
> @@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
>  			omap_pm_enable_off_mode();
>  		else
>  			omap_pm_disable_off_mode();
> -		if (cpu_is_omap34xx())
> -			omap3_pm_off_mode_enable(val);
> +
> +		omap3_pm_off_mode_enable(val);
>  	}
>  
> +	if (option == &enable_oswr_mode)
> +		omap4_pm_oswr_mode_enable(val);
> +
>  	return 0;
>  }
>  
> @@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
>  
>  	pwrdm_for_each(pwrdms_setup, (void *)d);
>  
> -	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
> -				   &enable_off_mode, &pm_dbg_option_fops);
> +	if (cpu_is_omap34xx())
> +		(void) debugfs_create_file("enable_off_mode",
> +			S_IRUGO | S_IWUSR, d, &enable_off_mode,
> +			&pm_dbg_option_fops);
> +
> +	if (cpu_is_omap44xx())
> +		(void) debugfs_create_file("enable_oswr_mode",
> +			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
> +			&pm_dbg_option_fops);
> +
>  	pm_dbg_init_done = 1;
>  
>  	return 0;
> diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> index 36fa90b..c36ab63 100644
> --- a/arch/arm/mach-omap2/pm.h
> +++ b/arch/arm/mach-omap2/pm.h
> @@ -17,6 +17,7 @@
>  
>  extern void *omap3_secure_ram_storage;
>  extern void omap3_pm_off_mode_enable(int);
> +extern void omap4_pm_oswr_mode_enable(int);
>  extern void omap_sram_idle(void);
>  extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
>  extern int omap3_idle_init(void);
> diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> index cc85576..07ac0d3 100644
> --- a/arch/arm/mach-omap2/pm44xx.c
> +++ b/arch/arm/mach-omap2/pm44xx.c
> @@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
>  	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
>  }
>  
> +void omap4_pm_oswr_mode_enable(int enable)
> +{
> +	u32 next_logic_state;
> +	struct power_state *pwrst;
> +
> +	if (enable)
> +		next_logic_state = PWRDM_POWER_OFF;
> +	else
> +		next_logic_state = PWRDM_POWER_RET;
> +
> +	list_for_each_entry(pwrst, &pwrst_list, node) {
> +		pwrst->next_logic_state = next_logic_state;
> +		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
> +	}
> +}
> +
>  /**
>   * omap_default_idle - OMAP4 default ilde routine.'
>   *

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
  2012-05-15 19:52     ` Kevin Hilman
@ 2012-05-16  8:37       ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:37 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: paul, linux-omap, linux-arm-kernel, Rajendra Nayak

On Tue, 2012-05-15 at 12:52 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > From: Rajendra Nayak <rnayak@ti.com>
> >
> > Remove the FIXME's in the suspend sequence since
> > we now intend to support system level RET support.
> 
> minor: this should probably go at the end of the series, after retention
> is supported.  Otherwise, ending up with only this patch applied
> (e.g. during a git bisect) will lead to a broken boot I suspect.

Ok, will move this to the end.

-Tero

> 
> Kevin
> 
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> > Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > ---
> >  arch/arm/mach-omap2/pm44xx.c |    6 ------
> >  1 files changed, 0 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> > index 8856253..31990d5 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> >  	if (!strncmp(pwrdm->name, "cpu", 3))
> >  		return 0;
> >  
> > -	/*
> > -	 * FIXME: Remove this check when core retention is supported
> > -	 * Only MPUSS power domain is added in the list.
> > -	 */
> > -	if (strcmp(pwrdm->name, "mpu_pwrdm"))
> > -		return 0;
> >  
> >  	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
> >  	if (!pwrst)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention
@ 2012-05-16  8:37       ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-05-15 at 12:52 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > From: Rajendra Nayak <rnayak@ti.com>
> >
> > Remove the FIXME's in the suspend sequence since
> > we now intend to support system level RET support.
> 
> minor: this should probably go at the end of the series, after retention
> is supported.  Otherwise, ending up with only this patch applied
> (e.g. during a git bisect) will lead to a broken boot I suspect.

Ok, will move this to the end.

-Tero

> 
> Kevin
> 
> > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> > Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > ---
> >  arch/arm/mach-omap2/pm44xx.c |    6 ------
> >  1 files changed, 0 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> > index 8856253..31990d5 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -101,12 +101,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> >  	if (!strncmp(pwrdm->name, "cpu", 3))
> >  		return 0;
> >  
> > -	/*
> > -	 * FIXME: Remove this check when core retention is supported
> > -	 * Only MPUSS power domain is added in the list.
> > -	 */
> > -	if (strcmp(pwrdm->name, "mpu_pwrdm"))
> > -		return 0;
> >  
> >  	pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
> >  	if (!pwrst)

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-15 21:44     ` Kevin Hilman
@ 2012-05-16  8:54       ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:54 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Santosh Shilimkar, linux-omap, paul, linux-arm-kernel

On Tue, 2012-05-15 at 14:44 -0700, Kevin Hilman wrote:
> Santosh,
> 
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >
> > GIC distributor control register has changed between CortexA9 r1pX and
> > r2pX. The Control Register secure banked version is now composed of 2
> > bits:
> >      bit 0 == Secure Enable
> >      bit 1 == Non-Secure Enable
> > The Non-Secure banked register has not changed. 
> 
> For those without the r1pX TRM handy, please include what this look like
> before (presumably 1 bit?)  The changelog and in-code comments should
> both be enhanced.
> 
> > Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
> > will cause a problem to CPU0 Non-Secure SW.
> 
> Please describe the problem, so we can better understand the specifics
> of the workaround.

Santosh, can you provide a better changelog for this?

> 
> Also, is there an erratum number for this?

Nothing public. I don't think there are any public documents about ROM
code, including erratas.

> 
> > The workaround must be:
> >      1) Before doing the CPU1 wakeup, CPU0 must disable
> >         the GIC distributor
> >      2) CPU1 must re-enable the GIC distributor on
> >         it's wakeup path.
> 
> Again, because the problem was not described, I am not entirely sure why
> the workaround "must" be this, and how it fixes the problem.  Remember
> to put yourself in the shoes of a reviewer who has not been deeply
> involved in the code, so what seems obvious to you will not be obvious
> to the reviewer without having to study the code and dig in to the TRMs.
> 
> > With this procedure, the GIC configuration done between the
> > CPU0 wakeup and CPU1 wakeup will not be lost but during this
> > short windows, the CPU0 will not receive interrupts
> 
> Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
> devices? 

Yes.

> 
> Also, the changelog doesn't describe what power states this affects, and
> whether it's an idle problem or just a supend problem.  A quick glance
> at the code suggests that only suspend is being addressed by this patch.
> However, with the addition of coupled CPUidle (coming very soon now),
> won't we have this same problem in idle?  IMO, this patch should address
> both.

My understanding is that this happens if mpu_pwrdm goes off. Cpuidle
support is not added to this patch as it does not exist yet. Probably
shouldn't be that big fix.

> 
> This workaround also assumes that you always want CPU1 to wakeup
> immediately after CPU0.  I guess that will be the case for the coupled
> states that would be affected by this bug, but the changelog should
> describe that as well

Yes, this patch assumes both CPUs attempt to wake-up, thus cpu1 is stuck
in the hold loop. The device-off set patch #17 addresses this issue and
puts cpu1 back to idle immediately if no wake request is received from
cpu0. That patch should be possible to move to this set if needed.


> 
> Some minor comments below...
> 
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> > ---
> >  arch/arm/mach-omap2/common.h              |    2 +
> >  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
> >  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
> >  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
> >  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
> >  5 files changed, 80 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> > index 57da7f4..48d1ebe 100644
> > --- a/arch/arm/mach-omap2/common.h
> > +++ b/arch/arm/mach-omap2/common.h
> > @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
> >  #endif
> >  
> >  extern void __init gic_init_irq(void);
> > +extern void gic_dist_disable(void);
> >  extern void omap_smc1(u32 fn, u32 arg);
> >  extern void __iomem *omap4_get_sar_ram_base(void);
> >  extern void omap_do_wfi(void);
> > @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
> >  #ifdef CONFIG_SMP
> >  /* Needed for secondary core boot */
> >  extern void omap_secondary_startup(void);
> > +extern void omap_secondary_startup_4460(void);
> >  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
> >  extern void omap_auxcoreboot_addr(u32 cpu_addr);
> >  extern u32 omap_read_auxcoreboot0(void);
> > diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
> > index 503ac77..d602555 100644
> > --- a/arch/arm/mach-omap2/omap-headsmp.S
> > +++ b/arch/arm/mach-omap2/omap-headsmp.S
> > @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
> >  	b	secondary_startup
> >  ENDPROC(omap_secondary_startup)
> >  
> > +ENTRY(omap_secondary_startup_4460)
> > +hold_2:	ldr	r12,=0x103
> > +	dsb
> > +	smc	#0			@ read from AuxCoreBoot0
> > +	mov	r0, r0, lsr #9
> > +	mrc	p15, 0, r4, c0, c0, 5
> > +	and	r4, r4, #0x0f
> > +	cmp	r0, r4
> > +	bne	hold_2
> > +
> > +	/*
> > +	 * GIC distributor control register has changed between
> > +	 * CortexA9 r1pX and r2pX. The Control Register secure
> > +	 * banked version is now composed of 2 bits:
> > +	 * bit 0 == Secure Enable
> > +	 * bit 1 == Non-Secure Enable
> > +	 * The Non-Secure banked register has not changed
> > +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
> > +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> > +	 * The workaround must be:
> > +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> > +	 * the GIC distributor
> > +	 * 2) CPU1 must re-enable the GIC distributor on
> > +	 * it's wakeup path.
> > +	 */
> > +	ldr	r1, =0x48241000
> 
> Why not OMAP44XX_GIC_DIST_BASE for readability sake?

Will change this.

> 
> > +	ldr	r0, [r1]
> > +	orr	r0, #1
> > +	str	r0, [r1]
> > +
> > +	/*
> > +	 * we've been released from the wait loop,secondary_stack
> > +	 * should now contain the SVC stack for this core
> > +	 */
> > +	b	secondary_startup
> > +ENDPROC(omap_secondary_startup_4460)
> > diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > index 13670aa..e02c082 100644
> > --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
> >  	void __iomem *scu_sar_addr;
> >  	void __iomem *wkup_sar_addr;
> >  	void __iomem *l2x0_sar_addr;
> > +	void (*secondary_startup)(void);
> >  };
> >  
> >  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> > @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> >  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
> >  {
> >  	unsigned int cpu_state = 0;
> > +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
> >  
> >  	if (omap_rev() == OMAP4430_REV_ES1_0)
> >  		return -ENXIO;
> > @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
> >  
> >  	clear_cpu_prev_pwrst(cpu);
> >  	set_cpu_next_pwrst(cpu, power_state);
> > -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
> > +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
> >  	scu_pwrst_prepare(cpu, power_state);
> >  
> >  	/*
> > @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
> >  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
> >  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
> >  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
> > +	if (cpu_is_omap446x())
> > +		pm_info->secondary_startup = omap_secondary_startup_4460;
> > +	else
> > +		pm_info->secondary_startup = omap_secondary_startup;
> 
> Does this exist on 4470 too?

No, only valid for 4460. ROM code should be fixed on 4470 (haven't
tested that though as I don't have access to 4470 devices.)

> 
> Using a PM erratum check here instead of cpu_is* would make this more
> scalable.  
> 
> Same comment for the cpu_is* check in wakeup_secondary()
> 
> Then, where the erratum is defined, it should state clearly why this
> affects 446x and not before (presumably because 4430 has r1pX and 4460
> has r2pX.)

Yea, I can add errata flag for this. The errata support for omap4 PM is
currently defined in the device off set, so I guess I need to pull that
to this set.

> 
> >  	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
> >  	if (!pm_info->pwrdm) {
> >  		pr_err("Lookup failed for CPU1 pwrdm\n");
> > diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> > index deffbf1..c3eb9e8 100644
> > --- a/arch/arm/mach-omap2/omap-smp.c
> > +++ b/arch/arm/mach-omap2/omap-smp.c
> > @@ -33,6 +33,7 @@
> >  
> >  /* SCU base address */
> >  static void __iomem *scu_base;
> > +bool omap4_smp_romcode_errata;
> 
> static?

Yes should be.

-Tero



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-16  8:54       ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-05-15 at 14:44 -0700, Kevin Hilman wrote:
> Santosh,
> 
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >
> > GIC distributor control register has changed between CortexA9 r1pX and
> > r2pX. The Control Register secure banked version is now composed of 2
> > bits:
> >      bit 0 == Secure Enable
> >      bit 1 == Non-Secure Enable
> > The Non-Secure banked register has not changed. 
> 
> For those without the r1pX TRM handy, please include what this look like
> before (presumably 1 bit?)  The changelog and in-code comments should
> both be enhanced.
> 
> > Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
> > will cause a problem to CPU0 Non-Secure SW.
> 
> Please describe the problem, so we can better understand the specifics
> of the workaround.

Santosh, can you provide a better changelog for this?

> 
> Also, is there an erratum number for this?

Nothing public. I don't think there are any public documents about ROM
code, including erratas.

> 
> > The workaround must be:
> >      1) Before doing the CPU1 wakeup, CPU0 must disable
> >         the GIC distributor
> >      2) CPU1 must re-enable the GIC distributor on
> >         it's wakeup path.
> 
> Again, because the problem was not described, I am not entirely sure why
> the workaround "must" be this, and how it fixes the problem.  Remember
> to put yourself in the shoes of a reviewer who has not been deeply
> involved in the code, so what seems obvious to you will not be obvious
> to the reviewer without having to study the code and dig in to the TRMs.
> 
> > With this procedure, the GIC configuration done between the
> > CPU0 wakeup and CPU1 wakeup will not be lost but during this
> > short windows, the CPU0 will not receive interrupts
> 
> Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
> devices? 

Yes.

> 
> Also, the changelog doesn't describe what power states this affects, and
> whether it's an idle problem or just a supend problem.  A quick glance
> at the code suggests that only suspend is being addressed by this patch.
> However, with the addition of coupled CPUidle (coming very soon now),
> won't we have this same problem in idle?  IMO, this patch should address
> both.

My understanding is that this happens if mpu_pwrdm goes off. Cpuidle
support is not added to this patch as it does not exist yet. Probably
shouldn't be that big fix.

> 
> This workaround also assumes that you always want CPU1 to wakeup
> immediately after CPU0.  I guess that will be the case for the coupled
> states that would be affected by this bug, but the changelog should
> describe that as well

Yes, this patch assumes both CPUs attempt to wake-up, thus cpu1 is stuck
in the hold loop. The device-off set patch #17 addresses this issue and
puts cpu1 back to idle immediately if no wake request is received from
cpu0. That patch should be possible to move to this set if needed.


> 
> Some minor comments below...
> 
> > Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> > ---
> >  arch/arm/mach-omap2/common.h              |    2 +
> >  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
> >  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
> >  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
> >  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
> >  5 files changed, 80 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
> > index 57da7f4..48d1ebe 100644
> > --- a/arch/arm/mach-omap2/common.h
> > +++ b/arch/arm/mach-omap2/common.h
> > @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
> >  #endif
> >  
> >  extern void __init gic_init_irq(void);
> > +extern void gic_dist_disable(void);
> >  extern void omap_smc1(u32 fn, u32 arg);
> >  extern void __iomem *omap4_get_sar_ram_base(void);
> >  extern void omap_do_wfi(void);
> > @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
> >  #ifdef CONFIG_SMP
> >  /* Needed for secondary core boot */
> >  extern void omap_secondary_startup(void);
> > +extern void omap_secondary_startup_4460(void);
> >  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
> >  extern void omap_auxcoreboot_addr(u32 cpu_addr);
> >  extern u32 omap_read_auxcoreboot0(void);
> > diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
> > index 503ac77..d602555 100644
> > --- a/arch/arm/mach-omap2/omap-headsmp.S
> > +++ b/arch/arm/mach-omap2/omap-headsmp.S
> > @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
> >  	b	secondary_startup
> >  ENDPROC(omap_secondary_startup)
> >  
> > +ENTRY(omap_secondary_startup_4460)
> > +hold_2:	ldr	r12,=0x103
> > +	dsb
> > +	smc	#0			@ read from AuxCoreBoot0
> > +	mov	r0, r0, lsr #9
> > +	mrc	p15, 0, r4, c0, c0, 5
> > +	and	r4, r4, #0x0f
> > +	cmp	r0, r4
> > +	bne	hold_2
> > +
> > +	/*
> > +	 * GIC distributor control register has changed between
> > +	 * CortexA9 r1pX and r2pX. The Control Register secure
> > +	 * banked version is now composed of 2 bits:
> > +	 * bit 0 == Secure Enable
> > +	 * bit 1 == Non-Secure Enable
> > +	 * The Non-Secure banked register has not changed
> > +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
> > +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> > +	 * The workaround must be:
> > +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> > +	 * the GIC distributor
> > +	 * 2) CPU1 must re-enable the GIC distributor on
> > +	 * it's wakeup path.
> > +	 */
> > +	ldr	r1, =0x48241000
> 
> Why not OMAP44XX_GIC_DIST_BASE for readability sake?

Will change this.

> 
> > +	ldr	r0, [r1]
> > +	orr	r0, #1
> > +	str	r0, [r1]
> > +
> > +	/*
> > +	 * we've been released from the wait loop,secondary_stack
> > +	 * should now contain the SVC stack for this core
> > +	 */
> > +	b	secondary_startup
> > +ENDPROC(omap_secondary_startup_4460)
> > diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > index 13670aa..e02c082 100644
> > --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
> > @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
> >  	void __iomem *scu_sar_addr;
> >  	void __iomem *wkup_sar_addr;
> >  	void __iomem *l2x0_sar_addr;
> > +	void (*secondary_startup)(void);
> >  };
> >  
> >  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
> > @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
> >  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
> >  {
> >  	unsigned int cpu_state = 0;
> > +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
> >  
> >  	if (omap_rev() == OMAP4430_REV_ES1_0)
> >  		return -ENXIO;
> > @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
> >  
> >  	clear_cpu_prev_pwrst(cpu);
> >  	set_cpu_next_pwrst(cpu, power_state);
> > -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
> > +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
> >  	scu_pwrst_prepare(cpu, power_state);
> >  
> >  	/*
> > @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
> >  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
> >  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
> >  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
> > +	if (cpu_is_omap446x())
> > +		pm_info->secondary_startup = omap_secondary_startup_4460;
> > +	else
> > +		pm_info->secondary_startup = omap_secondary_startup;
> 
> Does this exist on 4470 too?

No, only valid for 4460. ROM code should be fixed on 4470 (haven't
tested that though as I don't have access to 4470 devices.)

> 
> Using a PM erratum check here instead of cpu_is* would make this more
> scalable.  
> 
> Same comment for the cpu_is* check in wakeup_secondary()
> 
> Then, where the erratum is defined, it should state clearly why this
> affects 446x and not before (presumably because 4430 has r1pX and 4460
> has r2pX.)

Yea, I can add errata flag for this. The errata support for omap4 PM is
currently defined in the device off set, so I guess I need to pull that
to this set.

> 
> >  	pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
> >  	if (!pm_info->pwrdm) {
> >  		pr_err("Lookup failed for CPU1 pwrdm\n");
> > diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> > index deffbf1..c3eb9e8 100644
> > --- a/arch/arm/mach-omap2/omap-smp.c
> > +++ b/arch/arm/mach-omap2/omap-smp.c
> > @@ -33,6 +33,7 @@
> >  
> >  /* SCU base address */
> >  static void __iomem *scu_base;
> > +bool omap4_smp_romcode_errata;
> 
> static?

Yes should be.

-Tero

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
  2012-05-15 22:36     ` Kevin Hilman
@ 2012-05-16  8:55       ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:55 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, paul, linux-arm-kernel

On Tue, 2012-05-15 at 15:36 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > On OMAP4, there is no support to read previous logic state
> > or previous memory state achieved when a power domain transitions
> > to RET. Instead there are module level context registers.
> >
> > In order to support the powerdomain level logic/mem_off_counters
> > on OMAP4, instead use the previous power state achieved (RET) and
> > the *programmed* logic/mem RET state to derive if a powerdomain lost
> > logic or did not.
> >
> > If the powerdomain is programmed to enter RET state and lose logic
> > in RET state, knowing that the powerdomain entered RET is good enough
> > to derive that the logic was lost as well, in such cases.
> >
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> Looks OK, but these new functions need some kerneldoc to describe the
> decision making.

Will add.

-Tero

> 
> Kevin
> 
> > ---
> >  arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
> >  1 files changed, 32 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> > index 601325b..ab00736 100644
> > --- a/arch/arm/mach-omap2/powerdomain44xx.c
> > +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> > @@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
> >  	return v;
> >  }
> >  
> > +static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
> > +{
> > +	int state;
> > +
> > +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> > +
> > +	if (state == PWRDM_POWER_OFF)
> > +		return PWRDM_POWER_OFF;
> > +
> > +	if (state != PWRDM_POWER_RET)
> > +		return PWRDM_POWER_ON;
> > +
> > +	return omap4_pwrdm_read_logic_retst(pwrdm);
> > +}
> > +
> >  static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> >  {
> >  	u32 m, v;
> > @@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
> >  	return v;
> >  }
> >  
> > +static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> > +{
> > +	int state;
> > +
> > +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> > +
> > +	if (state == PWRDM_POWER_OFF)
> > +		return PWRDM_POWER_OFF;
> > +
> > +	if (state != PWRDM_POWER_RET)
> > +		return PWRDM_POWER_ON;
> > +
> > +	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
> > +}
> > +
> >  static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
> >  {
> >  	u32 c = 0;
> > @@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
> >  	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
> >  	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
> >  	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
> > +	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
> >  	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
> >  	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
> >  	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
> > +	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
> >  	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
> >  	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
> >  	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states
@ 2012-05-16  8:55       ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  8:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-05-15 at 15:36 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > On OMAP4, there is no support to read previous logic state
> > or previous memory state achieved when a power domain transitions
> > to RET. Instead there are module level context registers.
> >
> > In order to support the powerdomain level logic/mem_off_counters
> > on OMAP4, instead use the previous power state achieved (RET) and
> > the *programmed* logic/mem RET state to derive if a powerdomain lost
> > logic or did not.
> >
> > If the powerdomain is programmed to enter RET state and lose logic
> > in RET state, knowing that the powerdomain entered RET is good enough
> > to derive that the logic was lost as well, in such cases.
> >
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> Looks OK, but these new functions need some kerneldoc to describe the
> decision making.

Will add.

-Tero

> 
> Kevin
> 
> > ---
> >  arch/arm/mach-omap2/powerdomain44xx.c |   32 ++++++++++++++++++++++++++++++++
> >  1 files changed, 32 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
> > index 601325b..ab00736 100644
> > --- a/arch/arm/mach-omap2/powerdomain44xx.c
> > +++ b/arch/arm/mach-omap2/powerdomain44xx.c
> > @@ -151,6 +151,21 @@ static int omap4_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
> >  	return v;
> >  }
> >  
> > +static int omap4_pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm)
> > +{
> > +	int state;
> > +
> > +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> > +
> > +	if (state == PWRDM_POWER_OFF)
> > +		return PWRDM_POWER_OFF;
> > +
> > +	if (state != PWRDM_POWER_RET)
> > +		return PWRDM_POWER_ON;
> > +
> > +	return omap4_pwrdm_read_logic_retst(pwrdm);
> > +}
> > +
> >  static int omap4_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> >  {
> >  	u32 m, v;
> > @@ -179,6 +194,21 @@ static int omap4_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
> >  	return v;
> >  }
> >  
> > +static int omap4_pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
> > +{
> > +	int state;
> > +
> > +	state = omap4_pwrdm_read_prev_pwrst(pwrdm);
> > +
> > +	if (state == PWRDM_POWER_OFF)
> > +		return PWRDM_POWER_OFF;
> > +
> > +	if (state != PWRDM_POWER_RET)
> > +		return PWRDM_POWER_ON;
> > +
> > +	return omap4_pwrdm_read_mem_retst(pwrdm, bank);
> > +}
> > +
> >  static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
> >  {
> >  	u32 c = 0;
> > @@ -217,9 +247,11 @@ struct pwrdm_ops omap4_pwrdm_operations = {
> >  	.pwrdm_clear_all_prev_pwrst	= omap4_pwrdm_clear_all_prev_pwrst,
> >  	.pwrdm_set_logic_retst	= omap4_pwrdm_set_logic_retst,
> >  	.pwrdm_read_logic_pwrst	= omap4_pwrdm_read_logic_pwrst,
> > +	.pwrdm_read_prev_logic_pwrst	= omap4_pwrdm_read_prev_logic_pwrst,
> >  	.pwrdm_read_logic_retst	= omap4_pwrdm_read_logic_retst,
> >  	.pwrdm_read_mem_pwrst	= omap4_pwrdm_read_mem_pwrst,
> >  	.pwrdm_read_mem_retst	= omap4_pwrdm_read_mem_retst,
> > +	.pwrdm_read_prev_mem_pwrst	= omap4_pwrdm_read_prev_mem_pwrst,
> >  	.pwrdm_set_mem_onst	= omap4_pwrdm_set_mem_onst,
> >  	.pwrdm_set_mem_retst	= omap4_pwrdm_set_mem_retst,
> >  	.pwrdm_wait_transition	= omap4_pwrdm_wait_transition,

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
  2012-05-15 22:41     ` Kevin Hilman
@ 2012-05-16  9:10       ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  9:10 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: linux-omap, paul, linux-arm-kernel

On Tue, 2012-05-15 at 15:41 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > PM debug now contains a file that can be used to control OSWR support
> > enable / disable on OMAP4. Also removed the off_mode_enable file for
> > the same platform as it is unsupported.
> >
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
> not interested managing another new flag for OSWR.
> 
> For OMAP4, this should just be the default, and any drivers that are
> broken just need to be fixed either by implementing context save/restore
> or by using constraints.

Well, it is not flag as such, as it is static variable internal to
pm-debug.c. I could drop this, however it is extremely useful as a
testing feature. Without this, it is difficult to test CSWR / OSWR. If
you have taken a look at the device-off set, I am actually adding the
flag back for omap4 there for enabling device off. If this flag is also
dropped, the device will always just go to device off, in which case
testing CSWR / OSWR becomes an issue again, and I don't think this is
ideal.

Speaking of enable_off_mode, it might be possible to change it also be
static and remove all the references to it from code. Currently it is
only used from cpuidle34xx.c.

-Tero

> 
> Kevin
> 
> > ---
> >  arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
> >  arch/arm/mach-omap2/pm.h       |    1 +
> >  arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
> >  3 files changed, 33 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> > index 814bcd9..d9a8e42 100644
> > --- a/arch/arm/mach-omap2/pm-debug.c
> > +++ b/arch/arm/mach-omap2/pm-debug.c
> > @@ -39,6 +39,7 @@
> >  #include "pm.h"
> >  
> >  u32 enable_off_mode;
> > +static u32 enable_oswr_mode;
> >  
> >  #ifdef CONFIG_DEBUG_FS
> >  #include <linux/debugfs.h>
> > @@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
> >  			omap_pm_enable_off_mode();
> >  		else
> >  			omap_pm_disable_off_mode();
> > -		if (cpu_is_omap34xx())
> > -			omap3_pm_off_mode_enable(val);
> > +
> > +		omap3_pm_off_mode_enable(val);
> >  	}
> >  
> > +	if (option == &enable_oswr_mode)
> > +		omap4_pm_oswr_mode_enable(val);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
> >  
> >  	pwrdm_for_each(pwrdms_setup, (void *)d);
> >  
> > -	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
> > -				   &enable_off_mode, &pm_dbg_option_fops);
> > +	if (cpu_is_omap34xx())
> > +		(void) debugfs_create_file("enable_off_mode",
> > +			S_IRUGO | S_IWUSR, d, &enable_off_mode,
> > +			&pm_dbg_option_fops);
> > +
> > +	if (cpu_is_omap44xx())
> > +		(void) debugfs_create_file("enable_oswr_mode",
> > +			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
> > +			&pm_dbg_option_fops);
> > +
> >  	pm_dbg_init_done = 1;
> >  
> >  	return 0;
> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> > index 36fa90b..c36ab63 100644
> > --- a/arch/arm/mach-omap2/pm.h
> > +++ b/arch/arm/mach-omap2/pm.h
> > @@ -17,6 +17,7 @@
> >  
> >  extern void *omap3_secure_ram_storage;
> >  extern void omap3_pm_off_mode_enable(int);
> > +extern void omap4_pm_oswr_mode_enable(int);
> >  extern void omap_sram_idle(void);
> >  extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
> >  extern int omap3_idle_init(void);
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> > index cc85576..07ac0d3 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> >  	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
> >  }
> >  
> > +void omap4_pm_oswr_mode_enable(int enable)
> > +{
> > +	u32 next_logic_state;
> > +	struct power_state *pwrst;
> > +
> > +	if (enable)
> > +		next_logic_state = PWRDM_POWER_OFF;
> > +	else
> > +		next_logic_state = PWRDM_POWER_RET;
> > +
> > +	list_for_each_entry(pwrst, &pwrst_list, node) {
> > +		pwrst->next_logic_state = next_logic_state;
> > +		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
> > +	}
> > +}
> > +
> >  /**
> >   * omap_default_idle - OMAP4 default ilde routine.'
> >   *



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
@ 2012-05-16  9:10       ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-16  9:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-05-15 at 15:41 -0700, Kevin Hilman wrote:
> Tero Kristo <t-kristo@ti.com> writes:
> 
> > PM debug now contains a file that can be used to control OSWR support
> > enable / disable on OMAP4. Also removed the off_mode_enable file for
> > the same platform as it is unsupported.
> >
> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
> 
> I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
> not interested managing another new flag for OSWR.
> 
> For OMAP4, this should just be the default, and any drivers that are
> broken just need to be fixed either by implementing context save/restore
> or by using constraints.

Well, it is not flag as such, as it is static variable internal to
pm-debug.c. I could drop this, however it is extremely useful as a
testing feature. Without this, it is difficult to test CSWR / OSWR. If
you have taken a look at the device-off set, I am actually adding the
flag back for omap4 there for enabling device off. If this flag is also
dropped, the device will always just go to device off, in which case
testing CSWR / OSWR becomes an issue again, and I don't think this is
ideal.

Speaking of enable_off_mode, it might be possible to change it also be
static and remove all the references to it from code. Currently it is
only used from cpuidle34xx.c.

-Tero

> 
> Kevin
> 
> > ---
> >  arch/arm/mach-omap2/pm-debug.c |   20 ++++++++++++++++----
> >  arch/arm/mach-omap2/pm.h       |    1 +
> >  arch/arm/mach-omap2/pm44xx.c   |   16 ++++++++++++++++
> >  3 files changed, 33 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> > index 814bcd9..d9a8e42 100644
> > --- a/arch/arm/mach-omap2/pm-debug.c
> > +++ b/arch/arm/mach-omap2/pm-debug.c
> > @@ -39,6 +39,7 @@
> >  #include "pm.h"
> >  
> >  u32 enable_off_mode;
> > +static u32 enable_oswr_mode;
> >  
> >  #ifdef CONFIG_DEBUG_FS
> >  #include <linux/debugfs.h>
> > @@ -247,10 +248,13 @@ static int option_set(void *data, u64 val)
> >  			omap_pm_enable_off_mode();
> >  		else
> >  			omap_pm_disable_off_mode();
> > -		if (cpu_is_omap34xx())
> > -			omap3_pm_off_mode_enable(val);
> > +
> > +		omap3_pm_off_mode_enable(val);
> >  	}
> >  
> > +	if (option == &enable_oswr_mode)
> > +		omap4_pm_oswr_mode_enable(val);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -274,8 +278,16 @@ static int __init pm_dbg_init(void)
> >  
> >  	pwrdm_for_each(pwrdms_setup, (void *)d);
> >  
> > -	(void) debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
> > -				   &enable_off_mode, &pm_dbg_option_fops);
> > +	if (cpu_is_omap34xx())
> > +		(void) debugfs_create_file("enable_off_mode",
> > +			S_IRUGO | S_IWUSR, d, &enable_off_mode,
> > +			&pm_dbg_option_fops);
> > +
> > +	if (cpu_is_omap44xx())
> > +		(void) debugfs_create_file("enable_oswr_mode",
> > +			S_IRUGO | S_IWUSR, d, &enable_oswr_mode,
> > +			&pm_dbg_option_fops);
> > +
> >  	pm_dbg_init_done = 1;
> >  
> >  	return 0;
> > diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
> > index 36fa90b..c36ab63 100644
> > --- a/arch/arm/mach-omap2/pm.h
> > +++ b/arch/arm/mach-omap2/pm.h
> > @@ -17,6 +17,7 @@
> >  
> >  extern void *omap3_secure_ram_storage;
> >  extern void omap3_pm_off_mode_enable(int);
> > +extern void omap4_pm_oswr_mode_enable(int);
> >  extern void omap_sram_idle(void);
> >  extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
> >  extern int omap3_idle_init(void);
> > diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
> > index cc85576..07ac0d3 100644
> > --- a/arch/arm/mach-omap2/pm44xx.c
> > +++ b/arch/arm/mach-omap2/pm44xx.c
> > @@ -115,6 +115,22 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
> >  	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
> >  }
> >  
> > +void omap4_pm_oswr_mode_enable(int enable)
> > +{
> > +	u32 next_logic_state;
> > +	struct power_state *pwrst;
> > +
> > +	if (enable)
> > +		next_logic_state = PWRDM_POWER_OFF;
> > +	else
> > +		next_logic_state = PWRDM_POWER_RET;
> > +
> > +	list_for_each_entry(pwrst, &pwrst_list, node) {
> > +		pwrst->next_logic_state = next_logic_state;
> > +		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
> > +	}
> > +}
> > +
> >  /**
> >   * omap_default_idle - OMAP4 default ilde routine.'
> >   *

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-15 21:44     ` Kevin Hilman
@ 2012-05-16  9:16       ` Santosh Shilimkar
  -1 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16  9:16 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
> Santosh,
> 
> Tero Kristo <t-kristo@ti.com> writes:
> 
>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>
>> GIC distributor control register has changed between CortexA9 r1pX and
>> r2pX. The Control Register secure banked version is now composed of 2
>> bits:
>>      bit 0 == Secure Enable
>>      bit 1 == Non-Secure Enable
>> The Non-Secure banked register has not changed. 
> 
> For those without the r1pX TRM handy, please include what this look like
> before (presumably 1 bit?)  The changelog and in-code comments should
> both be enhanced.
>
You are right. There was only one bit previously which was used for
secure/non-secure mode. So ROM over-writes the non-secure bit
accidentally.

>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>> will cause a problem to CPU0 Non-Secure SW.
> 
> Please describe the problem, so we can better understand the specifics
> of the workaround.
> 
> Also, is there an erratum number for this?
> 
>> The workaround must be:
>>      1) Before doing the CPU1 wakeup, CPU0 must disable
>>         the GIC distributor
>>      2) CPU1 must re-enable the GIC distributor on
>>         it's wakeup path.
> 
> Again, because the problem was not described, I am not entirely sure why
> the workaround "must" be this, and how it fixes the problem.  Remember
> to put yourself in the shoes of a reviewer who has not been deeply
> involved in the code, so what seems obvious to you will not be obvious
> to the reviewer without having to study the code and dig in to the TRMs.
>
Agree and sorry for assuming that the TRM reference should be enough.

>> With this procedure, the GIC configuration done between the
>> CPU0 wakeup and CPU1 wakeup will not be lost but during this
>> short windows, the CPU0 will not receive interrupts
> 
> Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
> devices? 
> 
Yes. Thats the case otherwise too, on all OMAP4 devices :-(

> Also, the changelog doesn't describe what power states this affects, and
> whether it's an idle problem or just a supend problem.  A quick glance
> at the code suggests that only suspend is being addressed by this patch.
> However, with the addition of coupled CPUidle (coming very soon now),
> won't we have this same problem in idle?  IMO, this patch should address
> both.
> 
MPU OSWR and onwards states only. Will add that info in the changelog.

> This workaround also assumes that you always want CPU1 to wakeup
> immediately after CPU0.  I guess that will be the case for the coupled
> states that would be affected by this bug, but the changelog should
> describe that as well
>
You are right. It does affect couple idle as well. The old idle code
was relying on hotplug path and this fix is in that path which helps
suspend as well as cpuidle with CPU1 hotplug in/out

Actually this BUG is really nasty and the WA is worst.

> Some minor comments below...
> 
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> ---
>>  arch/arm/mach-omap2/common.h              |    2 +
>>  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
>>  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
>>  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
>>  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
>>  5 files changed, 80 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
>> index 57da7f4..48d1ebe 100644
>> --- a/arch/arm/mach-omap2/common.h
>> +++ b/arch/arm/mach-omap2/common.h
>> @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
>>  #endif
>>  
>>  extern void __init gic_init_irq(void);
>> +extern void gic_dist_disable(void);
>>  extern void omap_smc1(u32 fn, u32 arg);
>>  extern void __iomem *omap4_get_sar_ram_base(void);
>>  extern void omap_do_wfi(void);
>> @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
>>  #ifdef CONFIG_SMP
>>  /* Needed for secondary core boot */
>>  extern void omap_secondary_startup(void);
>> +extern void omap_secondary_startup_4460(void);
>>  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
>>  extern void omap_auxcoreboot_addr(u32 cpu_addr);
>>  extern u32 omap_read_auxcoreboot0(void);
>> diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
>> index 503ac77..d602555 100644
>> --- a/arch/arm/mach-omap2/omap-headsmp.S
>> +++ b/arch/arm/mach-omap2/omap-headsmp.S
>> @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
>>  	b	secondary_startup
>>  ENDPROC(omap_secondary_startup)
>>  
>> +ENTRY(omap_secondary_startup_4460)
>> +hold_2:	ldr	r12,=0x103
>> +	dsb
>> +	smc	#0			@ read from AuxCoreBoot0
>> +	mov	r0, r0, lsr #9
>> +	mrc	p15, 0, r4, c0, c0, 5
>> +	and	r4, r4, #0x0f
>> +	cmp	r0, r4
>> +	bne	hold_2
>> +
>> +	/*
>> +	 * GIC distributor control register has changed between
>> +	 * CortexA9 r1pX and r2pX. The Control Register secure
>> +	 * banked version is now composed of 2 bits:
>> +	 * bit 0 == Secure Enable
>> +	 * bit 1 == Non-Secure Enable
>> +	 * The Non-Secure banked register has not changed
>> +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
>> +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
>> +	 * The workaround must be:
>> +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
>> +	 * the GIC distributor
>> +	 * 2) CPU1 must re-enable the GIC distributor on
>> +	 * it's wakeup path.
>> +	 */
>> +	ldr	r1, =0x48241000
> 
> Why not OMAP44XX_GIC_DIST_BASE for readability sake?
>
Will fix that.

>> +	ldr	r0, [r1]
>> +	orr	r0, #1
>> +	str	r0, [r1]
>> +
>> +	/*
>> +	 * we've been released from the wait loop,secondary_stack
>> +	 * should now contain the SVC stack for this core
>> +	 */
>> +	b	secondary_startup
>> +ENDPROC(omap_secondary_startup_4460)
>> diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> index 13670aa..e02c082 100644
>> --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
>>  	void __iomem *scu_sar_addr;
>>  	void __iomem *wkup_sar_addr;
>>  	void __iomem *l2x0_sar_addr;
>> +	void (*secondary_startup)(void);
>>  };
>>  
>>  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
>> @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
>>  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>>  {
>>  	unsigned int cpu_state = 0;
>> +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
>>  
>>  	if (omap_rev() == OMAP4430_REV_ES1_0)
>>  		return -ENXIO;
>> @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>>  
>>  	clear_cpu_prev_pwrst(cpu);
>>  	set_cpu_next_pwrst(cpu, power_state);
>> -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
>> +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
>>  	scu_pwrst_prepare(cpu, power_state);
>>  
>>  	/*
>> @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
>>  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
>>  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
>>  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
>> +	if (cpu_is_omap446x())
>> +		pm_info->secondary_startup = omap_secondary_startup_4460;
>> +	else
>> +		pm_info->secondary_startup = omap_secondary_startup;
> 
> Does this exist on 4470 too?
>
This OMAP4460 issue only. OMAP4470 ROM code BUG is fixed.

> Using a PM erratum check here instead of cpu_is* would make this more
> scalable.  
> 
> Same comment for the cpu_is* check in wakeup_secondary()
> 
> Then, where the erratum is defined, it should state clearly why this
> affects 446x and not before (presumably because 4430 has r1pX and 4460
> has r2pX.)
> 
Ok

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-16  9:16       ` Santosh Shilimkar
  0 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16  9:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
> Santosh,
> 
> Tero Kristo <t-kristo@ti.com> writes:
> 
>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>
>> GIC distributor control register has changed between CortexA9 r1pX and
>> r2pX. The Control Register secure banked version is now composed of 2
>> bits:
>>      bit 0 == Secure Enable
>>      bit 1 == Non-Secure Enable
>> The Non-Secure banked register has not changed. 
> 
> For those without the r1pX TRM handy, please include what this look like
> before (presumably 1 bit?)  The changelog and in-code comments should
> both be enhanced.
>
You are right. There was only one bit previously which was used for
secure/non-secure mode. So ROM over-writes the non-secure bit
accidentally.

>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>> will cause a problem to CPU0 Non-Secure SW.
> 
> Please describe the problem, so we can better understand the specifics
> of the workaround.
> 
> Also, is there an erratum number for this?
> 
>> The workaround must be:
>>      1) Before doing the CPU1 wakeup, CPU0 must disable
>>         the GIC distributor
>>      2) CPU1 must re-enable the GIC distributor on
>>         it's wakeup path.
> 
> Again, because the problem was not described, I am not entirely sure why
> the workaround "must" be this, and how it fixes the problem.  Remember
> to put yourself in the shoes of a reviewer who has not been deeply
> involved in the code, so what seems obvious to you will not be obvious
> to the reviewer without having to study the code and dig in to the TRMs.
>
Agree and sorry for assuming that the TRM reference should be enough.

>> With this procedure, the GIC configuration done between the
>> CPU0 wakeup and CPU1 wakeup will not be lost but during this
>> short windows, the CPU0 will not receive interrupts
> 
> Hmm, so I guess this means that CPU0 always has to wakeup first, even on GP
> devices? 
> 
Yes. Thats the case otherwise too, on all OMAP4 devices :-(

> Also, the changelog doesn't describe what power states this affects, and
> whether it's an idle problem or just a supend problem.  A quick glance
> at the code suggests that only suspend is being addressed by this patch.
> However, with the addition of coupled CPUidle (coming very soon now),
> won't we have this same problem in idle?  IMO, this patch should address
> both.
> 
MPU OSWR and onwards states only. Will add that info in the changelog.

> This workaround also assumes that you always want CPU1 to wakeup
> immediately after CPU0.  I guess that will be the case for the coupled
> states that would be affected by this bug, but the changelog should
> describe that as well
>
You are right. It does affect couple idle as well. The old idle code
was relying on hotplug path and this fix is in that path which helps
suspend as well as cpuidle with CPU1 hotplug in/out

Actually this BUG is really nasty and the WA is worst.

> Some minor comments below...
> 
>> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
>> Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> ---
>>  arch/arm/mach-omap2/common.h              |    2 +
>>  arch/arm/mach-omap2/omap-headsmp.S        |   36 +++++++++++++++++++++++++++++
>>  arch/arm/mach-omap2/omap-mpuss-lowpower.c |    9 ++++++-
>>  arch/arm/mach-omap2/omap-smp.c            |   28 +++++++++++++++++++++-
>>  arch/arm/mach-omap2/omap4-common.c        |    8 +++++-
>>  5 files changed, 80 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
>> index 57da7f4..48d1ebe 100644
>> --- a/arch/arm/mach-omap2/common.h
>> +++ b/arch/arm/mach-omap2/common.h
>> @@ -199,6 +199,7 @@ static inline void __iomem *omap4_get_scu_base(void)
>>  #endif
>>  
>>  extern void __init gic_init_irq(void);
>> +extern void gic_dist_disable(void);
>>  extern void omap_smc1(u32 fn, u32 arg);
>>  extern void __iomem *omap4_get_sar_ram_base(void);
>>  extern void omap_do_wfi(void);
>> @@ -206,6 +207,7 @@ extern void omap_do_wfi(void);
>>  #ifdef CONFIG_SMP
>>  /* Needed for secondary core boot */
>>  extern void omap_secondary_startup(void);
>> +extern void omap_secondary_startup_4460(void);
>>  extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
>>  extern void omap_auxcoreboot_addr(u32 cpu_addr);
>>  extern u32 omap_read_auxcoreboot0(void);
>> diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
>> index 503ac77..d602555 100644
>> --- a/arch/arm/mach-omap2/omap-headsmp.S
>> +++ b/arch/arm/mach-omap2/omap-headsmp.S
>> @@ -43,3 +43,39 @@ hold:	ldr	r12,=0x103
>>  	b	secondary_startup
>>  ENDPROC(omap_secondary_startup)
>>  
>> +ENTRY(omap_secondary_startup_4460)
>> +hold_2:	ldr	r12,=0x103
>> +	dsb
>> +	smc	#0			@ read from AuxCoreBoot0
>> +	mov	r0, r0, lsr #9
>> +	mrc	p15, 0, r4, c0, c0, 5
>> +	and	r4, r4, #0x0f
>> +	cmp	r0, r4
>> +	bne	hold_2
>> +
>> +	/*
>> +	 * GIC distributor control register has changed between
>> +	 * CortexA9 r1pX and r2pX. The Control Register secure
>> +	 * banked version is now composed of 2 bits:
>> +	 * bit 0 == Secure Enable
>> +	 * bit 1 == Non-Secure Enable
>> +	 * The Non-Secure banked register has not changed
>> +	 * Because the ROM Code is based on the r1pX GIC, the CPU1
>> +	 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
>> +	 * The workaround must be:
>> +	 * 1) Before doing the CPU1 wakeup, CPU0 must disable
>> +	 * the GIC distributor
>> +	 * 2) CPU1 must re-enable the GIC distributor on
>> +	 * it's wakeup path.
>> +	 */
>> +	ldr	r1, =0x48241000
> 
> Why not OMAP44XX_GIC_DIST_BASE for readability sake?
>
Will fix that.

>> +	ldr	r0, [r1]
>> +	orr	r0, #1
>> +	str	r0, [r1]
>> +
>> +	/*
>> +	 * we've been released from the wait loop,secondary_stack
>> +	 * should now contain the SVC stack for this core
>> +	 */
>> +	b	secondary_startup
>> +ENDPROC(omap_secondary_startup_4460)
>> diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> index 13670aa..e02c082 100644
>> --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
>> @@ -68,6 +68,7 @@ struct omap4_cpu_pm_info {
>>  	void __iomem *scu_sar_addr;
>>  	void __iomem *wkup_sar_addr;
>>  	void __iomem *l2x0_sar_addr;
>> +	void (*secondary_startup)(void);
>>  };
>>  
>>  static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
>> @@ -300,6 +301,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
>>  int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>>  {
>>  	unsigned int cpu_state = 0;
>> +	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
>>  
>>  	if (omap_rev() == OMAP4430_REV_ES1_0)
>>  		return -ENXIO;
>> @@ -309,7 +311,7 @@ int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
>>  
>>  	clear_cpu_prev_pwrst(cpu);
>>  	set_cpu_next_pwrst(cpu, power_state);
>> -	set_cpu_wakeup_addr(cpu, virt_to_phys(omap_secondary_startup));
>> +	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
>>  	scu_pwrst_prepare(cpu, power_state);
>>  
>>  	/*
>> @@ -360,6 +362,11 @@ int __init omap4_mpuss_init(void)
>>  	pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
>>  	pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
>>  	pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
>> +	if (cpu_is_omap446x())
>> +		pm_info->secondary_startup = omap_secondary_startup_4460;
>> +	else
>> +		pm_info->secondary_startup = omap_secondary_startup;
> 
> Does this exist on 4470 too?
>
This OMAP4460 issue only. OMAP4470 ROM code BUG is fixed.

> Using a PM erratum check here instead of cpu_is* would make this more
> scalable.  
> 
> Same comment for the cpu_is* check in wakeup_secondary()
> 
> Then, where the erratum is defined, it should state clearly why this
> affects 446x and not before (presumably because 4430 has r1pX and 4460
> has r2pX.)
> 
Ok

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-16  9:16       ` Santosh Shilimkar
@ 2012-05-16 12:23         ` Santosh Shilimkar
  -1 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16 12:23 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

Kevin,

On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>> Santosh,
>>
>> Tero Kristo <t-kristo@ti.com> writes:
>>
>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>
>>> GIC distributor control register has changed between CortexA9 r1pX and
>>> r2pX. The Control Register secure banked version is now composed of 2
>>> bits:
>>>      bit 0 == Secure Enable
>>>      bit 1 == Non-Secure Enable
>>> The Non-Secure banked register has not changed. 
>>
>> For those without the r1pX TRM handy, please include what this look like
>> before (presumably 1 bit?)  The changelog and in-code comments should
>> both be enhanced.
>>
> You are right. There was only one bit previously which was used for
> secure/non-secure mode. So ROM over-writes the non-secure bit
> accidentally.
> 
>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>> will cause a problem to CPU0 Non-Secure SW.
>>
>> Please describe the problem, so we can better understand the specifics
>> of the workaround.
>>
Below is the updated changelog.

--------------
ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
register change

With MPUSS programmed to OSWR(Open Switch retention), GIC context is
lost. On the CPU wakeup paths, ROM code gets executed which will setup
GIC secure configurations and restore the GIC context if it was saved
based on SAR_BACKUP_STATUS.

The ROM Code GIC distributor restoration is split in two parts:
CPU specific register done by each CPU and common register done by
only one CPU. If the GIC Distributor Control Register = 1, the
second CPU will not do the common GIC restoration.

GIC distributor control register has changed between CortexA9 r1pX and
r2pX. The Control Register secure banked version is now composed of 2
bits vs only one bit before r1px:
     bit 0 == Secure Enable
     bit 1 == Non-Secure Enable
Hence the value of Control register will be 3 and not 1 as the r1pX
based ROM code expects. So he CPU1 on it's wakeup ROM code path, will
go to the GIC initialization procedure and will so reset the full GIC
and NS GIC distributor Enable bit will get cleared.
Since the GIC distributor gets disabled in a live system, CPU1 will
hang because the interrupts stop firing.

Workaround for the issue:
     1) Before doing the CPU1 wakeup, CPU0 must disable
        the GIC distributor and wait for it to be enabled.
     2) CPU1 must re-enable the GIC distributor on
        it's wakeup path.

With this procedure, the GIC configuration done between the
CPU0 wakeup and CPU1 wakeup will not be lost but during this
short windows, the CPU0 will not receive interrupts.

The BUG is applicable to only OMAP4460(r2pX) devices.
OMAP4470(r2Px), ROM code is fixed for this BUG.
----------------

Let me know if it clarifies the issue ?

Regards
Santosh


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-16 12:23         ` Santosh Shilimkar
  0 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16 12:23 UTC (permalink / raw)
  To: linux-arm-kernel

Kevin,

On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>> Santosh,
>>
>> Tero Kristo <t-kristo@ti.com> writes:
>>
>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>
>>> GIC distributor control register has changed between CortexA9 r1pX and
>>> r2pX. The Control Register secure banked version is now composed of 2
>>> bits:
>>>      bit 0 == Secure Enable
>>>      bit 1 == Non-Secure Enable
>>> The Non-Secure banked register has not changed. 
>>
>> For those without the r1pX TRM handy, please include what this look like
>> before (presumably 1 bit?)  The changelog and in-code comments should
>> both be enhanced.
>>
> You are right. There was only one bit previously which was used for
> secure/non-secure mode. So ROM over-writes the non-secure bit
> accidentally.
> 
>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>> will cause a problem to CPU0 Non-Secure SW.
>>
>> Please describe the problem, so we can better understand the specifics
>> of the workaround.
>>
Below is the updated changelog.

--------------
ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
register change

With MPUSS programmed to OSWR(Open Switch retention), GIC context is
lost. On the CPU wakeup paths, ROM code gets executed which will setup
GIC secure configurations and restore the GIC context if it was saved
based on SAR_BACKUP_STATUS.

The ROM Code GIC distributor restoration is split in two parts:
CPU specific register done by each CPU and common register done by
only one CPU. If the GIC Distributor Control Register = 1, the
second CPU will not do the common GIC restoration.

GIC distributor control register has changed between CortexA9 r1pX and
r2pX. The Control Register secure banked version is now composed of 2
bits vs only one bit before r1px:
     bit 0 == Secure Enable
     bit 1 == Non-Secure Enable
Hence the value of Control register will be 3 and not 1 as the r1pX
based ROM code expects. So he CPU1 on it's wakeup ROM code path, will
go to the GIC initialization procedure and will so reset the full GIC
and NS GIC distributor Enable bit will get cleared.
Since the GIC distributor gets disabled in a live system, CPU1 will
hang because the interrupts stop firing.

Workaround for the issue:
     1) Before doing the CPU1 wakeup, CPU0 must disable
        the GIC distributor and wait for it to be enabled.
     2) CPU1 must re-enable the GIC distributor on
        it's wakeup path.

With this procedure, the GIC configuration done between the
CPU0 wakeup and CPU1 wakeup will not be lost but during this
short windows, the CPU0 will not receive interrupts.

The BUG is applicable to only OMAP4460(r2pX) devices.
OMAP4470(r2Px), ROM code is fixed for this BUG.
----------------

Let me know if it clarifies the issue ?

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-16 12:31     ` Santosh Shilimkar
  -1 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16 12:31 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, khilman, paul, linux-arm-kernel

Tero,

On Monday 14 May 2012 03:33 PM, Tero Kristo wrote:
> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> 
> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits:
>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable

[..]

> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index deffbf1..c3eb9e8 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -33,6 +33,7 @@
>  
>  /* SCU base address */
>  static void __iomem *scu_base;
> +bool omap4_smp_romcode_errata;
>  
>  static DEFINE_SPINLOCK(boot_lock);
>  
> @@ -104,6 +105,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
>  	 *	4.3.4.2 Power States of CPU0 and CPU1
>  	 */
>  	if (booted) {
> +		/*
> +		 * GIC distributor control register has changed between
> +		 * CortexA9 r1pX and r2pX. The Control Register secure
> +		 * banked version is now composed of 2 bits:
> +		 * bit 0 == Secure Enable
> +		 * bit 1 == Non-Secure Enable
> +		 * The Non-Secure banked register has not changed
> +		 * Because the ROM Code is based on the r1pX GIC, the CPU1
> +		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> +		 * The workaround must be:
> +		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> +		 * the GIC distributor
> +		 * 2) CPU1 must re-enable the GIC distributor on
> +		 * it's wakeup path.
> +		 */
> +		if (omap4_smp_romcode_errata)
For safety, disable local IRQ here.
		local_irq_disable();
> +			gic_dist_disable();
> +
And CPU0 needs to wait here till CPU1 re-enables the distributor
to avoid any random issues.

The BUG is applicable for CPUIDLE as well with MPUSS OSWR state, but
we can fix the idle in another patch to avoid dependency.
Basically above 3 lines should also be part of idle code where we
wakeup the CPU1 using force wakeup.

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-16 12:31     ` Santosh Shilimkar
  0 siblings, 0 replies; 56+ messages in thread
From: Santosh Shilimkar @ 2012-05-16 12:31 UTC (permalink / raw)
  To: linux-arm-kernel

Tero,

On Monday 14 May 2012 03:33 PM, Tero Kristo wrote:
> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
> 
> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits:
>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable

[..]

> diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
> index deffbf1..c3eb9e8 100644
> --- a/arch/arm/mach-omap2/omap-smp.c
> +++ b/arch/arm/mach-omap2/omap-smp.c
> @@ -33,6 +33,7 @@
>  
>  /* SCU base address */
>  static void __iomem *scu_base;
> +bool omap4_smp_romcode_errata;
>  
>  static DEFINE_SPINLOCK(boot_lock);
>  
> @@ -104,6 +105,24 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
>  	 *	4.3.4.2 Power States of CPU0 and CPU1
>  	 */
>  	if (booted) {
> +		/*
> +		 * GIC distributor control register has changed between
> +		 * CortexA9 r1pX and r2pX. The Control Register secure
> +		 * banked version is now composed of 2 bits:
> +		 * bit 0 == Secure Enable
> +		 * bit 1 == Non-Secure Enable
> +		 * The Non-Secure banked register has not changed
> +		 * Because the ROM Code is based on the r1pX GIC, the CPU1
> +		 * GIC restoration will cause a problem to CPU0 Non-Secure SW.
> +		 * The workaround must be:
> +		 * 1) Before doing the CPU1 wakeup, CPU0 must disable
> +		 * the GIC distributor
> +		 * 2) CPU1 must re-enable the GIC distributor on
> +		 * it's wakeup path.
> +		 */
> +		if (omap4_smp_romcode_errata)
For safety, disable local IRQ here.
		local_irq_disable();
> +			gic_dist_disable();
> +
And CPU0 needs to wait here till CPU1 re-enables the distributor
to avoid any random issues.

The BUG is applicable for CPUIDLE as well with MPUSS OSWR state, but
we can fix the idle in another patch to avoid dependency.
Basically above 3 lines should also be part of idle code where we
wakeup the CPU1 using force wakeup.

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-16 12:23         ` Santosh Shilimkar
@ 2012-05-16 16:51           ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-16 16:51 UTC (permalink / raw)
  To: Santosh Shilimkar; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> Kevin,
>
> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>> Santosh,
>>>
>>> Tero Kristo <t-kristo@ti.com> writes:
>>>
>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>
>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>> bits:
>>>>      bit 0 == Secure Enable
>>>>      bit 1 == Non-Secure Enable
>>>> The Non-Secure banked register has not changed. 
>>>
>>> For those without the r1pX TRM handy, please include what this look like
>>> before (presumably 1 bit?)  The changelog and in-code comments should
>>> both be enhanced.
>>>
>> You are right. There was only one bit previously which was used for
>> secure/non-secure mode. So ROM over-writes the non-secure bit
>> accidentally.
>> 
>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>> will cause a problem to CPU0 Non-Secure SW.
>>>
>>> Please describe the problem, so we can better understand the specifics
>>> of the workaround.
>>>
> Below is the updated changelog.

Much better, thanks.  But it still took me several reads to fully
understand.  Maybe it's because the cold I have is stuffing up my head,
so it takes me awhile to understand...  Anyways, some minor comments to
help clarify...

Sorry to be so picky about changelogs, but this is a really nasty bug,
and the workaround has some rather important side effects, so I want the
description of the bug and the workaround to be well described.

> --------------
> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
> register change
>
> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
> lost. On the CPU wakeup paths, ROM code gets executed which will setup
> GIC secure configurations and restore the GIC context if it was saved
> based on SAR_BACKUP_STATUS.
>
> The ROM Code GIC distributor restoration is split in two parts:
> CPU specific register done by each CPU and common register done by
> only one CPU. If the GIC Distributor Control Register = 1, the
> second CPU will not do the common GIC restoration.

s/second CPU/second CPU to wake up/

> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits vs only one bit before r1px:

before r1pX?  

>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable

And what did this look like for r1pX?    Presumably bit0 was non-secure
enable?

> Hence the value of Control register will be 3 and not 1 as the r1pX
> based ROM code expects. 

Why will it be 3?

Will it be 3 on GP devices?

> So he CPU1 on it's wakeup ROM code path, will

s/it's/its/

> go to the GIC initialization procedure and will so reset the full GIC
> and NS GIC distributor Enable bit will get cleared.

This is where it's confusing.

On r2pX, NS enable bit is bit 1.  It's not mentioned here, but I'm
assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
TRM)

Since ROM code is r1pX-based, I would assume that it would continue to
clear bit 0, which is only now the secure enable bit?

Or, is it the case that ROM code clears all the bits?  That should be described.

> Since the GIC distributor gets disabled in a live system, CPU1 will
> hang because the interrupts stop firing.
>      1) Before doing the CPU1 wakeup, CPU0 must disable
>         the GIC distributor and wait for it to be enabled.

what does 'disable GIC distributor' mean.  secure? non-secure? both?

>      2) CPU1 must re-enable the GIC distributor on
>         it's wakeup path.

Describe why this works.  e.g. because it cause ROM code to skip its
broken restore path.

> With this procedure, the GIC configuration done between the
> CPU0 wakeup and CPU1 wakeup will not be lost but during this
> short windows, the CPU0 will not receive interrupts.
>
> The BUG is applicable to only OMAP4460(r2pX) devices.
> OMAP4470(r2Px), ROM code is fixed for this BUG.

OMAP4470 (also r2pX) is not affected by this bug because ROM code has
been fixed.

Kevin

> ----------------
>
> Let me know if it clarifies the issue ?
>
> Regards
> Santosh
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-16 16:51           ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-16 16:51 UTC (permalink / raw)
  To: linux-arm-kernel

Santosh Shilimkar <santosh.shilimkar@ti.com> writes:

> Kevin,
>
> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>> Santosh,
>>>
>>> Tero Kristo <t-kristo@ti.com> writes:
>>>
>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>
>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>> bits:
>>>>      bit 0 == Secure Enable
>>>>      bit 1 == Non-Secure Enable
>>>> The Non-Secure banked register has not changed. 
>>>
>>> For those without the r1pX TRM handy, please include what this look like
>>> before (presumably 1 bit?)  The changelog and in-code comments should
>>> both be enhanced.
>>>
>> You are right. There was only one bit previously which was used for
>> secure/non-secure mode. So ROM over-writes the non-secure bit
>> accidentally.
>> 
>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>> will cause a problem to CPU0 Non-Secure SW.
>>>
>>> Please describe the problem, so we can better understand the specifics
>>> of the workaround.
>>>
> Below is the updated changelog.

Much better, thanks.  But it still took me several reads to fully
understand.  Maybe it's because the cold I have is stuffing up my head,
so it takes me awhile to understand...  Anyways, some minor comments to
help clarify...

Sorry to be so picky about changelogs, but this is a really nasty bug,
and the workaround has some rather important side effects, so I want the
description of the bug and the workaround to be well described.

> --------------
> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
> register change
>
> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
> lost. On the CPU wakeup paths, ROM code gets executed which will setup
> GIC secure configurations and restore the GIC context if it was saved
> based on SAR_BACKUP_STATUS.
>
> The ROM Code GIC distributor restoration is split in two parts:
> CPU specific register done by each CPU and common register done by
> only one CPU. If the GIC Distributor Control Register = 1, the
> second CPU will not do the common GIC restoration.

s/second CPU/second CPU to wake up/

> GIC distributor control register has changed between CortexA9 r1pX and
> r2pX. The Control Register secure banked version is now composed of 2
> bits vs only one bit before r1px:

before r1pX?  

>      bit 0 == Secure Enable
>      bit 1 == Non-Secure Enable

And what did this look like for r1pX?    Presumably bit0 was non-secure
enable?

> Hence the value of Control register will be 3 and not 1 as the r1pX
> based ROM code expects. 

Why will it be 3?

Will it be 3 on GP devices?

> So he CPU1 on it's wakeup ROM code path, will

s/it's/its/

> go to the GIC initialization procedure and will so reset the full GIC
> and NS GIC distributor Enable bit will get cleared.

This is where it's confusing.

On r2pX, NS enable bit is bit 1.  It's not mentioned here, but I'm
assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
TRM)

Since ROM code is r1pX-based, I would assume that it would continue to
clear bit 0, which is only now the secure enable bit?

Or, is it the case that ROM code clears all the bits?  That should be described.

> Since the GIC distributor gets disabled in a live system, CPU1 will
> hang because the interrupts stop firing.
>      1) Before doing the CPU1 wakeup, CPU0 must disable
>         the GIC distributor and wait for it to be enabled.

what does 'disable GIC distributor' mean.  secure? non-secure? both?

>      2) CPU1 must re-enable the GIC distributor on
>         it's wakeup path.

Describe why this works.  e.g. because it cause ROM code to skip its
broken restore path.

> With this procedure, the GIC configuration done between the
> CPU0 wakeup and CPU1 wakeup will not be lost but during this
> short windows, the CPU0 will not receive interrupts.
>
> The BUG is applicable to only OMAP4460(r2pX) devices.
> OMAP4470(r2Px), ROM code is fixed for this BUG.

OMAP4470 (also r2pX) is not affected by this bug because ROM code has
been fixed.

Kevin

> ----------------
>
> Let me know if it clarifies the issue ?
>
> Regards
> Santosh
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
  2012-05-16  9:10       ` Tero Kristo
@ 2012-05-16 18:03         ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-16 18:03 UTC (permalink / raw)
  To: t-kristo; +Cc: linux-omap, paul, linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> On Tue, 2012-05-15 at 15:41 -0700, Kevin Hilman wrote:
>> Tero Kristo <t-kristo@ti.com> writes:
>> 
>> > PM debug now contains a file that can be used to control OSWR support
>> > enable / disable on OMAP4. Also removed the off_mode_enable file for
>> > the same platform as it is unsupported.
>> >>
>> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> 
>> I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
>> not interested managing another new flag for OSWR.
>> 
>> For OMAP4, this should just be the default, and any drivers that are
>> broken just need to be fixed either by implementing context save/restore
>> or by using constraints.
>
> Well, it is not flag as such, as it is static variable internal to
> pm-debug.c. I could drop this, however it is extremely useful as a
> testing feature. Without this, it is difficult to test CSWR / OSWR. 

I understand its usefulness for testing (and I will use it to test this
series), but IMO it should live out of tree.  Having this in tree makes
it possible for drivers to be merged that don't support off-mode.  I
added this flag to OMAP3 as a short-term feature hoping that drivers
would eventually be converted, and I was wrong.  We still have drivers
that don't support off-mode upstream.  I don't want to make that mistake
again.

> If you have taken a look at the device-off set, I am actually adding
> the flag back for omap4 there for enabling device off. If this flag is
> also dropped, the device will always just go to device off, in which
> case testing CSWR / OSWR becomes an issue again, and I don't think
> this is ideal.
>
> Speaking of enable_off_mode, it might be possible to change it also be
> static and remove all the references to it from code. Currently it is
> only used from cpuidle34xx.c.

I would prefer to get rid of all of these flags, and use the new sysfs
controls[1] for CPUidle C-states to disable/enable certain C-states for
debugging/testing.

Kevin

[1] Example shell snippet using new sysfs interface:

# CPUidle: disable everything but C1
cd /sys/devices/system/cpu/cpu0/cpuidle
for state in state[1-6]*; do
  if [ -e ${state} ]; then
    echo 1 > ${state}/disable
  fi
done


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR
@ 2012-05-16 18:03         ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-16 18:03 UTC (permalink / raw)
  To: linux-arm-kernel

Tero Kristo <t-kristo@ti.com> writes:

> On Tue, 2012-05-15 at 15:41 -0700, Kevin Hilman wrote:
>> Tero Kristo <t-kristo@ti.com> writes:
>> 
>> > PM debug now contains a file that can be used to control OSWR support
>> > enable / disable on OMAP4. Also removed the off_mode_enable file for
>> > the same platform as it is unsupported.
>> >>
>> > Signed-off-by: Tero Kristo <t-kristo@ti.com>
>> 
>> I'll gladly take a patch that makes enable_off_mode OMAP3-only, but I am
>> not interested managing another new flag for OSWR.
>> 
>> For OMAP4, this should just be the default, and any drivers that are
>> broken just need to be fixed either by implementing context save/restore
>> or by using constraints.
>
> Well, it is not flag as such, as it is static variable internal to
> pm-debug.c. I could drop this, however it is extremely useful as a
> testing feature. Without this, it is difficult to test CSWR / OSWR. 

I understand its usefulness for testing (and I will use it to test this
series), but IMO it should live out of tree.  Having this in tree makes
it possible for drivers to be merged that don't support off-mode.  I
added this flag to OMAP3 as a short-term feature hoping that drivers
would eventually be converted, and I was wrong.  We still have drivers
that don't support off-mode upstream.  I don't want to make that mistake
again.

> If you have taken a look at the device-off set, I am actually adding
> the flag back for omap4 there for enabling device off. If this flag is
> also dropped, the device will always just go to device off, in which
> case testing CSWR / OSWR becomes an issue again, and I don't think
> this is ideal.
>
> Speaking of enable_off_mode, it might be possible to change it also be
> static and remove all the references to it from code. Currently it is
> only used from cpuidle34xx.c.

I would prefer to get rid of all of these flags, and use the new sysfs
controls[1] for CPUidle C-states to disable/enable certain C-states for
debugging/testing.

Kevin

[1] Example shell snippet using new sysfs interface:

# CPUidle: disable everything but C1
cd /sys/devices/system/cpu/cpu0/cpuidle
for state in state[1-6]*; do
  if [ -e ${state} ]; then
    echo 1 > ${state}/disable
  fi
done

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-16 16:51           ` Kevin Hilman
@ 2012-05-17  6:46             ` Shilimkar, Santosh
  -1 siblings, 0 replies; 56+ messages in thread
From: Shilimkar, Santosh @ 2012-05-17  6:46 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
>> Kevin,
>>
>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>> Santosh,
>>>>
>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>
>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>
>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>> bits:
>>>>>      bit 0 == Secure Enable
>>>>>      bit 1 == Non-Secure Enable
>>>>> The Non-Secure banked register has not changed.
>>>>
>>>> For those without the r1pX TRM handy, please include what this look like
>>>> before (presumably 1 bit?)  The changelog and in-code comments should
>>>> both be enhanced.
>>>>
>>> You are right. There was only one bit previously which was used for
>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>> accidentally.
>>>
>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>
>>>> Please describe the problem, so we can better understand the specifics
>>>> of the workaround.
>>>>
>> Below is the updated changelog.
>
> Much better, thanks.  But it still took me several reads to fully
> understand.  Maybe it's because the cold I have is stuffing up my head,
> so it takes me awhile to understand...  Anyways, some minor comments to
> help clarify...
>
> Sorry to be so picky about changelogs, but this is a really nasty bug,
> and the workaround has some rather important side effects, so I want the
> description of the bug and the workaround to be well described.
>
>> --------------
>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>> register change
>>
>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>> GIC secure configurations and restore the GIC context if it was saved
>> based on SAR_BACKUP_STATUS.
>>
>> The ROM Code GIC distributor restoration is split in two parts:
>> CPU specific register done by each CPU and common register done by
>> only one CPU. If the GIC Distributor Control Register = 1, the
>> second CPU will not do the common GIC restoration.
>
> s/second CPU/second CPU to wake up/
>
ok
>> GIC distributor control register has changed between CortexA9 r1pX and
>> r2pX. The Control Register secure banked version is now composed of 2
>> bits vs only one bit before r1px:
>
> before r1pX?
I mean r1px, r0px etc.

>
>>      bit 0 == Secure Enable
>>      bit 1 == Non-Secure Enable
>
> And what did this look like for r1pX?    Presumably bit0 was non-secure
> enable?
>
Yes. Same bit is used. It's banked bit which has secure and non-secure view.

>> Hence the value of Control register will be 3 and not 1 as the r1pX
>> based ROM code expects.
>
> Why will it be 3?
>
> Will it be 3 on GP devices?
>
Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
be set by ROM code]
and bit 0 will be set by Linux.

>> So he CPU1 on it's wakeup ROM code path, will
>
> s/it's/its/
>
ok
>> go to the GIC initialization procedure and will so reset the full GIC
>> and NS GIC distributor Enable bit will get cleared.
>
> This is where it's confusing.
>
Hmm.

> On r2pX, NS enable bit is bit 1.  It's not mentioned here, but I'm
> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
> TRM)
>
Yes. As I mentioned earlier, will make that more clear.

> Since ROM code is r1pX-based, I would assume that it would continue to
> clear bit 0, which is only now the secure enable bit?
>
> Or, is it the case that ROM code clears all the bits?  That should be described.
>
ROM code reads the register value and compares it with value == 1
" If the GIC Distributor Control Register = 1, the
second CPU will not do the common GIC restoration"
On r2Px, the value becomes 3 and entire ROM code logic goofs up
and take wrong code path.

>> Since the GIC distributor gets disabled in a live system, CPU1 will
>> hang because the interrupts stop firing.
>>      1) Before doing the CPU1 wakeup, CPU0 must disable
>>         the GIC distributor and wait for it to be enabled.
>
> what does 'disable GIC distributor' mean.  secure? non-secure? both?
>
HLOS is a non-secure view so it can disable only non-secure bit.

>>      2) CPU1 must re-enable the GIC distributor on
>>         it's wakeup path.
>
> Describe why this works.  e.g. because it cause ROM code to skip its
> broken restore path.
>
ROM code logic find the control register value 1 because bit 1 is
cleared by non-secure SW during the check.

>> With this procedure, the GIC configuration done between the
>> CPU0 wakeup and CPU1 wakeup will not be lost but during this
>> short windows, the CPU0 will not receive interrupts.
>>
>> The BUG is applicable to only OMAP4460(r2pX) devices.
>> OMAP4470(r2Px), ROM code is fixed for this BUG.
>
> OMAP4470 (also r2pX) is not affected by this bug because ROM code has
> been fixed.
>
Ok

Regards
Santosh
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-17  6:46             ` Shilimkar, Santosh
  0 siblings, 0 replies; 56+ messages in thread
From: Shilimkar, Santosh @ 2012-05-17  6:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>
>> Kevin,
>>
>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>> Santosh,
>>>>
>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>
>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>
>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>> bits:
>>>>> ? ? ?bit 0 == Secure Enable
>>>>> ? ? ?bit 1 == Non-Secure Enable
>>>>> The Non-Secure banked register has not changed.
>>>>
>>>> For those without the r1pX TRM handy, please include what this look like
>>>> before (presumably 1 bit?) ?The changelog and in-code comments should
>>>> both be enhanced.
>>>>
>>> You are right. There was only one bit previously which was used for
>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>> accidentally.
>>>
>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>
>>>> Please describe the problem, so we can better understand the specifics
>>>> of the workaround.
>>>>
>> Below is the updated changelog.
>
> Much better, thanks. ?But it still took me several reads to fully
> understand. ?Maybe it's because the cold I have is stuffing up my head,
> so it takes me awhile to understand... ?Anyways, some minor comments to
> help clarify...
>
> Sorry to be so picky about changelogs, but this is a really nasty bug,
> and the workaround has some rather important side effects, so I want the
> description of the bug and the workaround to be well described.
>
>> --------------
>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>> register change
>>
>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>> GIC secure configurations and restore the GIC context if it was saved
>> based on SAR_BACKUP_STATUS.
>>
>> The ROM Code GIC distributor restoration is split in two parts:
>> CPU specific register done by each CPU and common register done by
>> only one CPU. If the GIC Distributor Control Register = 1, the
>> second CPU will not do the common GIC restoration.
>
> s/second CPU/second CPU to wake up/
>
ok
>> GIC distributor control register has changed between CortexA9 r1pX and
>> r2pX. The Control Register secure banked version is now composed of 2
>> bits vs only one bit before r1px:
>
> before r1pX?
I mean r1px, r0px etc.

>
>> ? ? ?bit 0 == Secure Enable
>> ? ? ?bit 1 == Non-Secure Enable
>
> And what did this look like for r1pX? ? ?Presumably bit0 was non-secure
> enable?
>
Yes. Same bit is used. It's banked bit which has secure and non-secure view.

>> Hence the value of Control register will be 3 and not 1 as the r1pX
>> based ROM code expects.
>
> Why will it be 3?
>
> Will it be 3 on GP devices?
>
Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
be set by ROM code]
and bit 0 will be set by Linux.

>> So he CPU1 on it's wakeup ROM code path, will
>
> s/it's/its/
>
ok
>> go to the GIC initialization procedure and will so reset the full GIC
>> and NS GIC distributor Enable bit will get cleared.
>
> This is where it's confusing.
>
Hmm.

> On r2pX, NS enable bit is bit 1. ?It's not mentioned here, but I'm
> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
> TRM)
>
Yes. As I mentioned earlier, will make that more clear.

> Since ROM code is r1pX-based, I would assume that it would continue to
> clear bit 0, which is only now the secure enable bit?
>
> Or, is it the case that ROM code clears all the bits? ?That should be described.
>
ROM code reads the register value and compares it with value == 1
" If the GIC Distributor Control Register = 1, the
second CPU will not do the common GIC restoration"
On r2Px, the value becomes 3 and entire ROM code logic goofs up
and take wrong code path.

>> Since the GIC distributor gets disabled in a live system, CPU1 will
>> hang because the interrupts stop firing.
>> ? ? ?1) Before doing the CPU1 wakeup, CPU0 must disable
>> ? ? ? ? the GIC distributor and wait for it to be enabled.
>
> what does 'disable GIC distributor' mean. ?secure? non-secure? both?
>
HLOS is a non-secure view so it can disable only non-secure bit.

>> ? ? ?2) CPU1 must re-enable the GIC distributor on
>> ? ? ? ? it's wakeup path.
>
> Describe why this works. ?e.g. because it cause ROM code to skip its
> broken restore path.
>
ROM code logic find the control register value 1 because bit 1 is
cleared by non-secure SW during the check.

>> With this procedure, the GIC configuration done between the
>> CPU0 wakeup and CPU1 wakeup will not be lost but during this
>> short windows, the CPU0 will not receive interrupts.
>>
>> The BUG is applicable to only OMAP4460(r2pX) devices.
>> OMAP4470(r2Px), ROM code is fixed for this BUG.
>
> OMAP4470 (also r2pX) is not affected by this bug because ROM code has
> been fixed.
>
Ok

Regards
Santosh

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-17  6:46             ` Shilimkar, Santosh
@ 2012-05-17 17:15               ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-17 17:15 UTC (permalink / raw)
  To: Shilimkar, Santosh; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

"Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:

> On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>
>>> Kevin,
>>>
>>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>>> Santosh,
>>>>>
>>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>>
>>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>>
>>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>>> bits:
>>>>>>      bit 0 == Secure Enable
>>>>>>      bit 1 == Non-Secure Enable
>>>>>> The Non-Secure banked register has not changed.
>>>>>
>>>>> For those without the r1pX TRM handy, please include what this look like
>>>>> before (presumably 1 bit?)  The changelog and in-code comments should
>>>>> both be enhanced.
>>>>>
>>>> You are right. There was only one bit previously which was used for
>>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>>> accidentally.
>>>>
>>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>>
>>>>> Please describe the problem, so we can better understand the specifics
>>>>> of the workaround.
>>>>>
>>> Below is the updated changelog.
>>
>> Much better, thanks.  But it still took me several reads to fully
>> understand.  Maybe it's because the cold I have is stuffing up my head,
>> so it takes me awhile to understand...  Anyways, some minor comments to
>> help clarify...
>>
>> Sorry to be so picky about changelogs, but this is a really nasty bug,
>> and the workaround has some rather important side effects, so I want the
>> description of the bug and the workaround to be well described.
>>
>>> --------------
>>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>>> register change
>>>
>>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>>> GIC secure configurations and restore the GIC context if it was saved
>>> based on SAR_BACKUP_STATUS.
>>>
>>> The ROM Code GIC distributor restoration is split in two parts:
>>> CPU specific register done by each CPU and common register done by
>>> only one CPU. If the GIC Distributor Control Register = 1, the
>>> second CPU will not do the common GIC restoration.
>>
>> s/second CPU/second CPU to wake up/
>>
> ok
>>> GIC distributor control register has changed between CortexA9 r1pX and
>>> r2pX. The Control Register secure banked version is now composed of 2
>>> bits vs only one bit before r1px:
>>
>> before r1pX?
> I mean r1px, r0px etc.
>>
>>>      bit 0 == Secure Enable
>>>      bit 1 == Non-Secure Enable
>>
>> And what did this look like for r1pX?    Presumably bit0 was non-secure
>> enable?
>>
> Yes. Same bit is used. It's banked bit which has secure and non-secure view.
>
>>> Hence the value of Control register will be 3 and not 1 as the r1pX
>>> based ROM code expects.
>>
>> Why will it be 3?
>>
>> Will it be 3 on GP devices?
>>
> Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
> be set by ROM code]
> and bit 0 will be set by Linux.

Why will the secure enable bit be set on GP devices?

>>> So he CPU1 on it's wakeup ROM code path, will
>>
>> s/it's/its/
>>
> ok
>>> go to the GIC initialization procedure and will so reset the full GIC
>>> and NS GIC distributor Enable bit will get cleared.
>>
>> This is where it's confusing.
>>
> Hmm.
>
>> On r2pX, NS enable bit is bit 1.  It's not mentioned here, but I'm
>> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
>> TRM)
>>
> Yes. As I mentioned earlier, will make that more clear.
>
>> Since ROM code is r1pX-based, I would assume that it would continue to
>> clear bit 0, which is only now the secure enable bit?
>>
>> Or, is it the case that ROM code clears all the bits?  That should be described.
>>
> ROM code reads the register value and compares it with value == 1
> " If the GIC Distributor Control Register = 1, the
> second CPU will not do the common GIC restoration"
> On r2Px, the value becomes 3 and entire ROM code logic goofs up
> and take wrong code path.

That part is clear.  

What's not at all clear is what the ROM code does *after* this.  Does it
clear both bits?  or just bit 0?  Since it's r1pX based, I would expect
that it doesn't touch anything other than bit 0.

>>> Since the GIC distributor gets disabled in a live system, CPU1 will
>>> hang because the interrupts stop firing.
>>>      1) Before doing the CPU1 wakeup, CPU0 must disable
>>>         the GIC distributor and wait for it to be enabled.
>>
>> what does 'disable GIC distributor' mean.  secure? non-secure? both?
>>
> HLOS is a non-secure view so it can disable only non-secure bit.

The changelog is not talking about the HLOS, it's talking about the ROM
code, which presumably can set/clear both bits.

>>>      2) CPU1 must re-enable the GIC distributor on
>>>         it's wakeup path.
>>
>> Describe why this works.  e.g. because it cause ROM code to skip its
>> broken restore path.
>>
> ROM code logic find the control register value 1 because bit 1 is
> cleared by non-secure SW during the check.

and because it finds the control regster value to be 1...

Santosh, I do understand what is happening here.  But I play dumb so
that it will be described in great detail in the changelog so that when
I forget (and you forget) we can go back to this and get a quick
understanding of both the bug and the workaround.

Since you are very deeply familiar with this bug, it's understandably
hard to write this changelog since most things probably seem obvious to
you.  A suggestion would be to have a few colleagues that are not
familiar with this bug read the changelog and try and describe it back
to you.

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-17 17:15               ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-17 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

"Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:

> On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>
>>> Kevin,
>>>
>>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>>> Santosh,
>>>>>
>>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>>
>>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>>
>>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>>> bits:
>>>>>> ? ? ?bit 0 == Secure Enable
>>>>>> ? ? ?bit 1 == Non-Secure Enable
>>>>>> The Non-Secure banked register has not changed.
>>>>>
>>>>> For those without the r1pX TRM handy, please include what this look like
>>>>> before (presumably 1 bit?) ?The changelog and in-code comments should
>>>>> both be enhanced.
>>>>>
>>>> You are right. There was only one bit previously which was used for
>>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>>> accidentally.
>>>>
>>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>>
>>>>> Please describe the problem, so we can better understand the specifics
>>>>> of the workaround.
>>>>>
>>> Below is the updated changelog.
>>
>> Much better, thanks. ?But it still took me several reads to fully
>> understand. ?Maybe it's because the cold I have is stuffing up my head,
>> so it takes me awhile to understand... ?Anyways, some minor comments to
>> help clarify...
>>
>> Sorry to be so picky about changelogs, but this is a really nasty bug,
>> and the workaround has some rather important side effects, so I want the
>> description of the bug and the workaround to be well described.
>>
>>> --------------
>>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>>> register change
>>>
>>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>>> GIC secure configurations and restore the GIC context if it was saved
>>> based on SAR_BACKUP_STATUS.
>>>
>>> The ROM Code GIC distributor restoration is split in two parts:
>>> CPU specific register done by each CPU and common register done by
>>> only one CPU. If the GIC Distributor Control Register = 1, the
>>> second CPU will not do the common GIC restoration.
>>
>> s/second CPU/second CPU to wake up/
>>
> ok
>>> GIC distributor control register has changed between CortexA9 r1pX and
>>> r2pX. The Control Register secure banked version is now composed of 2
>>> bits vs only one bit before r1px:
>>
>> before r1pX?
> I mean r1px, r0px etc.
>>
>>> ? ? ?bit 0 == Secure Enable
>>> ? ? ?bit 1 == Non-Secure Enable
>>
>> And what did this look like for r1pX? ? ?Presumably bit0 was non-secure
>> enable?
>>
> Yes. Same bit is used. It's banked bit which has secure and non-secure view.
>
>>> Hence the value of Control register will be 3 and not 1 as the r1pX
>>> based ROM code expects.
>>
>> Why will it be 3?
>>
>> Will it be 3 on GP devices?
>>
> Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
> be set by ROM code]
> and bit 0 will be set by Linux.

Why will the secure enable bit be set on GP devices?

>>> So he CPU1 on it's wakeup ROM code path, will
>>
>> s/it's/its/
>>
> ok
>>> go to the GIC initialization procedure and will so reset the full GIC
>>> and NS GIC distributor Enable bit will get cleared.
>>
>> This is where it's confusing.
>>
> Hmm.
>
>> On r2pX, NS enable bit is bit 1. ?It's not mentioned here, but I'm
>> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
>> TRM)
>>
> Yes. As I mentioned earlier, will make that more clear.
>
>> Since ROM code is r1pX-based, I would assume that it would continue to
>> clear bit 0, which is only now the secure enable bit?
>>
>> Or, is it the case that ROM code clears all the bits? ?That should be described.
>>
> ROM code reads the register value and compares it with value == 1
> " If the GIC Distributor Control Register = 1, the
> second CPU will not do the common GIC restoration"
> On r2Px, the value becomes 3 and entire ROM code logic goofs up
> and take wrong code path.

That part is clear.  

What's not at all clear is what the ROM code does *after* this.  Does it
clear both bits?  or just bit 0?  Since it's r1pX based, I would expect
that it doesn't touch anything other than bit 0.

>>> Since the GIC distributor gets disabled in a live system, CPU1 will
>>> hang because the interrupts stop firing.
>>> ? ? ?1) Before doing the CPU1 wakeup, CPU0 must disable
>>> ? ? ? ? the GIC distributor and wait for it to be enabled.
>>
>> what does 'disable GIC distributor' mean. ?secure? non-secure? both?
>>
> HLOS is a non-secure view so it can disable only non-secure bit.

The changelog is not talking about the HLOS, it's talking about the ROM
code, which presumably can set/clear both bits.

>>> ? ? ?2) CPU1 must re-enable the GIC distributor on
>>> ? ? ? ? it's wakeup path.
>>
>> Describe why this works. ?e.g. because it cause ROM code to skip its
>> broken restore path.
>>
> ROM code logic find the control register value 1 because bit 1 is
> cleared by non-secure SW during the check.

and because it finds the control regster value to be 1...

Santosh, I do understand what is happening here.  But I play dumb so
that it will be described in great detail in the changelog so that when
I forget (and you forget) we can go back to this and get a quick
understanding of both the bug and the workaround.

Since you are very deeply familiar with this bug, it's understandably
hard to write this changelog since most things probably seem obvious to
you.  A suggestion would be to have a few colleagues that are not
familiar with this bug read the changelog and try and describe it back
to you.

Kevin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-17 17:15               ` Kevin Hilman
@ 2012-05-18  6:05                 ` Shilimkar, Santosh
  -1 siblings, 0 replies; 56+ messages in thread
From: Shilimkar, Santosh @ 2012-05-18  6:05 UTC (permalink / raw)
  To: Kevin Hilman; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

On Thu, May 17, 2012 at 10:45 PM, Kevin Hilman <khilman@ti.com> wrote:
> "Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:
>
>> On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
>>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>>
>>>> Kevin,
>>>>
>>>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>>>> Santosh,
>>>>>>
>>>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>>>
>>>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>>>
>>>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>>>> bits:
>>>>>>>      bit 0 == Secure Enable
>>>>>>>      bit 1 == Non-Secure Enable
>>>>>>> The Non-Secure banked register has not changed.
>>>>>>
>>>>>> For those without the r1pX TRM handy, please include what this look like
>>>>>> before (presumably 1 bit?)  The changelog and in-code comments should
>>>>>> both be enhanced.
>>>>>>
>>>>> You are right. There was only one bit previously which was used for
>>>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>>>> accidentally.
>>>>>
>>>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>>>
>>>>>> Please describe the problem, so we can better understand the specifics
>>>>>> of the workaround.
>>>>>>
>>>> Below is the updated changelog.
>>>
>>> Much better, thanks.  But it still took me several reads to fully
>>> understand.  Maybe it's because the cold I have is stuffing up my head,
>>> so it takes me awhile to understand...  Anyways, some minor comments to
>>> help clarify...
>>>
>>> Sorry to be so picky about changelogs, but this is a really nasty bug,
>>> and the workaround has some rather important side effects, so I want the
>>> description of the bug and the workaround to be well described.
>>>
>>>> --------------
>>>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>>>> register change
>>>>
>>>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>>>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>>>> GIC secure configurations and restore the GIC context if it was saved
>>>> based on SAR_BACKUP_STATUS.
>>>>
>>>> The ROM Code GIC distributor restoration is split in two parts:
>>>> CPU specific register done by each CPU and common register done by
>>>> only one CPU. If the GIC Distributor Control Register = 1, the
>>>> second CPU will not do the common GIC restoration.
>>>
>>> s/second CPU/second CPU to wake up/
>>>
>> ok
>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>> bits vs only one bit before r1px:
>>>
>>> before r1pX?
>> I mean r1px, r0px etc.
>>>
>>>>      bit 0 == Secure Enable
>>>>      bit 1 == Non-Secure Enable
>>>
>>> And what did this look like for r1pX?    Presumably bit0 was non-secure
>>> enable?
>>>
>> Yes. Same bit is used. It's banked bit which has secure and non-secure view.
>>
>>>> Hence the value of Control register will be 3 and not 1 as the r1pX
>>>> based ROM code expects.
>>>
>>> Why will it be 3?
>>>
>>> Will it be 3 on GP devices?
>>>
>> Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
>> be set by ROM code]
>> and bit 0 will be set by Linux.
>
> Why will the secure enable bit be set on GP devices?
>
>>>> So he CPU1 on it's wakeup ROM code path, will
>>>
>>> s/it's/its/
>>>
>> ok
>>>> go to the GIC initialization procedure and will so reset the full GIC
>>>> and NS GIC distributor Enable bit will get cleared.
>>>
>>> This is where it's confusing.
>>>
>> Hmm.
>>
>>> On r2pX, NS enable bit is bit 1.  It's not mentioned here, but I'm
>>> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
>>> TRM)
>>>
>> Yes. As I mentioned earlier, will make that more clear.
>>
>>> Since ROM code is r1pX-based, I would assume that it would continue to
>>> clear bit 0, which is only now the secure enable bit?
>>>
>>> Or, is it the case that ROM code clears all the bits?  That should be described.
>>>
>> ROM code reads the register value and compares it with value == 1
>> " If the GIC Distributor Control Register = 1, the
>> second CPU will not do the common GIC restoration"
>> On r2Px, the value becomes 3 and entire ROM code logic goofs up
>> and take wrong code path.
>
> That part is clear.
>
> What's not at all clear is what the ROM code does *after* this.  Does it
> clear both bits?  or just bit 0?  Since it's r1pX based, I would expect
> that it doesn't touch anything other than bit 0.
>
Actually since the condition of control register == 1 is not satisfied,
It re-inits entire GIC thinking it's not configured at all. So everything
will be cleared and including non-secure GIC dist. enable bit.

>>>> Since the GIC distributor gets disabled in a live system, CPU1 will
>>>> hang because the interrupts stop firing.
>>>>      1) Before doing the CPU1 wakeup, CPU0 must disable
>>>>         the GIC distributor and wait for it to be enabled.
>>>
>>> what does 'disable GIC distributor' mean.  secure? non-secure? both?
>>>
>> HLOS is a non-secure view so it can disable only non-secure bit.
>
> The changelog is not talking about the HLOS, it's talking about the ROM
> code, which presumably can set/clear both bits.
>
>>>>      2) CPU1 must re-enable the GIC distributor on
>>>>         it's wakeup path.
>>>
>>> Describe why this works.  e.g. because it cause ROM code to skip its
>>> broken restore path.
>>>
>> ROM code logic find the control register value 1 because bit 1 is
>> cleared by non-secure SW during the check.
>
> and because it finds the control regster value to be 1...
>
> Santosh, I do understand what is happening here.  But I play dumb so
> that it will be described in great detail in the changelog so that when
> I forget (and you forget) we can go back to this and get a quick
> understanding of both the bug and the workaround.
>
> Since you are very deeply familiar with this bug, it's understandably
> hard to write this changelog since most things probably seem obvious to
> you.  A suggestion would be to have a few colleagues that are not
> familiar with this bug read the changelog and try and describe it back
> to you.
>
I agree with you. This is side effect of knowing some BUGs too much.
I will work with Tero so that change log captures more details.

Regards
Santosh
without any assumptions.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-18  6:05                 ` Shilimkar, Santosh
  0 siblings, 0 replies; 56+ messages in thread
From: Shilimkar, Santosh @ 2012-05-18  6:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, May 17, 2012 at 10:45 PM, Kevin Hilman <khilman@ti.com> wrote:
> "Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:
>
>> On Wed, May 16, 2012 at 10:21 PM, Kevin Hilman <khilman@ti.com> wrote:
>>> Santosh Shilimkar <santosh.shilimkar@ti.com> writes:
>>>
>>>> Kevin,
>>>>
>>>> On Wednesday 16 May 2012 02:46 PM, Santosh Shilimkar wrote:
>>>>> On Wednesday 16 May 2012 03:14 AM, Kevin Hilman wrote:
>>>>>> Santosh,
>>>>>>
>>>>>> Tero Kristo <t-kristo@ti.com> writes:
>>>>>>
>>>>>>> From: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>>>
>>>>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>>>>> bits:
>>>>>>> ? ? ?bit 0 == Secure Enable
>>>>>>> ? ? ?bit 1 == Non-Secure Enable
>>>>>>> The Non-Secure banked register has not changed.
>>>>>>
>>>>>> For those without the r1pX TRM handy, please include what this look like
>>>>>> before (presumably 1 bit?) ?The changelog and in-code comments should
>>>>>> both be enhanced.
>>>>>>
>>>>> You are right. There was only one bit previously which was used for
>>>>> secure/non-secure mode. So ROM over-writes the non-secure bit
>>>>> accidentally.
>>>>>
>>>>>>> Since the ROM Code is based on the r1pX GIC, the CPU1 GIC restoration
>>>>>>> will cause a problem to CPU0 Non-Secure SW.
>>>>>>
>>>>>> Please describe the problem, so we can better understand the specifics
>>>>>> of the workaround.
>>>>>>
>>>> Below is the updated changelog.
>>>
>>> Much better, thanks. ?But it still took me several reads to fully
>>> understand. ?Maybe it's because the cold I have is stuffing up my head,
>>> so it takes me awhile to understand... ?Anyways, some minor comments to
>>> help clarify...
>>>
>>> Sorry to be so picky about changelogs, but this is a really nasty bug,
>>> and the workaround has some rather important side effects, so I want the
>>> description of the bug and the workaround to be well described.
>>>
>>>> --------------
>>>> ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control
>>>> register change
>>>>
>>>> With MPUSS programmed to OSWR(Open Switch retention), GIC context is
>>>> lost. On the CPU wakeup paths, ROM code gets executed which will setup
>>>> GIC secure configurations and restore the GIC context if it was saved
>>>> based on SAR_BACKUP_STATUS.
>>>>
>>>> The ROM Code GIC distributor restoration is split in two parts:
>>>> CPU specific register done by each CPU and common register done by
>>>> only one CPU. If the GIC Distributor Control Register = 1, the
>>>> second CPU will not do the common GIC restoration.
>>>
>>> s/second CPU/second CPU to wake up/
>>>
>> ok
>>>> GIC distributor control register has changed between CortexA9 r1pX and
>>>> r2pX. The Control Register secure banked version is now composed of 2
>>>> bits vs only one bit before r1px:
>>>
>>> before r1pX?
>> I mean r1px, r0px etc.
>>>
>>>> ? ? ?bit 0 == Secure Enable
>>>> ? ? ?bit 1 == Non-Secure Enable
>>>
>>> And what did this look like for r1pX? ? ?Presumably bit0 was non-secure
>>> enable?
>>>
>> Yes. Same bit is used. It's banked bit which has secure and non-secure view.
>>
>>>> Hence the value of Control register will be 3 and not 1 as the r1pX
>>>> based ROM code expects.
>>>
>>> Why will it be 3?
>>>
>>> Will it be 3 on GP devices?
>>>
>> Yes. Because you have 2 bits. Since both bits will be set [ Bit 1 will
>> be set by ROM code]
>> and bit 0 will be set by Linux.
>
> Why will the secure enable bit be set on GP devices?
>
>>>> So he CPU1 on it's wakeup ROM code path, will
>>>
>>> s/it's/its/
>>>
>> ok
>>>> go to the GIC initialization procedure and will so reset the full GIC
>>>> and NS GIC distributor Enable bit will get cleared.
>>>
>>> This is where it's confusing.
>>>
>> Hmm.
>>
>>> On r2pX, NS enable bit is bit 1. ?It's not mentioned here, but I'm
>>> assuming that it's bit 0 on r1pX, right? (I can't seem to find an r1pX
>>> TRM)
>>>
>> Yes. As I mentioned earlier, will make that more clear.
>>
>>> Since ROM code is r1pX-based, I would assume that it would continue to
>>> clear bit 0, which is only now the secure enable bit?
>>>
>>> Or, is it the case that ROM code clears all the bits? ?That should be described.
>>>
>> ROM code reads the register value and compares it with value == 1
>> " If the GIC Distributor Control Register = 1, the
>> second CPU will not do the common GIC restoration"
>> On r2Px, the value becomes 3 and entire ROM code logic goofs up
>> and take wrong code path.
>
> That part is clear.
>
> What's not at all clear is what the ROM code does *after* this. ?Does it
> clear both bits? ?or just bit 0? ?Since it's r1pX based, I would expect
> that it doesn't touch anything other than bit 0.
>
Actually since the condition of control register == 1 is not satisfied,
It re-inits entire GIC thinking it's not configured at all. So everything
will be cleared and including non-secure GIC dist. enable bit.

>>>> Since the GIC distributor gets disabled in a live system, CPU1 will
>>>> hang because the interrupts stop firing.
>>>> ? ? ?1) Before doing the CPU1 wakeup, CPU0 must disable
>>>> ? ? ? ? the GIC distributor and wait for it to be enabled.
>>>
>>> what does 'disable GIC distributor' mean. ?secure? non-secure? both?
>>>
>> HLOS is a non-secure view so it can disable only non-secure bit.
>
> The changelog is not talking about the HLOS, it's talking about the ROM
> code, which presumably can set/clear both bits.
>
>>>> ? ? ?2) CPU1 must re-enable the GIC distributor on
>>>> ? ? ? ? it's wakeup path.
>>>
>>> Describe why this works. ?e.g. because it cause ROM code to skip its
>>> broken restore path.
>>>
>> ROM code logic find the control register value 1 because bit 1 is
>> cleared by non-secure SW during the check.
>
> and because it finds the control regster value to be 1...
>
> Santosh, I do understand what is happening here. ?But I play dumb so
> that it will be described in great detail in the changelog so that when
> I forget (and you forget) we can go back to this and get a quick
> understanding of both the bug and the workaround.
>
> Since you are very deeply familiar with this bug, it's understandably
> hard to write this changelog since most things probably seem obvious to
> you. ?A suggestion would be to have a few colleagues that are not
> familiar with this bug read the changelog and try and describe it back
> to you.
>
I agree with you. This is side effect of knowing some BUGs too much.
I will work with Tero so that change log captures more details.

Regards
Santosh
without any assumptions.

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
  2012-05-18  6:05                 ` Shilimkar, Santosh
@ 2012-05-18 14:13                   ` Kevin Hilman
  -1 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-18 14:13 UTC (permalink / raw)
  To: Shilimkar, Santosh; +Cc: Tero Kristo, linux-omap, paul, linux-arm-kernel

"Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:

> On Thu, May 17, 2012 at 10:45 PM, Kevin Hilman <khilman@ti.com> wrote:

[...]

>> What's not at all clear is what the ROM code does *after* this.  Does it
>> clear both bits?  or just bit 0?  Since it's r1pX based, I would expect
>> that it doesn't touch anything other than bit 0.
>>
> Actually since the condition of control register == 1 is not satisfied,
> It re-inits entire GIC thinking it's not configured at all. So everything
> will be cleared and including non-secure GIC dist. enable bit.

Aha, that's the missing piece of the puzzle: The ROM code is clearing
bits that are unused on r1pX (but used on r2pX).  That is the root of
this bug and needs more description.

Thanks for clarifying.

[...]

>> Santosh, I do understand what is happening here.  But I play dumb so
>> that it will be described in great detail in the changelog so that when
>> I forget (and you forget) we can go back to this and get a quick
>> understanding of both the bug and the workaround.
>>
>> Since you are very deeply familiar with this bug, it's understandably
>> hard to write this changelog since most things probably seem obvious to
>> you.  A suggestion would be to have a few colleagues that are not
>> familiar with this bug read the changelog and try and describe it back
>> to you.
>>
> I agree with you. This is side effect of knowing some BUGs too much.
> I will work with Tero so that change log captures more details.

Thanks.

Maybe Jon Hunter can help review the changelog too.  IMO, he is the
reigning champion of thorough, descriptive and detailed changelogs.  :)

Kevin
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change
@ 2012-05-18 14:13                   ` Kevin Hilman
  0 siblings, 0 replies; 56+ messages in thread
From: Kevin Hilman @ 2012-05-18 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

"Shilimkar, Santosh" <santosh.shilimkar@ti.com> writes:

> On Thu, May 17, 2012 at 10:45 PM, Kevin Hilman <khilman@ti.com> wrote:

[...]

>> What's not at all clear is what the ROM code does *after* this. ?Does it
>> clear both bits? ?or just bit 0? ?Since it's r1pX based, I would expect
>> that it doesn't touch anything other than bit 0.
>>
> Actually since the condition of control register == 1 is not satisfied,
> It re-inits entire GIC thinking it's not configured at all. So everything
> will be cleared and including non-secure GIC dist. enable bit.

Aha, that's the missing piece of the puzzle: The ROM code is clearing
bits that are unused on r1pX (but used on r2pX).  That is the root of
this bug and needs more description.

Thanks for clarifying.

[...]

>> Santosh, I do understand what is happening here. ?But I play dumb so
>> that it will be described in great detail in the changelog so that when
>> I forget (and you forget) we can go back to this and get a quick
>> understanding of both the bug and the workaround.
>>
>> Since you are very deeply familiar with this bug, it's understandably
>> hard to write this changelog since most things probably seem obvious to
>> you. ?A suggestion would be to have a few colleagues that are not
>> familiar with this bug read the changelog and try and describe it back
>> to you.
>>
> I agree with you. This is side effect of knowing some BUGs too much.
> I will work with Tero so that change log captures more details.

Thanks.

Maybe Jon Hunter can help review the changelog too.  IMO, he is the
reigning champion of thorough, descriptive and detailed changelogs.  :)

Kevin

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
  2012-05-14 10:03   ` Tero Kristo
@ 2012-05-29 19:32     ` Menon, Nishanth
  -1 siblings, 0 replies; 56+ messages in thread
From: Menon, Nishanth @ 2012-05-29 19:32 UTC (permalink / raw)
  To: Tero Kristo; +Cc: linux-omap, khilman, paul, Rajendra Nayak, linux-arm-kernel

On Mon, May 14, 2012 at 5:03 AM, Tero Kristo <t-kristo@ti.com> wrote:
[...]
> +/**
>  * _enable - enable an omap_hwmod
>  * @oh: struct omap_hwmod *
>  *
> @@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
>        _enable_clocks(oh);
>        _enable_module(oh);
>
> +       _omap4_update_context_lost(oh);
> +
>        r = _wait_target_ready(oh);
>        if (!r) {
>                /*

Dumb q: Since we monitor the count around _enable, how do we ensure
that context loss counter is accurate
around OFF and idle transitions for domains that could have been
hwauto? it might be good to have limitations
in the $commit_message if it is not targeted to do so.

Regards,
Nishanth Menon
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
@ 2012-05-29 19:32     ` Menon, Nishanth
  0 siblings, 0 replies; 56+ messages in thread
From: Menon, Nishanth @ 2012-05-29 19:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 14, 2012 at 5:03 AM, Tero Kristo <t-kristo@ti.com> wrote:
[...]
> +/**
> ?* _enable - enable an omap_hwmod
> ?* @oh: struct omap_hwmod *
> ?*
> @@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
> ? ? ? ?_enable_clocks(oh);
> ? ? ? ?_enable_module(oh);
>
> + ? ? ? _omap4_update_context_lost(oh);
> +
> ? ? ? ?r = _wait_target_ready(oh);
> ? ? ? ?if (!r) {
> ? ? ? ? ? ? ? ?/*

Dumb q: Since we monitor the count around _enable, how do we ensure
that context loss counter is accurate
around OFF and idle transitions for domains that could have been
hwauto? it might be good to have limitations
in the $commit_message if it is not targeted to do so.

Regards,
Nishanth Menon

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
  2012-05-29 19:32     ` Menon, Nishanth
@ 2012-05-30  8:02       ` Tero Kristo
  -1 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-30  8:02 UTC (permalink / raw)
  To: Menon, Nishanth
  Cc: linux-omap, khilman, paul, Rajendra Nayak, linux-arm-kernel

On Tue, 2012-05-29 at 14:32 -0500, Menon, Nishanth wrote:
> On Mon, May 14, 2012 at 5:03 AM, Tero Kristo <t-kristo@ti.com> wrote:
> [...]
> > +/**
> >  * _enable - enable an omap_hwmod
> >  * @oh: struct omap_hwmod *
> >  *
> > @@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
> >        _enable_clocks(oh);
> >        _enable_module(oh);
> >
> > +       _omap4_update_context_lost(oh);
> > +
> >        r = _wait_target_ready(oh);
> >        if (!r) {
> >                /*
> 
> Dumb q: Since we monitor the count around _enable, how do we ensure
> that context loss counter is accurate
> around OFF and idle transitions for domains that could have been
> hwauto? it might be good to have limitations
> in the $commit_message if it is not targeted to do so.

True, I can add a comment to the commit msg about this.

-Tero


^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count
@ 2012-05-30  8:02       ` Tero Kristo
  0 siblings, 0 replies; 56+ messages in thread
From: Tero Kristo @ 2012-05-30  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-05-29 at 14:32 -0500, Menon, Nishanth wrote:
> On Mon, May 14, 2012 at 5:03 AM, Tero Kristo <t-kristo@ti.com> wrote:
> [...]
> > +/**
> >  * _enable - enable an omap_hwmod
> >  * @oh: struct omap_hwmod *
> >  *
> > @@ -1599,6 +1629,8 @@ static int _enable(struct omap_hwmod *oh)
> >        _enable_clocks(oh);
> >        _enable_module(oh);
> >
> > +       _omap4_update_context_lost(oh);
> > +
> >        r = _wait_target_ready(oh);
> >        if (!r) {
> >                /*
> 
> Dumb q: Since we monitor the count around _enable, how do we ensure
> that context loss counter is accurate
> around OFF and idle transitions for domains that could have been
> hwauto? it might be good to have limitations
> in the $commit_message if it is not targeted to do so.

True, I can add a comment to the commit msg about this.

-Tero

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2012-05-30  8:02 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-14 10:03 [PATCHv5 0/8] ARM: OMAP4: core retention support Tero Kristo
2012-05-14 10:03 ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 1/8] ARM: OMAP4: suspend: Program all domains to retention Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-15 19:52   ` Kevin Hilman
2012-05-15 19:52     ` Kevin Hilman
2012-05-16  8:37     ` Tero Kristo
2012-05-16  8:37       ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 2/8] TEMP: ARM: OMAP4: hwmod_data: Do not get DSP out of reset at boot time Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 3/8] ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX gic control register change Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-15 21:44   ` Kevin Hilman
2012-05-15 21:44     ` Kevin Hilman
2012-05-16  8:54     ` Tero Kristo
2012-05-16  8:54       ` Tero Kristo
2012-05-16  9:16     ` Santosh Shilimkar
2012-05-16  9:16       ` Santosh Shilimkar
2012-05-16 12:23       ` Santosh Shilimkar
2012-05-16 12:23         ` Santosh Shilimkar
2012-05-16 16:51         ` Kevin Hilman
2012-05-16 16:51           ` Kevin Hilman
2012-05-17  6:46           ` Shilimkar, Santosh
2012-05-17  6:46             ` Shilimkar, Santosh
2012-05-17 17:15             ` Kevin Hilman
2012-05-17 17:15               ` Kevin Hilman
2012-05-18  6:05               ` Shilimkar, Santosh
2012-05-18  6:05                 ` Shilimkar, Santosh
2012-05-18 14:13                 ` Kevin Hilman
2012-05-18 14:13                   ` Kevin Hilman
2012-05-16 12:31   ` Santosh Shilimkar
2012-05-16 12:31     ` Santosh Shilimkar
2012-05-14 10:03 ` [PATCHv5 4/8] ARM: OMAP4: hwmod: flag hwmods/modules supporting module level context status Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 5/8] ARM: OMAP: hwmod: Add support for per hwmod/module context lost count Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-29 19:32   ` Menon, Nishanth
2012-05-29 19:32     ` Menon, Nishanth
2012-05-30  8:02     ` Tero Kristo
2012-05-30  8:02       ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 6/8] ARM: OMAP4: pwrdm: add support for reading prev logic and mem states Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-15 22:36   ` Kevin Hilman
2012-05-15 22:36     ` Kevin Hilman
2012-05-16  8:55     ` Tero Kristo
2012-05-16  8:55       ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 7/8] ARM: OMAP4: PM: Add next_logic_state param to power_state Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-14 10:03 ` [PATCHv5 8/8] ARM: OMAP4: PM: Added option for enabling OSWR Tero Kristo
2012-05-14 10:03   ` Tero Kristo
2012-05-15 22:41   ` Kevin Hilman
2012-05-15 22:41     ` Kevin Hilman
2012-05-16  9:10     ` Tero Kristo
2012-05-16  9:10       ` Tero Kristo
2012-05-16 18:03       ` Kevin Hilman
2012-05-16 18:03         ` Kevin Hilman

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.