Skip to contentSkip to conversation

ARM: OMAP4: device off support

PATCH Superseded Tero Kristo 6 participants 87 messages May 14, 2012 – May 31, 2012

Subsystems (5)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover ARM: OMAP4: device off support

Hi,

Changes compared to previous version:

- generic: dropped a few redundant cpu_is_omapXxxx checks
- generic: changed the ordering of patches a bit to allow new code + their users to be added in the same patch
- patch 3: removed dpll/cm/sar calls from this patch
- patch 4: added call to dpll save/restore to idle loop
- patch 5: indentation changes, added call to cm save/restore to idle loop merged cm1/cm2 save/restore funcs to single cm save/restores
- patch 6: added call to sar_save to idle loop
- patch 12: added errata flag for the feature instead of runtime cpu type check
- patch 15: reads the value of the register to be restored instead of using a magic number

Device off requires I2C save/restore context patch to function properly, otherwise MMC driver sees issues during wakeup from off.

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-dev-off-v2

-Tero

#1 lore raw

PATCH v2 1/19 ARM: OMAP4: PM: powerdomain: Add HWSAR flag to L3INIT

From: Santosh Shilimkar <[email protected]>

L3INIT powerdomain has USB HOST and USB TLL modules which support hardware save-and-restore (HW SAR) mechanism.
This patch updates the L3INIT power domain to mark them as capable of doing H/w save and restore and provides functions to do them explicitly.

Note: Eventually, these custom function implementation will be abstracted and might be done in hwmod or in other layer.

---
 arch/arm/mach-omap2/powerdomain44xx.c       |   41 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomains44xx_data.c |    2 +-
 2 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/powerdomain44xx.c +41 -0
index ab00736..37f7e12 100644
@@ -23,6 +23,10 @@
 #include "prm44xx.h"
 #include "prminst44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "cm2_44xx.h"
+#include "cminst44xx.h"
 
 static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
@@ -238,6 +242,41 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 	return 0;
 }
 
+static int omap4_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	/*
+	 * FIXME: This should be fixed right way by moving it into HWMOD
+	 * or clock framework since sar control is moved to module level
+	 */
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+	return 0;
+}
+
+static int omap4_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	/*
+	 * FIXME: This should be fixed right way by moving it into HWMOD
+	 * or clock framework since sar control is moved to module level
+	 */
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+
+	return 0;
+}
+
 struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
@@ -255,4 +294,6 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 	.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,
+	.pwrdm_enable_hdwr_sar	= omap4_pwrdm_enable_hdwr_sar,
+	.pwrdm_disable_hdwr_sar	= omap4_pwrdm_disable_hdwr_sar,
 };
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -1
index 704664c..d8701ce 100644
@@ -276,7 +276,7 @@ static struct powerdomain l3init_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
-	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE | PWRDM_HAS_HDWR_SAR,
 };
 
 /* l4per_44xx_pwrdm: Target peripherals power domain */
Signature · 1 line
1.7.4.1
#2 lore raw

PATCH v2 1/19 ARM: OMAP4: PM: powerdomain: Add HWSAR flag to L3INIT

Quoted 10 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

L3INIT powerdomain has USB HOST and USB TLL modules which support hardware save-and-restore (HW SAR) mechanism.
This patch updates the L3INIT power domain to mark them as capable of doing H/w save and restore and provides functions to do them explicitly.

Note: Eventually, these custom function implementation will be abstracted and might be done in hwmod or in other layer.

Why not do it the right way now?

Also, these new functions need kerneldoc.

Kevin

Quoted 84 lines
---
 arch/arm/mach-omap2/powerdomain44xx.c       |   41 +++++++++++++++++++++++++++
 arch/arm/mach-omap2/powerdomains44xx_data.c |    2 +-
 2 files changed, 42 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/powerdomain44xx.c +41 -0
index ab00736..37f7e12 100644
@@ -23,6 +23,10 @@
 #include "prm44xx.h"
 #include "prminst44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm-regbits-44xx.h"
+#include "prcm44xx.h"
+#include "cm2_44xx.h"
+#include "cminst44xx.h"
 
 static int omap4_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 {
@@ -238,6 +242,41 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 	return 0;
 }
 
+static int omap4_pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	/*
+	 * FIXME: This should be fixed right way by moving it into HWMOD
+	 * or clock framework since sar control is moved to module level
+	 */
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		1 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+	return 0;
+}
+
+static int omap4_pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
+{
+	/*
+	 * FIXME: This should be fixed right way by moving it into HWMOD
+	 * or clock framework since sar control is moved to module level
+	 */
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET);
+	omap4_cminst_rmw_inst_reg_bits(OMAP4430_SAR_MODE_MASK,
+		0 << OMAP4430_SAR_MODE_SHIFT, OMAP4430_CM2_PARTITION,
+		OMAP4430_CM2_L3INIT_INST,
+		OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET);
+
+	return 0;
+}
+
 struct pwrdm_ops omap4_pwrdm_operations = {
 	.pwrdm_set_next_pwrst	= omap4_pwrdm_set_next_pwrst,
 	.pwrdm_read_next_pwrst	= omap4_pwrdm_read_next_pwrst,
@@ -255,4 +294,6 @@ struct pwrdm_ops omap4_pwrdm_operations = {
 	.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,
+	.pwrdm_enable_hdwr_sar	= omap4_pwrdm_enable_hdwr_sar,
+	.pwrdm_disable_hdwr_sar	= omap4_pwrdm_disable_hdwr_sar,
 };
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -1
index 704664c..d8701ce 100644
@@ -276,7 +276,7 @@ static struct powerdomain l3init_44xx_pwrdm = {
 	.pwrsts_mem_on	= {
 		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
-	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+	.flags		  = PWRDM_HAS_LOWPOWERSTATECHANGE | PWRDM_HAS_HDWR_SAR,
 };
 
 /* l4per_44xx_pwrdm: Target peripherals power domain */
#3 lore raw

PATCH v2 2/19 ARM: OMAP4: Add SAR ROM base address

In reply to Tero Kristo

Added in preparation for device off mode. SAR ROM contains the mapping from SAR RAM to IO registers, and this will eventually be parsed during init time to do the reverse before device off.

---
 arch/arm/plat-omap/include/plat/omap44xx.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/plat-omap/include/plat/omap44xx.h +1 -0
index c0d478e..1a45700 100644
@@ -46,6 +46,7 @@
 #define OMAP44XX_MCPDM_BASE		0x40132000
 #define OMAP44XX_MCPDM_L3_BASE		0x49032000
 #define OMAP44XX_SAR_RAM_BASE		0x4a326000
+#define OMAP44XX_SAR_ROM_BASE		0x4a05e000
 
 #define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
 #define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
Signature · 1 line
1.7.4.1
#4 lore raw

PATCH v2 2/19 ARM: OMAP4: Add SAR ROM base address

Quoted 5 lines · Tero Kristo

Added in preparation for device off mode. SAR ROM contains the mapping from SAR RAM to IO registers, and this will eventually be parsed during init time to do the reverse before device off.

This should be combined with the patch that uses the #define.

Kevin

Quoted 16 lines
---
 arch/arm/plat-omap/include/plat/omap44xx.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/plat-omap/include/plat/omap44xx.h +1 -0
index c0d478e..1a45700 100644
@@ -46,6 +46,7 @@
 #define OMAP44XX_MCPDM_BASE		0x40132000
 #define OMAP44XX_MCPDM_L3_BASE		0x49032000
 #define OMAP44XX_SAR_RAM_BASE		0x4a326000
+#define OMAP44XX_SAR_ROM_BASE		0x4a05e000
 
 #define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
 #define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
#5 lore raw

PATCH v2 2/19 ARM: OMAP4: Add SAR ROM base address

Quoted 9 lines · Kevin Hilman
Quoted 5 lines · Tero Kristo

Added in preparation for device off mode. SAR ROM contains the mapping from SAR RAM to IO registers, and this will eventually be parsed during init time to do the reverse before device off.

This should be combined with the patch that uses the #define.

Okay sounds good.

-Tero

Quoted 19 lines

Kevin

Quoted 16 lines
---
 arch/arm/plat-omap/include/plat/omap44xx.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/plat-omap/include/plat/omap44xx.h +1 -0
index c0d478e..1a45700 100644
@@ -46,6 +46,7 @@
 #define OMAP44XX_MCPDM_BASE		0x40132000
 #define OMAP44XX_MCPDM_L3_BASE		0x49032000
 #define OMAP44XX_SAR_RAM_BASE		0x4a326000
+#define OMAP44XX_SAR_ROM_BASE		0x4a05e000
 
 #define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
 #define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
#6 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

In reply to Tero Kristo

This patch adds device off support to OMAP4 device type.

OFF mode is disabled by default, however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry
echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

[t-kristo at ti.com: largely re-structured the code]
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 ++++-
 arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++++++++++++++++++-
 arch/arm/mach-omap2/pm-debug.c            |   17 +++++--
 arch/arm/mach-omap2/pm.h                  |   20 +++++++++
 arch/arm/mach-omap2/pm44xx.c              |   45 +++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.c             |   66 +++++++++++++++++++++++++++++
 6 files changed, 197 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +9 -1
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm44xx.h"
 
 #ifdef CONFIG_SMP
 
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+	if (omap4_device_next_state_off())
+		save_state = 3;
+	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
+	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+		save_state = 3;
 
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
+	if (omap4_device_prev_state_off())
+		omap4_device_clear_prev_off_state();
+
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +45 -2

82 lines not on this page · raw message

arch/arm/mach-omap2/pm-debug.c +12 -5
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 u32 enable_off_mode;
 static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)
 		else
 			omap_pm_disable_off_mode();
 
-		omap3_pm_off_mode_enable(val);
+		if (off_mode_enable_func)
+			off_mode_enable_func(val);
 	}
 
 	if (option == &enable_oswr_mode)
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	if (cpu_is_omap34xx())
-		(void) debugfs_create_file("enable_off_mode",
-			S_IRUGO | S_IWUSR, d, &enable_off_mode,
-			&pm_dbg_option_fops);
+	(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);
 
+	if (cpu_is_omap34xx())
+		off_mode_enable_func = omap3_pm_off_mode_enable;
+
+	if (cpu_is_omap44xx())
+		off_mode_enable_func = omap4_pm_off_mode_enable;
+
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+	return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+	return false;
+}
+#endif
+
 #if defined(CONFIG_PM_OPP)
 extern int omap3_opp_init(void);
 extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +45 -0

57 lines not on this page · raw message

arch/arm/mach-omap2/prm44xx.c +66 -0

72 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#7 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 1 line

OFF mode is disabled by default,

why?

Quoted 5 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. Basically, I think this feature needs to be supported by using constraints on functional
power states. Having checks all over the place is getting unwieldy and
not attractive to maintain.

The combination of constraints and functional power states should make
this much more manageable. Until we have that, I'd prefer to keep
the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Quoted 2 lines
[t-kristo at ti.com: largely re-structured the code]

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

First, some general comments:

There is a lot going on in this patch, so it is hard to follow what all is related, and why. Just a quick glance suggests it needs to be broken up into at least a few parts:

- low-level PRM support: new APIs for various off-mode features) (should probably be done on top of functional power states)
- powerdomain core support or "achievable" states (should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC but it's not obvious why)
- PM debug support to enable/disable off-mode
(for testing only, not for merge)

Quoted 23 lines
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 ++++-
 arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++++++++++++++++++-
 arch/arm/mach-omap2/pm-debug.c            |   17 +++++--
 arch/arm/mach-omap2/pm.h                  |   20 +++++++++
 arch/arm/mach-omap2/pm44xx.c              |   45 +++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.c             |   66 +++++++++++++++++++++++++++++
 6 files changed, 197 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +1 -0
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm44xx.h"
 
 #ifdef CONFIG_SMP
 

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 268

Quoted 6 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +2 -1
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+	if (omap4_device_next_state_off())
+		save_state = 3;

Why?

I don't see why this check is needed in addition to the mpuss_pd check added just below?

Quoted 8 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
+	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+		save_state = 3;
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 298

Quoted 6 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
+	if (omap4_device_prev_state_off())
+		omap4_device_clear_prev_off_state();
+

The 'clear prev off state' is subsequently removed in the last patch "ARM: OMAP4: powerdomain: update mpu / core off counters during device
off." Why is it needed here?

Quoted 43 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +5 -2
index 42cd7fb..805d08d 100644
@@ -32,6 +32,7 @@
 
 #include "omap4-sar-layout.h"
 #include "common.h"
+#include "pm.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -46,6 +47,8 @@ static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
+static struct powerdomain *mpuss_pd;
+
 /*
  * Static helper functions.
  */
@@ -259,7 +262,7 @@ static void irq_save_context(void)
 /*
  * Clear WakeupGen SAR backup status.
  */
-void irq_sar_clear(void)
+static void irq_sar_clear(void)
 {
 	u32 val;
 	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
@@ -271,7 +274,7 @@ void irq_sar_clear(void)
  * Save GIC and Wakeupgen interrupt context using secure API
  * for HS/EMU devices.
  */
-static void irq_save_secure_context(void)
+static void irq_save_secure_gic(void)
 {
 	u32 ret;
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 290

Quoted 6 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
@@ -282,6 +285,40 @@ static void irq_save_secure_context(void)
 }
 #endif
 
+static void save_secure_ram(void)
+{
+	u32 ret;

CodingStyle nit: blank line needed here (and in multiple other places)

Quoted 8 lines
arch/arm/mach-omap2/omap-wakeupgen.c +8 -0
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVESECURERAM_INDEX,
+				FLAG_START_CRITICAL,
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure ram context save failed\n");
+}
+

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 308

Quoted 10 lines
arch/arm/mach-omap2/omap-wakeupgen.c +10 -0
+static void save_secure_all(void)
+{
+	u32 ret;
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
+				FLAG_START_CRITICAL,
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure all context save failed\n");
+}

This secure mode save/restore seems misplaced in the wakeupgen driver. Seems to me like it belongs in omap-secure.c.

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 314

Quoted 6 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
+
+static void irq_save_secure_context(void)
+{
+	if (omap4_device_next_state_off()) {
+		save_secure_all();
+	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {

Why is this check needed? This is called from the CPU_CLUSTER_PM_ENTER notifier, which AFAICT, is only called when the cluster is going off.

Quoted 126 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+		irq_save_secure_gic();
+		save_secure_ram();
+	} else {
+		irq_save_secure_gic();
+	}
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
 					 unsigned long action, void *hcpu)
@@ -388,5 +425,11 @@ int __init omap_wakeupgen_init(void)
 	irq_hotplug_init();
 	irq_pm_init();
 
+	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+	if (!mpuss_pd) {
+		pr_err("wakeupgen: unable to get mpu_pwrdm\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
arch/arm/mach-omap2/pm-debug.c +12 -5
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 u32 enable_off_mode;
 static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)
 		else
 			omap_pm_disable_off_mode();
 
-		omap3_pm_off_mode_enable(val);
+		if (off_mode_enable_func)
+			off_mode_enable_func(val);
 	}
 
 	if (option == &enable_oswr_mode)
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	if (cpu_is_omap34xx())
-		(void) debugfs_create_file("enable_off_mode",
-			S_IRUGO | S_IWUSR, d, &enable_off_mode,
-			&pm_dbg_option_fops);
+	(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);
 
+	if (cpu_is_omap34xx())
+		off_mode_enable_func = omap3_pm_off_mode_enable;
+
+	if (cpu_is_omap44xx())
+		off_mode_enable_func = omap4_pm_off_mode_enable;
+
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+	return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+	return false;
+}
+#endif
+
 #if defined(CONFIG_PM_OPP)
 extern int omap3_opp_init(void);
 extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +10 -0
index 07ac0d3..8f0ec56 100644
@@ -87,6 +87,27 @@ static int omap4_pm_suspend(void)
 }
 #endif /* CONFIG_SUSPEND */
 
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states:	what states are available
+ * @req_min_state:	what state is the minimum we'd like to hit
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case, the next higher power
+ * state which is supported is returned. This is because a combination
+ * of system power states where the parent PD's state is not in line

arch/arm/mach-omap2/pm44xx.c static int omap4_pm_suspend(void) · line 109

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ * with expectation can result in system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state)
+{
+	u16 mask = 0xFF << req_min_state;
+
+	if (available_states & mask)
+		return __ffs(available_states & mask);
+	return PWRDM_POWER_ON;
+}

This feature needs to be generalized (preferably on top of functional power states) because we have the same need on various AM3xxx SoCs which don't support RET/OFF. Mark Greer has started on this, but I think it needs to be part of the functional power states work.

It also needs to be part of the powerdomain layer, IMO.

Quoted 55 lines
arch/arm/mach-omap2/pm44xx.c +24 -0
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
 	struct power_state *pwrst;
@@ -115,6 +136,30 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
+void omap4_pm_off_mode_enable(int enable)
+{
+	u32 next_state = PWRDM_POWER_RET;
+	u32 next_logic_state = PWRDM_POWER_ON;
+	struct power_state *pwrst;
+
+	if (enable) {
+		next_state = PWRDM_POWER_OFF;
+		next_logic_state = PWRDM_POWER_OFF;
+	}
+
+	omap4_device_set_state_off(enable);
+
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		pwrst->next_state =
+			get_achievable_state(pwrst->pwrdm->pwrsts, next_state);
+		pwrst->next_logic_state =
+			get_achievable_state(pwrst->pwrdm->pwrsts_logic_ret,
+				next_logic_state);
+		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
+	}
+}
+
 void omap4_pm_oswr_mode_enable(int enable)
 {
 	u32 next_logic_state;
arch/arm/mach-omap2/prm44xx.c +13 -0
index 09d84de..86c6c6b 100644
@@ -289,6 +289,72 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 			OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
+/**
+ * omap4_device_set_state_off() - setup device off state
+ * @enable:	set to off or not.
+ *
+ * When Device OFF is enabled, Device is allowed to perform
+ * transition to off mode as soon as all power domains in MPU, IVA
+ * and CORE voltage are in OFF or OSWR state (open switch retention)
+ */
+void omap4_device_set_state_off(u8 enable)
+{
+	if (enable)
+		omap4_prminst_write_inst_reg(0x1 <<
+				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 314

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_DEVICE_INST,
+				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+	else
+		omap4_prminst_write_inst_reg(0x0 <<
+				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_DEVICE_INST,
+				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+}

minor: a more compact, and more readable (so it's obvious at first glance that the same register is being written) would be:

void omap4_device_set_state_off(u8 enable)

{
        u8 val = enable ? 0x1 : 0x0;

	omap4_prminst_write_inst_reg(val <<
				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
				OMAP4430_PRM_PARTITION,
				OMAP4430_PRM_DEVICE_INST,
				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
}

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 326

Quoted 11 lines
arch/arm/mach-omap2/prm44xx.c +11 -0
+/**
+ * omap4_device_prev_state_off:
+ * returns true if the device hit OFF mode
+ * This is API to check whether OMAP is waking up from device OFF mode.
+ * There is no other status bit available for SW to read whether last state
+ * entered was device OFF. To work around this, CORE PD, RFF context state
+ * is used which is lost only when we hit device OFF state
+ */
+bool omap4_device_prev_state_off(void)
+{
+	u32 reg;

minor: reg makes me think the result of the read is a register address, not a value. How about s/reg/val/.

Quoted 18 lines
arch/arm/mach-omap2/prm44xx.c +18 -0
+	reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_CORE_INST,
+				OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET)
+		& OMAP4430_LOSTCONTEXT_RFF_MASK;
+
+	return reg ? true : false;
+}
+
+void omap4_device_clear_prev_off_state(void)
+{
+	omap4_prminst_write_inst_reg(OMAP4430_LOSTCONTEXT_RFF_MASK |
+				OMAP4430_LOSTCONTEXT_DFF_MASK,
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_CORE_INST,
+				OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET);
+}
+
+/**

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 355

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+ * omap4_device_next_state_off:
+ * returns true if the device next state is OFF
+ * This is API to check whether OMAP is programmed for device OFF
+ */
+bool omap4_device_next_state_off(void)
+{
+	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+			OMAP4430_PRM_DEVICE_INST,
+			OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET)
+			& OMAP4430_DEVICE_OFF_ENABLE_MASK ? true : false;

minor: when using these long register read helpers, IMO readability improves if this is of the form:

       val = <read register>;
       val &= <mask>;
       return val ? true : false;

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 360

Quoted 5 lines
arch/arm/mach-omap2/prm44xx.c +2 -0
+}
+
 static int __init omap4xxx_prcm_init(void)
 {
 	if (cpu_is_omap44xx()) {

Kevin

#8 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

Quoted 47 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 1 line

OFF mode is disabled by default,

why?

Quoted 5 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. ?Basically, I think this feature needs to be supported by using constraints on functional power states. ? Having checks all over the place is getting unwieldy and not attractive to maintain.

The combination of constraints and functional power states should make this much more manageable. ? Until we have that, I'd prefer to keep the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Quoted 2 lines
[t-kristo at ti.com: largely re-structured the code]

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

First, ?some general comments:

There is a lot going on in this patch, so it is hard to follow what all is related, and why. ?Just a quick glance suggests it needs to be broken up into at least a few parts:

Quoted 10 lines

- low-level PRM support: new APIs for various off-mode features) ?(should probably be done on top of functional power states)
- powerdomain core support or "achievable" states ?(should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC ?but it's not obvious why)
- PM debug support to enable/disable off-mode
?(for testing only, not for merge)

Further split sounds good to me.

Regards
santosh

#9 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

In reply to Kevin Hilman
Quoted 11 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 1 line

OFF mode is disabled by default,

why?

Good question. For historical reference I guess. The device off works pretty nicely with the current kernel already, so it should be possible to enable it by default and blame the people who break it.

Quoted 18 lines
Quoted 6 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. Basically, I think this feature needs to be supported by using constraints on functional
power states. Having checks all over the place is getting unwieldy and
not attractive to maintain.

Quoted 4 lines

The combination of constraints and functional power states should make
this much more manageable. Until we have that, I'd prefer to keep
the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Okay, this sounds like a good plan.

Quoted 7 lines
Quoted 3 lines
[t-kristo at ti.com: largely re-structured the code]

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

Yeah... I am not quite sure where the line goes here as I am modifying the patches quite heavily but try to keep credits to the original authors... will change this like so.

Quoted 6 lines

First, some general comments:

There is a lot going on in this patch, so it is hard to follow what all is related, and why. Just a quick glance suggests it needs to be broken up into at least a few parts:

What is the merge plan for the func power state stuff? I don't want to create new dependencies if unnecessary. Otherwise the split should be okay.

Quoted 8 lines

- low-level PRM support: new APIs for various off-mode features) (should probably be done on top of functional power states)
- powerdomain core support or "achievable" states (should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC but it's not obvious why)

This is tightly coupled to GIC because the ROM code has following API calls:

- save gic
- save secure RAM
- save secure all (gic + RAM + some other mysterious stuff)

It is difficult/impossible to separate these without adding redundant code execution (e.g. doing a GIC save from the GIC code + then doing a second GIC save with save secure all from core PM code.)

Quoted 35 lines

- PM debug support to enable/disable off-mode
(for testing only, not for merge)

Quoted 23 lines
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 ++++-
 arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++++++++++++++++++-
 arch/arm/mach-omap2/pm-debug.c            |   17 +++++--
 arch/arm/mach-omap2/pm.h                  |   20 +++++++++
 arch/arm/mach-omap2/pm44xx.c              |   45 +++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.c             |   66 +++++++++++++++++++++++++++++
 6 files changed, 197 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +1 -0
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm44xx.h"
 
 #ifdef CONFIG_SMP
 

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 268

Quoted 6 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +2 -1
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+	if (omap4_device_next_state_off())
+		save_state = 3;

Why?

Quoted 2 lines

I don't see why this check is needed in addition to the mpuss_pd check added just below?

mpuss_pd does not go to off, thats why. It goes to OSWR state during standard device-off. It is possible for it to go to OFF mode, but it is not recommended.

Quoted 12 lines
Quoted 12 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
+	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+		save_state = 3;
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
Quoted 7 lines

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 298

Quoted 3 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	if (omap4_device_prev_state_off())
+		omap4_device_clear_prev_off_state();
+

The 'clear prev off state' is subsequently removed in the last patch "ARM: OMAP4: powerdomain: update mpu / core off counters during device
off." Why is it needed here?

That patch is moving the clear part to the lost_context_rff func, it is probably not that clear. Should be easier to follow the logic once I re-structure the code a bit more (separate the prm support funcs out to their own set etc.)

Quoted 47 lines
Quoted 47 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +5 -2
index 42cd7fb..805d08d 100644
@@ -32,6 +32,7 @@
 
 #include "omap4-sar-layout.h"
 #include "common.h"
+#include "pm.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -46,6 +47,8 @@ static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
+static struct powerdomain *mpuss_pd;
+
 /*
  * Static helper functions.
  */
@@ -259,7 +262,7 @@ static void irq_save_context(void)
 /*
  * Clear WakeupGen SAR backup status.
  */
-void irq_sar_clear(void)
+static void irq_sar_clear(void)
 {
 	u32 val;
 	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
@@ -271,7 +274,7 @@ void irq_sar_clear(void)
  * Save GIC and Wakeupgen interrupt context using secure API
  * for HS/EMU devices.
  */
-static void irq_save_secure_context(void)
+static void irq_save_secure_gic(void)
 {
 	u32 ret;
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
@@ -282,6 +285,40 @@ static void irq_save_secure_context(void)
 }
 #endif
 
Quoted 5 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 290

Quoted 3 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+static void save_secure_ram(void)
+{
+	u32 ret;

CodingStyle nit: blank line needed here (and in multiple other places)

Okay.

Quoted 14 lines
Quoted 14 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVESECURERAM_INDEX,
+				FLAG_START_CRITICAL,
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure ram context save failed\n");
+}
+
+static void save_secure_all(void)
+{
+	u32 ret;
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
+				FLAG_START_CRITICAL,
Quoted 8 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 308

Quoted 5 lines
arch/arm/mach-omap2/omap-wakeupgen.c +5 -0
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure all context save failed\n");
+}

This secure mode save/restore seems misplaced in the wakeupgen driver. Seems to me like it belongs in omap-secure.c.

Can't really move it there, as described above. Unless we want to save GIC context twice.

Quoted 10 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 314

Quoted 7 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
+
+static void irq_save_secure_context(void)
+{
+	if (omap4_device_next_state_off()) {
+		save_secure_all();
+	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {

Why is this check needed? This is called from the CPU_CLUSTER_PM_ENTER notifier, which AFAICT, is only called when the cluster is going off.

This is checking against the different MPU PD states we can go into. If:
- MPU OSWR => GIC save needed only
- MPU OFF => GIC + secure RAM save needed (not recommended to be used though)
- MPU OSWR / OFF + device-off => save all needed

Quoted 143 lines
Quoted 127 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+		irq_save_secure_gic();
+		save_secure_ram();
+	} else {
+		irq_save_secure_gic();
+	}
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
 					 unsigned long action, void *hcpu)
@@ -388,5 +425,11 @@ int __init omap_wakeupgen_init(void)
 	irq_hotplug_init();
 	irq_pm_init();
 
+	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+	if (!mpuss_pd) {
+		pr_err("wakeupgen: unable to get mpu_pwrdm\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
arch/arm/mach-omap2/pm-debug.c +12 -5
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 u32 enable_off_mode;
 static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)
 		else
 			omap_pm_disable_off_mode();
 
-		omap3_pm_off_mode_enable(val);
+		if (off_mode_enable_func)
+			off_mode_enable_func(val);
 	}
 
 	if (option == &enable_oswr_mode)
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	if (cpu_is_omap34xx())
-		(void) debugfs_create_file("enable_off_mode",
-			S_IRUGO | S_IWUSR, d, &enable_off_mode,
-			&pm_dbg_option_fops);
+	(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);
 
+	if (cpu_is_omap34xx())
+		off_mode_enable_func = omap3_pm_off_mode_enable;
+
+	if (cpu_is_omap44xx())
+		off_mode_enable_func = omap4_pm_off_mode_enable;
+
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+	return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+	return false;
+}
+#endif
+
 #if defined(CONFIG_PM_OPP)
 extern int omap3_opp_init(void);
 extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +10 -0
index 07ac0d3..8f0ec56 100644
@@ -87,6 +87,27 @@ static int omap4_pm_suspend(void)
 }
 #endif /* CONFIG_SUSPEND */
 
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states:	what states are available
+ * @req_min_state:	what state is the minimum we'd like to hit
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case, the next higher power
+ * state which is supported is returned. This is because a combination
+ * of system power states where the parent PD's state is not in line

arch/arm/mach-omap2/pm44xx.c static int omap4_pm_suspend(void) · line 109

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ * with expectation can result in system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state)
+{
+	u16 mask = 0xFF << req_min_state;
+
+	if (available_states & mask)
+		return __ffs(available_states & mask);
+	return PWRDM_POWER_ON;
+}

This feature needs to be generalized (preferably on top of functional power states) because we have the same need on various AM3xxx SoCs which don't support RET/OFF. Mark Greer has started on this, but I think it needs to be part of the functional power states work.

Quoted 1 line

It also needs to be part of the powerdomain layer, IMO.

So, are you saying this whole set should be re-based on top of the functional power states stuff? If yes, that can be done (Jean actually already did some work on this and got it working I think.)

Quoted 71 lines
Quoted 56 lines
arch/arm/mach-omap2/pm44xx.c +24 -0
 static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 {
 	struct power_state *pwrst;
@@ -115,6 +136,30 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
+void omap4_pm_off_mode_enable(int enable)
+{
+	u32 next_state = PWRDM_POWER_RET;
+	u32 next_logic_state = PWRDM_POWER_ON;
+	struct power_state *pwrst;
+
+	if (enable) {
+		next_state = PWRDM_POWER_OFF;
+		next_logic_state = PWRDM_POWER_OFF;
+	}
+
+	omap4_device_set_state_off(enable);
+
+	list_for_each_entry(pwrst, &pwrst_list, node) {
+		pwrst->next_state =
+			get_achievable_state(pwrst->pwrdm->pwrsts, next_state);
+		pwrst->next_logic_state =
+			get_achievable_state(pwrst->pwrdm->pwrsts_logic_ret,
+				next_logic_state);
+		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+		pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
+	}
+}
+
 void omap4_pm_oswr_mode_enable(int enable)
 {
 	u32 next_logic_state;
arch/arm/mach-omap2/prm44xx.c +13 -0
index 09d84de..86c6c6b 100644
@@ -289,6 +289,72 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 			OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
+/**
+ * omap4_device_set_state_off() - setup device off state
+ * @enable:	set to off or not.
+ *
+ * When Device OFF is enabled, Device is allowed to perform
+ * transition to off mode as soon as all power domains in MPU, IVA
+ * and CORE voltage are in OFF or OSWR state (open switch retention)
+ */
+void omap4_device_set_state_off(u8 enable)
+{
+	if (enable)
+		omap4_prminst_write_inst_reg(0x1 <<
+				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 314

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_DEVICE_INST,
+				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+	else
+		omap4_prminst_write_inst_reg(0x0 <<
+				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_DEVICE_INST,
+				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+}

minor: a more compact, and more readable (so it's obvious at first glance that the same register is being written) would be:

void omap4_device_set_state_off(u8 enable)

Quoted 9 lines
{
        u8 val = enable ? 0x1 : 0x0;

	omap4_prminst_write_inst_reg(val <<
				OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
				OMAP4430_PRM_PARTITION,
				OMAP4430_PRM_DEVICE_INST,
				OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
}

True.

Quoted 15 lines

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 326

Quoted 12 lines
arch/arm/mach-omap2/prm44xx.c +11 -0
+/**
+ * omap4_device_prev_state_off:
+ * returns true if the device hit OFF mode
+ * This is API to check whether OMAP is waking up from device OFF mode.
+ * There is no other status bit available for SW to read whether last state
+ * entered was device OFF. To work around this, CORE PD, RFF context state
+ * is used which is lost only when we hit device OFF state
+ */
+bool omap4_device_prev_state_off(void)
+{
+	u32 reg;

minor: reg makes me think the result of the read is a register address, not a value. How about s/reg/val/.

Yea, good point.

Quoted 33 lines
Quoted 19 lines
arch/arm/mach-omap2/prm44xx.c +18 -0
+	reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_CORE_INST,
+				OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET)
+		& OMAP4430_LOSTCONTEXT_RFF_MASK;
+
+	return reg ? true : false;
+}
+
+void omap4_device_clear_prev_off_state(void)
+{
+	omap4_prminst_write_inst_reg(OMAP4430_LOSTCONTEXT_RFF_MASK |
+				OMAP4430_LOSTCONTEXT_DFF_MASK,
+				OMAP4430_PRM_PARTITION,
+				OMAP4430_PRM_CORE_INST,
+				OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET);
+}
+
+/**

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 355

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+ * omap4_device_next_state_off:
+ * returns true if the device next state is OFF
+ * This is API to check whether OMAP is programmed for device OFF
+ */
+bool omap4_device_next_state_off(void)
+{
+	return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+			OMAP4430_PRM_DEVICE_INST,
+			OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET)
+			& OMAP4430_DEVICE_OFF_ENABLE_MASK ? true : false;

minor: when using these long register read helpers, IMO readability improves if this is of the form:

Quoted 3 lines
       val = <read register>;
       val &= <mask>;
       return val ? true : false;

True.

Quoted 9 lines

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 360

Quoted 6 lines
arch/arm/mach-omap2/prm44xx.c +2 -0
+}
+
 static int __init omap4xxx_prcm_init(void)
 {
 	if (cpu_is_omap44xx()) {

Kevin

#10 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

Hi Tero, Kevin, Santosh,

Quoted 9 lines · Tero Kristo
Quoted 8 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

OFF mode is disabled by default,

why?

Good question. For historical reference I guess. The device off works pretty nicely with the current kernel already, so it should be possible to enable it by default and blame the people who break it.

Agree. The next problem is 'who will fix the breakage?'.

Quoted 39 lines
Quoted 17 lines
Quoted 5 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. ?Basically, I think this feature needs to be supported by using constraints on functional power states. ? Having checks all over the place is getting unwieldy and not attractive to maintain.

Quoted 4 lines

The combination of constraints and functional power states should make this much more manageable. ? Until we have that, I'd prefer to keep the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Okay, this sounds like a good plan.

Quoted 7 lines
Quoted 3 lines
[t-kristo at ti.com: largely re-structured the code]

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

Yeah... I am not quite sure where the line goes here as I am modifying the patches quite heavily but try to keep credits to the original authors... will change this like so.

Quoted 3 lines

First, ?some general comments:

Quoted 7 lines
Quoted 3 lines

There is a lot going on in this patch, so it is hard to follow what all is related, and why. ?Just a quick glance suggests it needs to be broken up into at least a few parts:

What is the merge plan for the func power state stuff? I don't want to create new dependencies if unnecessary. Otherwise the split should be okay.

That is something I am interested in too ;p
I did port and test Tero's patches on top of the functional power states, which is the logical approach to me. Now given the reviews status on both this patch series and the func power states series I am not sure which one needs to be ported on top of the other ;-|
[1] https://gitorious.org/jpihet/linux-omap/commits/omap4_dev_off

Using the functional power states for the OMAP4 core and device off has some advantages in simplifying the code, especially in the previous/current/next states checking and programming.

Quoted 329 lines
Quoted 9 lines

- low-level PRM support: new APIs for various off-mode features) ? (should probably be done on top of functional power states)
- powerdomain core support or "achievable" states
? (should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC ? but it's not obvious why)

This is tightly coupled to GIC because the ROM code has following API calls:

- save gic
- save secure RAM
- save secure all (gic + RAM + some other mysterious stuff)

It is difficult/impossible to separate these without adding redundant code execution (e.g. doing a GIC save from the GIC code + then doing a second GIC save with save secure all from core PM code.)

Quoted 35 lines

- PM debug support to enable/disable off-mode
? (for testing only, not for merge)

Quoted 23 lines

---

?arch/arm/mach-omap2/omap-mpuss-lowpower.c | ? 10 ++++-
?arch/arm/mach-omap2/omap-wakeupgen.c ? ? ?| ? 47 +++++++++++++++++++-
?arch/arm/mach-omap2/pm-debug.c ? ? ? ? ? ?| ? 17 +++++--
?arch/arm/mach-omap2/pm.h ? ? ? ? ? ? ? ? ?| ? 20 +++++++++
?arch/arm/mach-omap2/pm44xx.c ? ? ? ? ? ? ?| ? 45 +++++++++++++++++++
?arch/arm/mach-omap2/prm44xx.c ? ? ? ? ? ? | ? 66 +++++++++++++++++++++++++++++

?6 files changed, 197 insertions(+), 8 deletions(-)

arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@

?#include "prcm44xx.h"
?#include "prm44xx.h"
?#include "prm-regbits-44xx.h"
+#include "cm44xx.h"

?#ifdef CONFIG_SMP

arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
Quoted 6 lines

? ? ?* In MPUSS OSWR or device OFF, interrupt controller ?contest is lost. ? ? ?*/
? ? mpuss_clear_prev_logic_pwrst();
- ? if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+ ? if (omap4_device_next_state_off())
+ ? ? ? ? ? save_state = 3;

Why?

Quoted 2 lines

I don't see why this check is needed in addition to the mpuss_pd check added just below?

mpuss_pd does not go to off, thats why. It goes to OSWR state during standard device-off. It is possible for it to go to OFF mode, but it is not recommended.

Quoted 12 lines
Quoted 12 lines

+ ? else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) && ? ? ? ? ? ? (pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) ? ? ? ? ? ? save_state = 2;
+ ? else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+ ? ? ? ? ? save_state = 3;
? ? cpu_clear_prev_logic_pwrst(cpu);
? ? set_cpu_next_pwrst(cpu, power_state);

arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 ? ? wakeup_cpu = smp_processor_id();
 ? ? set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
Quoted 7 lines

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 298

Quoted 3 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+ ? if (omap4_device_prev_state_off())
+ ? ? ? ? ? omap4_device_clear_prev_off_state();
+

The 'clear prev off state' is subsequently removed in the last patch "ARM: OMAP4: powerdomain: update mpu / core off counters during device off." ? Why is it needed here?

That patch is moving the clear part to the lost_context_rff func, it is probably not that clear. Should be easier to follow the logic once I re-structure the code a bit more (separate the prm support funcs out to their own set etc.)

Quoted 47 lines
Quoted 47 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 ? ? pwrdm_post_transition();
 
 ? ? return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +0 -0
index 42cd7fb..805d08d 100644
@@ -32,6 +32,7 @@
 

?#include "omap4-sar-layout.h"
?#include "common.h"
+#include "pm.h"

?#define NR_REG_BANKS ? ? ? ? ? ? ? 4
?#define MAX_IRQS ? ? ? ? ? 128

arch/arm/mach-omap2/omap-wakeupgen.c +2 -0
@@ -46,6 +47,8 @@ static void __iomem *sar_base;
 ?static DEFINE_SPINLOCK(wakeupgen_lock);
 ?static unsigned int irq_target_cpu[NR_IRQS];
 
+static struct powerdomain *mpuss_pd;
+

?/*
? * Static helper functions.
? */

arch/arm/mach-omap2/omap-wakeupgen.c +0 -0
@@ -259,7 +262,7 @@ static void irq_save_context(void)

?/*
? * Clear WakeupGen SAR backup status.
? */

arch/arm/mach-omap2/omap-wakeupgen.c +1 -1
-void irq_sar_clear(void)
+static void irq_sar_clear(void)

?{
? ? u32 val;
? ? val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);

arch/arm/mach-omap2/omap-wakeupgen.c +0 -0
@@ -271,7 +274,7 @@ void irq_sar_clear(void)

? * Save GIC and Wakeupgen interrupt context using secure API ? * for HS/EMU devices.
? */

arch/arm/mach-omap2/omap-wakeupgen.c +1 -1
-static void irq_save_secure_context(void)
+static void irq_save_secure_gic(void)

?{
? ? u32 ret;
? ? ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,

arch/arm/mach-omap2/omap-wakeupgen.c +0 -0
@@ -282,6 +285,40 @@ static void irq_save_secure_context(void)
 ?}

?#endif

Quoted 5 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void)

Quoted 3 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+static void save_secure_ram(void)
+{
+ ? u32 ret;

CodingStyle nit: blank line needed here (and in multiple other places)

Okay.

Quoted 14 lines
Quoted 14 lines

+ ? ret = omap_secure_dispatcher(OMAP4_HAL_SAVESECURERAM_INDEX,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? FLAG_START_CRITICAL,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? 1, omap_secure_ram_mempool_base(),
+ ? ? ? ? ? ? ? ? ? ? ? ? ? 0, 0, 0);
+ ? if (ret != API_HAL_RET_VALUE_OK)
+ ? ? ? ? ? pr_err("Secure ram context save failed\n");

arch/arm/mach-omap2/omap-wakeupgen.c +7 -0
+}
+
+static void save_secure_all(void)
+{
+ ? u32 ret;
+ ? ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? FLAG_START_CRITICAL,
Quoted 8 lines
Quoted 5 lines

+ ? ? ? ? ? ? ? ? ? ? ? ? ? 1, omap_secure_ram_mempool_base(),
+ ? ? ? ? ? ? ? ? ? ? ? ? ? 0, 0, 0);
+ ? if (ret != API_HAL_RET_VALUE_OK)
+ ? ? ? ? ? pr_err("Secure all context save failed\n"); +}

This secure mode save/restore seems misplaced in the wakeupgen driver. Seems to me like it belongs in omap-secure.c.

Can't really move it there, as described above. Unless we want to save GIC context twice.

Quoted 10 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void)

Quoted 7 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
+
+static void irq_save_secure_context(void)
+{
+ ? if (omap4_device_next_state_off()) {
+ ? ? ? ? ? save_secure_all();
+ ? } else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {

Why is this check needed? ?This is called from the CPU_CLUSTER_PM_ENTER notifier, which AFAICT, is only called when the cluster is going off.

This is checking against the different MPU PD states we can go into. If:
- MPU OSWR => GIC save needed only
- MPU OFF => GIC + secure RAM save needed (not recommended to be used though)
- MPU OSWR / OFF + device-off => save all needed

Quoted 143 lines
Quoted 127 lines

+ ? ? ? ? ? irq_save_secure_gic();
+ ? ? ? ? ? save_secure_ram();
+ ? } else {
+ ? ? ? ? ? irq_save_secure_gic();
+ ? }

arch/arm/mach-omap2/omap-wakeupgen.c +2 -0
+}
+

?#ifdef CONFIG_HOTPLUG_CPU
?static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long action, void *hcpu)

arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
@@ -388,5 +425,11 @@ int __init omap_wakeupgen_init(void)
 ? ? irq_hotplug_init();
 ? ? irq_pm_init();
 
+ ? mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+ ? if (!mpuss_pd) {
+ ? ? ? ? ? pr_err("wakeupgen: unable to get mpu_pwrdm\n");
+ ? ? ? ? ? return -EINVAL;
+ ? }
+
 ? ? return 0;
 ?}
arch/arm/mach-omap2/pm-debug.c +1 -0
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 ?u32 enable_off_mode;
 ?static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 

?#ifdef CONFIG_DEBUG_FS
?#include <linux/debugfs.h>

arch/arm/mach-omap2/pm-debug.c +0 -0
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)

? ? ? ? ? ? else
? ? ? ? ? ? ? ? ? ? omap_pm_disable_off_mode();

- ? ? ? ? ? omap3_pm_off_mode_enable(val);
+ ? ? ? ? ? if (off_mode_enable_func)
+ ? ? ? ? ? ? ? ? ? off_mode_enable_func(val);
? ? }

? ? if (option == &enable_oswr_mode)

arch/arm/mach-omap2/pm-debug.c +9 -4
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 ? ? pwrdm_for_each(pwrdms_setup, (void *)d);
 
- ? if (cpu_is_omap34xx())
- ? ? ? ? ? (void) debugfs_create_file("enable_off_mode",
- ? ? ? ? ? ? ? ? ? S_IRUGO | S_IWUSR, d, &enable_off_mode,
- ? ? ? ? ? ? ? ? ? &pm_dbg_option_fops);
+ ? (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);
 
+ ? if (cpu_is_omap34xx())
+ ? ? ? ? ? off_mode_enable_func = omap3_pm_off_mode_enable;
+
+ ? if (cpu_is_omap44xx())
+ ? ? ? ? ? off_mode_enable_func = omap4_pm_off_mode_enable;
+
 ? ? pm_dbg_init_done = 1;
 
 ? ? return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 ?extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 ?extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+ ? return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+ ? return false;
+}
+#endif
+
 ?#if defined(CONFIG_PM_OPP)
 ?extern int omap3_opp_init(void);
 ?extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +0 -0
index 07ac0d3..8f0ec56 100644
@@ -87,6 +87,27 @@ static int omap4_pm_suspend(void)
 ?}

?#endif /* CONFIG_SUSPEND */

arch/arm/mach-omap2/pm44xx.c +10 -0
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states: ? ? ?what states are available
+ * @req_min_state: what state is the minimum we'd like to hit
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case, the next higher power
+ * state which is supported is returned. This is because a combination
+ * of system power states where the parent PD's state is not in line

arch/arm/mach-omap2/pm44xx.c static int omap4_pm_suspend(void) · line 109

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ * with expectation can result in system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state)
+{
+ ? u16 mask = 0xFF << req_min_state;
+
+ ? if (available_states & mask)
+ ? ? ? ? ? return __ffs(available_states & mask);
+ ? return PWRDM_POWER_ON;
+}

This feature needs to be generalized (preferably on top of functional power states) because we have the same need on various AM3xxx SoCs which don't support RET/OFF. ?Mark Greer has started on this, but I think it needs to be part of the functional power states work.

Quoted 5 lines
Quoted 1 line

It also needs to be part of the powerdomain layer, IMO.

So, are you saying this whole set should be re-based on top of the functional power states stuff? If yes, that can be done (Jean actually already did some work on this and got it working I think.)

Indeed, cf. [1]. It has been done and works on OMAP3&4 with cpuidle and suspend/resume.

Quoted 134 lines
Quoted 74 lines
Quoted 56 lines

?static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) ?{
? ? struct power_state *pwrst;

arch/arm/mach-omap2/pm44xx.c +24 -0
@@ -115,6 +136,30 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 ? ? return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 ?}
 
+void omap4_pm_off_mode_enable(int enable)
+{
+ ? u32 next_state = PWRDM_POWER_RET;
+ ? u32 next_logic_state = PWRDM_POWER_ON;
+ ? struct power_state *pwrst;
+
+ ? if (enable) {
+ ? ? ? ? ? next_state = PWRDM_POWER_OFF;
+ ? ? ? ? ? next_logic_state = PWRDM_POWER_OFF;
+ ? }
+
+ ? omap4_device_set_state_off(enable);
+
+ ? list_for_each_entry(pwrst, &pwrst_list, node) {
+ ? ? ? ? ? pwrst->next_state =
+ ? ? ? ? ? ? ? ? ? get_achievable_state(pwrst->pwrdm->pwrsts, next_state);
+ ? ? ? ? ? pwrst->next_logic_state =
+ ? ? ? ? ? ? ? ? ? get_achievable_state(pwrst->pwrdm->pwrsts_logic_ret,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? next_logic_state);
+ ? ? ? ? ? omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+ ? ? ? ? ? pwrdm_set_logic_retst(pwrst->pwrdm, pwrst->next_logic_state);
+ ? }
+}
+
 ?void omap4_pm_oswr_mode_enable(int enable)
 ?{
 ? ? u32 next_logic_state;
arch/arm/mach-omap2/prm44xx.c +13 -0
index 09d84de..86c6c6b 100644
@@ -289,6 +289,72 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 ? ? ? ? ? ? ? ? ? ? OMAP4_PRM_IO_PMCTRL_OFFSET);
 ?}
 
+/**
+ * omap4_device_set_state_off() - setup device off state
+ * @enable: ? ? ? ?set to off or not.
+ *
+ * When Device OFF is enabled, Device is allowed to perform
+ * transition to off mode as soon as all power domains in MPU, IVA
+ * and CORE voltage are in OFF or OSWR state (open switch retention)
+ */
+void omap4_device_set_state_off(u8 enable)
+{
+ ? if (enable)
+ ? ? ? ? ? omap4_prminst_write_inst_reg(0x1 <<
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_DEVICE_OFF_ENABLE_SHIFT,

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 314

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_PARTITION,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_DEVICE_INST,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+ ? else
+ ? ? ? ? ? omap4_prminst_write_inst_reg(0x0 <<
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_DEVICE_OFF_ENABLE_SHIFT,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_PARTITION,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_DEVICE_INST,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET);
+}

minor: a more compact, and more readable (so it's obvious at first glance that the same register is being written) would be:

void omap4_device_set_state_off(u8 enable)
{
? ? ? ? u8 val = enable ? 0x1 : 0x0;

Quoted 6 lines

? ? ? omap4_prminst_write_inst_reg(val <<
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_DEVICE_OFF_ENABLE_SHIFT, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_PARTITION, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_DEVICE_INST, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET); }

True.

Quoted 15 lines

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void)

Quoted 12 lines
arch/arm/mach-omap2/prm44xx.c +11 -0
+/**
+ * omap4_device_prev_state_off:
+ * returns true if the device hit OFF mode
+ * This is API to check whether OMAP is waking up from device OFF mode.
+ * There is no other status bit available for SW to read whether last state
+ * entered was device OFF. To work around this, CORE PD, RFF context state
+ * is used which is lost only when we hit device OFF state
+ */
+bool omap4_device_prev_state_off(void)
+{
+ ? u32 reg;

minor: reg makes me think the result of the read is a register address, not a value. ?How about s/reg/val/.

Yea, good point.

Quoted 33 lines
Quoted 19 lines
arch/arm/mach-omap2/prm44xx.c +18 -0
+ ? reg = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_CORE_INST,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET)
+ ? ? ? ? ? & OMAP4430_LOSTCONTEXT_RFF_MASK;
+
+ ? return reg ? true : false;
+}
+
+void omap4_device_clear_prev_off_state(void)
+{
+ ? omap4_prminst_write_inst_reg(OMAP4430_LOSTCONTEXT_RFF_MASK |
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_LOSTCONTEXT_DFF_MASK,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_PARTITION,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4430_PRM_CORE_INST,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET);
+}
+
+/**

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void)

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+ * omap4_device_next_state_off:
+ * returns true if the device next state is OFF
+ * This is API to check whether OMAP is programmed for device OFF
+ */
+bool omap4_device_next_state_off(void)
+{
+ ? return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION,
+ ? ? ? ? ? ? ? ? ? OMAP4430_PRM_DEVICE_INST,
+ ? ? ? ? ? ? ? ? ? OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET)
+ ? ? ? ? ? ? ? ? ? & OMAP4430_DEVICE_OFF_ENABLE_MASK ? true : false;

minor: when using these long register read helpers, IMO readability improves if this is of the form:

Quoted 17 lines
Quoted 3 lines

? ? ? ?val = <read register>;
? ? ? ?val &= <mask>;
? ? ? ?return val ? true : false;

True.

Quoted 9 lines

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 358

Quoted 6 lines
arch/arm/mach-omap2/prm44xx.c +2 -0
+}
+
 ?static int __init omap4xxx_prcm_init(void)
 ?{
 ? ? if (cpu_is_omap44xx()) {

Kevin

Jean

#11 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

Quoted 74 lines · Jean Pihet

Hi Tero, Kevin, Santosh,

Quoted 9 lines · Tero Kristo
Quoted 8 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

OFF mode is disabled by default,

why?

Good question. For historical reference I guess. The device off works pretty nicely with the current kernel already, so it should be possible to enable it by default and blame the people who break it.

Agree. The next problem is 'who will fix the breakage?'.

Quoted 39 lines
Quoted 17 lines
Quoted 5 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. ?Basically, I think this feature needs to be supported by using constraints on functional power states. ? Having checks all over the place is getting unwieldy and not attractive to maintain.

Quoted 4 lines

The combination of constraints and functional power states should make this much more manageable. ? Until we have that, I'd prefer to keep the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Okay, this sounds like a good plan.

Quoted 7 lines
Quoted 3 lines
[t-kristo at ti.com: largely re-structured the code]

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

Yeah... I am not quite sure where the line goes here as I am modifying the patches quite heavily but try to keep credits to the original authors... will change this like so.

Quoted 3 lines

First, ?some general comments:

Quoted 7 lines
Quoted 3 lines

There is a lot going on in this patch, so it is hard to follow what all is related, and why. ?Just a quick glance suggests it needs to be broken up into at least a few parts:

What is the merge plan for the func power state stuff? I don't want to create new dependencies if unnecessary. Otherwise the split should be okay.

That is something I am interested in too ;p
I did port and test Tero's patches on top of the functional power states, which is the logical approach to me. Now given the reviews status on both this patch series and the func power states series I am not sure which one needs to be ported on top of the other ;-|
[1] https://gitorious.org/jpihet/linux-omap/commits/omap4_dev_off

Quoted 3 lines

Using the functional power states for the OMAP4 core and device off has some advantages in simplifying the code, especially in the previous/current/next states checking and programming.

For these reasons, I suggest basing this series on top of the functional power states series.

Kevin

#12 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

In reply to Tero Kristo
Quoted 46 lines · Tero Kristo
Quoted 11 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 1 line

OFF mode is disabled by default,

why?

Good question. For historical reference I guess. The device off works pretty nicely with the current kernel already, so it should be possible to enable it by default and blame the people who break it.

Quoted 18 lines
Quoted 6 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. Basically, I think this feature needs to be supported by using constraints on functional
power states. Having checks all over the place is getting unwieldy and
not attractive to maintain.

Quoted 4 lines

The combination of constraints and functional power states should make
this much more manageable. Until we have that, I'd prefer to keep
the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Okay, this sounds like a good plan.

Quoted 4 lines
Quoted 3 lines
[t-kristo at ti.com: largely re-structured the code]
Quoted 7 lines
Quoted 3 lines

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

Yeah... I am not quite sure where the line goes here as I am modifying the patches quite heavily but try to keep credits to the original authors... will change this like so.

I guess it's up to you whether you keep Santosh as author. It all depends how much you've changed the original. But you can use the changlog to give credits to Santosh, or state it was a collaboration, whatever you like. You can say stuff like "based on an origianl patch by...", and/or briefly summarize the changes you made from the original verions, etc.

Quoted 22 lines
Quoted 6 lines

First, some general comments:

There is a lot going on in this patch, so it is hard to follow what all is related, and why. Just a quick glance suggests it needs to be broken up into at least a few parts:

What is the merge plan for the func power state stuff? I don't want to create new dependencies if unnecessary. Otherwise the split should be okay.

Quoted 8 lines

- low-level PRM support: new APIs for various off-mode features) (should probably be done on top of functional power states)
- powerdomain core support or "achievable" states (should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC but it's not obvious why)

This is tightly coupled to GIC because the ROM code has following API calls:

Quoted 7 lines

- save gic
- save secure RAM
- save secure all (gic + RAM + some other mysterious stuff)

It is difficult/impossible to separate these without adding redundant code execution (e.g. doing a GIC save from the GIC code + then doing a second GIC save with save secure all from core PM code.)

Ok, thanks for clarifying.

That should be explained in the changelog for this patch when it's broken up.

Quoted 35 lines
Quoted 35 lines

- PM debug support to enable/disable off-mode
(for testing only, not for merge)

Quoted 23 lines
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 ++++-
 arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++++++++++++++++++-
 arch/arm/mach-omap2/pm-debug.c            |   17 +++++--
 arch/arm/mach-omap2/pm.h                  |   20 +++++++++
 arch/arm/mach-omap2/pm44xx.c              |   45 +++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.c             |   66 +++++++++++++++++++++++++++++
 6 files changed, 197 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +1 -0
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm44xx.h"
 
 #ifdef CONFIG_SMP
 

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 268

Quoted 6 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +2 -1
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+	if (omap4_device_next_state_off())
+		save_state = 3;

Why?

Quoted 6 lines
Quoted 2 lines

I don't see why this check is needed in addition to the mpuss_pd check added just below?

mpuss_pd does not go to off, thats why. It goes to OSWR state during standard device-off. It is possible for it to go to OFF mode, but it is not recommended.

What is confusing is that the check below specifically checks for mpuss_pd == off.

Quoted 20 lines
Quoted 12 lines
Quoted 12 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
+	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+		save_state = 3;
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
Quoted 7 lines

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 298

Quoted 3 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	if (omap4_device_prev_state_off())
+		omap4_device_clear_prev_off_state();
+

The 'clear prev off state' is subsequently removed in the last patch "ARM: OMAP4: powerdomain: update mpu / core off counters during device
off." Why is it needed here?

Quoted 4 lines

That patch is moving the clear part to the lost_context_rff func, it is probably not that clear. Should be easier to follow the logic once I re-structure the code a bit more (separate the prm support funcs out to their own set etc.)

Yes, thanks.

Quoted 78 lines
Quoted 47 lines
Quoted 47 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +5 -2
index 42cd7fb..805d08d 100644
@@ -32,6 +32,7 @@
 
 #include "omap4-sar-layout.h"
 #include "common.h"
+#include "pm.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -46,6 +47,8 @@ static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
+static struct powerdomain *mpuss_pd;
+
 /*
  * Static helper functions.
  */
@@ -259,7 +262,7 @@ static void irq_save_context(void)
 /*
  * Clear WakeupGen SAR backup status.
  */
-void irq_sar_clear(void)
+static void irq_sar_clear(void)
 {
 	u32 val;
 	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
@@ -271,7 +274,7 @@ void irq_sar_clear(void)
  * Save GIC and Wakeupgen interrupt context using secure API
  * for HS/EMU devices.
  */
-static void irq_save_secure_context(void)
+static void irq_save_secure_gic(void)
 {
 	u32 ret;
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
@@ -282,6 +285,40 @@ static void irq_save_secure_context(void)
 }
 #endif
 
Quoted 5 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 290

Quoted 3 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+static void save_secure_ram(void)
+{
+	u32 ret;

CodingStyle nit: blank line needed here (and in multiple other places)

Okay.

Quoted 14 lines
Quoted 14 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVESECURERAM_INDEX,
+				FLAG_START_CRITICAL,
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure ram context save failed\n");
+}
+
+static void save_secure_all(void)
+{
+	u32 ret;
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
+				FLAG_START_CRITICAL,
Quoted 8 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 308

Quoted 5 lines
arch/arm/mach-omap2/omap-wakeupgen.c +5 -0
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure all context save failed\n");
+}

This secure mode save/restore seems misplaced in the wakeupgen driver. Seems to me like it belongs in omap-secure.c.

Quoted 2 lines

Can't really move it there, as described above. Unless we want to save GIC context twice.

OK

Quoted 11 lines
Quoted 10 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 314

Quoted 7 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
+
+static void irq_save_secure_context(void)
+{
+	if (omap4_device_next_state_off()) {
+		save_secure_all();
+	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {

Why is this check needed? This is called from the CPU_CLUSTER_PM_ENTER notifier, which AFAICT, is only called when the cluster is going off.

Quoted 5 lines

This is checking against the different MPU PD states we can go into. If:
- MPU OSWR => GIC save needed only
- MPU OFF => GIC + secure RAM save needed (not recommended to be used though)
- MPU OSWR / OFF + device-off => save all needed

OK, more detailed changelog and descriptive kerneldoc for this function would certainly help.

Quoted 143 lines
Quoted 143 lines
Quoted 127 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+		irq_save_secure_gic();
+		save_secure_ram();
+	} else {
+		irq_save_secure_gic();
+	}
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
 					 unsigned long action, void *hcpu)
@@ -388,5 +425,11 @@ int __init omap_wakeupgen_init(void)
 	irq_hotplug_init();
 	irq_pm_init();
 
+	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+	if (!mpuss_pd) {
+		pr_err("wakeupgen: unable to get mpu_pwrdm\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
arch/arm/mach-omap2/pm-debug.c +12 -5
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 u32 enable_off_mode;
 static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)
 		else
 			omap_pm_disable_off_mode();
 
-		omap3_pm_off_mode_enable(val);
+		if (off_mode_enable_func)
+			off_mode_enable_func(val);
 	}
 
 	if (option == &enable_oswr_mode)
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	if (cpu_is_omap34xx())
-		(void) debugfs_create_file("enable_off_mode",
-			S_IRUGO | S_IWUSR, d, &enable_off_mode,
-			&pm_dbg_option_fops);
+	(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);
 
+	if (cpu_is_omap34xx())
+		off_mode_enable_func = omap3_pm_off_mode_enable;
+
+	if (cpu_is_omap44xx())
+		off_mode_enable_func = omap4_pm_off_mode_enable;
+
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+	return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+	return false;
+}
+#endif
+
 #if defined(CONFIG_PM_OPP)
 extern int omap3_opp_init(void);
 extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +10 -0
index 07ac0d3..8f0ec56 100644
@@ -87,6 +87,27 @@ static int omap4_pm_suspend(void)
 }
 #endif /* CONFIG_SUSPEND */
 
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states:	what states are available
+ * @req_min_state:	what state is the minimum we'd like to hit
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case, the next higher power
+ * state which is supported is returned. This is because a combination
+ * of system power states where the parent PD's state is not in line

arch/arm/mach-omap2/pm44xx.c static int omap4_pm_suspend(void) · line 109

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ * with expectation can result in system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state)
+{
+	u16 mask = 0xFF << req_min_state;
+
+	if (available_states & mask)
+		return __ffs(available_states & mask);
+	return PWRDM_POWER_ON;
+}

This feature needs to be generalized (preferably on top of functional power states) because we have the same need on various AM3xxx SoCs which don't support RET/OFF. Mark Greer has started on this, but I think it needs to be part of the functional power states work.

Quoted 5 lines
Quoted 1 line

It also needs to be part of the powerdomain layer, IMO.

So, are you saying this whole set should be re-based on top of the functional power states stuff? If yes, that can be done (Jean actually already did some work on this and got it working I think.)

Yes please.

Kevin

#13 lore raw

PATCH v2 3/19 ARM: OMAP4: PM: Add device-off support

Quoted 89 lines · Kevin Hilman
Quoted 46 lines · Tero Kristo
Quoted 11 lines · Kevin Hilman

+Jean for functional power states

Quoted 1 line · Tero Kristo

This patch adds device off support to OMAP4 device type.

Description is rather thin for a patch that is doing so much.

Quoted 1 line

OFF mode is disabled by default,

why?

Good question. For historical reference I guess. The device off works pretty nicely with the current kernel already, so it should be possible to enable it by default and blame the people who break it.

Quoted 18 lines
Quoted 6 lines

however, there are two ways to enable OFF mode:
a) In the board file, call omap4_pm_off_mode_enable(1)
b) Enable OFF mode using the debugfs entry echo "1">/sys/kernel/debug/pm_debug/enable_off_mode (conversely echo '0' will disable it as well).

This part needs to be a separate patch.

But, as stated in the core retention series, I'd like to move away from these global flags all together.

The way we manage the disabling of certain states (like off) is already clumsy for OMAP3, and it's getting worse with OMAP4. Basically, I think this feature needs to be supported by using constraints on functional
power states. Having checks all over the place is getting unwieldy and
not attractive to maintain.

Quoted 4 lines

The combination of constraints and functional power states should make
this much more manageable. Until we have that, I'd prefer to keep
the debugfs enable/disable stuff as separate patches at the end of the series used only for testing.

Okay, this sounds like a good plan.

Quoted 4 lines
Quoted 3 lines
[t-kristo at ti.com: largely re-structured the code]
Quoted 7 lines
Quoted 3 lines

then the sign-off above from Santosh probably doesn't apply anymore. You should change that to a Cc and just mention tht this is based upon some original work from Santosh.

Yeah... I am not quite sure where the line goes here as I am modifying the patches quite heavily but try to keep credits to the original authors... will change this like so.

I guess it's up to you whether you keep Santosh as author. It all depends how much you've changed the original. But you can use the changlog to give credits to Santosh, or state it was a collaboration, whatever you like. You can say stuff like "based on an origianl patch by...", and/or briefly summarize the changes you made from the original verions, etc.

Quoted 26 lines
Quoted 6 lines

First, some general comments:

There is a lot going on in this patch, so it is hard to follow what all is related, and why. Just a quick glance suggests it needs to be broken up into at least a few parts:

What is the merge plan for the func power state stuff? I don't want to create new dependencies if unnecessary. Otherwise the split should be okay.

Quoted 8 lines

- low-level PRM support: new APIs for various off-mode features) (should probably be done on top of functional power states)
- powerdomain core support or "achievable" states (should probably be done on top of functional power states)
- IRQ/GIC context save/restore
- secure RAM save/restore (this has been tightly coupled to the GIC but it's not obvious why)

This is tightly coupled to GIC because the ROM code has following API calls:

- save gic
- save secure RAM
- save secure all (gic + RAM + some other mysterious stuff)

Quoted 8 lines
Quoted 3 lines

It is difficult/impossible to separate these without adding redundant code execution (e.g. doing a GIC save from the GIC code + then doing a second GIC save with save secure all from core PM code.)

Ok, thanks for clarifying.

That should be explained in the changelog for this patch when it's broken up.

Ok will add some comment about this.

Quoted 39 lines
Quoted 39 lines
Quoted 38 lines

- PM debug support to enable/disable off-mode
(for testing only, not for merge)

Quoted 23 lines
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   10 ++++-
 arch/arm/mach-omap2/omap-wakeupgen.c      |   47 +++++++++++++++++++-
 arch/arm/mach-omap2/pm-debug.c            |   17 +++++--
 arch/arm/mach-omap2/pm.h                  |   20 +++++++++
 arch/arm/mach-omap2/pm44xx.c              |   45 +++++++++++++++++++
 arch/arm/mach-omap2/prm44xx.c             |   66 +++++++++++++++++++++++++++++
 6 files changed, 197 insertions(+), 8 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +1 -0
index e02c082..7418e7c 100644
@@ -60,6 +60,7 @@
 #include "prcm44xx.h"
 #include "prm44xx.h"
 #include "prm-regbits-44xx.h"
+#include "cm44xx.h"
 
 #ifdef CONFIG_SMP
 

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 268

Quoted 6 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +2 -1
@@ -263,9 +264,13 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+	if (omap4_device_next_state_off())
+		save_state = 3;

Why?

I don't see why this check is needed in addition to the mpuss_pd check added just below?

Quoted 6 lines
Quoted 3 lines

mpuss_pd does not go to off, thats why. It goes to OSWR state during standard device-off. It is possible for it to go to OFF mode, but it is not recommended.

What is confusing is that the check below specifically checks for mpuss_pd == off.

Yes, I guess I'll just drop that check out. Or add an error if someone actually tries to use it.

Quoted 122 lines
Quoted 21 lines
Quoted 13 lines
Quoted 13 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
 		save_state = 2;
+	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+		save_state = 3;
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
@@ -288,6 +293,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
Quoted 7 lines

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 298

Quoted 3 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +3 -0
+	if (omap4_device_prev_state_off())
+		omap4_device_clear_prev_off_state();
+

The 'clear prev off state' is subsequently removed in the last patch "ARM: OMAP4: powerdomain: update mpu / core off counters during device
off." Why is it needed here?

Quoted 4 lines

That patch is moving the clear part to the lost_context_rff func, it is probably not that clear. Should be easier to follow the logic once I re-structure the code a bit more (separate the prm support funcs out to their own set etc.)

Yes, thanks.

Quoted 78 lines
Quoted 47 lines
Quoted 47 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-wakeupgen.c +5 -2
index 42cd7fb..805d08d 100644
@@ -32,6 +32,7 @@
 
 #include "omap4-sar-layout.h"
 #include "common.h"
+#include "pm.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -46,6 +47,8 @@ static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
+static struct powerdomain *mpuss_pd;
+
 /*
  * Static helper functions.
  */
@@ -259,7 +262,7 @@ static void irq_save_context(void)
 /*
  * Clear WakeupGen SAR backup status.
  */
-void irq_sar_clear(void)
+static void irq_sar_clear(void)
 {
 	u32 val;
 	val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
@@ -271,7 +274,7 @@ void irq_sar_clear(void)
  * Save GIC and Wakeupgen interrupt context using secure API
  * for HS/EMU devices.
  */
-static void irq_save_secure_context(void)
+static void irq_save_secure_gic(void)
 {
 	u32 ret;
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEGIC_INDEX,
@@ -282,6 +285,40 @@ static void irq_save_secure_context(void)
 }
 #endif
 
Quoted 5 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 290

Quoted 3 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+static void save_secure_ram(void)
+{
+	u32 ret;

CodingStyle nit: blank line needed here (and in multiple other places)

Okay.

Quoted 14 lines
Quoted 14 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVESECURERAM_INDEX,
+				FLAG_START_CRITICAL,
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure ram context save failed\n");
+}
+
+static void save_secure_all(void)
+{
+	u32 ret;
+	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
+				FLAG_START_CRITICAL,
Quoted 8 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 308

Quoted 5 lines
arch/arm/mach-omap2/omap-wakeupgen.c +5 -0
+				1, omap_secure_ram_mempool_base(),
+				0, 0, 0);
+	if (ret != API_HAL_RET_VALUE_OK)
+		pr_err("Secure all context save failed\n");
+}

This secure mode save/restore seems misplaced in the wakeupgen driver. Seems to me like it belongs in omap-secure.c.

Quoted 2 lines

Can't really move it there, as described above. Unless we want to save GIC context twice.

OK

Quoted 11 lines
Quoted 10 lines

arch/arm/mach-omap2/omap-wakeupgen.c static void irq_save_secure_context(void) · line 314

Quoted 7 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
+
+static void irq_save_secure_context(void)
+{
+	if (omap4_device_next_state_off()) {
+		save_secure_all();
+	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {

Why is this check needed? This is called from the CPU_CLUSTER_PM_ENTER notifier, which AFAICT, is only called when the cluster is going off.

Quoted 8 lines
Quoted 5 lines

This is checking against the different MPU PD states we can go into. If:
- MPU OSWR => GIC save needed only
- MPU OFF => GIC + secure RAM save needed (not recommended to be used though)
- MPU OSWR / OFF + device-off => save all needed

OK, more detailed changelog and descriptive kerneldoc for this function would certainly help.

Yep will add.

Quoted 144 lines
Quoted 144 lines
Quoted 144 lines
Quoted 128 lines
arch/arm/mach-omap2/omap-wakeupgen.c +13 -0
+		irq_save_secure_gic();
+		save_secure_ram();
+	} else {
+		irq_save_secure_gic();
+	}
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self,
 					 unsigned long action, void *hcpu)
@@ -388,5 +425,11 @@ int __init omap_wakeupgen_init(void)
 	irq_hotplug_init();
 	irq_pm_init();
 
+	mpuss_pd = pwrdm_lookup("mpu_pwrdm");
+	if (!mpuss_pd) {
+		pr_err("wakeupgen: unable to get mpu_pwrdm\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
arch/arm/mach-omap2/pm-debug.c +12 -5
index d9a8e42..d8cf5e5 100644
@@ -40,6 +40,7 @@
 
 u32 enable_off_mode;
 static u32 enable_oswr_mode;
+static void (*off_mode_enable_func) (int);
 
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
@@ -249,7 +250,8 @@ static int option_set(void *data, u64 val)
 		else
 			omap_pm_disable_off_mode();
 
-		omap3_pm_off_mode_enable(val);
+		if (off_mode_enable_func)
+			off_mode_enable_func(val);
 	}
 
 	if (option == &enable_oswr_mode)
@@ -278,16 +280,21 @@ static int __init pm_dbg_init(void)
 
 	pwrdm_for_each(pwrdms_setup, (void *)d);
 
-	if (cpu_is_omap34xx())
-		(void) debugfs_create_file("enable_off_mode",
-			S_IRUGO | S_IWUSR, d, &enable_off_mode,
-			&pm_dbg_option_fops);
+	(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);
 
+	if (cpu_is_omap34xx())
+		off_mode_enable_func = omap3_pm_off_mode_enable;
+
+	if (cpu_is_omap44xx())
+		off_mode_enable_func = omap4_pm_off_mode_enable;
+
 	pm_dbg_init_done = 1;
 
 	return 0;
arch/arm/mach-omap2/pm.h +20 -0
index c36ab63..d95f8c5 100644
@@ -18,6 +18,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 omap4_pm_off_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);
@@ -25,6 +26,25 @@ extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
+#ifdef CONFIG_PM
+extern void omap4_device_set_state_off(u8 enable);
+extern bool omap4_device_prev_state_off(void);
+extern bool omap4_device_next_state_off(void);
+extern void omap4_device_clear_prev_off_state(void);
+#else
+static inline void omap4_device_set_state_off(u8 enable)
+{
+}
+static inline bool omap4_device_prev_state_off(void)
+{
+	return false;
+}
+static inline bool omap4_device_next_state_off(void)
+{
+	return false;
+}
+#endif
+
 #if defined(CONFIG_PM_OPP)
 extern int omap3_opp_init(void);
 extern int omap4_opp_init(void);
arch/arm/mach-omap2/pm44xx.c +10 -0
index 07ac0d3..8f0ec56 100644
@@ -87,6 +87,27 @@ static int omap4_pm_suspend(void)
 }
 #endif /* CONFIG_SUSPEND */
 
+/**
+ * get_achievable_state() - Provide achievable state
+ * @available_states:	what states are available
+ * @req_min_state:	what state is the minimum we'd like to hit
+ *
+ * Power domains have varied capabilities. When attempting a low power
+ * state such as OFF/RET, a specific min requested state may not be
+ * supported on the power domain, in which case, the next higher power
+ * state which is supported is returned. This is because a combination
+ * of system power states where the parent PD's state is not in line

arch/arm/mach-omap2/pm44xx.c static int omap4_pm_suspend(void) · line 109

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ * with expectation can result in system instabilities.
+ */
+static inline u8 get_achievable_state(u8 available_states, u8 req_min_state)
+{
+	u16 mask = 0xFF << req_min_state;
+
+	if (available_states & mask)
+		return __ffs(available_states & mask);
+	return PWRDM_POWER_ON;
+}

This feature needs to be generalized (preferably on top of functional power states) because we have the same need on various AM3xxx SoCs which don't support RET/OFF. Mark Greer has started on this, but I think it needs to be part of the functional power states work.

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

It also needs to be part of the powerdomain layer, IMO.

So, are you saying this whole set should be re-based on top of the functional power states stuff? If yes, that can be done (Jean actually already did some work on this and got it working I think.)

Yes please.

Okay, next version will be based on top of func power states.

-Tero

#14 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

In reply to Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

---
 arch/arm/mach-omap2/cm44xx.h              |    5 +
 arch/arm/mach-omap2/dpll44xx.c            |  271 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   14 +-
 3 files changed, 285 insertions(+), 5 deletions(-)
arch/arm/mach-omap2/cm44xx.h +5 -0
index 3380bee..5fba0fa 100644
@@ -23,4 +23,9 @@
 #define OMAP4_CM_CLKSTCTRL				0x0000
 #define OMAP4_CM_STATICDEP				0x0004
 
+#ifndef __ASSEMBLER__
+extern void omap4_dpll_prepare_off(void);
+extern void omap4_dpll_resume_off(void);
+#endif
+
 #endif
arch/arm/mach-omap2/dpll44xx.c +271 -0

286 lines not on this page · raw message

arch/arm/mach-omap2/omap-mpuss-lowpower.c +9 -5
index 7418e7c..0a1d5c5 100644
@@ -264,13 +264,15 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 * In MPUSS OSWR or device OFF, interrupt controller  contest is lost.
 	 */
 	mpuss_clear_prev_logic_pwrst();
-	if (omap4_device_next_state_off())
+	if (omap4_device_next_state_off()) {
+		omap4_dpll_prepare_off();
 		save_state = 3;
-	else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
-		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF))
+	} else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
+		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) {
 		save_state = 2;
-	else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF)
+	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
 		save_state = 3;
+	}
 
 	cpu_clear_prev_logic_pwrst(cpu);
 	set_cpu_next_pwrst(cpu, power_state);
@@ -293,8 +295,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
-	if (omap4_device_prev_state_off())
+	if (omap4_device_prev_state_off()) {
+		omap4_dpll_resume_off();
 		omap4_device_clear_prev_off_state();
+	}
 
 	pwrdm_post_transition();
 
Signature · 1 line
1.7.4.1
#15 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines

Some general comments:

- the register dump/print doesn't belong here. If needed, should be a debug feature if needed.

- Rather than hooking into omap4_enter_lowpower(), should use the cluster PM enter/exit notifier chain.

Kevin

#16 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 15 lines · Kevin Hilman
Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines
Quoted 8 lines

Some general comments:

- the register dump/print doesn't belong here. ?If needed, should be a ?debug feature if needed.

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Regards
Santosh

#17 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 21 lines · Santosh
Quoted 20 lines · Kevin Hilman
Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines

Some general comments:

- the register dump/print doesn't belong here. ?If needed, should be a ?debug feature if needed.

Quoted 9 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Regards
Santosh

#18 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 29 lines · Santosh
Quoted 27 lines · Santosh
Quoted 15 lines · Kevin Hilman
Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines
Quoted 8 lines

Some general comments:

- the register dump/print doesn't belong here. ?If needed, should be a ?debug feature if needed.

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Yes, I like this idea.

It allows a much cleaner collection of all the activities needed for device off.

Kevin

#19 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 34 lines · Kevin Hilman
Quoted 32 lines · Santosh
Quoted 30 lines · Santosh
Quoted 15 lines · Kevin Hilman
Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines
Quoted 8 lines

Some general comments:

- the register dump/print doesn't belong here. If needed, should be a debug feature if needed.

- Rather than hooking into omap4_enter_lowpower(), should use the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Quoted 8 lines
Quoted 3 lines

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Yes, I like this idea.

It allows a much cleaner collection of all the activities needed for device off.

I can just read the device next state off in the notifier func.

-Tero

#20 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

In reply to Shilimkar, Santosh
Quoted 5 lines · Santosh
Quoted 3 lines · Santosh
Quoted 2 lines · Kevin Hilman

Tero Kristo <[email protected]> writes:

[...]

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Like the overall idea, but one minor dumb concern might be sequencing of notifiers
- OFF entry and restore needs things to be executed in a specific sequence.
How do we plan to ensure the sequence is maintained in a notifier call chain? one
possible option might be a "priority" based scheme?

Regards,
Nishanth Menon

#21 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 21 lines · Nishanth
Quoted 5 lines · Santosh
Quoted 3 lines · Santosh
Quoted 2 lines · Kevin Hilman

Tero Kristo <[email protected]> writes:

[...]

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Quoted 6 lines

Like the overall idea, but one minor dumb concern might be sequencing of notifiers
- OFF entry and restore needs things to be executed in a specific sequence.
How do we plan to ensure the sequence is maintained in a notifier call chain? one
possible option might be a "priority" based scheme?

Or just combine the events that need a specific sequence into single notifier callback function.

Kevin

#22 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 30 lines · Kevin Hilman
Quoted 21 lines · Nishanth
Quoted 5 lines · Santosh
Quoted 3 lines · Santosh
Quoted 2 lines · Kevin Hilman

Tero Kristo <[email protected]> writes:

[...]

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Quoted 6 lines

Like the overall idea, but one minor dumb concern might be sequencing of notifiers
?- OFF entry and restore needs things to be executed in a specific sequence. How do we plan to ensure the sequence is maintained in a notifier call chain? one
possible option might be a "priority" based scheme?

Quoted 2 lines

Or just combine the events that need a specific sequence into single notifier callback function.

There is other issues in case of failure cases -> abort of OFF sequence due to pending interrupt
detected as part of a notifier - error handling needs to be sane in proper sequence.
I understand and appreciate the intent of replacing the single mega enter_sleep with a chain of notifiers
but any such option will need to be scalable enough to handle weird erratum handling (HSI CAWAKE as an example)
which potentially break the logic flow and be either be equal or better than what we have today interms of
error handling. since these notifiers will be triggered for CPUIDLE(performance sensitive) and suspend, the intricacies might be better understood by seeing how this proposed notifiers look like.

Regards,
Nishanth Menon

#23 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 33 lines · Nishanth
Quoted 30 lines · Kevin Hilman
Quoted 21 lines · Nishanth
Quoted 5 lines · Santosh
Quoted 3 lines · Santosh
Quoted 2 lines · Kevin Hilman

Tero Kristo <[email protected]> writes:

[...]

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Quoted 6 lines

Like the overall idea, but one minor dumb concern might be sequencing of notifiers
?- OFF entry and restore needs things to be executed in a specific sequence. How do we plan to ensure the sequence is maintained in a notifier call chain? one
possible option might be a "priority" based scheme?

Quoted 2 lines

Or just combine the events that need a specific sequence into single notifier callback function.

Quoted 13 lines

There is other issues in case of failure cases -> abort of OFF sequence due to pending interrupt
detected as part of a notifier - error handling needs to be sane in proper sequence.
I understand and appreciate the intent of replacing the single mega enter_sleep with a chain of notifiers
but any such option will need to be scalable enough to handle weird erratum handling (HSI CAWAKE as an example)
which potentially break the logic flow and be either be equal or better than what we have today interms of
error handling. since these notifiers will be triggered for CPUIDLE(performance sensitive) and suspend, the intricacies might be better understood by seeing how this proposed notifiers look like.

Makes sense. Thanks for clarifying.

What $SUBJECT series proposed was indeed a "mega function", but one that was just a list of function calls with no error checking or recovery, and no documentation/description about dependencies/sequencing etc. etc. Based on the patches at hadn (which is all reviewers have to go on), notifiers seemed to be a good fit.

If there are good reasons that all of the device-off events need to be coordinated/synchronized/sequenced (and it sounds like there are, thanks for pointing them out), I am not opposed to that approach. It simply needs to be well described in the changlog.

Thanks,

Kevin

#24 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

Quoted 57 lines · Kevin Hilman
Quoted 33 lines · Nishanth
Quoted 30 lines · Kevin Hilman
Quoted 21 lines · Nishanth
Quoted 5 lines · Santosh
Quoted 3 lines · Santosh
Quoted 2 lines · Kevin Hilman

Tero Kristo <[email protected]> writes:

[...]

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use ?the cluster PM enter/exit notifier chain.

This is again specific to device OFF only and not related to CPU cluster state as such. So I don't think notifiers should be used here.

Quoted 6 lines
Quoted 3 lines

O.w even when we attempt just MPU OSWR C-state, all these functions will get called in notifier chain.

Just a thought, we can have a separate notifier chain for device OFF. It can allow use to get rid of 'enable_off_mode" kind of flags and can be used by many drivers too.

Quoted 6 lines

Like the overall idea, but one minor dumb concern might be sequencing of notifiers
?- OFF entry and restore needs things to be executed in a specific sequence. How do we plan to ensure the sequence is maintained in a notifier call chain? one
possible option might be a "priority" based scheme?

Quoted 2 lines

Or just combine the events that need a specific sequence into single notifier callback function.

Quoted 13 lines

There is other issues in case of failure cases -> abort of OFF sequence due to pending interrupt
detected as part of a notifier - error handling needs to be sane in proper sequence.
I understand and appreciate the intent of replacing the single mega enter_sleep with a chain of notifiers
but any such option will need to be scalable enough to handle weird erratum handling (HSI CAWAKE as an example)
which potentially break the logic flow and be either be equal or better than what we have today interms of
error handling. since these notifiers will be triggered for CPUIDLE(performance sensitive) and suspend, the intricacies might be better understood by seeing how this proposed notifiers look like.

Makes sense. ?Thanks for clarifying.

What $SUBJECT series proposed was indeed a "mega function", but one that was just a list of function calls with no error checking or recovery, and no documentation/description about dependencies/sequencing etc. etc. Based on the patches at hadn (which is all reviewers have to go on), notifiers seemed to be a good fit.

Quoted 5 lines

If there are good reasons that all of the device-off events need to be coordinated/synchronized/sequenced (and it sounds like there are, thanks for pointing them out), I am not opposed to that approach. ?It simply needs to be well described in the changlog.

There are sequence dependencies but lot of code can be extracted and put into smaller blocks that is independent.

I agree for the error handling part notifier chain could be an issue.

Regards
Santosh

#25 lore raw

PATCH v2 4/19 ARM: OMAP4: PM: save/restore all DPLL settings in OFF mode

In reply to Kevin Hilman
Quoted 15 lines · Kevin Hilman
Quoted 7 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

SAR/ROM code restores only CORE DPLL to its original state post wakeup from OFF mode.
The rest of the DPLL's in OMAP4 platform (MPU/IVA/ABE/USB/PER) are saved and restored here during an OFF transition.

Quoted 5 lines
Quoted 4 lines

Some general comments:

- the register dump/print doesn't belong here. If needed, should be a debug feature if needed.

Okay, I'll just drop it out.

Quoted 3 lines

- Rather than hooking into omap4_enter_lowpower(), should use the cluster PM enter/exit notifier chain.

Yes can do that.

-Tero

#26 lore raw

PATCH v2 5/19 ARM: OMAP4: PM: save/restore all CM1/2 settings in OFF mode

In reply to Tero Kristo

From: Rajendra Nayak <[email protected]>

Restore all CM1/2 module registers as they are lost in OFF mode.

---
 arch/arm/mach-omap2/cm44xx.c              |  328 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/cm44xx.h              |    2 +
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |    2 +
 3 files changed, 332 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/cm44xx.c +328 -0
index 535d66e..1958808 100644
@@ -21,8 +21,11 @@
 #include "iomap.h"
 #include "common.h"
 #include "cm.h"
+#include "cm44xx.h"
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
+#include "cminst44xx.h"
+#include "prcm44xx.h"
 #include "cm-regbits-44xx.h"
 
 /* CM1 hardware module low-level functions */
@@ -50,3 +53,328 @@ void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 reg)
 {
 	__raw_writel(val, OMAP44XX_CM2_REGADDR(inst, reg));
 }
+
+#define MAX_CM_REGISTERS 51
+
+struct omap4_cm_reg {
+	u16 offset;
+	u32 val;
+};
+
+struct omap4_cm_regs {
+	u16 mod_off;
+	u16 no_reg;
+	struct omap4_cm_reg reg[MAX_CM_REGISTERS];
+};
+
+static struct omap4_cm_regs cm1_regs[] = {
+	/* OMAP4430_CM1_OCP_SOCKET_MOD */
+	{ .mod_off = OMAP4430_CM1_OCP_SOCKET_INST, .no_reg = 1,
+		{
+			{ OMAP4_CM_CM1_PROFILING_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM1_CKGEN_MOD */
+	{ .mod_off = OMAP4430_CM1_CKGEN_INST, .no_reg = 4,
+		{
+			{ OMAP4_CM_CLKSEL_CORE_OFFSET },
+			{ OMAP4_CM_CLKSEL_ABE_OFFSET },
+			{ OMAP4_CM_DLL_CTRL_OFFSET },
+			{ OMAP4_CM_DYN_DEP_PRESCAL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM1_MPU_MOD */
+	{ .mod_off = OMAP4430_CM1_MPU_INST, .no_reg = 4,
+		{
+			{ OMAP4_CM_MPU_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_MPU_STATICDEP_OFFSET },
+			{ OMAP4_CM_MPU_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_MPU_MPU_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM1_TESLA_MOD */
+	{ .mod_off = OMAP4430_CM1_TESLA_INST, .no_reg = 4,
+		{
+			{ OMAP4_CM_TESLA_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_TESLA_STATICDEP_OFFSET },
+			{ OMAP4_CM_TESLA_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_TESLA_TESLA_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM1_ABE_MOD */
+	{ .mod_off = OMAP4430_CM1_ABE_INST, .no_reg = 15,
+		{
+			{ OMAP4_CM1_ABE_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_L4ABE_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_AESS_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_SLIMBUS_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET },
+			{ OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET }
+		},
+	},
+};
+
+static struct omap4_cm_regs cm2_regs[] = {
+	/* OMAP4430_CM2_OCP_SOCKET_MOD */
+	{ .mod_off = OMAP4430_CM2_OCP_SOCKET_INST, .no_reg = 1,
+		{
+			{ OMAP4_CM_CM2_PROFILING_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_CKGEN_MOD */
+	{ .mod_off = OMAP4430_CM2_CKGEN_INST, .no_reg = 12,
+		{
+			{ OMAP4_CM_CLKSEL_DUCATI_ISS_ROOT_OFFSET },
+			{ OMAP4_CM_CLKSEL_USB_60MHZ_OFFSET },
+			{ OMAP4_CM_SCALE_FCLK_OFFSET },
+			{ OMAP4_CM_CORE_DVFS_PERF1_OFFSET },
+			{ OMAP4_CM_CORE_DVFS_PERF2_OFFSET },
+			{ OMAP4_CM_CORE_DVFS_PERF3_OFFSET },
+			{ OMAP4_CM_CORE_DVFS_PERF4_OFFSET },
+			{ OMAP4_CM_CORE_DVFS_CURRENT_OFFSET },
+			{ OMAP4_CM_IVA_DVFS_PERF_TESLA_OFFSET },
+			{ OMAP4_CM_IVA_DVFS_PERF_IVAHD_OFFSET },
+			{ OMAP4_CM_IVA_DVFS_PERF_ABE_OFFSET },
+			{ OMAP4_CM_IVA_DVFS_CURRENT_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_ALWAYS_ON_MOD */
+	{ .mod_off = OMAP4430_CM2_ALWAYS_ON_INST, .no_reg = 6,
+		{
+			{ OMAP4_CM_ALWON_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_ALWON_MDMINTC_CLKCTRL_OFFSET },
+			{ OMAP4_CM_ALWON_SR_MPU_CLKCTRL_OFFSET },
+			{ OMAP4_CM_ALWON_SR_IVA_CLKCTRL_OFFSET },
+			{ OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET },
+			{ OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_CORE_MOD */
+	{ .mod_off = OMAP4430_CM2_CORE_INST, .no_reg = 41,
+		{
+			{ OMAP4_CM_L3_1_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L3_1_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L3_1_L3_1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3_2_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L3_2_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L3_2_L3_2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3_2_GPMC_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3_2_OCMC_RAM_CLKCTRL_OFFSET },
+			{ OMAP4_CM_DUCATI_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_DUCATI_STATICDEP_OFFSET },
+			{ OMAP4_CM_DUCATI_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_DUCATI_DUCATI_CLKCTRL_OFFSET },
+			{ OMAP4_CM_SDMA_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_SDMA_STATICDEP_OFFSET },
+			{ OMAP4_CM_SDMA_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_SDMA_SDMA_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_DMM_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_EMIF_FW_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_EMIF_1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_EMIF_2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_DLL_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_EMIF_H1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_EMIF_H2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_MEMIF_DLL_H_CLKCTRL_OFFSET },
+			{ OMAP4_CM_D2D_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_D2D_STATICDEP_OFFSET },
+			{ OMAP4_CM_D2D_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_D2D_SAD2D_CLKCTRL_OFFSET },
+			{ OMAP4_CM_D2D_MODEM_ICR_CLKCTRL_OFFSET },
+			{ OMAP4_CM_D2D_SAD2D_FW_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4CFG_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L4CFG_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L4CFG_L4_CFG_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4CFG_HW_SEM_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4CFG_MAILBOX_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4CFG_SAR_ROM_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INSTR_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L3INSTR_L3_3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_IVAHD_MOD */
+	{ .mod_off = OMAP4430_CM2_IVAHD_INST, .no_reg = 5,
+		{
+			{ OMAP4_CM_IVAHD_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_IVAHD_STATICDEP_OFFSET },
+			{ OMAP4_CM_IVAHD_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET },
+			{ OMAP4_CM_IVAHD_SL2_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_CAM_MOD */
+	{ .mod_off = OMAP4430_CM2_CAM_INST, .no_reg = 5,
+		{
+			{ OMAP4_CM_CAM_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_CAM_STATICDEP_OFFSET },
+			{ OMAP4_CM_CAM_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET },
+			{ OMAP4_CM_CAM_FDIF_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_DSS_MOD */
+	{ .mod_off = OMAP4430_CM2_DSS_INST, .no_reg = 5,
+		{
+			{ OMAP4_CM_DSS_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_DSS_STATICDEP_OFFSET },
+			{ OMAP4_CM_DSS_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET },
+			{ OMAP4_CM_DSS_DEISS_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_GFX_MOD */
+	{ .mod_off = OMAP4430_CM2_GFX_INST, .no_reg = 4,
+		{
+			{ OMAP4_CM_GFX_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_GFX_STATICDEP_OFFSET },
+			{ OMAP4_CM_GFX_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_L3INIT_MOD */
+	{ .mod_off = OMAP4430_CM2_L3INIT_INST, .no_reg = 20,
+		{
+			{ OMAP4_CM_L3INIT_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_STATICDEP_OFFSET },
+			{ OMAP4_CM_L3INIT_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_HSI_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_UNIPRO1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_USB_OTG_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_P1500_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_EMAC_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_SATA_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_TPPSS_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_PCIESS_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_CCPTX_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_XHPI_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_MMC6_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_USB_HOST_FS_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_L4PER_MOD */
+	{ .mod_off = OMAP4430_CM2_L4PER_INST, .no_reg = 51,
+		{
+			{ OMAP4_CM_L4PER_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L4PER_ADC_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_ELM_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_HECC1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_HECC2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_L4PER_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCASP2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCASP3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MGATE_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MSPROHG_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_SLIMBUS2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4PER_I2C5_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_STATICDEP_OFFSET },
+			{ OMAP4_CM_L4SEC_DYNAMICDEP_OFFSET },
+			{ OMAP4_CM_L4SEC_AES1_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_AES2_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_DES3DES_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_PKAEIP29_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_RNG_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET },
+			{ OMAP4_CM_L4SEC_CRYPTODMA_CLKCTRL_OFFSET }
+		},
+	},
+	/* OMAP4430_CM2_CEFUSE_MOD */
+	{ .mod_off = OMAP4430_CM2_CEFUSE_INST, .no_reg = 2,
+		{
+			{ OMAP4_CM_CEFUSE_CLKSTCTRL_OFFSET },
+			{ OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET }
+		},
+	},
+};
+
+static void omap4_cm_part_prepare_off(u32 part, struct omap4_cm_regs *cm_reg,
+				      int size)
+{
+	u32 i, j;
+
+	for (i = 0; i < size; i++, cm_reg++) {
+		for (j = 0; j < cm_reg->no_reg; j++) {
+			cm_reg->reg[j].val =
+			    omap4_cminst_read_inst_reg(part,
+						       cm_reg->mod_off,
+						       cm_reg->reg[j].offset);
+		}
+	}
+}
+
+static void omap4_cm_part_resume_off(u32 part, struct omap4_cm_regs *cm_reg,
+				     int size)
+{
+	u32 i, j;
+
+	for (i = 0; i < size; i++, cm_reg++) {
+		for (j = 0; j < cm_reg->no_reg; j++) {
+			omap4_cminst_write_inst_reg(cm_reg->reg[j].val,
+						    part,
+						    cm_reg->mod_off,
+						    cm_reg->reg[j].offset);
+		}
+	}
+}
+
+void omap4_cm_prepare_off(void)
+{
+	omap4_cm_part_prepare_off(OMAP4430_CM1_PARTITION, cm1_regs,
+				  ARRAY_SIZE(cm1_regs));
+	omap4_cm_part_prepare_off(OMAP4430_CM2_PARTITION, cm2_regs,
+				  ARRAY_SIZE(cm2_regs));
+}
+
+void omap4_cm_resume_off(void)
+{
+	omap4_cm_part_resume_off(OMAP4430_CM1_PARTITION, cm1_regs,
+				 ARRAY_SIZE(cm1_regs));
+	omap4_cm_part_resume_off(OMAP4430_CM2_PARTITION, cm2_regs,
+				 ARRAY_SIZE(cm2_regs));
+}
arch/arm/mach-omap2/cm44xx.h +2 -0
index 5fba0fa..b3b0f21 100644
@@ -24,6 +24,8 @@
 #define OMAP4_CM_STATICDEP				0x0004
 
 #ifndef __ASSEMBLER__
+extern void omap4_cm_prepare_off(void);
+extern void omap4_cm_resume_off(void);
 extern void omap4_dpll_prepare_off(void);
 extern void omap4_dpll_resume_off(void);
 #endif
arch/arm/mach-omap2/omap-mpuss-lowpower.c +2 -0
index 0a1d5c5..68923af 100644
@@ -265,6 +265,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 */
 	mpuss_clear_prev_logic_pwrst();
 	if (omap4_device_next_state_off()) {
+		omap4_cm_prepare_off();
 		omap4_dpll_prepare_off();
 		save_state = 3;
 	} else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
@@ -297,6 +298,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 
 	if (omap4_device_prev_state_off()) {
 		omap4_dpll_resume_off();
+		omap4_cm_resume_off();
 		omap4_device_clear_prev_off_state();
 	}
 
Signature · 1 line
1.7.4.1
#27 lore raw

PATCH v2 5/19 ARM: OMAP4: PM: save/restore all CM1/2 settings in OFF mode

Quoted 3 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

Restore all CM1/2 module registers as they are lost in OFF mode.

Save and restore?

Also, as in the previous patch. Can this be done using cluster PM
notifier as well? (I realize that this series was probably done
before the PM notifiers were upstream, but now that we have them, we should use them.)

Kevin

#28 lore raw

PATCH v2 5/19 ARM: OMAP4: PM: save/restore all CM1/2 settings in OFF mode

Quoted 4 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

Quoted 9 lines
Quoted 1 line

Restore all CM1/2 module registers as they are lost in OFF mode.

Save and restore?

Also, as in the previous patch. ?Can this be done using cluster PM notifier as well? ? ?(I realize that this series was probably done before the PM notifiers were upstream, but now that we have them, we should use them.)

Device OFF specific and not related to CPU cluster state as such.

Regards
Santosh

#29 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

In reply to Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode. The register layout is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

---------------------------------------------------------------
Access mode Bank Address Range
---------------------------------------------------------------
HS/GP : Public 1 0x4A32_6000 - 0x4A32_6FFF (4kB)
HS/GP : Public 2 0x4A32_7000 - 0x4A32_73FF (1kB)

HS/EMU : Secured
GP : Public 3 0x4A32_8000 - 0x4A32_87FF (2kB)

HS/GP :Secure
write once. 4 0x4A32_9000 - 0x4A32_93FF (1kB)
---------------------------------------------------------------

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

[with contributions for 4460, cleanups from:
Rajeev Kulkarni <[email protected]>
Nishanth Menon <[email protected]>
Axel Haslam <[email protected]>
Avinash.H.M <[email protected]>]

[t-kristo at ti.com: dropped huge data tables as they are no longer needed
with subsequent patches that generate the layouts based on SAR ROM contents, also dropped unnecessary dmm-44xx.h header file.]

---
 arch/arm/mach-omap2/Makefile               |    2 +-
 arch/arm/mach-omap2/cm1_44xx.h             |    2 +
 arch/arm/mach-omap2/cm2_44xx.h             |    2 +
 arch/arm/mach-omap2/omap-mpuss-lowpower.c  |    7 +
 arch/arm/mach-omap2/omap-sar.c             |  330 ++++++++++++++++++++++++++++
 arch/arm/mach-omap2/omap4-common.c         |   28 ---
 arch/arm/mach-omap2/omap4-sar-layout.h     |   50 +++++
 arch/arm/mach-omap2/pm.h                   |   12 +
 arch/arm/plat-omap/include/plat/omap44xx.h |    5 +
 9 files changed, 409 insertions(+), 29 deletions(-)
 create mode 100644 arch/arm/mach-omap2/omap-sar.c
arch/arm/mach-omap2/Makefile +1 -1
index 49f92bc..a978679 100644
@@ -27,7 +27,7 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
 obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= omap-hotplug.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap4-common.o omap-wakeupgen.o \
-					   sleep44xx.o
+					   sleep44xx.o omap-sar.o
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec)
arch/arm/mach-omap2/cm1_44xx.h +2 -0
index 1bc00dc..c21b660 100644
@@ -218,8 +218,10 @@
 #define OMAP4430_CM1_ABE_WDT3_CLKCTRL			OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_INST, 0x0088)
 
 /* Function prototypes */
+#ifndef __ASSEMBLER__
 extern u32 omap4_cm1_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_cm1_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_cm1_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+#endif
 
 #endif
arch/arm/mach-omap2/cm2_44xx.h +2 -0
index b9de72d..3e8871e 100644
@@ -450,8 +450,10 @@
 #define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL		OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_INST, 0x0020)
 
 /* Function prototypes */
+#ifndef __ASSEMBLER__
 extern u32 omap4_cm2_read_inst_reg(s16 inst, u16 idx);
 extern void omap4_cm2_write_inst_reg(u32 val, s16 inst, u16 idx);
 extern u32 omap4_cm2_rmw_inst_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+#endif
 
 #endif
arch/arm/mach-omap2/omap-mpuss-lowpower.c +7 -0
index 68923af..2d994dd 100644
@@ -233,6 +233,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
+	int ret;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -265,6 +266,11 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	 */
 	mpuss_clear_prev_logic_pwrst();
 	if (omap4_device_next_state_off()) {
+		/* Save the device context to SAR RAM */
+		ret = omap_sar_save();
+		if (ret)
+			goto sar_save_failed;
+		omap_sar_overwrite();
 		omap4_cm_prepare_off();
 		omap4_dpll_prepare_off();
 		save_state = 3;
@@ -302,6 +308,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 		omap4_device_clear_prev_off_state();
 	}
 
+sar_save_failed:
 	pwrdm_post_transition();
 
 	return 0;
arch/arm/mach-omap2/omap-sar.c new file +330 -0

330 lines not on this page · raw message

arch/arm/mach-omap2/omap4-common.c +0 -28
index cc6a915..7ea4652 100644
@@ -37,7 +37,6 @@
 static void __iomem *l2cache_base;
 #endif
 
-static void __iomem *sar_ram_base;
 static void __iomem *gic_dist_base_addr;
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
@@ -186,30 +185,3 @@ static int __init omap_l2_cache_init(void)
 }
 early_initcall(omap_l2_cache_init);
 #endif
-
-void __iomem *omap4_get_sar_ram_base(void)
-{
-	return sar_ram_base;
-}
-
-/*
- * SAR RAM used to save and restore the HW
- * context in low power modes
- */
-static int __init omap4_sar_ram_init(void)
-{
-	/*
-	 * To avoid code running on other OMAPs in
-	 * multi-omap builds
-	 */
-	if (!cpu_is_omap44xx())
-		return -ENOMEM;
-
-	/* Static mapping, never released */
-	sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
-	if (WARN_ON(!sar_ram_base))
-		return -ENOMEM;
-
-	return 0;
-}
-early_initcall(omap4_sar_ram_init);
arch/arm/mach-omap2/omap4-sar-layout.h +50 -0

56 lines not on this page · raw message

arch/arm/mach-omap2/pm.h +12 -0
index d95f8c5..ce1e27f 100644
@@ -157,4 +157,16 @@ static inline int omap4_twl_init(void)
 }
 #endif
 
+#ifdef CONFIG_PM
+extern int omap_sar_save(void);
+extern void omap_sar_overwrite(void);
+#else
+static inline void omap_sar_save(void)
+{
+}
+static inline void omap_sar_overwrite(void)
+{
+}
+#endif
+
 #endif
arch/arm/plat-omap/include/plat/omap44xx.h +5 -0
index 1a45700..8e83e16 100644
@@ -22,6 +22,9 @@
 #define L4_PER_44XX_BASE		0x48000000
 #define L4_EMU_44XX_BASE		0x54000000
 #define L3_44XX_BASE			0x44000000
+#define L3_44XX_BASE_CLK1		L3_44XX_BASE
+#define L3_44XX_BASE_CLK2		0x44800000
+#define L3_44XX_BASE_CLK3		0x45000000
 #define OMAP44XX_EMIF1_BASE		0x4c000000
 #define OMAP44XX_EMIF2_BASE		0x4d000000
 #define OMAP44XX_DMM_BASE		0x4e000000
@@ -59,5 +62,7 @@
 #define OMAP44XX_HSUSB_OHCI_BASE	(L4_44XX_BASE + 0x64800)
 #define OMAP44XX_HSUSB_EHCI_BASE	(L4_44XX_BASE + 0x64C00)
 
+#define OMAP44XX_C2C_BASE		0x5c000000
+
 #endif /* __ASM_ARCH_OMAP44XX_H */
 
Signature · 1 line
1.7.4.1
#30 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

Quoted 3 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode.

so why is this patch bothering to save and restore it?

-ECONFUSED

Quoted 13 lines

The register layout
is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

---------------------------------------------------------------
Access mode Bank Address Range
---------------------------------------------------------------
HS/GP : Public 1 0x4A32_6000 - 0x4A32_6FFF (4kB)
HS/GP : Public 2 0x4A32_7000 - 0x4A32_73FF (1kB)

HS/EMU : Secured
GP : Public 3 0x4A32_8000 - 0x4A32_87FF (2kB)

Quoted 8 lines

HS/GP :Secure
write once. 4 0x4A32_9000 - 0x4A32_93FF (1kB)
---------------------------------------------------------------

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

Some general comments:

- can the cluster PM notifier be used for the save path?

- This patch adds lots of data that is immediately removed by the next patch. Probably the two just need to be combined.

- BUG_ON() should not be used unless there is absolutely no recovery
path, since it casues a full kernel panic. Instead, some error
recovery should be added.

Kevin

#31 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode.

so why is this patch bothering to save and restore it?

SAR RAM is maintained(not powered down) but somebody needs to feel the contents which will be preserved :-)

Quoted 19 lines

-ECONFUSED

Quoted 17 lines

The register layout
is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

?--------------------------------------------------------------- ?Access mode ? ? ? ? ?Bank ? ?Address Range ?--------------------------------------------------------------- ?HS/GP : Public ? ? ? ? ? ? ? 1 ? ? ? 0x4A32_6000 - 0x4A32_6FFF (4kB) ?HS/GP : Public ? ? ? ? ? ? ? 2 ? ? ? 0x4A32_7000 - 0x4A32_73FF (1kB)

?HS/EMU : Secured
?GP : Public ? ? ? ? ?3 ? ? ? 0x4A32_8000 - 0x4A32_87FF (2kB)

?HS/GP :Secure
?write once. ? ? ? ? ?4 ? ? ? 0x4A32_9000 - 0x4A32_93FF (1kB) ?---------------------------------------------------------------

Quoted 9 lines
Quoted 4 lines

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

Some general comments:

- can the cluster PM notifier be used for the save path?

Nope. This is for device OFF only case. CPU Cluster state as such has no dependency.

Quoted 3 lines

- This patch adds lots of data that is immediately removed by the next ?patch. ?Probably the two just need to be combined.

iormap() hunk from this patch can be completely dropped since it is getting fixed in next patch. Other infrastructure is maintained.

Quoted 4 lines

- BUG_ON() should not be used unless there is absolutely no recovery ?path, since it casues a full kernel panic. ? Instead, some error ?recovery should be added.

WARN_ON should suffice.

#32 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

Quoted 36 lines · Santosh
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode.

so why is this patch bothering to save and restore it?

SAR RAM is maintained(not powered down) but somebody needs to feel the contents which will be preserved :-)

Quoted 24 lines

-ECONFUSED

Quoted 21 lines

The register layout
is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

?--------------------------------------------------------------- ?Access mode ? ? ? ? ?Bank ? ?Address Range ?--------------------------------------------------------------- ?HS/GP : Public ? ? ? ? ? ? ? 1 ? ? ? 0x4A32_6000 - 0x4A32_6FFF (4kB) ?HS/GP : Public ? ? ? ? ? ? ? 2 ? ? ? 0x4A32_7000 - 0x4A32_73FF (1kB)

?HS/EMU : Secured
?GP : Public ? ? ? ? ?3 ? ? ? 0x4A32_8000 - 0x4A32_87FF (2kB)

?HS/GP :Secure
?write once. ? ? ? ? ?4 ? ? ? 0x4A32_9000 - 0x4A32_93FF (1kB) ?---------------------------------------------------------------

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

Quoted 6 lines
Quoted 4 lines

Some general comments:

- can the cluster PM notifier be used for the save path?

Nope. This is for device OFF only case. CPU Cluster state as such has no dependency.

Yeah, I see now. I like your idea of a device-off notifier chain modeled on the CPU PM notifier chain.

Quoted 5 lines
Quoted 3 lines

- This patch adds lots of data that is immediately removed by the next ?patch. ?Probably the two just need to be combined.

iormap() hunk from this patch can be completely dropped since it is getting fixed in next patch. Other infrastructure is maintained.

Look again at how much stuff is deleted in the next patch that is added in this patch, and think about how a reviewer is supposed to follow that easily.

Quoted 5 lines
Quoted 4 lines

- BUG_ON() should not be used unless there is absolutely no recovery ?path, since it casues a full kernel panic. ? Instead, some error ?recovery should be added.

WARN_ON should suffice.

Not really. Error recovery should be added.

Kevin

#33 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

Quoted 51 lines · Kevin Hilman
Quoted 36 lines · Santosh
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode.

so why is this patch bothering to save and restore it?

SAR RAM is maintained(not powered down) but somebody needs to feel the contents which will be preserved :-)

Quoted 24 lines

-ECONFUSED

Quoted 21 lines

The register layout
is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

?--------------------------------------------------------------- ?Access mode ? ? ? ? ?Bank ? ?Address Range ?--------------------------------------------------------------- ?HS/GP : Public ? ? ? ? ? ? ? 1 ? ? ? 0x4A32_6000 - 0x4A32_6FFF (4kB) ?HS/GP : Public ? ? ? ? ? ? ? 2 ? ? ? 0x4A32_7000 - 0x4A32_73FF (1kB)

?HS/EMU : Secured
?GP : Public ? ? ? ? ?3 ? ? ? 0x4A32_8000 - 0x4A32_87FF (2kB)

?HS/GP :Secure
?write once. ? ? ? ? ?4 ? ? ? 0x4A32_9000 - 0x4A32_93FF (1kB) ?---------------------------------------------------------------

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

Quoted 6 lines
Quoted 4 lines

Some general comments:

- can the cluster PM notifier be used for the save path?

Nope. This is for device OFF only case. CPU Cluster state as such has no dependency.

Yeah, I see now. ?I like your idea of a device-off notifier chain modeled on the CPU PM notifier chain.

Quoted 3 lines
Quoted 3 lines

- This patch adds lots of data that is immediately removed by the next ?patch. ?Probably the two just need to be combined.

Quoted 7 lines
Quoted 2 lines

iormap() hunk from this patch can be completely dropped since it is getting fixed in next patch. Other infrastructure is maintained.

Look again at how much stuff is deleted in the next patch that is added in this patch, and think about how a reviewer is supposed to follow that easily.

OK. With me. Actually with proposed split of further patch, things can be sorted out in different patches quite well.

Quoted 8 lines
Quoted 5 lines
Quoted 4 lines

- BUG_ON() should not be used unless there is absolutely no recovery ?path, since it casues a full kernel panic. ? Instead, some error ?recovery should be added.

WARN_ON should suffice.

Not really. ?Error recovery should be added.

Agree

#34 lore raw

PATCH v2 6/19 ARM: OMAP4: PM: Add SAR backup support towards device OFF

Quoted 55 lines · Santosh
Quoted 54 lines · Kevin Hilman
Quoted 36 lines · Santosh
Quoted 8 lines · Kevin Hilman
Quoted 3 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The SAR RAM is maintained during Device OFF mode.

so why is this patch bothering to save and restore it?

SAR RAM is maintained(not powered down) but somebody needs to feel the contents which will be preserved :-)

Quoted 24 lines

-ECONFUSED

Quoted 21 lines

The register layout
is fixed in SAR ROM. SAR is split into 4 banks with different privilege accesses based on device type

---------------------------------------------------------------
Access mode Bank Address Range
---------------------------------------------------------------

 HS/GP : Public               1       0x4A32_6000 - 0x4A32_6FFF (4kB)
 HS/GP : Public               2       0x4A32_7000 - 0x4A32_73FF (1kB)

HS/EMU : Secured
GP : Public 3 0x4A32_8000 - 0x4A32_87FF (2kB)

HS/GP :Secure
write once. 4 0x4A32_9000 - 0x4A32_93FF (1kB)
---------------------------------------------------------------

The save process is done entirely by software and restore is done by hardware using the auto-restore feature. The restore feature is enabled by default and cannot be disabled. The software must save the data to be restored in a dedicated location in SAR RAM.

Quoted 6 lines
Quoted 4 lines

Some general comments:

- can the cluster PM notifier be used for the save path?

Nope. This is for device OFF only case. CPU Cluster state as such has no dependency.

Yeah, I see now. I like your idea of a device-off notifier chain modeled on the CPU PM notifier chain.

Quoted 5 lines
Quoted 3 lines

- This patch adds lots of data that is immediately removed by the next patch. Probably the two just need to be combined.

iormap() hunk from this patch can be completely dropped since it is getting fixed in next patch. Other infrastructure is maintained.

Quoted 6 lines
Quoted 4 lines

Look again at how much stuff is deleted in the next patch that is added in this patch, and think about how a reviewer is supposed to follow that easily.

OK. With me. Actually with proposed split of further patch, things can be sorted out in different patches quite well.

I'll take a look if I'll merge these patches completely or modify the contents. In some work version I had, this patch was completely merged with the next.

Quoted 10 lines
Quoted 9 lines
Quoted 6 lines
Quoted 5 lines

- BUG_ON() should not be used unless there is absolutely no recovery
path, since it casues a full kernel panic. Instead, some error
recovery should be added.

WARN_ON should suffice.

Not really. Error recovery should be added.

Agree

Will fix that also.

-Tero

#35 lore raw

PATCH v2 7/19 ARM: OMAP4: Auto generate SAR layout contents

In reply to Tero Kristo

SAR layout contents are now generated automatically based on SAR ROM contents during boot.

u32 offset description
---------- -------------------------
0 pointer to next entry
1 size of DMA transfer in bytes
2 SAR RAM address for save / restore
3 IO address for save / restore

sar_layout_generate() parses this info and stores the resulting data to a list of sar_ram_entry structs, which in turn will be used by sar_save.

---
 arch/arm/mach-omap2/omap-sar.c |  270 +++++++++++++++++++++++++++-------------
 1 files changed, 183 insertions(+), 87 deletions(-)
arch/arm/mach-omap2/omap-sar.c +183 -87
index 141aebc..b49ae16 100644
@@ -2,7 +2,8 @@
  * OMAP4 Save Restore source file
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
- * Written by Santosh Shilimkar <[email protected]>
+ * Santosh Shilimkar <[email protected]>
+ * Tero Kristo <[email protected]>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/slab.h>
 
 #include "iomap.h"
 #include "pm.h"
@@ -25,35 +27,18 @@
 #include "cminst44xx.h"
 
 static void __iomem *sar_ram_base;
-static void __iomem *omap4_sar_modules[MAX_SAR_MODULES];
 static struct powerdomain *l3init_pwrdm;
 	static struct clockdomain *l3init_clkdm;
 static struct clk *usb_host_ck, *usb_tll_ck;
 
-/*
- * SAR_RAM1 register layout consist of EMIF1, EMIF2, CM1, CM2,
- * CONTROL_CORE efuse, DMM and USB TLL registers.
- * The layout is arranged is a two dimentional array like
- * below,
- * const u32 sar_ramX_layout[nb_regs_sets][4] = {
- *	{module_index, reg_offset, size, sar_ram_offset},
- * }
- */
-static const u32 omap443x_sar_ram1_layout[][4] = {
-};
-
-/*
- * SAR_RAM2 register layout consist of SYSCTRL_PADCONF_CORE regsiters
- */
-static const u32 omap443x_sar_ram2_layout[][4] = {
+struct sar_ram_entry {
+	void __iomem *io_base;
+	u32 offset;
+	u32 size;
+	u32 ram_addr;
 };
 
-/*
- * SAR_RAM3 and  SAR_RAM4 layout is not listed since moslty it's handle by
- * secure software.
- */
-static const u32 omap443x_sar_ram3_layout[][4] = {
-};
+static struct sar_ram_entry *sar_ram_layout[3];
 
 /*
  * omap_sar_save :
@@ -63,25 +48,20 @@ static const u32 omap443x_sar_ram3_layout[][4] = {
  * @sar_bank_offset - where to backup
  * @sar_layout - constant table containing the backup info
  */
-static void sar_save(u32 nb_regs, u32 sar_bank, const u32 sar_layout_table[][4])
+static void sar_save(struct sar_ram_entry *entry)
 {
-	u32 reg_val, size, i, j;
+	u32 reg_val, size, i;
 	void __iomem *reg_read_addr, *sar_wr_addr;
 
-	for (i = 0; i < nb_regs; i++) {
-		if (omap4_sar_modules[(sar_layout_table[i][MODULE_ADDR_IDX])]) {
-			size = sar_layout_table[i][MODULE_NB_REGS_IDX];
-			reg_read_addr =
-			    omap4_sar_modules[sar_layout_table[i]
-					      [MODULE_ADDR_IDX]]
-			    + sar_layout_table[i][MODULE_OFFSET_IDX];
-			sar_wr_addr = sar_ram_base + sar_bank +
-			    sar_layout_table[i][SAR_RAM_OFFSET_IDX];
-			for (j = 0; j < size; j++) {
-				reg_val = __raw_readl(reg_read_addr + j * 4);
-				__raw_writel(reg_val, sar_wr_addr + j * 4);
-			}
+	while (entry->size) {
+		size = entry->size;
+		reg_read_addr = entry->io_base + entry->offset;
+		sar_wr_addr = sar_ram_base + entry->ram_addr;
+		for (i = 0; i < size; i++) {
+			reg_val = __raw_readl(reg_read_addr + i * 4);
+			__raw_writel(reg_val, sar_wr_addr + i * 4);
 		}
+		entry++;
 	}
 }
 
@@ -100,8 +80,7 @@ static void save_sar_bank3(void)
 	l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
 	clkdm_wakeup(l4_secure_clkdm);
 
-	sar_save(ARRAY_SIZE(omap443x_sar_ram3_layout), SAR_BANK3_OFFSET,
-		 omap443x_sar_ram3_layout);
+	sar_save(sar_ram_layout[2]);
 
 	clkdm_allow_idle(l4_secure_clkdm);
 }
@@ -155,8 +134,7 @@ int omap_sar_save(void)
 	clk_enable(usb_tll_ck);
 
 	/* Save SAR BANK1 */
-	sar_save(ARRAY_SIZE(omap443x_sar_ram1_layout), SAR_BANK1_OFFSET,
-		 omap443x_sar_ram1_layout);
+	sar_save(sar_ram_layout[0]);
 
 	clk_disable(usb_host_ck);
 	clk_disable(usb_tll_ck);
@@ -164,8 +142,7 @@ int omap_sar_save(void)
 	clkdm_allow_idle(l3init_clkdm);
 
 	/* Save SAR BANK2 */
-	sar_save(ARRAY_SIZE(omap443x_sar_ram2_layout), SAR_BANK2_OFFSET,
-		 omap443x_sar_ram2_layout);
+	sar_save(sar_ram_layout[1]);
 
 	return 0;
 }
@@ -189,7 +166,8 @@ int omap_sar_save(void)
 void omap_sar_overwrite(void)
 {
 	u32 val = 0;
-	u32 offset = 0;
+	u32 usb_offset = 0x2ec;
+	u32 usb_offset2 = 0x91c;
 
 	/* Overwriting Phase1 data to be restored */
 	/* CM2 MEMIF_CLKTRCTRL = SW_WKUP, before FREQ UPDATE */
@@ -204,7 +182,7 @@ void omap_sar_overwrite(void)
 	/* CM1 CM_SHADOW_FREQ_CONFIG1, Enable FREQ UPDATE */
 	val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
 	val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
-	val &= ~OMAP4430_DLL_OVERRIDE_MASK;
+	val &= ~OMAP4430_DLL_OVERRIDE_2_2_MASK;
 	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x104);
 	/* CM2 MEMIF_CLKTRCTRL = HW_AUTO, after FREQ UPDATE */
 	__raw_writel(0x3, sar_ram_base + SAR_BANK1_OFFSET + 0x124);
@@ -212,29 +190,29 @@ void omap_sar_overwrite(void)
 	/* Overwriting Phase2a data to be restored */
 	/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 1, MODULEMODE = 2 */
 	__raw_writel(0x00000012,
-		     sar_ram_base + SAR_BANK1_OFFSET + 0x2ec + offset);
+		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset);
 	/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 1, MODULEMODE = 1 */
 	__raw_writel(0x00000011,
-		     sar_ram_base + SAR_BANK1_OFFSET + 0x2f0 + offset);
+		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 4);
 	/* CM2 CM_SDMA_STATICDEP : Enable static depedency for SAR modules */
 	__raw_writel(0x000090e8,
-		     sar_ram_base + SAR_BANK1_OFFSET + 0x2f4 + offset);
+		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 8);
 
 	/* Overwriting Phase2b data to be restored */
 	/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
 	val = __raw_readl(OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL);
 	val &= (OMAP4430_CLKSEL_UTMI_P1_MASK | OMAP4430_CLKSEL_UTMI_P2_MASK);
-	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x91c + offset);
+	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + usb_offset2);
 	/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
 	__raw_writel(0x0000000,
-		     sar_ram_base + SAR_BANK1_OFFSET + 0x920 + offset);
+		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 4);
 	/* CM2 CM_SDMA_STATICDEP : Clear the static depedency */
 	__raw_writel(0x00000040,
-		     sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset);
+		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8);
 
 	/* readback to ensure data reaches to SAR RAM */
 	barrier();
-	val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + 0x924 + offset);
+	val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8);
 }
 
 void __iomem *omap4_get_sar_ram_base(void)
@@ -242,6 +220,152 @@ void __iomem *omap4_get_sar_ram_base(void)
 	return sar_ram_base;
 }
 
+static const u32 sar_rom_phases[] = {
+	0, 0x30, 0x60
+};
+
+struct sar_module {
+	void __iomem *io_base;
+	u32 base;
+	u32 size;
+	bool invalid;
+};
+
+static struct sar_module *sar_modules;
+
+static void sar_ioremap_modules(void)
+{
+	struct sar_module *mod;
+
+	mod = sar_modules;
+
+	while (mod->base) {
+		if (!mod->invalid) {
+			mod->io_base = ioremap(mod->base, mod->size);
+			if (!mod->io_base)
+				pr_err("%s: ioremap failed for %08x[%08x]\n",
+					__func__, mod->base, mod->size);
+			BUG_ON(!mod->io_base);
+		}
+		mod++;
+	}
+}
+
+static int set_sar_io_addr(struct sar_ram_entry *entry, u32 addr)
+{
+	struct sar_module *mod;
+
+	mod = sar_modules;
+
+	while (mod->base) {
+		if (addr >= mod->base && addr <= mod->base + mod->size) {
+			if (mod->invalid)
+				break;
+			entry->io_base = mod->io_base;
+			entry->offset = addr - mod->base;
+			return 0;
+		}
+		mod++;
+	}
+	pr_warn("%s: no matching sar_module for %08x\n", __func__, addr);
+	return -EINVAL;
+}
+
+static int sar_layout_generate(void)
+{
+	int phase;
+	void __iomem *sarrom;
+	u32 rombase, romend, rambase, ramend;
+	u32 offset, next;
+	u16 size;
+	u32 ram_addr, io_addr;
+	void *sarram;
+	struct sar_ram_entry *entry[3];
+	int bank;
+	int ret = 0;
+
+	pr_info("generating sar_ram layout...\n");
+
+	rombase = OMAP44XX_SAR_ROM_BASE;
+	romend = rombase + SZ_8K;
+	rambase = OMAP44XX_SAR_RAM_BASE;
+	ramend = rambase + SAR_BANK4_OFFSET - 1;
+
+	sarrom = ioremap(rombase, SZ_8K);
+
+	/* Allocate temporary memory for sar ram layout */
+	sarram = kmalloc(SAR_BANK4_OFFSET, GFP_KERNEL);
+	for (bank = 0; bank < 3; bank++)
+		entry[bank] = sarram + SAR_BANK2_OFFSET * bank;
+
+	for (phase = 0; phase < ARRAY_SIZE(sar_rom_phases); phase++) {
+		offset = sar_rom_phases[phase];
+
+		while (1) {
+			next = __raw_readl(sarrom + offset);
+			size = __raw_readl(sarrom + offset + 4) & 0xffff;
+			ram_addr = __raw_readl(sarrom + offset + 8);
+			io_addr = __raw_readl(sarrom + offset + 12);
+
+			if (ram_addr >= rambase && ram_addr <= ramend) {
+				/* Valid ram address, add entry */
+				ram_addr -= rambase;
+				bank = ram_addr / SAR_BANK2_OFFSET;
+				if (!set_sar_io_addr(entry[bank], io_addr)) {
+					entry[bank]->size = size;
+					entry[bank]->ram_addr = ram_addr;
+					entry[bank]++;
+				}
+			}
+
+			if (next < rombase || next > romend)
+				break;
+
+			offset = next - rombase;
+		}
+	}
+
+	for (bank = 0; bank < 3; bank++) {
+		size = (u32)entry[bank] -
+			(u32)(sarram + SAR_BANK2_OFFSET * bank);
+		sar_ram_layout[bank] = kmalloc(size +
+			sizeof(struct sar_ram_entry), GFP_KERNEL);
+		if (!sar_ram_layout[bank]) {
+			pr_err("%s: kmalloc failed\n", __func__);
+			goto cleanup;
+		}
+		memcpy(sar_ram_layout[bank], sarram + SAR_BANK2_OFFSET * bank,
+			size);
+		memset((void *)sar_ram_layout[bank] + size, 0,
+			sizeof(struct sar_ram_entry));
+		entry[bank] = sar_ram_layout[bank];
+	}
+
+cleanup:
+	kfree(sarram);
+	iounmap(sarrom);
+	pr_info("sar ram layout created\n");
+	return ret;
+}
+
+static struct sar_module omap44xx_sar_modules[] = {
+	{ .base = OMAP44XX_EMIF1_BASE, .size = SZ_1M },
+	{ .base = OMAP44XX_EMIF2_BASE, .size = SZ_1M },
+	{ .base = OMAP44XX_DMM_BASE, .size = SZ_1M },
+	{ .base = OMAP4430_CM1_BASE, .size = SZ_8K },
+	{ .base = OMAP4430_CM2_BASE, .size = SZ_8K },
+	{ .base = OMAP44XX_C2C_BASE, .size = SZ_1M },
+	{ .base = OMAP443X_CTRL_BASE, .size = SZ_4K },
+	{ .base = L3_44XX_BASE_CLK1, .size = SZ_1M },
+	{ .base = L3_44XX_BASE_CLK2, .size = SZ_1M },
+	{ .base = L3_44XX_BASE_CLK3, .size = SZ_1M },
+	{ .base = OMAP44XX_USBTLL_BASE, .size = SZ_1M },
+	{ .base = OMAP44XX_UHH_CONFIG_BASE, .size = SZ_1M },
+	{ .base = L4_44XX_PHYS, .size = SZ_4M },
+	{ .base = L4_PER_44XX_PHYS, .size = SZ_4M },
+	{ .base = 0 },
+};
+
 /*
  * SAR RAM used to save and restore the HW
  * context in low power modes
@@ -262,39 +386,11 @@ static int __init omap4_sar_ram_init(void)
 	sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
 	BUG_ON(!sar_ram_base);
 
-	/*
-	 * All these are static mappings so ioremap() will
-	 * just return with mapped VA
-	 */
-	omap4_sar_modules[EMIF1_INDEX] = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[EMIF1_INDEX]);
-	omap4_sar_modules[EMIF2_INDEX] = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[EMIF2_INDEX]);
-	omap4_sar_modules[DMM_INDEX] = ioremap(OMAP44XX_DMM_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[DMM_INDEX]);
-	omap4_sar_modules[CM1_INDEX] = ioremap(OMAP4430_CM1_BASE, SZ_8K);
-	BUG_ON(!omap4_sar_modules[CM1_INDEX]);
-	omap4_sar_modules[CM2_INDEX] = ioremap(OMAP4430_CM2_BASE, SZ_8K);
-	BUG_ON(!omap4_sar_modules[CM2_INDEX]);
-	omap4_sar_modules[C2C_INDEX] = ioremap(OMAP44XX_C2C_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[C2C_INDEX]);
-	omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX] =
-	    ioremap(OMAP443X_CTRL_BASE, SZ_4K);
-	BUG_ON(!omap4_sar_modules[CTRL_MODULE_PAD_CORE_INDEX]);
-	omap4_sar_modules[L3_CLK1_INDEX] = ioremap(L3_44XX_BASE_CLK1, SZ_1M);
-	BUG_ON(!omap4_sar_modules[L3_CLK1_INDEX]);
-	omap4_sar_modules[L3_CLK2_INDEX] = ioremap(L3_44XX_BASE_CLK2, SZ_1M);
-	BUG_ON(!omap4_sar_modules[L3_CLK2_INDEX]);
-	omap4_sar_modules[L3_CLK3_INDEX] = ioremap(L3_44XX_BASE_CLK3, SZ_1M);
-	BUG_ON(!omap4_sar_modules[L3_CLK3_INDEX]);
-	omap4_sar_modules[USBTLL_INDEX] = ioremap(OMAP44XX_USBTLL_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[USBTLL_INDEX]);
-	omap4_sar_modules[UHH_INDEX] = ioremap(OMAP44XX_UHH_CONFIG_BASE, SZ_1M);
-	BUG_ON(!omap4_sar_modules[UHH_INDEX]);
-	omap4_sar_modules[L4CORE_INDEX] = ioremap(L4_44XX_PHYS, SZ_4M);
-	BUG_ON(!omap4_sar_modules[L4CORE_INDEX]);
-	omap4_sar_modules[L4PER_INDEX] = ioremap(L4_PER_44XX_PHYS, SZ_4M);
-	BUG_ON(!omap4_sar_modules[L4PER_INDEX]);
+	sar_modules = omap44xx_sar_modules;
+
+	sar_ioremap_modules();
+
+	sar_layout_generate();
 
 	/*
 	 * SAR BANK3 contains all firewall settings and it's saved through
Signature · 1 line
1.7.4.1
#36 lore raw

PATCH v2 8/19 ARM: OMAP4: SAR: generate overwrite data based on SAR ROM contents

In reply to Tero Kristo

omap_sar_overwrite() now uses offsets detected during init time from the SAR ROM contents.

---
 arch/arm/mach-omap2/omap-sar.c |  159 +++++++++++++++++++++++++++++-----------
 1 files changed, 115 insertions(+), 44 deletions(-)
arch/arm/mach-omap2/omap-sar.c +115 -44
index b49ae16..4244ee6 100644
@@ -38,7 +38,52 @@ struct sar_ram_entry {
 	u32 ram_addr;
 };
 
+struct sar_overwrite_entry {
+	u32 reg_addr;
+	u32 sar_offset;
+	bool valid;
+};
+
+enum {
+	MEMIF_CLKSTCTRL_IDX,
+	SHADOW_FREQ_CFG2_IDX,
+	SHADOW_FREQ_CFG1_IDX,
+	MEMIF_CLKSTCTRL_2_IDX,
+	HSUSBHOST_CLKCTRL_IDX,
+	HSUSBHOST_CLKCTRL_2_IDX,
+	OW_IDX_SIZE
+};
+
 static struct sar_ram_entry *sar_ram_layout[3];
+static struct sar_overwrite_entry *sar_overwrite_data;
+
+static struct sar_overwrite_entry omap4_sar_overwrite_data[OW_IDX_SIZE] = {
+	[MEMIF_CLKSTCTRL_IDX] = { .reg_addr = 0x4a009e0c },
+	[SHADOW_FREQ_CFG2_IDX] = { .reg_addr = 0x4a004e2c },
+	[SHADOW_FREQ_CFG1_IDX] = { .reg_addr = 0x4a004e30 },
+	[MEMIF_CLKSTCTRL_2_IDX] = { .reg_addr = 0x4a009e0c },
+	[HSUSBHOST_CLKCTRL_IDX] = { .reg_addr = 0x4a009e54 },
+	[HSUSBHOST_CLKCTRL_2_IDX] = { .reg_addr = 0x4a009e54 },
+};
+
+static void check_overwrite_data(u32 io_addr, u32 ram_addr, int size)
+{
+	int i;
+
+	while (size) {
+		for (i = 0; i < OW_IDX_SIZE; i++) {
+			if (sar_overwrite_data[i].reg_addr == io_addr &&
+			    !sar_overwrite_data[i].valid) {
+				sar_overwrite_data[i].sar_offset = ram_addr;
+				sar_overwrite_data[i].valid = true;
+				break;
+			}
+		}
+		size--;
+		io_addr += 4;
+		ram_addr += 4;
+	}
+}
 
 /*
  * omap_sar_save :
@@ -166,53 +211,76 @@ int omap_sar_save(void)
 void omap_sar_overwrite(void)
 {
 	u32 val = 0;
-	u32 usb_offset = 0x2ec;
-	u32 usb_offset2 = 0x91c;
-
-	/* Overwriting Phase1 data to be restored */
-	/* CM2 MEMIF_CLKTRCTRL = SW_WKUP, before FREQ UPDATE */
-	__raw_writel(0x2, sar_ram_base + SAR_BANK1_OFFSET + 0xd0);
-	/* CM1 CM_SHADOW_FREQ_CONFIG2, Enable FREQ UPDATE */
-	val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG2);
-	/*
-	 * FIXME: Implement FREQ UPDATE for L#/M5 before enabling this
-	 * val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
-	 */
-	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x100);
-	/* CM1 CM_SHADOW_FREQ_CONFIG1, Enable FREQ UPDATE */
-	val = __raw_readl(OMAP4430_CM_SHADOW_FREQ_CONFIG1);
-	val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
-	val &= ~OMAP4430_DLL_OVERRIDE_2_2_MASK;
-	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + 0x104);
-	/* CM2 MEMIF_CLKTRCTRL = HW_AUTO, after FREQ UPDATE */
-	__raw_writel(0x3, sar_ram_base + SAR_BANK1_OFFSET + 0x124);
-
-	/* Overwriting Phase2a data to be restored */
-	/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 1, MODULEMODE = 2 */
-	__raw_writel(0x00000012,
-		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset);
-	/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 1, MODULEMODE = 1 */
-	__raw_writel(0x00000011,
-		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 4);
-	/* CM2 CM_SDMA_STATICDEP : Enable static depedency for SAR modules */
-	__raw_writel(0x000090e8,
-		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset + 8);
-
-	/* Overwriting Phase2b data to be restored */
-	/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
-	val = __raw_readl(OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL);
-	val &= (OMAP4430_CLKSEL_UTMI_P1_MASK | OMAP4430_CLKSEL_UTMI_P2_MASK);
-	__raw_writel(val, sar_ram_base + SAR_BANK1_OFFSET + usb_offset2);
-	/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
-	__raw_writel(0x0000000,
-		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 4);
-	/* CM2 CM_SDMA_STATICDEP : Clear the static depedency */
-	__raw_writel(0x00000040,
-		     sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8);
+	u32 offset = 0;
+
+	if (sar_overwrite_data[MEMIF_CLKSTCTRL_IDX].valid)
+		__raw_writel(0x2, sar_ram_base +
+			sar_overwrite_data[MEMIF_CLKSTCTRL_IDX].sar_offset);
+
+	if (sar_overwrite_data[SHADOW_FREQ_CFG1_IDX].valid) {
+		offset = sar_overwrite_data[SHADOW_FREQ_CFG1_IDX].sar_offset;
+		val = __raw_readl(sar_ram_base + offset);
+		val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
+		val &= ~OMAP4430_DLL_OVERRIDE_2_2_MASK;
+		__raw_writel(val, sar_ram_base + offset);
+	}
+
+	if (sar_overwrite_data[SHADOW_FREQ_CFG2_IDX].valid) {
+		offset = sar_overwrite_data[SHADOW_FREQ_CFG2_IDX].sar_offset;
+		val = __raw_readl(sar_ram_base + offset);
+		/*
+		 * FIXME: Implement FREQ UPDATE for L#/M5 before enabling
+		 * val |= 1 << OMAP4430_FREQ_UPDATE_SHIFT;
+		 */
+		__raw_writel(val, sar_ram_base + offset);
+	}
+
+	if (sar_overwrite_data[MEMIF_CLKSTCTRL_2_IDX].valid)
+		__raw_writel(0x3, sar_ram_base +
+			sar_overwrite_data[MEMIF_CLKSTCTRL_2_IDX].sar_offset);
+
+	if (sar_overwrite_data[HSUSBHOST_CLKCTRL_IDX].valid) {
+		offset = sar_overwrite_data[HSUSBHOST_CLKCTRL_IDX].sar_offset;
+
+		/* Overwriting Phase2a data to be restored */
+		/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 1, MODULEMODE = 2 */
+		__raw_writel(OMAP4430_SAR_MODE_MASK | 0x2,
+			sar_ram_base + offset);
+		/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 1, MODULEMODE = 1 */
+		__raw_writel(OMAP4430_SAR_MODE_MASK | 0x1,
+			sar_ram_base + offset + 4);
+		/*
+		 * CM2 CM_SDMA_STATICDEP : Enable static depedency for
+		 * SAR modules
+		 */
+		__raw_writel(OMAP4430_L4WKUP_STATDEP_MASK |
+			     OMAP4430_L4CFG_STATDEP_MASK |
+			     OMAP4430_L3INIT_STATDEP_MASK |
+			     OMAP4430_L3_1_STATDEP_MASK |
+			     OMAP4430_L3_2_STATDEP_MASK |
+			     OMAP4430_ABE_STATDEP_MASK,
+			     sar_ram_base + offset + 8);
+	}
+
+	if (sar_overwrite_data[HSUSBHOST_CLKCTRL_2_IDX].valid) {
+		offset = sar_overwrite_data[HSUSBHOST_CLKCTRL_2_IDX].sar_offset;
+
+		/* Overwriting Phase2b data to be restored */
+		/* CM_L3INIT_USB_HOST_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
+		val = __raw_readl(OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL);
+		val &= (OMAP4430_CLKSEL_UTMI_P1_MASK |
+			OMAP4430_CLKSEL_UTMI_P2_MASK);
+		__raw_writel(val, sar_ram_base + offset);
+		/* CM_L3INIT_USB_TLL_CLKCTRL: SAR_MODE = 0, MODULEMODE = 0 */
+		__raw_writel(0, sar_ram_base + offset + 4);
+		/* CM2 CM_SDMA_STATICDEP : Clear the static depedency */
+		__raw_writel(OMAP4430_L3_2_STATDEP_MASK,
+			     sar_ram_base + offset + 8);
+	}
 
 	/* readback to ensure data reaches to SAR RAM */
 	barrier();
-	val = __raw_readl(sar_ram_base + SAR_BANK1_OFFSET + usb_offset2 + 8);
+	val = __raw_readl(sar_ram_base + offset);
 }
 
 void __iomem *omap4_get_sar_ram_base(void)
@@ -314,6 +382,8 @@ static int sar_layout_generate(void)
 				if (!set_sar_io_addr(entry[bank], io_addr)) {
 					entry[bank]->size = size;
 					entry[bank]->ram_addr = ram_addr;
+					check_overwrite_data(io_addr, ram_addr,
+						size);
 					entry[bank]++;
 				}
 			}
@@ -387,6 +457,7 @@ static int __init omap4_sar_ram_init(void)
 	BUG_ON(!sar_ram_base);
 
 	sar_modules = omap44xx_sar_modules;
+	sar_overwrite_data = omap4_sar_overwrite_data;
 
 	sar_ioremap_modules();
 
Signature · 1 line
1.7.4.1
#37 lore raw

PATCH v2 9/19 ARM: OMAP4: PM: add errata support

In reply to Tero Kristo

Added similar PM errata flag support as omap3 has. A few errata flags will be added in subsequent patches.

---
 arch/arm/mach-omap2/pm.h     |    7 +++++++
 arch/arm/mach-omap2/pm44xx.c |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm.h +7 -0
index ce1e27f..e53ee3c 100644
@@ -130,6 +130,13 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+extern u16 pm44xx_errata;
+#define IS_PM44XX_ERRATUM(id)		(pm44xx_errata & (id))
+#else
+#define IS_PM44XX_ERRATUM(id)		0
+#endif
+
 #ifdef CONFIG_OMAP_SMARTREFLEX
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
arch/arm/mach-omap2/pm44xx.c +1 -0
index 8f0ec56..8238097 100644
@@ -35,6 +35,7 @@ struct power_state {
 };
 
 static LIST_HEAD(pwrst_list);
+u16 pm44xx_errata;
 
 #ifdef CONFIG_SUSPEND
 static int omap4_pm_suspend(void)
Signature · 1 line
1.7.4.1
#38 lore raw

PATCH v2 9/19 ARM: OMAP4: PM: add errata support

Quoted 2 lines · Tero Kristo

Added similar PM errata flag support as omap3 has. A few errata flags will be added in subsequent patches.

Considering that we might have erratas for future SoCs as well, should'nt we just
set up a common errata flag for all SoCs and since we have i123 numbers, would it help being able to reuse errata flags cross SoC generations (if we need to)?

Quoted 40 lines

---
?arch/arm/mach-omap2/pm.h ? ? | ? ?7 +++++++
?arch/arm/mach-omap2/pm44xx.c | ? ?1 +
?2 files changed, 8 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/pm.h +0 -0
index ce1e27f..e53ee3c 100644
@@ -130,6 +130,13 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 ?static inline void enable_omap3630_toggle_l2_on_restore(void) { }

?#endif ? ? ? ? /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */

arch/arm/mach-omap2/pm.h +7 -0
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+extern u16 pm44xx_errata;
+#define IS_PM44XX_ERRATUM(id) ? ? ? ? ?(pm44xx_errata & (id))
+#else
+#define IS_PM44XX_ERRATUM(id) ? ? ? ? ?0
+#endif
+

?#ifdef CONFIG_OMAP_SMARTREFLEX
?extern int omap_devinit_smartreflex(void); ?extern void omap_enable_smartreflex_on_init(void);

arch/arm/mach-omap2/pm44xx.c +1 -0
index 8f0ec56..8238097 100644
@@ -35,6 +35,7 @@ struct power_state {
 ?};
 
 ?static LIST_HEAD(pwrst_list);
+u16 pm44xx_errata;
 

?#ifdef CONFIG_SUSPEND
?static int omap4_pm_suspend(void)
--
1.7.4.1

Quoted 4 lines

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Regards,
Nishanth Menon

#39 lore raw

PATCH v2 9/19 ARM: OMAP4: PM: add errata support

Quoted 8 lines · Nishanth
Quoted 2 lines · Tero Kristo

Added similar PM errata flag support as omap3 has. A few errata flags will be added in subsequent patches.

Considering that we might have erratas for future SoCs as well, should'nt we just
set up a common errata flag for all SoCs and since we have i123 numbers, would it help being able to reuse errata flags cross SoC generations (if we need to)?

Not sure... how quickly do we run out of bits that way? :) Also, at least pm34xx / pm44xx erratas don't have anything in common. We can probably re-use pm44xx erratas for omap5 though.

One annoyance is that, the OMAP4 erratas are going to have a number of ROM code erratas on them, which don't really have any public i123 numbers available. >.<

-Tero

Quoted 49 lines
Quoted 41 lines
---
 arch/arm/mach-omap2/pm.h     |    7 +++++++
 arch/arm/mach-omap2/pm44xx.c |    1 +
 2 files changed, 8 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm.h +7 -0
index ce1e27f..e53ee3c 100644
@@ -130,6 +130,13 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif         /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
+#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
+extern u16 pm44xx_errata;
+#define IS_PM44XX_ERRATUM(id)          (pm44xx_errata & (id))
+#else
+#define IS_PM44XX_ERRATUM(id)          0
+#endif
+
 #ifdef CONFIG_OMAP_SMARTREFLEX
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
arch/arm/mach-omap2/pm44xx.c +1 -1
index 8f0ec56..8238097 100644
@@ -35,6 +35,7 @@ struct power_state {
 };
 
 static LIST_HEAD(pwrst_list);
+u16 pm44xx_errata;
 
 #ifdef CONFIG_SUSPEND
 static int omap4_pm_suspend(void)
--

1.7.4.1

Quoted 4 lines

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Regards,
Nishanth Menon

#40 lore raw

PATCH v2 9/19 ARM: OMAP4: PM: add errata support

Quoted 10 lines · Tero Kristo
Quoted 8 lines · Nishanth
Quoted 2 lines · Tero Kristo

Added similar PM errata flag support as omap3 has. A few errata flags will be added in subsequent patches.

Considering that we might have erratas for future SoCs as well, should'nt we just
set up a common errata flag for all SoCs and since we have i123 numbers, would it help being able to reuse errata flags cross SoC generations (if we need to)?

Quoted 7 lines

Not sure... how quickly do we run out of bits that way? :) Also, at least pm34xx / pm44xx erratas don't have anything in common. We can probably re-use pm44xx erratas for omap5 though.

One annoyance is that, the OMAP4 erratas are going to have a number of ROM code erratas on them, which don't really have any public i123 numbers available. >.<

Sounds good to me.

Regards,
Nishanth Menon

#41 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

In reply to Tero Kristo

From: Santosh Shilimkar <[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.
The IVAHD Clocks and Power Domain settings are:
IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF
The TESLA Clocks and Power Domain settings are:
TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

This erratum impacts only OMAP4430 HS/EMU and is fixed on devices from OMAP4430 ES2.3 onwards.

[t-kristo at ti.com: added omap4 pm errata support]
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   53 +++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm.h                  |    2 +
 arch/arm/mach-omap2/pm44xx.c              |   11 ++++++
 3 files changed, 66 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +53 -0
index 2d994dd..73e45a5 100644
@@ -52,6 +52,7 @@
 
 #include <plat/omap44xx.h>
 
+#include "iomap.h"
 #include "common.h"
 #include "omap4-sar-layout.h"
 #include "pm.h"
@@ -76,6 +77,24 @@ static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
 static struct powerdomain *mpuss_pd;
 static void __iomem *sar_base;
 
+struct reg_tuple {
+	void __iomem *addr;
+	u32 val;
+};
+
+static struct reg_tuple tesla_reg[] = {
+	{.addr = OMAP4430_CM_TESLA_CLKSTCTRL},
+	{.addr = OMAP4430_CM_TESLA_TESLA_CLKCTRL},
+	{.addr = OMAP4430_PM_TESLA_PWRSTCTRL},
+};
+
+static struct reg_tuple ivahd_reg[] = {
+	{.addr = OMAP4430_CM_IVAHD_CLKSTCTRL},
+	{.addr = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL},
+	{.addr = OMAP4430_CM_IVAHD_SL2_CLKCTRL},
+	{.addr = OMAP4430_PM_IVAHD_PWRSTCTRL}
+};
+
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
  * used for OFF or DORMANT wakeup.
@@ -215,6 +234,34 @@ static void save_l2x0_context(void)
 {}
 #endif
 
+static inline void save_ivahd_tesla_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(tesla_reg); i++)
+		tesla_reg[i].val = __raw_readl(tesla_reg[i].addr);
+
+	for (i = 0; i < ARRAY_SIZE(ivahd_reg); i++)
+		ivahd_reg[i].val = __raw_readl(ivahd_reg[i].addr);
+}
+
+static inline void restore_ivahd_tesla_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(tesla_reg); i++)
+		__raw_writel(tesla_reg[i].val, tesla_reg[i].addr);
+
+	for (i = 0; i < ARRAY_SIZE(ivahd_reg); i++)
+		__raw_writel(ivahd_reg[i].val, ivahd_reg[i].addr);
+}
+
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -273,11 +320,14 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 		omap_sar_overwrite();
 		omap4_cm_prepare_off();
 		omap4_dpll_prepare_off();
+		save_ivahd_tesla_regs();
 		save_state = 3;
 	} else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) {
+		save_ivahd_tesla_regs();
 		save_state = 2;
 	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
+		save_ivahd_tesla_regs();
 		save_state = 3;
 	}
 
@@ -302,6 +352,9 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
+	if (omap4_mpuss_read_prev_context_state())
+		restore_ivahd_tesla_regs();
+
 	if (omap4_device_prev_state_off()) {
 		omap4_dpll_resume_off();
 		omap4_cm_resume_off();
arch/arm/mach-omap2/pm.h +2 -0
index e53ee3c..d2d468e 100644
@@ -130,6 +130,8 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
+#define PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM	(1 << 0)
+
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 extern u16 pm44xx_errata;
 #define IS_PM44XX_ERRATUM(id)		(pm44xx_errata & (id))
arch/arm/mach-omap2/pm44xx.c +11 -0
index 8238097..3870c08 100644
@@ -263,6 +263,17 @@ static int __init omap4_pm_init(void)
 
 	(void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
 
+	/*
+	 * ROM code initializes IVAHD and TESLA clock registers during
+	 * secure RAM restore phase on omap4430 EMU/HS devices, thus
+	 * IVAHD / TESLA clock registers must be saved / restored
+	 * during MPU OSWR / device off.
+	 */
+	if (omap_rev() >= OMAP4430_REV_ES1_0 &&
+	    omap_rev() < OMAP4430_REV_ES2_3 &&
+	    omap_type() != OMAP2_DEVICE_TYPE_GP)
+		pm44xx_errata |= PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM;
+
 #ifdef CONFIG_SUSPEND
 	omap_pm_suspend = omap4_pm_suspend;
 #endif
Signature · 1 line
1.7.4.1
#42 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 10 lines

The IVAHD Clocks and Power Domain settings are:
IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF
The TESLA Clocks and Power Domain settings are:
TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

Quoted 5 lines

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

I don't see where this restriction is implemented.

And, can this be hooked into cluster PM notifiers.

Kevin

#43 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 26 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar<[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 13 lines

The IVAHD Clocks and Power Domain settings are:
IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF
The TESLA Clocks and Power Domain settings are:
TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Quoted 6 lines
Quoted 2 lines

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

I don't see where this restriction is implemented.

And, can this be hooked into cluster PM notifiers.

Especially since this only effects a subset of revisions, installing the notifier only on effected revisions also removes any overhead on working revisions.

Kevin

#44 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 30 lines · Kevin Hilman
Quoted 29 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar<[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 15 lines

The IVAHD Clocks and Power Domain settings are:
IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF
The TESLA Clocks and Power Domain settings are:
TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

Quoted 7 lines
Quoted 3 lines

I don't see where this restriction is implemented.

And, can this be hooked into cluster PM notifiers.

Especially since this only effects a subset of revisions, installing the notifier only on effected revisions also removes any overhead on working revisions.

Where would you recommend adding the notifiers to? Just to the same file or...? pm44xx.c?

-Tero

#45 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 33 lines · Tero Kristo
Quoted 32 lines · Kevin Hilman
Quoted 31 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar<[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 10 lines

The IVAHD Clocks and Power Domain settings are:
IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF
The TESLA Clocks and Power Domain settings are:
TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

Quoted 5 lines

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

I don't see where this restriction is implemented.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

And, can this be hooked into cluster PM notifiers.

Especially since this only effects a subset of revisions, installing the notifier only on effected revisions also removes any overhead on working revisions.

Where would you recommend adding the notifiers to? Just to the same file or...? pm44xx.c?

Same file should be ok.

Kevin

#46 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

In reply to Kevin Hilman
Quoted 23 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 10 lines

The IVAHD Clocks and Power Domain settings are:
? ? ? IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF The TESLA Clocks and Power Domain settings are:
? ? ? TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE ? ? ? TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

Quoted 8 lines
Quoted 5 lines

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

I don't see where this restriction is implemented.

It's handled and the patch is in mainline for some time. We de-scoped MPU OFF from OMAP4430 devices in SW and hardware team de-scoped it in hardware from OMAP4460 onwards. Deepest state on MPUSS cluster is OSWR.

------------
commit a57341f780660800e1463eaedb80ed152ad6b5de

Author: Santosh Shilimkar <[email protected]>
Date:   Sat Jul 9 20:42:59 2011 -0600

OMAP4: powerdomain data: Remove unsupported MPU powerdomain state

On OMAP4430 devices, because of boot ROM code bug, MPU OFF state can't be attempted independently. When coming out of MPU OFF state, ROM code disables the clocks of IVAHD, TESLA which is not desirable. Hence the MPU OFF state is not usable on OMAP4430 devices.

OMAP4460 onwards, MPU OFF state will be descoped completely because the DDR firewall falls in MPU power domain. When the MPU hit OFF state, DDR won't be accessible for other initiators. The deepest state supported is open switch retention (OSWR) just like CORE and PER PD on OMAP4430.

So in summary MPU power domain OFF state is not supported on OMAP4 and onwards designs. Thanks to new PRCM design, device off mode can still be achieved with power domains hitting OSWR state.

[b-cousson at ti.com: Fix changelog typos]

---------------------------------------------

Quoted 2 lines

And, can this be hooked into cluster PM notifiers.

Not needed.

#47 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 30 lines · Santosh
Quoted 29 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 15 lines

The IVAHD Clocks and Power Domain settings are:
? ? ? IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF The TESLA Clocks and Power Domain settings are:
? ? ? TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE ? ? ? TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

Quoted 6 lines
Quoted 2 lines

I don't see where this restriction is implemented.

It's handled and the patch is in mainline for some time. We de-scoped MPU OFF from OMAP4430 devices in SW and hardware team de-scoped it in hardware from OMAP4460 onwards. Deepest state on MPUSS cluster is OSWR.

The question was about the changelog.

The changelog makes it sound like the restriction is part of the patch, but it is not. Please update the changlog to clarify that, ideally adding a reference to the commit you mentioned.

Kevin

#48 lore raw

PATCH v2 10/19 ARM: OMAP4: PM: Work-around for ROM code BUG of IVAHD/TESLA

Quoted 39 lines · Kevin Hilman
Quoted 30 lines · Santosh
Quoted 29 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

The ROM BUG is when MPU Domain OFF wake up sequence that can compromise IVA and Tesla execution.

At wakeup from MPU OFF on HS device only (not GP device), when restoring the Secure RAM, the ROM Code reconfigures the clocks the same way it is done at Cold Reset.

Ouch.

Quoted 15 lines

The IVAHD Clocks and Power Domain settings are:
? ? ? IVAHD_CM2 IVAHD_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKCTRL_MODULE_MODE = DISABLE ? ? ? IVAHD_CM2 SL2_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? IVAHD_PRM IVAHD_PWRSTCTRL_POWERSTATE = OFF The TESLA Clocks and Power Domain settings are:
? ? ? TESLA_CM1 TESLA_CLKCTRL_MODULE_MODE = DISABLE ? ? ? TESLA_CM1 TESLA_CLKSTCTRL_CLKTRCTRL = HW_AUTO ? ? ? TESLA_PRM TESLA_PWRSTCTRL_POWERSTATE = OFF

This patch fixes the low power OFF mode code so that the these registers are saved and restore across MPU OFF state.

Also because of this limitation, MPU OFF alone is not targeted without device OFF to avoid IVAHD and TESLA execution impact

Quoted 6 lines
Quoted 2 lines

I don't see where this restriction is implemented.

It's handled and the patch is in mainline for some time. We de-scoped MPU OFF from OMAP4430 devices in SW and hardware team de-scoped it in hardware from OMAP4460 onwards. Deepest state on MPUSS cluster is OSWR.

Quoted 6 lines

The question was about the changelog.

The changelog makes it sound like the restriction is part of the patch, but it is not. ?Please update the changlog to clarify that, ideally adding a reference to the commit you mentioned.

Agree.

#49 lore raw

PATCH v2 11/19 ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode

In reply to Tero Kristo

From: Rajendra Nayak <[email protected]>

On HS devices on the way out of MPU OSWR and OFF ROM code wrongly overwrites the CM L3INSTR registers. So to avoid this, save them and restore on the way out from MPU OSWR/OFF.

This errata applies to all HS/EMU versions of OMAP4.

[t-kristo at ti.com: added omap4 pm errata support]
---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c |   35 ++++++++++++++++++++++++++++-
 arch/arm/mach-omap2/pm.h                  |    1 +
 arch/arm/mach-omap2/pm44xx.c              |    8 ++++++
 3 files changed, 43 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +34 -1
index 73e45a5..f555ac2 100644
@@ -95,6 +95,12 @@ static struct reg_tuple ivahd_reg[] = {
 	{.addr = OMAP4430_PM_IVAHD_PWRSTCTRL}
 };
 
+static struct reg_tuple l3instr_reg[] = {
+	{.addr = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL},
+	{.addr = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL},
+	{.addr = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL},
+};
+
 /*
  * Program the wakeup routine address for the CPU0 and CPU1
  * used for OFF or DORMANT wakeup.
@@ -262,6 +268,28 @@ static inline void restore_ivahd_tesla_regs(void)
 		__raw_writel(ivahd_reg[i].val, ivahd_reg[i].addr);
 }
 
+static inline void save_l3instr_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_L3INSTR_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+		l3instr_reg[i].val = __raw_readl(l3instr_reg[i].addr);
+}
+
+static inline void restore_l3instr_regs(void)
+{
+	int i;
+
+	if (!IS_PM44XX_ERRATUM(PM_OMAP4_ROM_L3INSTR_ERRATUM))
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(l3instr_reg); i++)
+		__raw_writel(l3instr_reg[i].val, l3instr_reg[i].addr);
+}
+
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -321,13 +349,16 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 		omap4_cm_prepare_off();
 		omap4_dpll_prepare_off();
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 3;
 	} else if ((pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_RET) &&
 		(pwrdm_read_logic_retst(mpuss_pd) == PWRDM_POWER_OFF)) {
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 2;
 	} else if (pwrdm_read_next_pwrst(mpuss_pd) == PWRDM_POWER_OFF) {
 		save_ivahd_tesla_regs();
+		save_l3instr_regs();
 		save_state = 3;
 	}
 
@@ -352,8 +383,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	wakeup_cpu = smp_processor_id();
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
-	if (omap4_mpuss_read_prev_context_state())
+	if (omap4_mpuss_read_prev_context_state()) {
 		restore_ivahd_tesla_regs();
+		restore_l3instr_regs();
+	}
 
 	if (omap4_device_prev_state_off()) {
 		omap4_dpll_resume_off();
arch/arm/mach-omap2/pm.h +1 -0
index d2d468e..b971f6f 100644
@@ -131,6 +131,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
 #define PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM	(1 << 0)
+#define PM_OMAP4_ROM_L3INSTR_ERRATUM		(1 << 1)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 extern u16 pm44xx_errata;
arch/arm/mach-omap2/pm44xx.c +8 -0
index 3870c08..8591df2 100644
@@ -274,6 +274,14 @@ static int __init omap4_pm_init(void)
 	    omap_type() != OMAP2_DEVICE_TYPE_GP)
 		pm44xx_errata |= PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM;
 
+	/*
+	 * Similar to above errata, ROM code modifies L3INSTR clock
+	 * registers also and these must be saved / restored during
+	 * MPU OSWR / device off.
+	 */
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+		pm44xx_errata |= PM_OMAP4_ROM_L3INSTR_ERRATUM;
+
 #ifdef CONFIG_SUSPEND
 	omap_pm_suspend = omap4_pm_suspend;
 #endif
Signature · 1 line
1.7.4.1
#50 lore raw

PATCH v2 11/19 ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode

Quoted 6 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

On HS devices on the way out of MPU OSWR and OFF ROM code wrongly overwrites the CM L3INSTR registers. So to avoid this, save them and restore on the way out from MPU OSWR/OFF.

Quoted 6 lines

This errata applies to all HS/EMU versions of OMAP4.

[t-kristo at ti.com: added omap4 pm errata support]

Let's use the cluster PM notifiers here too, using the PM errata check when registering the notifier.

Kevin

#51 lore raw

PATCH v2 11/19 ARM: OMAP4: PM: save/restore CM L3INSTR registers when MPU hits OSWR/OFF mode

Quoted 10 lines · Kevin Hilman
Quoted 8 lines · Tero Kristo

From: Rajendra Nayak <[email protected]>

On HS devices on the way out of MPU OSWR and OFF ROM code wrongly overwrites the CM L3INSTR registers. So to avoid this, save them and restore on the way out from MPU OSWR/OFF.

This errata applies to all HS/EMU versions of OMAP4.

Quoted 8 lines
Quoted 4 lines
[t-kristo at ti.com: added omap4 pm errata support]

Let's use the cluster PM notifiers here too, using the PM errata check when registering the notifier.

Good idea.

#52 lore raw

PATCH v2 12/19 ARM: OMAP4: PM: update ROM return address for OSWR and OFF

In reply to Tero Kristo

From: Carlos Leija <[email protected]>

At wakeup from OFF/OSWR CPU1 will call secure HAL service through a local secure dispatcher with MMU off, thus ROM will save a PA return address. Later in the wakeup, when SMC driver calls an RPC through omap4_secure_dispatcher (MMU is on now), ROM code won't log the new return address as RPCs are handled different. Thus ROM will attempt to return to a PA address when the MMU is on and the system will hang.

We need to do this for OSWR state and OFF state of mpu power domain, not just for device off(mpu pd OFF).

[t-kristo at ti.com: merged the two patches into one]
---
 arch/arm/mach-omap2/include/mach/omap-secure.h |    1 +
 arch/arm/mach-omap2/omap-mpuss-lowpower.c      |   13 +++++++++++++
 arch/arm/mach-omap2/pm.h                       |    1 +
 arch/arm/mach-omap2/pm44xx.c                   |    8 ++++++++
 4 files changed, 23 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/omap-secure.h +1 -0
index c90a435..d9bde61 100644
@@ -43,6 +43,7 @@
 #define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
 
 /* Secure PPA(Primary Protected Application) APIs */
+#define OMAP4_PPA_SERVICE_0		0x21
 #define OMAP4_PPA_L2_POR_INDEX		0x23
 #define OMAP4_PPA_CPU_ACTRL_SMP_INDEX	0x25
 
arch/arm/mach-omap2/omap-mpuss-lowpower.c +13 -0
index f555ac2..1f06f97 100644
@@ -52,6 +52,8 @@
 
 #include <plat/omap44xx.h>
 
+#include <mach/omap-secure.h>
+
 #include "iomap.h"
 #include "common.h"
 #include "omap4-sar-layout.h"
@@ -384,6 +386,17 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
 	if (omap4_mpuss_read_prev_context_state()) {
+		/*
+		 * Dummy dispatcher call after OSWR and OFF
+		 * Restore the right return Kernel address (with MMU on) for
+		 * subsequent calls to secure ROM. Otherwise the return address
+		 * will be to a PA return address and the system will hang.
+		 */
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_RETURN_ADDRESS_ERRATUM))
+			omap_secure_dispatcher(OMAP4_PPA_SERVICE_0,
+					       FLAG_START_CRITICAL,
+					       0, 0, 0, 0, 0);
+
 		restore_ivahd_tesla_regs();
 		restore_l3instr_regs();
 	}
arch/arm/mach-omap2/pm.h +1 -0
index b971f6f..1d24b96 100644
@@ -132,6 +132,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 
 #define PM_OMAP4_ROM_IVAHD_TESLA_ERRATUM	(1 << 0)
 #define PM_OMAP4_ROM_L3INSTR_ERRATUM		(1 << 1)
+#define PM_OMAP4_ROM_RETURN_ADDRESS_ERRATUM	(1 << 2)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4)
 extern u16 pm44xx_errata;
arch/arm/mach-omap2/pm44xx.c +8 -0
index 8591df2..215b80e 100644
@@ -282,6 +282,14 @@ static int __init omap4_pm_init(void)
 	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
 		pm44xx_errata |= PM_OMAP4_ROM_L3INSTR_ERRATUM;
 
+	/*
+	 * Restore the right return Kernel address (with MMU on) for
+	 * subsequent calls to secure ROM. Otherwise the return address
+	 * will be to a PA return address and the system will hang.
+	 */
+	if (omap_type() != OMAP2_DEVICE_TYPE_GP)
+		pm44xx_errata |= PM_OMAP4_ROM_RETURN_ADDRESS_ERRATUM;
+
 #ifdef CONFIG_SUSPEND
 	omap_pm_suspend = omap4_pm_suspend;
 #endif
Signature · 1 line
1.7.4.1
#53 lore raw

PATCH v2 12/19 ARM: OMAP4: PM: update ROM return address for OSWR and OFF

Quoted 4 lines · Tero Kristo

From: Carlos Leija <[email protected]>

At wakeup from OFF/OSWR CPU1 will call secure HAL service through a local secure dispatcher with MMU off,

Reviewers who are uninitaited in this level of detail need some more help here (even those who are deeply familiar will need more help in a few months when they forget the details.)

So, some more detail about where this is in the code would be helpful here.

Quoted 3 lines

thus ROM will save a PA return address.
Later in the wakeup, when SMC driver calls an RPC through omap4_secure_dispatcher (MMU is on now),

Again, pointer to where is this in the code would be helpful.

Also, it's not obvious why RPC use used here. Is that referring to the fact that the secure calls on CPU1 are dispatched to CPU0? Whatever it means, it should be summarized in the changelog.

Quoted 6 lines

ROM code won't log the new return
address as RPCs are handled different. Thus ROM will attempt to return to a PA address when the MMU is on and the system will hang.

We need to do this for OSWR state and OFF state of mpu power domain, not just for device off(mpu pd OFF).

The code suggests that affects *all* OMAP4 revisions? Is that correct?

And once again, can this be implmented using cluster PM notifiers, where the notifier is registered only on affected revisions?

(Sheesh, the number of ROM code workaounds in this series is rather disconcerting.)

Kevin

#54 lore raw

PATCH v2 12/19 ARM: OMAP4: PM: update ROM return address for OSWR and OFF

Quoted 11 lines · Kevin Hilman
Quoted 4 lines · Tero Kristo

From: Carlos Leija <[email protected]>

At wakeup from OFF/OSWR CPU1 will call secure HAL service through a local secure dispatcher with MMU off,

Reviewers who are uninitaited in this level of detail need some more help here (even those who are deeply familiar will need more help in a few months when they forget the details.)

Quoted 8 lines

So, some more detail about where this is in the code would be helpful here.

Quoted 3 lines

thus ROM will save a PA return address.
Later in the wakeup, when SMC driver calls an RPC through omap4_secure_dispatcher (MMU is on now),

Again, pointer to where is this in the code would be helpful.

I believe this refers to any of the SMC calls done in the ASM files. Most notably the one in omap-headsmp.S, which is added (rather) illogically after this patch in the set though.

Quoted 4 lines

Also, it's not obvious why RPC use used here. Is that referring to the fact that the secure calls on CPU1 are dispatched to CPU0? Whatever it means, it should be summarized in the changelog.

Not sure about this, maybe security guys can comment on this.

Quoted 9 lines
Quoted 7 lines

ROM code won't log the new return
address as RPCs are handled different. Thus ROM will attempt to return to a PA address when the MMU is on and the system will hang.

We need to do this for OSWR state and OFF state of mpu power domain, not just for device off(mpu pd OFF).

The code suggests that affects *all* OMAP4 revisions? Is that correct?

I think thats right.

Quoted 3 lines

And once again, can this be implmented using cluster PM notifiers, where the notifier is registered only on affected revisions?

Should be okay to do that. I guess this should move to omap-secure.c.

Quoted 7 lines

(Sheesh, the number of ROM code workaounds in this series is rather disconcerting.)

Kevin

#55 lore raw

PATCH v2 13/19 ARM: OMAP4: PM: Mark the PPI and SPI interrupts as non-secure for GP

In reply to Tero Kristo

From: Axel Haslam <[email protected]>

ROM code restores part of the GIC context during wakeup from device off mode from the SAR RAM. If the PPI and SPI interrupts are not marked as non-secure on GP chips, this crashes the device during wakeup, thus mark them as non-secure.

[t-kristo at ti.com: fixed commit message, merged multiple patches to one]
---
 arch/arm/mach-omap2/common.h           |    1 +
 arch/arm/mach-omap2/omap-wakeupgen.c   |   21 +++++++++++++++++++++
 arch/arm/mach-omap2/omap4-common.c     |    5 +++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    3 +++
 4 files changed, 30 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/common.h +1 -0
index 48d1ebe..0fbb4e2 100644
@@ -200,6 +200,7 @@ static inline void __iomem *omap4_get_scu_base(void)
 
 extern void __init gic_init_irq(void);
 extern void gic_dist_disable(void);
+extern u32 gic_readl(u32 offset, u8 idx);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
arch/arm/mach-omap2/omap-wakeupgen.c +21 -0
index 805d08d..b2165e4 100644
@@ -41,6 +41,7 @@
 #define CPU_ENA_OFFSET		0x400
 #define CPU0_ID			0x0
 #define CPU1_ID			0x1
+#define GIC_ISR_NON_SECURE	0xffffffff
 
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
@@ -387,6 +388,7 @@ int __init omap_wakeupgen_init(void)
 {
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
+	int max_spi_reg;
 
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
@@ -422,6 +424,25 @@ int __init omap_wakeupgen_init(void)
 	for (i = 0; i < NR_IRQS; i++)
 		irq_target_cpu[i] = boot_cpu;
 
+	/*
+	 * Find out how many interrupts are supported.
+	 * OMAP4 supports max of 128 SPIs where as GIC can support
+	 * up to 1020 interrupt sources. On OMAP4, maximum SPIs are
+	 * fused in DIST_CTR bit-fields as 128. Hence the code is safe
+	 * from reserved register writes since its well within 1020.
+	 */
+	max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f;
+
+	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
+		for (i = 0; i < max_spi_reg; i++)
+			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+		iounmap(sar_base);
+		sar_base = NULL;
+	}
+
 	irq_hotplug_init();
 	irq_pm_init();
 
arch/arm/mach-omap2/omap4-common.c +5 -0
index 7ea4652..f6019f6 100644
@@ -112,6 +112,11 @@ void gic_dist_disable(void)
 		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 }
 
+u32 gic_readl(u32 offset, u8 idx)
+{
+	return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
arch/arm/mach-omap2/omap4-sar-layout.h +3 -0
index eef2839..0056667 100644
@@ -85,6 +85,9 @@
 #define SAR_BACKUP_STATUS_OFFSET		(SAR_BANK3_OFFSET + 0x500)
 #define SAR_SECURE_RAM_SIZE_OFFSET		(SAR_BANK3_OFFSET + 0x504)
 #define SAR_SECRAM_SAVED_AT_OFFSET		(SAR_BANK3_OFFSET + 0x508)
+#define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
+#define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
+#define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)
 
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)
Signature · 1 line
1.7.4.1
#56 lore raw

PATCH v2 13/19 ARM: OMAP4: PM: Mark the PPI and SPI interrupts as non-secure for GP

Quoted 34 lines · Tero Kristo

From: Axel Haslam <[email protected]>

ROM code restores part of the GIC context during wakeup from device off mode from the SAR RAM. If the PPI and SPI interrupts are not marked as non-secure on GP chips, this crashes the device during wakeup, thus mark them as non-secure.

[t-kristo at ti.com: fixed commit message, merged multiple patches to one]
---
 arch/arm/mach-omap2/common.h           |    1 +
 arch/arm/mach-omap2/omap-wakeupgen.c   |   21 +++++++++++++++++++++
 arch/arm/mach-omap2/omap4-common.c     |    5 +++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    3 +++
 4 files changed, 30 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/common.h +1 -0
index 48d1ebe..0fbb4e2 100644
@@ -200,6 +200,7 @@ static inline void __iomem *omap4_get_scu_base(void)
 
 extern void __init gic_init_irq(void);
 extern void gic_dist_disable(void);
+extern u32 gic_readl(u32 offset, u8 idx);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
arch/arm/mach-omap2/omap-wakeupgen.c +0 -0
index 805d08d..b2165e4 100644

arch/arm/mach-omap2/omap-wakeupgen.c line 44

Quoted 4 lines
arch/arm/mach-omap2/omap-wakeupgen.c +1 -0
@@ -41,6 +41,7 @@
 #define CPU_ENA_OFFSET		0x400
 #define CPU0_ID			0x0
 #define CPU1_ID			0x1
+#define GIC_ISR_NON_SECURE	0xffffffff

nit: alignment with preceeding #defines

Quoted 19 lines
arch/arm/mach-omap2/omap-wakeupgen.c +6 -0
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
@@ -387,6 +388,7 @@ int __init omap_wakeupgen_init(void)
 {
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
+	int max_spi_reg;
 
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
@@ -422,6 +424,25 @@ int __init omap_wakeupgen_init(void)
 	for (i = 0; i < NR_IRQS; i++)
 		irq_target_cpu[i] = boot_cpu;
 
+	/*
+	 * Find out how many interrupts are supported.
+	 * OMAP4 supports max of 128 SPIs where as GIC can support
+	 * up to 1020 interrupt sources. On OMAP4, maximum SPIs are
+	 * fused in DIST_CTR bit-fields as 128. Hence the code is safe

arch/arm/mach-omap2/omap-wakeupgen.c int __init omap_wakeupgen_init(void) · line 441

Quoted 10 lines
arch/arm/mach-omap2/omap-wakeupgen.c +10 -0
+	 * from reserved register writes since its well within 1020.
+	 */
+	max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f;
+
+	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
+		for (i = 0; i < max_spi_reg; i++)
+			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);

The above 4 lines are begging for some comments (something like the changelog). Since later in the series more stuff is added here, the end result has some readability problems.

Quoted 11 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+		iounmap(sar_base);
+		sar_base = NULL;
+	}
 	irq_hotplug_init();
 	irq_pm_init();
 
arch/arm/mach-omap2/omap4-common.c +0 -0
index 7ea4652..f6019f6 100644

arch/arm/mach-omap2/omap4-common.c void gic_dist_disable(void) · line 116

Quoted 5 lines
arch/arm/mach-omap2/omap4-common.c +2 -0
@@ -112,6 +112,11 @@ void gic_dist_disable(void)
 		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 }
 
+u32 gic_readl(u32 offset, u8 idx)
+{

probably want an 'if (gic_dist_base_addr)' like gic_dist_disable()

Quoted 11 lines
arch/arm/mach-omap2/omap4-common.c +3 -0
+	return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
 void __iomem *omap4_get_l2cache_base(void)
arch/arm/mach-omap2/omap4-sar-layout.h +0 -0
index eef2839..0056667 100644

arch/arm/mach-omap2/omap4-sar-layout.h line 90

Quoted 6 lines
arch/arm/mach-omap2/omap4-sar-layout.h +3 -0
@@ -85,6 +85,9 @@
 #define SAR_BACKUP_STATUS_OFFSET		(SAR_BANK3_OFFSET + 0x500)
 #define SAR_SECURE_RAM_SIZE_OFFSET		(SAR_BANK3_OFFSET + 0x504)
 #define SAR_SECRAM_SAVED_AT_OFFSET		(SAR_BANK3_OFFSET + 0x508)
+#define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
+#define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
+#define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)

SAR_ prefix?

arch/arm/mach-omap2/omap4-sar-layout.h line 93

Quoted 2 lines
arch/arm/mach-omap2/omap4-sar-layout.h +0 -0
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)

Kevin

#57 lore raw

PATCH v2 13/19 ARM: OMAP4: PM: Mark the PPI and SPI interrupts as non-secure for GP

Quoted 34 lines · Kevin Hilman
Quoted 32 lines · Tero Kristo

From: Axel Haslam <[email protected]>

ROM code restores part of the GIC context during wakeup from device off mode from the SAR RAM. If the PPI and SPI interrupts are not marked as non-secure on GP chips, this crashes the device during wakeup, thus mark them as non-secure.

[t-kristo at ti.com: fixed commit message, merged multiple patches to one]
---
 arch/arm/mach-omap2/common.h           |    1 +
 arch/arm/mach-omap2/omap-wakeupgen.c   |   21 +++++++++++++++++++++
 arch/arm/mach-omap2/omap4-common.c     |    5 +++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    3 +++
 4 files changed, 30 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/common.h +1 -0
index 48d1ebe..0fbb4e2 100644
@@ -200,6 +200,7 @@ static inline void __iomem *omap4_get_scu_base(void)
 
 extern void __init gic_init_irq(void);
 extern void gic_dist_disable(void);
+extern u32 gic_readl(u32 offset, u8 idx);
 extern void omap_smc1(u32 fn, u32 arg);
 extern void __iomem *omap4_get_sar_ram_base(void);
 extern void omap_do_wfi(void);
arch/arm/mach-omap2/omap-wakeupgen.c +0 -1
index 805d08d..b2165e4 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
Quoted 8 lines

arch/arm/mach-omap2/omap-wakeupgen.c line 44

Quoted 6 lines

+++ b/arch/arm/mach-omap2/omap-wakeupgen.c

arch/arm/mach-omap2/omap-wakeupgen.c +1 -0
@@ -41,6 +41,7 @@
 #define CPU_ENA_OFFSET		0x400
 #define CPU0_ID			0x0
 #define CPU1_ID			0x1
+#define GIC_ISR_NON_SECURE	0xffffffff

nit: alignment with preceeding #defines

Will fix that.

Quoted 26 lines
Quoted 26 lines
arch/arm/mach-omap2/omap-wakeupgen.c +12 -0
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
@@ -387,6 +388,7 @@ int __init omap_wakeupgen_init(void)
 {
 	int i;
 	unsigned int boot_cpu = smp_processor_id();
+	int max_spi_reg;
 
 	/* Not supported on OMAP4 ES1.0 silicon */
 	if (omap_rev() == OMAP4430_REV_ES1_0) {
@@ -422,6 +424,25 @@ int __init omap_wakeupgen_init(void)
 	for (i = 0; i < NR_IRQS; i++)
 		irq_target_cpu[i] = boot_cpu;
 
+	/*
+	 * Find out how many interrupts are supported.
+	 * OMAP4 supports max of 128 SPIs where as GIC can support
+	 * up to 1020 interrupt sources. On OMAP4, maximum SPIs are
+	 * fused in DIST_CTR bit-fields as 128. Hence the code is safe
+	 * from reserved register writes since its well within 1020.
+	 */
+	max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f;
+
+	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
+		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
Quoted 8 lines

arch/arm/mach-omap2/omap-wakeupgen.c int __init omap_wakeupgen_init(void) · line 441

Quoted 4 lines
arch/arm/mach-omap2/omap-wakeupgen.c +4 -0
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
+		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
+		for (i = 0; i < max_spi_reg; i++)
+			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);

The above 4 lines are begging for some comments (something like the changelog). Since later in the series more stuff is added here, the end result has some readability problems.

Will add.

Quoted 15 lines
Quoted 15 lines
arch/arm/mach-omap2/omap-wakeupgen.c +3 -0
+		iounmap(sar_base);
+		sar_base = NULL;
+	}
 	irq_hotplug_init();
 	irq_pm_init();
 
arch/arm/mach-omap2/omap4-common.c +0 -0
index 7ea4652..f6019f6 100644
@@ -112,6 +112,11 @@ void gic_dist_disable(void)
 		__raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 }
 
Quoted 4 lines

arch/arm/mach-omap2/omap4-common.c void gic_dist_disable(void) · line 116

Quoted 2 lines
arch/arm/mach-omap2/omap4-common.c +2 -0
+u32 gic_readl(u32 offset, u8 idx)
+{

probably want an 'if (gic_dist_base_addr)' like gic_dist_disable()

Yea, will add that.

Quoted 6 lines
Quoted 6 lines
arch/arm/mach-omap2/omap4-common.c +3 -0
+	return __raw_readl(gic_dist_base_addr + offset + 4 * idx);
+}
+
 #ifdef CONFIG_CACHE_L2X0
 
Quoted 14 lines

arch/arm/mach-omap2/omap4-sar-layout.h line 90

Quoted 12 lines
arch/arm/mach-omap2/omap4-common.c +0 -0
 void __iomem *omap4_get_l2cache_base(void)
arch/arm/mach-omap2/omap4-sar-layout.h +3 -0
index eef2839..0056667 100644
@@ -85,6 +85,9 @@
 #define SAR_BACKUP_STATUS_OFFSET		(SAR_BANK3_OFFSET + 0x500)
 #define SAR_SECURE_RAM_SIZE_OFFSET		(SAR_BANK3_OFFSET + 0x504)
 #define SAR_SECRAM_SAVED_AT_OFFSET		(SAR_BANK3_OFFSET + 0x508)
+#define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
+#define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
+#define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)

SAR_ prefix?

Will add that too.

-Tero

Quoted 5 lines

arch/arm/mach-omap2/omap4-sar-layout.h line 93

Quoted 3 lines
arch/arm/mach-omap2/omap4-sar-layout.h +0 -0
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)

Kevin

#58 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

In reply to Tero Kristo

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

---
 arch/arm/mach-omap2/omap-wakeupgen.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +20 -0
index b2165e4..c7c4db4 100644
@@ -29,10 +29,12 @@
 
 #include <mach/omap-wakeupgen.h>
 #include <mach/omap-secure.h>
+#include <plat/omap_hwmod.h>
 
 #include "omap4-sar-layout.h"
 #include "common.h"
 #include "pm.h"
+#include "clockdomain.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -49,6 +51,8 @@ static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
 static struct powerdomain *mpuss_pd;
+static struct clockdomain *l4_secure_clkdm;
+static struct omap_hwmod *l3_main_3_oh;
 
 /*
  * Static helper functions.
@@ -300,10 +304,18 @@ static void save_secure_ram(void)
 static void save_secure_all(void)
 {
 	u32 ret;
+
+	omap_hwmod_enable(l3_main_3_oh);
+	clkdm_wakeup(l4_secure_clkdm);
+
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
 				FLAG_START_CRITICAL,
 				1, omap_secure_ram_mempool_base(),
 				0, 0, 0);
+
+	clkdm_allow_idle(l4_secure_clkdm);
+	omap_hwmod_idle(l3_main_3_oh);
+
 	if (ret != API_HAL_RET_VALUE_OK)
 		pr_err("Secure all context save failed\n");
 }
@@ -441,6 +453,14 @@ int __init omap_wakeupgen_init(void)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
 		iounmap(sar_base);
 		sar_base = NULL;
+	} else {
+		l3_main_3_oh = omap_hwmod_lookup("l3_main_3");
+		if (!l3_main_3_oh)
+			pr_err("%s: failed to get l3_main_3_oh\n", __func__);
+
+		l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
+		if (!l4_secure_clkdm)
+			pr_err("%s: failed to get l4_secure_clkdm\n", __func__);
 	}
 
 	irq_hotplug_init();
Signature · 1 line
1.7.4.1
#59 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

+Benoit

Quoted 4 lines · Tero Kristo

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

Also, this patch suggests that the OCM RAM block needs a proper hwmod instead of manually fiddling with the l3_main_3 hwmod and the l4_secure clkdm.

Kevin

Quoted 64 lines
---
 arch/arm/mach-omap2/omap-wakeupgen.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +20 -0
index b2165e4..c7c4db4 100644
@@ -29,10 +29,12 @@
 
 #include <mach/omap-wakeupgen.h>
 #include <mach/omap-secure.h>
+#include <plat/omap_hwmod.h>
 
 #include "omap4-sar-layout.h"
 #include "common.h"
 #include "pm.h"
+#include "clockdomain.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -49,6 +51,8 @@ static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
 static struct powerdomain *mpuss_pd;
+static struct clockdomain *l4_secure_clkdm;
+static struct omap_hwmod *l3_main_3_oh;
 
 /*
  * Static helper functions.
@@ -300,10 +304,18 @@ static void save_secure_ram(void)
 static void save_secure_all(void)
 {
 	u32 ret;
+
+	omap_hwmod_enable(l3_main_3_oh);
+	clkdm_wakeup(l4_secure_clkdm);
+
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
 				FLAG_START_CRITICAL,
 				1, omap_secure_ram_mempool_base(),
 				0, 0, 0);
+
+	clkdm_allow_idle(l4_secure_clkdm);
+	omap_hwmod_idle(l3_main_3_oh);
+
 	if (ret != API_HAL_RET_VALUE_OK)
 		pr_err("Secure all context save failed\n");
 }
@@ -441,6 +453,14 @@ int __init omap_wakeupgen_init(void)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
 		iounmap(sar_base);
 		sar_base = NULL;
+	} else {
+		l3_main_3_oh = omap_hwmod_lookup("l3_main_3");
+		if (!l3_main_3_oh)
+			pr_err("%s: failed to get l3_main_3_oh\n", __func__);
+
+		l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
+		if (!l4_secure_clkdm)
+			pr_err("%s: failed to get l4_secure_clkdm\n", __func__);
 	}
 
 	irq_hotplug_init();
#60 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 4 lines · Kevin Hilman

+Benoit

Tero Kristo <[email protected]> writes:

Quoted 8 lines
Quoted 4 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

Attempting to do separate saves for secure RAM + GIC hang the device during wakeup, in addition to being really inefficient (secure API calls are expensive.)

-Tero

Quoted 70 lines

Also, this patch suggests that the OCM RAM block needs a proper hwmod instead of manually fiddling with the l3_main_3 hwmod and the l4_secure clkdm.

Kevin

Quoted 64 lines
---
 arch/arm/mach-omap2/omap-wakeupgen.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +20 -0
index b2165e4..c7c4db4 100644
@@ -29,10 +29,12 @@
 
 #include <mach/omap-wakeupgen.h>
 #include <mach/omap-secure.h>
+#include <plat/omap_hwmod.h>
 
 #include "omap4-sar-layout.h"
 #include "common.h"
 #include "pm.h"
+#include "clockdomain.h"
 
 #define NR_REG_BANKS		4
 #define MAX_IRQS		128
@@ -49,6 +51,8 @@ static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
 
 static struct powerdomain *mpuss_pd;
+static struct clockdomain *l4_secure_clkdm;
+static struct omap_hwmod *l3_main_3_oh;
 
 /*
  * Static helper functions.
@@ -300,10 +304,18 @@ static void save_secure_ram(void)
 static void save_secure_all(void)
 {
 	u32 ret;
+
+	omap_hwmod_enable(l3_main_3_oh);
+	clkdm_wakeup(l4_secure_clkdm);
+
 	ret = omap_secure_dispatcher(OMAP4_HAL_SAVEALL_INDEX,
 				FLAG_START_CRITICAL,
 				1, omap_secure_ram_mempool_base(),
 				0, 0, 0);
+
+	clkdm_allow_idle(l4_secure_clkdm);
+	omap_hwmod_idle(l3_main_3_oh);
+
 	if (ret != API_HAL_RET_VALUE_OK)
 		pr_err("Secure all context save failed\n");
 }
@@ -441,6 +453,14 @@ int __init omap_wakeupgen_init(void)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
 		iounmap(sar_base);
 		sar_base = NULL;
+	} else {
+		l3_main_3_oh = omap_hwmod_lookup("l3_main_3");
+		if (!l3_main_3_oh)
+			pr_err("%s: failed to get l3_main_3_oh\n", __func__);
+
+		l4_secure_clkdm = clkdm_lookup("l4_secure_clkdm");
+		if (!l4_secure_clkdm)
+			pr_err("%s: failed to get l4_secure_clkdm\n", __func__);
 	}
 
 	irq_hotplug_init();
#61 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 10 lines · Tero Kristo
Quoted 9 lines · Kevin Hilman

+Benoit

Quoted 4 lines · Tero Kristo

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

Quoted 8 lines
Quoted 3 lines

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

(mysterious: Entire firewall registers )

Regards
Santosh

#62 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

In reply to Tero Kristo
Quoted 14 lines · Tero Kristo
Quoted 4 lines · Kevin Hilman

+Benoit

Tero Kristo <[email protected]> writes:

Quoted 8 lines
Quoted 4 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

Quoted 8 lines

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

Attempting to do separate saves for secure RAM + GIC hang the device during wakeup, in addition to being really inefficient (secure API calls are expensive.)

I guess my comment wasn't that this isn't needed, but that it doesn't seem to belong in the wakeupgen base (which should probably converted into a real driver.)

Seems better to have this stuff in the secure code, maybe omap-secure.c?

Kevin

#63 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 25 lines · Kevin Hilman
Quoted 14 lines · Tero Kristo
Quoted 4 lines · Kevin Hilman

+Benoit

Tero Kristo <[email protected]> writes:

Quoted 8 lines
Quoted 4 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

Quoted 8 lines

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

Attempting to do separate saves for secure RAM + GIC hang the device during wakeup, in addition to being really inefficient (secure API calls are expensive.)

Quoted 6 lines

I guess my comment wasn't that this isn't needed, but that it doesn't seem to belong in the wakeupgen base (which should probably converted into a real driver.)

Seems better to have this stuff in the secure code, maybe omap-secure.c?

Perhaps OFF mode notifier might help best here. In addition - it might be safer to protect all calls with clkdm_wakeup around secure_dispatcher instead of just the save_secure_all.. ROM code is not smart enough around it.
an completely safe version used by security driver can be found here:
http://git.omapzoom.org/?p=kernel/omap.git;a=blob;f=security/smc/tf_comm_mshield.c;h=b5279fef0fa400438a57b3941af13d965e983bf0;hb=p-android-omap-3.0#l253

this is what the production kernels have used in the past. Regards,
Nishanth Menon

#64 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 33 lines · Nishanth
Quoted 25 lines · Kevin Hilman
Quoted 14 lines · Tero Kristo
Quoted 4 lines · Kevin Hilman

+Benoit

Tero Kristo <[email protected]> writes:

Quoted 8 lines
Quoted 4 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

Quoted 8 lines

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

Attempting to do separate saves for secure RAM + GIC hang the device during wakeup, in addition to being really inefficient (secure API calls are expensive.)

Quoted 6 lines

I guess my comment wasn't that this isn't needed, but that it doesn't seem to belong in the wakeupgen base (which should probably converted into a real driver.)

Seems better to have this stuff in the secure code, maybe omap-secure.c?

Quoted 7 lines

Perhaps OFF mode notifier might help best here. In addition - it might be safer to protect all calls with clkdm_wakeup around secure_dispatcher instead of just the save_secure_all.. ROM code is not smart enough around it.
an completely safe version used by security driver can be found here:
http://git.omapzoom.org/?p=kernel/omap.git;a=blob;f=security/smc/tf_comm_mshield.c;h=b5279fef0fa400438a57b3941af13d965e983bf0;hb=p-android-omap-3.0#l253

Thats true... the secure driver in mainline kernel is rather a stub. Previous version of this patch actually had clkdm_wakeup around every call to dispatcher, I just optimized it away. I can add it back in the next version if you think that is better.

-Tero

#65 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

In reply to Kevin Hilman
Quoted 25 lines · Kevin Hilman
Quoted 14 lines · Tero Kristo
Quoted 4 lines · Kevin Hilman

+Benoit

Tero Kristo <[email protected]> writes:

Quoted 8 lines
Quoted 4 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

I think I mentioned this already (I'm already lost in what I've said for thisseries), but I don't think the secure RAM stuff belongs in the wakeupgen driver.

Quoted 8 lines

As mentioned, save_secure_all saves:
- secure RAM
- GIC registers
- some other mysterious stuff

Attempting to do separate saves for secure RAM + GIC hang the device during wakeup, in addition to being really inefficient (secure API calls are expensive.)

Quoted 5 lines

I guess my comment wasn't that this isn't needed, but that it doesn't seem to belong in the wakeupgen base (which should probably converted into a real driver.)

Seems better to have this stuff in the secure code, maybe omap-secure.c?

That might be an option yes. I'll see if I can move these calls over there.

-Tero

maintainer
#66 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

In reply to Tero Kristo

Hi Tero

Quoted 2 lines · Tero Kristo

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

Do we know why the l3_main_3 interconnect has to be enabled? Is this needed to access some L3 or instrumentation registers?

- Paul

#67 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 9 lines · Paul Walmsley

Hi Tero

Quoted 2 lines · Tero Kristo

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

Do we know why the l3_main_3 interconnect has to be enabled? Is this needed to access some L3 or instrumentation registers?

Not sure, ROM code is doing something here which requires it, and the ROM code definitely crashes without this. Your guess sounds plausible.

-Tero

#68 lore raw

PATCH v2 14/19 ARM: OMAP4: wakeupgen: enable clocks for save_secure_all

Quoted 5 lines · Tero Kristo
Quoted 4 lines · Paul Walmsley

Hi Tero

On Mon, 14 May 2012, Tero Kristo wrote:

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

save_secure_all needs l3_main_3_ick and l4_secure_clkdm enabled, otherwise the secure ROM code will crash.

Do we know why the l3_main_3 interconnect has to be enabled? ?Is this needed to access some L3 or instrumentation registers?

Not sure, ROM code is doing something here which requires it, and the ROM code definitely crashes without this. Your guess sounds plausible.

ROM code accesses L3 firewall registers mostly apart from L2 INSTR firewall registers here and without that clock, those accesses will abort.

Regards
santosh

#69 lore raw

PATCH v2 15/19 ARM: OMAP4430: PM: workaround for DDR corruption on second CS

In reply to Tero Kristo

From: Santosh Shilimkar <[email protected]>

Work around for Errata ID: i632 "LPDDR2 Corruption After OFF Mode Transition When CS1 Is Used On EMIF" which impacts OMAP443x silicon The issue occurs when EMIF_SDRAM_CONFIG is restored first before EMIF_SDRAM_CONFIG_2 is not yet restored, the register configuration is not set properly, we apply the required workaround allowing the restore sequence to work properly.

[t-kristo at ti.com: moved workaround from omap-sar.c to pm44xx.c]
---
 .../include/mach/ctrl_module_wkup_44xx.h           |    2 +
 arch/arm/mach-omap2/pm44xx.c                       |   37 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +2 -0
index a0af9ba..b763a79 100644
@@ -28,6 +28,8 @@
 #define OMAP4_CTRL_MODULE_WKUP_IP_REVISION		0x0000
 #define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO		0x0004
 #define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG		0x0010
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG	0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG	0x011c
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0	0x0460
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1	0x0464
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2	0x0468
arch/arm/mach-omap2/pm44xx.c +37 -0
index 215b80e..dfaa254 100644
@@ -17,12 +17,18 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <asm/system_misc.h>
+#include <linux/io.h>
+
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/hardware.h>
 
 #include "common.h"
 #include "clockdomain.h"
 #include "powerdomain.h"
 #include "pm.h"
 
+#define EMIF_SDRAM_CONFIG2_OFFSET	0xc
+
 struct power_state {
 	struct powerdomain *pwrdm;
 	u32 next_state;
@@ -215,6 +221,37 @@ static int __init omap4_pm_init(void)
 
 	pr_err("Power Management for TI OMAP4.\n");
 
+	/*
+	 * Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+	 * Mode Transition When CS1 Is Used On EMIF":
+	 * Overwrite EMIF1/EMIF2
+	 * SECURE_EMIF1_SDRAM_CONFIG2_REG
+	 * SECURE_EMIF2_SDRAM_CONFIG2_REG
+	 */
+	if (cpu_is_omap443x()) {
+		void __iomem *secure_ctrl_mod;
+		void __iomem *emif1;
+		void __iomem *emif2;
+		u32 val;
+
+		secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+		emif1 = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
+		emif2 = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
+
+		BUG_ON(!secure_ctrl_mod || !emif1 || !emif2);
+
+		val = __raw_readl(emif1 + EMIF_SDRAM_CONFIG2_OFFSET);
+		__raw_writel(val, secure_ctrl_mod +
+			     OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG);
+		val = __raw_readl(emif2 + EMIF_SDRAM_CONFIG2_OFFSET);
+		__raw_writel(val, secure_ctrl_mod +
+			     OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG);
+		wmb();
+		iounmap(secure_ctrl_mod);
+		iounmap(emif1);
+		iounmap(emif2);
+	}
+
 	ret = pwrdm_for_each(pwrdms_setup, NULL);
 	if (ret) {
 		pr_err("Failed to setup powerdomains\n");
Signature · 1 line
1.7.4.1
#70 lore raw

PATCH v2 15/19 ARM: OMAP4430: PM: workaround for DDR corruption on second CS

Quoted 8 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

Work around for Errata ID: i632 "LPDDR2 Corruption After OFF Mode Transition When CS1 Is Used On EMIF" which impacts OMAP443x silicon The issue occurs when EMIF_SDRAM_CONFIG is restored first before EMIF_SDRAM_CONFIG_2 is not yet restored, the register configuration is not set properly, we apply the required workaround allowing the restore sequence to work properly.

Please summarize the workaround here as well.

Quoted 46 lines
[t-kristo at ti.com: moved workaround from omap-sar.c to pm44xx.c]
---
 .../include/mach/ctrl_module_wkup_44xx.h           |    2 +
 arch/arm/mach-omap2/pm44xx.c                       |   37 ++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +2 -0
index a0af9ba..b763a79 100644
@@ -28,6 +28,8 @@
 #define OMAP4_CTRL_MODULE_WKUP_IP_REVISION		0x0000
 #define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO		0x0004
 #define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG		0x0010
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG	0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG	0x011c
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0	0x0460
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1	0x0464
 #define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2	0x0468
arch/arm/mach-omap2/pm44xx.c +6 -0
index 215b80e..dfaa254 100644
@@ -17,12 +17,18 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <asm/system_misc.h>
+#include <linux/io.h>
+
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/hardware.h>
 
 #include "common.h"
 #include "clockdomain.h"
 #include "powerdomain.h"
 #include "pm.h"
 
+#define EMIF_SDRAM_CONFIG2_OFFSET	0xc
+
 struct power_state {
 	struct powerdomain *pwrdm;
 	u32 next_state;
@@ -215,6 +221,37 @@ static int __init omap4_pm_init(void)
 

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 231

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +8 -0
 	pr_err("Power Management for TI OMAP4.\n");
 
+	/*
+	 * Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+	 * Mode Transition When CS1 Is Used On EMIF":
+	 * Overwrite EMIF1/EMIF2
+	 * SECURE_EMIF1_SDRAM_CONFIG2_REG
+	 * SECURE_EMIF2_SDRAM_CONFIG2_REG
+	 */
+	if (cpu_is_omap443x()) {

This should probably be done later in this function, after PM_ERRATUM flags are setup, and then it should use a PM_ERRATUM flag instead of cpu_is*

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 241

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+		void __iomem *secure_ctrl_mod;
+		void __iomem *emif1;
+		void __iomem *emif2;
+		u32 val;
+
+		secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+		emif1 = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
+		emif2 = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
+
+		BUG_ON(!secure_ctrl_mod || !emif1 || !emif2);

Please avoid BUG_ON() and use proper error recovery. This is not a condition where the entire kernel should panic.

Quoted 5 lines
arch/arm/mach-omap2/pm44xx.c +5 -0
+		val = __raw_readl(emif1 + EMIF_SDRAM_CONFIG2_OFFSET);
+		__raw_writel(val, secure_ctrl_mod +
+			     OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG);
+		val = __raw_readl(emif2 + EMIF_SDRAM_CONFIG2_OFFSET);
+		__raw_writel(val, secure_ctrl_mod +

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 257

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +6 -0
+			     OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG);
+		wmb();
+		iounmap(secure_ctrl_mod);
+		iounmap(emif1);
+		iounmap(emif2);
+	}
 
 	ret = pwrdm_for_each(pwrdms_setup, NULL);
 	if (ret) {
 		pr_err("Failed to setup powerdomains\n");

Kevin

#71 lore raw

PATCH v2 15/19 ARM: OMAP4430: PM: workaround for DDR corruption on second CS

Quoted 4 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

Quoted 9 lines
Quoted 6 lines

Work around for Errata ID: i632 "LPDDR2 Corruption After OFF Mode Transition When CS1 Is Used On EMIF" which impacts OMAP443x silicon The issue occurs when EMIF_SDRAM_CONFIG is restored first before EMIF_SDRAM_CONFIG_2 is not yet restored, the register configuration is not set properly, we apply the required workaround allowing the restore sequence to work properly.

Please summarize the workaround here as well.

ok

Quoted 48 lines
Quoted 48 lines
[t-kristo at ti.com: moved workaround from omap-sar.c to pm44xx.c]

---
?.../include/mach/ctrl_module_wkup_44xx.h ? ? ? ? ? | ? ?2 + ?arch/arm/mach-omap2/pm44xx.c ? ? ? ? ? ? ? ? ? ? ? | ? 37 ++++++++++++++++++++ ?2 files changed, 39 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +0 -0
index a0af9ba..b763a79 100644
@@ -28,6 +28,8 @@

?#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION ? ? ? ? ? 0x0000 ?#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO ? ? ? ? ? ? 0x0004 ?#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG ? ? ? ? ?0x0010

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +2 -0
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG ? ?0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG ? ?0x011c

?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0 ?0x0460 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1 ?0x0464 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2 ?0x0468

arch/arm/mach-omap2/pm44xx.c +0 -0
index 215b80e..dfaa254 100644
@@ -17,12 +17,18 @@

?#include <linux/err.h>
?#include <linux/slab.h>
?#include <asm/system_misc.h>

arch/arm/mach-omap2/pm44xx.c +4 -0
+#include <linux/io.h>
+
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/hardware.h>

?#include "common.h"
?#include "clockdomain.h"
?#include "powerdomain.h"
?#include "pm.h"

arch/arm/mach-omap2/pm44xx.c +2 -0
+#define EMIF_SDRAM_CONFIG2_OFFSET ? ?0xc
+

?struct power_state {
? ? ? struct powerdomain *pwrdm;
? ? ? u32 next_state;

arch/arm/mach-omap2/pm44xx.c +0 -0
@@ -215,6 +221,37 @@ static int __init omap4_pm_init(void)
 
 ? ? ? pr_err("Power Management for TI OMAP4.\n");
 
Quoted 12 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 231

Quoted 8 lines
arch/arm/mach-omap2/pm44xx.c +8 -0
+ ? ? /*
+ ? ? ?* Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+ ? ? ?* Mode Transition When CS1 Is Used On EMIF":
+ ? ? ?* Overwrite EMIF1/EMIF2
+ ? ? ?* SECURE_EMIF1_SDRAM_CONFIG2_REG
+ ? ? ?* SECURE_EMIF2_SDRAM_CONFIG2_REG
+ ? ? ?*/
+ ? ? if (cpu_is_omap443x()) {

This should probably be done later in this function, after PM_ERRATUM flags are setup, and then it should use a PM_ERRATUM flag instead of cpu_is*

ok

Quoted 5 lines
Quoted 5 lines
arch/arm/mach-omap2/pm44xx.c +5 -0
+ ? ? ? ? ? ? void __iomem *secure_ctrl_mod;
+ ? ? ? ? ? ? void __iomem *emif1;
+ ? ? ? ? ? ? void __iomem *emif2;
+ ? ? ? ? ? ? u32 val;
+
Quoted 9 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 241

Quoted 5 lines
arch/arm/mach-omap2/pm44xx.c +5 -0
+ ? ? ? ? ? ? secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+ ? ? ? ? ? ? emif1 = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
+ ? ? ? ? ? ? emif2 = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
+
+ ? ? ? ? ? ? BUG_ON(!secure_ctrl_mod || !emif1 || !emif2);

Please avoid BUG_ON() and use proper error recovery. ?This is not a condition where the entire kernel should panic.

Agree. WARN_ON() should suffice.

Regards
santosh

#72 lore raw

PATCH v2 15/19 ARM: OMAP4430: PM: workaround for DDR corruption on second CS

Quoted 91 lines · Santosh
Quoted 4 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

Quoted 9 lines
Quoted 6 lines

Work around for Errata ID: i632 "LPDDR2 Corruption After OFF Mode Transition When CS1 Is Used On EMIF" which impacts OMAP443x silicon The issue occurs when EMIF_SDRAM_CONFIG is restored first before EMIF_SDRAM_CONFIG_2 is not yet restored, the register configuration is not set properly, we apply the required workaround allowing the restore sequence to work properly.

Please summarize the workaround here as well.

ok

Quoted 48 lines
Quoted 48 lines
[t-kristo at ti.com: moved workaround from omap-sar.c to pm44xx.c]

---
?.../include/mach/ctrl_module_wkup_44xx.h ? ? ? ? ? | ? ?2 + ?arch/arm/mach-omap2/pm44xx.c ? ? ? ? ? ? ? ? ? ? ? | ? 37 ++++++++++++++++++++ ?2 files changed, 39 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +0 -0
index a0af9ba..b763a79 100644
@@ -28,6 +28,8 @@

?#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION ? ? ? ? ? 0x0000 ?#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO ? ? ? ? ? ? 0x0004 ?#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG ? ? ? ? ?0x0010

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +2 -0
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG ? ?0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG ? ?0x011c

?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0 ?0x0460 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1 ?0x0464 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2 ?0x0468

arch/arm/mach-omap2/pm44xx.c +0 -0
index 215b80e..dfaa254 100644
@@ -17,12 +17,18 @@

?#include <linux/err.h>
?#include <linux/slab.h>
?#include <asm/system_misc.h>

arch/arm/mach-omap2/pm44xx.c +4 -0
+#include <linux/io.h>
+
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/hardware.h>

?#include "common.h"
?#include "clockdomain.h"
?#include "powerdomain.h"
?#include "pm.h"

arch/arm/mach-omap2/pm44xx.c +2 -0
+#define EMIF_SDRAM_CONFIG2_OFFSET ? ?0xc
+

?struct power_state {
? ? ? struct powerdomain *pwrdm;
? ? ? u32 next_state;

arch/arm/mach-omap2/pm44xx.c +0 -0
@@ -215,6 +221,37 @@ static int __init omap4_pm_init(void)
 
 ? ? ? pr_err("Power Management for TI OMAP4.\n");
 
Quoted 12 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 231

Quoted 8 lines
arch/arm/mach-omap2/pm44xx.c +8 -0
+ ? ? /*
+ ? ? ?* Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+ ? ? ?* Mode Transition When CS1 Is Used On EMIF":
+ ? ? ?* Overwrite EMIF1/EMIF2
+ ? ? ?* SECURE_EMIF1_SDRAM_CONFIG2_REG
+ ? ? ?* SECURE_EMIF2_SDRAM_CONFIG2_REG
+ ? ? ?*/
+ ? ? if (cpu_is_omap443x()) {

This should probably be done later in this function, after PM_ERRATUM flags are setup, and then it should use a PM_ERRATUM flag instead of cpu_is*

ok

Quoted 5 lines
Quoted 5 lines
arch/arm/mach-omap2/pm44xx.c +5 -0
+ ? ? ? ? ? ? void __iomem *secure_ctrl_mod;
+ ? ? ? ? ? ? void __iomem *emif1;
+ ? ? ? ? ? ? void __iomem *emif2;
+ ? ? ? ? ? ? u32 val;
+
Quoted 9 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 241

Quoted 5 lines
arch/arm/mach-omap2/pm44xx.c +5 -0
+ ? ? ? ? ? ? secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+ ? ? ? ? ? ? emif1 = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
+ ? ? ? ? ? ? emif2 = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
+
+ ? ? ? ? ? ? BUG_ON(!secure_ctrl_mod || !emif1 || !emif2);

Please avoid BUG_ON() and use proper error recovery. ?This is not a condition where the entire kernel should panic.

Quoted 1 line

Agree. WARN_ON() should suffice.

A WARN_ON() is ok (but noisy). Better is a pr_warn() with some proper error recovery.

Kevin

#73 lore raw

PATCH v2 15/19 ARM: OMAP4430: PM: workaround for DDR corruption on second CS

Quoted 93 lines · Kevin Hilman
Quoted 91 lines · Santosh
Quoted 4 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

From: Santosh Shilimkar <[email protected]>

Quoted 9 lines
Quoted 6 lines

Work around for Errata ID: i632 "LPDDR2 Corruption After OFF Mode Transition When CS1 Is Used On EMIF" which impacts OMAP443x silicon The issue occurs when EMIF_SDRAM_CONFIG is restored first before EMIF_SDRAM_CONFIG_2 is not yet restored, the register configuration is not set properly, we apply the required workaround allowing the restore sequence to work properly.

Please summarize the workaround here as well.

ok

Quoted 48 lines
Quoted 48 lines
[t-kristo at ti.com: moved workaround from omap-sar.c to pm44xx.c]

---
?.../include/mach/ctrl_module_wkup_44xx.h ? ? ? ? ? | ? ?2 + ?arch/arm/mach-omap2/pm44xx.c ? ? ? ? ? ? ? ? ? ? ? | ? 37 ++++++++++++++++++++ ?2 files changed, 39 insertions(+), 0 deletions(-)

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +0 -0
index a0af9ba..b763a79 100644
@@ -28,6 +28,8 @@

?#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION ? ? ? ? ? 0x0000 ?#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO ? ? ? ? ? ? 0x0004 ?#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG ? ? ? ? ?0x0010

arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h +2 -0
+#define OMAP4_CTRL_SECURE_EMIF1_SDRAM_CONFIG2_REG ? ?0x0114
+#define OMAP4_CTRL_SECURE_EMIF2_SDRAM_CONFIG2_REG ? ?0x011c

?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0 ?0x0460 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1 ?0x0464 ?#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2 ?0x0468

arch/arm/mach-omap2/pm44xx.c +0 -0
index 215b80e..dfaa254 100644
@@ -17,12 +17,18 @@

?#include <linux/err.h>
?#include <linux/slab.h>
?#include <asm/system_misc.h>

arch/arm/mach-omap2/pm44xx.c +4 -0
+#include <linux/io.h>
+
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/hardware.h>

?#include "common.h"
?#include "clockdomain.h"
?#include "powerdomain.h"
?#include "pm.h"

arch/arm/mach-omap2/pm44xx.c +2 -0
+#define EMIF_SDRAM_CONFIG2_OFFSET ? ?0xc
+

?struct power_state {
? ? ? struct powerdomain *pwrdm;
? ? ? u32 next_state;

arch/arm/mach-omap2/pm44xx.c +0 -0
@@ -215,6 +221,37 @@ static int __init omap4_pm_init(void)
 
 ? ? ? pr_err("Power Management for TI OMAP4.\n");
 
Quoted 12 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 231

Quoted 8 lines
arch/arm/mach-omap2/pm44xx.c +8 -0
+ ? ? /*
+ ? ? ?* Work around for OMAP443x Errata i632: "LPDDR2 Corruption After OFF
+ ? ? ?* Mode Transition When CS1 Is Used On EMIF":
+ ? ? ?* Overwrite EMIF1/EMIF2
+ ? ? ?* SECURE_EMIF1_SDRAM_CONFIG2_REG
+ ? ? ?* SECURE_EMIF2_SDRAM_CONFIG2_REG
+ ? ? ?*/
+ ? ? if (cpu_is_omap443x()) {

This should probably be done later in this function, after PM_ERRATUM flags are setup, and then it should use a PM_ERRATUM flag instead of cpu_is*

ok

Quoted 14 lines

arch/arm/mach-omap2/pm44xx.c static int __init omap4_pm_init(void) · line 241

Quoted 10 lines
arch/arm/mach-omap2/pm44xx.c +10 -0
+ ? ? ? ? ? ? void __iomem *secure_ctrl_mod;
+ ? ? ? ? ? ? void __iomem *emif1;
+ ? ? ? ? ? ? void __iomem *emif2;
+ ? ? ? ? ? ? u32 val;
+
+ ? ? ? ? ? ? secure_ctrl_mod = ioremap(OMAP4_CTRL_MODULE_WKUP, SZ_4K);
+ ? ? ? ? ? ? emif1 = ioremap(OMAP44XX_EMIF1_BASE, SZ_1M);
+ ? ? ? ? ? ? emif2 = ioremap(OMAP44XX_EMIF2_BASE, SZ_1M);
+
+ ? ? ? ? ? ? BUG_ON(!secure_ctrl_mod || !emif1 || !emif2);

Please avoid BUG_ON() and use proper error recovery. ?This is not a condition where the entire kernel should panic.

Quoted 5 lines
Quoted 1 line

Agree. WARN_ON() should suffice.

A WARN_ON() is ok (but noisy). ?Better is a pr_warn() with some proper error recovery.

OK

#74 lore raw

PATCH v2 16/19 TEMP: ARM: OMAP4: prevent voltage transitions

In reply to Tero Kristo

During device off, the off-mode voltage transitions are enabled on reset. Because the voltage control logic is not still completely functional for OMAP4, we must disable the voltage transitions for device off for now. This can only be done by disabling the I2C channel it seems.

This patch does not prevent voltage scaling done by voltdm->scale / DVFS.

---
 arch/arm/mach-omap2/pm44xx.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/pm44xx.c +22 -0
index dfaa254..5d97b21 100644
@@ -26,6 +26,9 @@
 #include "clockdomain.h"
 #include "powerdomain.h"
 #include "pm.h"
+#include "voltage.h"
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
 
 #define EMIF_SDRAM_CONFIG2_OFFSET	0xc
 
@@ -210,6 +213,7 @@ static int __init omap4_pm_init(void)
 	int ret;
 	struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm, *l4wkup;
 	struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per_clkdm;
+	struct voltagedomain *mpu_voltdm;
 
 	if (!cpu_is_omap44xx())
 		return -ENODEV;
@@ -292,6 +296,24 @@ static int __init omap4_pm_init(void)
 		goto err2;
 	}
 
+	/*
+	 * XXX: voltage config is not still completely valid for
+	 * OMAP4, and this causes crashes on some platform during
+	 * device off because voltage transitions for device off
+	 * are enabled on reset. Thus, we have to disable the I2C
+	 * channel completely in the VOLTCTRL register to avoid
+	 * trouble. Remove this once voltconfigs are valid.
+	 */
+	mpu_voltdm = voltdm_lookup("mpu");
+	if (!mpu_voltdm) {
+		pr_err("Failed to get MPU voltdm\n");
+		goto err2;
+	}
+	mpu_voltdm->write(OMAP4430_VDD_MPU_I2C_DISABLE_MASK |
+			  OMAP4430_VDD_CORE_I2C_DISABLE_MASK |
+			  OMAP4430_VDD_IVA_I2C_DISABLE_MASK,
+			  OMAP4_PRM_VOLTCTRL_OFFSET);
+
 	ret = omap4_mpuss_init();
 	if (ret) {
 		pr_err("Failed to initialise OMAP4 MPUSS\n");
Signature · 1 line
1.7.4.1
#75 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

In reply to Tero Kristo

If AUX_CORE_BOOT0 does not indicate wakeup request for cpu1, put it back to off. This is needed during wakeup from device off to prevent cpu1 from being stuck indefinitely in the wakeup loop and also to prevent wakeup problem on GP chips with device off mode.

---
 arch/arm/mach-omap2/omap-headsmp.S |   45 ++++++++++++++++++++++++++++++++---
 1 files changed, 41 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/omap-headsmp.S +41 -4
index d602555..59c6578 100644
@@ -17,8 +17,37 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <mach/omap-secure.h>
+#include "prcm_mpu44xx.h"
+
+#define CPU1_PWRSTCTRL (OMAP4430_PRCM_MPU_BASE + OMAP4430_PRCM_MPU_CPU1_INST + \
+			OMAP4_PM_CPU1_PWRSTCTRL_OFFSET)
 
 	__CPUINIT
+
+ENTRY(omap_cpu1_off)
+	ldr	r12, =CPU1_PWRSTCTRL
+	ldr	r0, [r12]
+	and	r0, #3
+	cmp	r0, #2
+	beq	exit_cpu1_off
+
+	mov	r0, #0x3
+	mov	r1, #0x0
+	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
+	dsb
+	smc     #0
+
+	isb
+	dsb
+	dmb
+	wfi
+	nop
+	nop
+exit_cpu1_off:
+	mov	pc, lr
+ENDPROC(omap_cpu1_off)
+
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
@@ -27,32 +56,40 @@
  * register AuxCoreBoot0.
  */
 ENTRY(omap_secondary_startup)
-hold:	ldr	r12,=0x103
+	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
+	beq	omap_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup
 
 	/*
 	 * we've been released from the wait loop,secondary_stack
 	 * should now contain the SVC stack for this core
 	 */
+omap_cont_boot:
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
 ENTRY(omap_secondary_startup_4460)
-hold_2:	ldr	r12,=0x103
+	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
+	beq	omap4460_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup_4460
 
+omap4460_cont_boot:
 	/*
 	 * GIC distributor control register has changed between
 	 * CortexA9 r1pX and r2pX. The Control Register secure
Signature · 1 line
1.7.4.1
#76 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

Quoted 2 lines · Tero Kristo

If AUX_CORE_BOOT0 does not indicate wakeup request for cpu1, put it back to off.

Why is it waking up then? (I know the answer, but will forget. The changelog serves as my long-term memory.)

Quoted 2 lines

This is needed during wakeup from device off to prevent cpu1 from being stuck indefinitely in the wakeup loop

Why does it get stuck?

Quoted 1 line

and also to prevent wakeup problem on GP chips with device off mode.

What wakeup problem?

Quoted 1 line

Assembly code should have some comments to aid comprehension.

Quoted 20 lines
---
 arch/arm/mach-omap2/omap-headsmp.S |   45 ++++++++++++++++++++++++++++++++---
 1 files changed, 41 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/omap-headsmp.S +6 -0
index d602555..59c6578 100644
@@ -17,8 +17,37 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <mach/omap-secure.h>
+#include "prcm_mpu44xx.h"
+
+#define CPU1_PWRSTCTRL (OMAP4430_PRCM_MPU_BASE + OMAP4430_PRCM_MPU_CPU1_INST + \
+			OMAP4_PM_CPU1_PWRSTCTRL_OFFSET)
 
 	__CPUINIT
+

arch/arm/mach-omap2/omap-headsmp.S line 37

Quoted 10 lines
arch/arm/mach-omap2/omap-headsmp.S +10 -0
+ENTRY(omap_cpu1_off)
+	ldr	r12, =CPU1_PWRSTCTRL
+	ldr	r0, [r12]
+	and	r0, #3
+	cmp	r0, #2
+	beq	exit_cpu1_off
+
+	mov	r0, #0x3
+	mov	r1, #0x0
+	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX

Help! no comments.

arch/arm/mach-omap2/omap-headsmp.S line 39

Quoted 2 lines
arch/arm/mach-omap2/omap-headsmp.S +2 -0
+	dsb
+	smc     #0

The DO_SMC in sleep44xx.S suggests there should be another dsb here.

arch/arm/mach-omap2/omap-headsmp.S line 46

Quoted 6 lines
arch/arm/mach-omap2/omap-headsmp.S +6 -0
+	isb
+	dsb
+	dmb
+	wfi
+	nop
+	nop

Shoudln't this use omap_do_wfi?

Kevin

Quoted 52 lines
arch/arm/mach-omap2/omap-headsmp.S +16 -4
+exit_cpu1_off:
+	mov	pc, lr
+ENDPROC(omap_cpu1_off)
+
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
@@ -27,32 +56,40 @@
  * register AuxCoreBoot0.
  */
 ENTRY(omap_secondary_startup)
-hold:	ldr	r12,=0x103
+	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
+	beq	omap_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup
 
 	/*
 	 * we've been released from the wait loop,secondary_stack
 	 * should now contain the SVC stack for this core
 	 */
+omap_cont_boot:
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
 ENTRY(omap_secondary_startup_4460)
-hold_2:	ldr	r12,=0x103
+	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
+	beq	omap4460_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup_4460
 
+omap4460_cont_boot:
 	/*
 	 * GIC distributor control register has changed between
 	 * CortexA9 r1pX and r2pX. The Control Register secure
#77 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

Quoted 7 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

If AUX_CORE_BOOT0 does not indicate wakeup request for cpu1, put it back to off.

Why is it waking up then? (I know the answer, but will forget. The changelog serves as my long-term memory.)

Will add comment. (Both cpus will wake-up after device-off reset.)

Quoted 5 lines
Quoted 3 lines

This is needed during wakeup from device off to prevent cpu1 from being stuck indefinitely in the wakeup loop

Why does it get stuck?

Related to the above, if the AUX_CORE_BOOT0 is not set, the code will wait for it indefinitely in busy loop.

Quoted 4 lines
Quoted 2 lines

and also to prevent wakeup problem on GP chips with device off mode.

What wakeup problem?

This is apparently related to the GIC restore issue addressed with patch 3/8 of the core-ret set (workaround for the ROM bug because of CA9 r2pX gic register change), the interrupts get disabled. Maybe Santosh has some comments on this one.

Quoted 4 lines
Quoted 2 lines

Assembly code should have some comments to aid comprehension.

Will add.

Quoted 35 lines
Quoted 22 lines

---
 arch/arm/mach-omap2/omap-headsmp.S |   45 ++++++++++++++++++++++++++++++++---
 1 files changed, 41 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/omap-headsmp.S +6 -0
index d602555..59c6578 100644
@@ -17,8 +17,37 @@
 
 #include <linux/linkage.h>
 #include <linux/init.h>
+#include <mach/omap-secure.h>
+#include "prcm_mpu44xx.h"
+
+#define CPU1_PWRSTCTRL (OMAP4430_PRCM_MPU_BASE + OMAP4430_PRCM_MPU_CPU1_INST + \
+			OMAP4_PM_CPU1_PWRSTCTRL_OFFSET)
 
 	__CPUINIT
+

arch/arm/mach-omap2/omap-headsmp.S line 37

Quoted 10 lines
arch/arm/mach-omap2/omap-headsmp.S +10 -0
+ENTRY(omap_cpu1_off)
+	ldr	r12, =CPU1_PWRSTCTRL
+	ldr	r0, [r12]
+	and	r0, #3
+	cmp	r0, #2
+	beq	exit_cpu1_off
+
+	mov	r0, #0x3
+	mov	r1, #0x0
+	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX

Help! no comments.

Quoted 4 lines

arch/arm/mach-omap2/omap-headsmp.S line 39

Quoted 2 lines
arch/arm/mach-omap2/omap-headsmp.S +2 -0
+	dsb
+	smc     #0

The DO_SMC in sleep44xx.S suggests there should be another dsb here.

Not sure if that is needed here as we have multiple barriers following this, but I'll add it just to be sure.

Quoted 9 lines

arch/arm/mach-omap2/omap-headsmp.S line 46

Quoted 7 lines
arch/arm/mach-omap2/omap-headsmp.S +6 -0
+	isb
+	dsb
+	dmb
+	wfi
+	nop
+	nop

Shoudln't this use omap_do_wfi?

Can't, as we don't have stack yet at this point, and omap_do_wfi attempts to push stuff into stack.

-Tero

Quoted 55 lines

Kevin

Quoted 52 lines
arch/arm/mach-omap2/omap-headsmp.S +16 -4
+exit_cpu1_off:
+	mov	pc, lr
+ENDPROC(omap_cpu1_off)
+
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
@@ -27,32 +56,40 @@
  * register AuxCoreBoot0.
  */
 ENTRY(omap_secondary_startup)
-hold:	ldr	r12,=0x103
+	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
+	beq	omap_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup
 
 	/*
 	 * we've been released from the wait loop,secondary_stack
 	 * should now contain the SVC stack for this core
 	 */
+omap_cont_boot:
 	b	secondary_startup
 ENDPROC(omap_secondary_startup)
 
 ENTRY(omap_secondary_startup_4460)
-hold_2:	ldr	r12,=0x103
+	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
+	beq	omap4460_cont_boot
+
+	bl	omap_cpu1_off
+	b	omap_secondary_startup_4460
 
+omap4460_cont_boot:
 	/*
 	 * GIC distributor control register has changed between
 	 * CortexA9 r1pX and r2pX. The Control Register secure
#78 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

Tero,

Quoted 21 lines · Tero Kristo
Quoted 7 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

If AUX_CORE_BOOT0 does not indicate wakeup request for cpu1, put it back to off.

Why is it waking up then? ?(I know the answer, but will forget. ?The changelog serves as my long-term memory.)

Will add comment. (Both cpus will wake-up after device-off reset.)

Quoted 5 lines
Quoted 3 lines

This is needed during wakeup from device off to prevent cpu1 from being stuck indefinitely in the wakeup loop

Why does it get stuck?

Related to the above, if the AUX_CORE_BOOT0 is not set, the code will wait for it indefinitely in busy loop.

Quoted 1 line
Quoted 9 lines
Quoted 3 lines
Quoted 1 line

and also to prevent wakeup problem on GP chips with device off mode.

What wakeup problem?

This is apparently related to the GIC restore issue addressed with patch 3/8 of the core-ret set (workaround for the ROM bug because of CA9 r2pX gic register change), the interrupts get disabled. Maybe Santosh has some comments on this one.

Quoted 1 line

Not sure what you mean wakeup issue on GP device.

IIUC, the issue is:
Wakeup from device OFF, hardware releases the reset for both CPUs, This is special case and applicable only for device OFF. The reason CPU1 needs to be hold back, because the security SW is affined with CPU0 which needs to be up and running for any of the ROM code APIs to work. Like setting up SMP bit, AUX control etc. Without CPU0 booted, CPU1 won't be able to execute those ROM functions and hence won't be able to boot properly.

I think the limitation is applicable to all OMAP4 devices as well as OMAP5 devices.

Regards
Santosh

#79 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

Quoted 35 lines · Santosh

Tero,

Quoted 21 lines · Tero Kristo
Quoted 7 lines · Kevin Hilman
Quoted 2 lines · Tero Kristo

If AUX_CORE_BOOT0 does not indicate wakeup request for cpu1, put it back to off.

Why is it waking up then? ?(I know the answer, but will forget. ?The changelog serves as my long-term memory.)

Will add comment. (Both cpus will wake-up after device-off reset.)

Quoted 5 lines
Quoted 3 lines

This is needed during wakeup from device off to prevent cpu1 from being stuck indefinitely in the wakeup loop

Why does it get stuck?

Related to the above, if the AUX_CORE_BOOT0 is not set, the code will wait for it indefinitely in busy loop.

Quoted 1 line
Quoted 9 lines
Quoted 3 lines
Quoted 1 line

and also to prevent wakeup problem on GP chips with device off mode.

What wakeup problem?

This is apparently related to the GIC restore issue addressed with patch 3/8 of the core-ret set (workaround for the ROM bug because of CA9 r2pX gic register change), the interrupts get disabled. Maybe Santosh has some comments on this one.

Quoted 1 line

Not sure what you mean wakeup issue on GP device.

Quoted 8 lines

IIUC, the issue is:
Wakeup from device OFF, hardware releases the reset for both CPUs, This is special case and applicable only for device OFF. The reason CPU1 needs to be hold back, because the security SW is affined with CPU0 which needs to be up and running for any of the ROM code APIs to work. Like setting up SMP bit, AUX control etc. Without CPU0 booted, CPU1 won't be able to execute those ROM functions and hence won't be able to boot properly.

That's a nice description of the problem. Please incorporate a summary like this into the changlog to describe the problem, then describe the solution.

Thanks,

Kevin

Quoted 2 lines

I think the limitation is applicable to all OMAP4 devices as well as OMAP5 devices.

#80 lore raw

PATCH v2 17/19 ARM: OMAP4: put cpu1 back to sleep if no wake request

In reply to Shilimkar, Santosh
Quoted 13 lines · Santosh
Quoted 2 lines
Quoted 2 lines

Not sure what you mean wakeup issue on GP device.

IIUC, the issue is:
Wakeup from device OFF, hardware releases the reset for both CPUs, This is special case and applicable only for device OFF. The reason CPU1 needs to be hold back, because the security SW is affined with CPU0 which needs to be up and running for any of the ROM code APIs to work. Like setting up SMP bit, AUX control etc. Without CPU0 booted, CPU1 won't be able to execute those ROM functions and hence won't be able to boot properly.

Quoted 2 lines

I think the limitation is applicable to all OMAP4 devices as well as OMAP5 devices.

yes, the stagger of CPU1 behind CPU0 has a few factors:
HS devices with an older PPA release has a bug where caches can be messed up and GP devices
need slightly different WA. with the older PPA, we put CPU1 back to OFF when we detect that CPU0 is not ready for action
you can find the details and documentation in the link below:
http://git.omapzoom.org/?p=kernel/omap.git;a=blob;f=arch/arm/mach-omap2/sleep44xx.S;h=0c28def8f644e9803564bb66c8cfe8c580898978;hb=p-android-omap-3.0#l342

Regards,
Nishanth Menon

#81 lore raw

PATCH v2 18/19 ARM: OMAP4460: wakeupgen: set GIC_CPU0 backup status flag always

In reply to Tero Kristo

Without this, CPU0 will crash in the ROM code during wakeup from device off. This patch also clears the GIC save area, to prevent ROM code from writing garbage to the GIC registers during wakeup. The actual GIC restore is done by kernel.

This bug fix applies only to OMAP4460, it is fixed on OMAP4470.

---
 arch/arm/mach-omap2/omap-wakeupgen.c   |   14 ++++++++++++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    1 +
 2 files changed, 15 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +14 -0
index c7c4db4..30da299 100644
@@ -447,10 +447,24 @@ int __init omap_wakeupgen_init(void)
 
 	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
 		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+		/* Clean GIC SAR area */
+		for (i = SAR_BACKUP_STATUS_OFFSET; i < WAKEUPGENENB_OFFSET_CPU0;
+			i += 4)
+			sar_writel(0, i, 0);
+
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
 		for (i = 0; i < max_spi_reg; i++)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+
+		/*
+		 * Set CPU0 GIC backup flag permanently for omap4460,
+		 * this is needed because of the ROM code bug that breaks
+		 * GIC during wakeup from device off
+		 */
+		if (cpu_is_omap446x())
+			__raw_writel(SAR_BACKUP_STATUS_GIC_CPU0,
+				     sar_base + SAR_BACKUP_STATUS_OFFSET);
 		iounmap(sar_base);
 		sar_base = NULL;
 	} else {
arch/arm/mach-omap2/omap4-sar-layout.h +1 -0
index 0056667..e621c51 100644
@@ -88,6 +88,7 @@
 #define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
 #define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
 #define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)
+#define SAR_BACKUP_STATUS_GIC_CPU0		0x1
 
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)
Signature · 1 line
1.7.4.1
#82 lore raw

PATCH v2 18/19 ARM: OMAP4460: wakeupgen: set GIC_CPU0 backup status flag always

Quoted 8 lines · Tero Kristo

Without this, CPU0 will crash in the ROM code during wakeup from device off. This patch also clears the GIC save area, to prevent ROM code from writing garbage to the GIC registers during wakeup. The actual GIC restore is done by kernel.

This bug fix applies only to OMAP4460, it is fixed on OMAP4470.

Please create/use PM_ERRATUM flag.

Kevin

Quoted 46 lines
---
 arch/arm/mach-omap2/omap-wakeupgen.c   |   14 ++++++++++++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    1 +
 2 files changed, 15 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +14 -0
index c7c4db4..30da299 100644
@@ -447,10 +447,24 @@ int __init omap_wakeupgen_init(void)
 
 	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
 		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+		/* Clean GIC SAR area */
+		for (i = SAR_BACKUP_STATUS_OFFSET; i < WAKEUPGENENB_OFFSET_CPU0;
+			i += 4)
+			sar_writel(0, i, 0);
+
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
 		for (i = 0; i < max_spi_reg; i++)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+
+		/*
+		 * Set CPU0 GIC backup flag permanently for omap4460,
+		 * this is needed because of the ROM code bug that breaks
+		 * GIC during wakeup from device off
+		 */
+		if (cpu_is_omap446x())
+			__raw_writel(SAR_BACKUP_STATUS_GIC_CPU0,
+				     sar_base + SAR_BACKUP_STATUS_OFFSET);
 		iounmap(sar_base);
 		sar_base = NULL;
 	} else {
arch/arm/mach-omap2/omap4-sar-layout.h +1 -0
index 0056667..e621c51 100644
@@ -88,6 +88,7 @@
 #define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
 #define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
 #define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)
+#define SAR_BACKUP_STATUS_GIC_CPU0		0x1
 
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)
#83 lore raw

PATCH v2 18/19 ARM: OMAP4460: wakeupgen: set GIC_CPU0 backup status flag always

Quoted 7 lines · Kevin Hilman
Quoted 5 lines · Tero Kristo

Without this, CPU0 will crash in the ROM code during wakeup from device off. This patch also clears the GIC save area, to prevent ROM code from writing garbage to the GIC registers during wakeup. The actual GIC restore is done by kernel.

Quoted 5 lines
Quoted 3 lines

This bug fix applies only to OMAP4460, it is fixed on OMAP4470.

Please create/use PM_ERRATUM flag.

Okay.

-Tero

Quoted 49 lines

Kevin

Quoted 46 lines
---
 arch/arm/mach-omap2/omap-wakeupgen.c   |   14 ++++++++++++++
 arch/arm/mach-omap2/omap4-sar-layout.h |    1 +
 2 files changed, 15 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap-wakeupgen.c +14 -0
index c7c4db4..30da299 100644
@@ -447,10 +447,24 @@ int __init omap_wakeupgen_init(void)
 
 	if (omap_type() == OMAP2_DEVICE_TYPE_GP) {
 		sar_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+		/* Clean GIC SAR area */
+		for (i = SAR_BACKUP_STATUS_OFFSET; i < WAKEUPGENENB_OFFSET_CPU0;
+			i += 4)
+			sar_writel(0, i, 0);
+
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU0_OFFSET, 0);
 		sar_writel(GIC_ISR_NON_SECURE, ICDISR_CPU1_OFFSET, 0);
 		for (i = 0; i < max_spi_reg; i++)
 			sar_writel(GIC_ISR_NON_SECURE, ICDISR_SPI_OFFSET, i);
+
+		/*
+		 * Set CPU0 GIC backup flag permanently for omap4460,
+		 * this is needed because of the ROM code bug that breaks
+		 * GIC during wakeup from device off
+		 */
+		if (cpu_is_omap446x())
+			__raw_writel(SAR_BACKUP_STATUS_GIC_CPU0,
+				     sar_base + SAR_BACKUP_STATUS_OFFSET);
 		iounmap(sar_base);
 		sar_base = NULL;
 	} else {
arch/arm/mach-omap2/omap4-sar-layout.h +1 -0
index 0056667..e621c51 100644
@@ -88,6 +88,7 @@
 #define ICDISR_CPU0_OFFSET			(SAR_BANK3_OFFSET + 0x50c)
 #define ICDISR_CPU1_OFFSET			(SAR_BANK3_OFFSET + 0x510)
 #define ICDISR_SPI_OFFSET			(SAR_BANK3_OFFSET + 0x514)
+#define SAR_BACKUP_STATUS_GIC_CPU0		0x1
 
 /* WakeUpGen save restore offset from OMAP44XX_SAR_RAM_BASE */
 #define WAKEUPGENENB_OFFSET_CPU0		(SAR_BANK3_OFFSET + 0x684)
#84 lore raw

PATCH v2 19/19 ARM: OMAP4: powerdomain: update mpu / core off counters during device off

In reply to Tero Kristo

Currently device off does not have any counters / timers of its own and it is impossible to track the time spent in this state. In device off, MPU / CORE powerdomains enter OSWR, so normally the RETENTION state times / counts are increased during device off.

This patch adds a new field to the powerdomain struct for context loss register, which is checked during pwrdm_post_transition to see if a device off type context loss has happened. If this is the case, the counters + timers for OFF state are touched instead of RETENTION.

---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c   |    1 -
 arch/arm/mach-omap2/powerdomain.c           |    9 +++++++++
 arch/arm/mach-omap2/powerdomain.h           |    2 ++
 arch/arm/mach-omap2/powerdomains44xx_data.c |    2 ++
 arch/arm/mach-omap2/prm44xx.c               |   15 +++++++++++++++
 arch/arm/mach-omap2/prm44xx.h               |    2 ++
 6 files changed, 30 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -1
index 1f06f97..f187025 100644
@@ -404,7 +404,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 	if (omap4_device_prev_state_off()) {
 		omap4_dpll_resume_off();
 		omap4_cm_resume_off();
-		omap4_device_clear_prev_off_state();
 	}
 
 sar_save_failed:
arch/arm/mach-omap2/powerdomain.c +9 -0
index 96ad3dbe..f13bb2c 100644
@@ -156,6 +156,15 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 		break;
 	case PWRDM_STATE_PREV:
 		prev = pwrdm_read_prev_pwrst(pwrdm);
+
+		/*
+		 * If powerdomain has context offset defined, check if
+		 * the domain has lost context (i.e. entered off)
+		 */
+		if (pwrdm->context_offs)
+			if (omap4_pwrdm_lost_context_rff(pwrdm->prcm_offs,
+							 pwrdm->context_offs))
+				prev = PWRDM_POWER_OFF;
 		if (pwrdm->state != prev)
 			pwrdm->state_counter[prev]++;
 		if (prev == PWRDM_POWER_RET)
arch/arm/mach-omap2/powerdomain.h +2 -0
index 0d72a8a..a427645 100644
@@ -82,6 +82,7 @@ struct powerdomain;
  * @name: Powerdomain name
  * @voltdm: voltagedomain containing this powerdomain
  * @prcm_offs: the address offset from CM_BASE/PRM_BASE
+ * @context_offs: the address offset for the CONTEXT register
  * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
  * @pwrsts: Possible powerdomain power states
  * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
@@ -106,6 +107,7 @@ struct powerdomain {
 		struct voltagedomain *ptr;
 	} voltdm;
 	const s16 prcm_offs;
+	const s16 context_offs;
 	const u8 pwrsts;
 	const u8 pwrsts_logic_ret;
 	const u8 flags;
arch/arm/mach-omap2/powerdomains44xx_data.c +2 -0
index d8701ce..c4de02f 100644
@@ -36,6 +36,7 @@ static struct powerdomain core_44xx_pwrdm = {
 	.voltdm		  = { .name = "core" },
 	.prcm_offs	  = OMAP4430_PRM_CORE_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
+	.context_offs	  = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
@@ -205,6 +206,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
 	.voltdm		  = { .name = "mpu" },
 	.prcm_offs	  = OMAP4430_PRM_MPU_INST,
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
+	.context_offs	  = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
 	.pwrsts		  = PWRSTS_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
arch/arm/mach-omap2/prm44xx.c +15 -0
index 86c6c6b..de9132f 100644
@@ -289,6 +289,21 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 			OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
+bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset)
+{
+	u32 val;
+
+	val = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst, offset);
+
+	if (val & OMAP4430_LOSTCONTEXT_RFF_MASK) {
+		omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, inst,
+					     offset);
+		return true;
+	}
+
+	return false;
+}
+
 /**
  * omap4_device_set_state_off() - setup device off state
  * @enable:	set to off or not.
arch/arm/mach-omap2/prm44xx.h +2 -0
index ee72ae6..fa76d9c 100644
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
 extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
 
+extern bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset);
+
 # endif
 
 #endif
Signature · 1 line
1.7.4.1
#85 lore raw

PATCH v2 19/19 ARM: OMAP4: powerdomain: update mpu / core off counters during device off

Quoted 25 lines · Tero Kristo

Currently device off does not have any counters / timers of its own and it is impossible to track the time spent in this state. In device off, MPU / CORE powerdomains enter OSWR, so normally the RETENTION state times / counts are increased during device off.

This patch adds a new field to the powerdomain struct for context loss register, which is checked during pwrdm_post_transition to see if a device off type context loss has happened. If this is the case, the counters + timers for OFF state are touched instead of RETENTION.

---

?arch/arm/mach-omap2/omap-mpuss-lowpower.c ? | ? ?1 -
?arch/arm/mach-omap2/powerdomain.c ? ? ? ? ? | ? ?9 +++++++++
?arch/arm/mach-omap2/powerdomain.h ? ? ? ? ? | ? ?2 ++
?arch/arm/mach-omap2/powerdomains44xx_data.c | ? ?2 ++
?arch/arm/mach-omap2/prm44xx.c ? ? ? ? ? ? ? | ? 15 +++++++++++++++
?arch/arm/mach-omap2/prm44xx.h ? ? ? ? ? ? ? | ? ?2 ++

?6 files changed, 30 insertions(+), 1 deletions(-)

arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
index 1f06f97..f187025 100644

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 407

Quoted 4 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -1
@@ -404,7 +404,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 ? ? ? ?if (omap4_device_prev_state_off()) {
 ? ? ? ? ? ? ? ?omap4_dpll_resume_off();
 ? ? ? ? ? ? ? ?omap4_cm_resume_off();
- ? ? ? ? ? ? ? omap4_device_clear_prev_off_state();

We should probably delete the function in it's entirety - not just the call - the original implementation just clears L3 and this implementation seems superior.

Quoted 11 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
 ? ? ? ?}
 

?sar_save_failed:

arch/arm/mach-omap2/powerdomain.c +0 -0
index 96ad3dbe..f13bb2c 100644
@@ -156,6 +156,15 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 ? ? ? ? ? ? ? ?break;

? ? ? ?case PWRDM_STATE_PREV:
? ? ? ? ? ? ? ?prev = pwrdm_read_prev_pwrst(pwrdm);

Quoted 8 lines

+
+ ? ? ? ? ? ? ? /*
+ ? ? ? ? ? ? ? ?* If powerdomain has context offset defined, check if
+ ? ? ? ? ? ? ? ?* the domain has lost context (i.e. entered off)
+ ? ? ? ? ? ? ? ?*/
+ ? ? ? ? ? ? ? if (pwrdm->context_offs)
+ ? ? ? ? ? ? ? ? ? ? ? if (omap4_pwrdm_lost_context_rff(pwrdm->prcm_offs,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?pwrdm->context_offs))

We should wrap this under pwrdm_lost_context(pwrdm) pwrdm_lost_context should call the arch_pwrdm->lost_context_rff as needed? the rest of the powerdomain.c does not use OMAP4 specific APIs.

Quoted 37 lines

+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? prev = PWRDM_POWER_OFF; ? ? ? ? ? ? ? ?if (pwrdm->state != prev)
? ? ? ? ? ? ? ? ? ? ? ?pwrdm->state_counter[prev]++; ? ? ? ? ? ? ? ?if (prev == PWRDM_POWER_RET)

arch/arm/mach-omap2/powerdomain.h +0 -0
index 0d72a8a..a427645 100644
@@ -82,6 +82,7 @@ struct powerdomain;

?* @name: Powerdomain name
?* @voltdm: voltagedomain containing this powerdomain
?* @prcm_offs: the address offset from CM_BASE/PRM_BASE
+ * @context_offs: the address offset for the CONTEXT register ?* @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs ?* @pwrsts: Possible powerdomain power states
?* @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION

arch/arm/mach-omap2/powerdomain.h +1 -0
@@ -106,6 +107,7 @@ struct powerdomain {
 ? ? ? ? ? ? ? ?struct voltagedomain *ptr;
 ? ? ? ?} voltdm;
 ? ? ? ?const s16 prcm_offs;
+ ? ? ? const s16 context_offs;
 ? ? ? ?const u8 pwrsts;
 ? ? ? ?const u8 pwrsts_logic_ret;
 ? ? ? ?const u8 flags;
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -0
index d8701ce..c4de02f 100644
@@ -36,6 +36,7 @@ static struct powerdomain core_44xx_pwrdm = {
 ? ? ? ?.voltdm ? ? ? ? ? = { .name = "core" },
 ? ? ? ?.prcm_offs ? ? ? ?= OMAP4430_PRM_CORE_INST,
 ? ? ? ?.prcm_partition ? = OMAP4430_PRM_PARTITION,
+ ? ? ? .context_offs ? ? = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
 ? ? ? ?.pwrsts ? ? ? ? ? = PWRSTS_RET_ON,
 ? ? ? ?.pwrsts_logic_ret = PWRSTS_OFF_RET,
 ? ? ? ?.banks ? ? ? ? ? ?= 5,

arch/arm/mach-omap2/powerdomains44xx_data.c static struct powerdomain mpu_44xx_pwrdm = { · line 212

Quoted 7 lines
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -0
@@ -205,6 +206,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
 ? ? ? ?.voltdm ? ? ? ? ? = { .name = "mpu" },
 ? ? ? ?.prcm_offs ? ? ? ?= OMAP4430_PRM_MPU_INST,
 ? ? ? ?.prcm_partition ? = OMAP4430_PRM_PARTITION,
+ ? ? ? .context_offs ? ? = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
 ? ? ? ?.pwrsts ? ? ? ? ? = PWRSTS_RET_ON,
 ? ? ? ?.pwrsts_logic_ret = PWRSTS_OFF_RET,
 ? ? ? ?.banks ? ? ? ? ? ?= 3,

Why are we not populating the rest of the CONTEXT_OFFSET registers?

Quoted 13 lines
arch/arm/mach-omap2/prm44xx.c +5 -0
index 86c6c6b..de9132f 100644
@@ -289,6 +289,21 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
 ? ? ? ? ? ? ? ? ? ? ? ?OMAP4_PRM_IO_PMCTRL_OFFSET);
 ?}
 
+bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset)
+{
+ ? ? ? u32 val;
+
+ ? ? ? val = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst, offset);

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 306

Quoted 10 lines
arch/arm/mach-omap2/prm44xx.c +10 -0
+
+ ? ? ? if (val & OMAP4430_LOSTCONTEXT_RFF_MASK) {
+ ? ? ? ? ? ? ? omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, inst,
+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?offset);
+ ? ? ? ? ? ? ? return true;
+ ? ? ? }
+
+ ? ? ? return false;
+}
+

could move to powerdomain4xx.c?

arch/arm/mach-omap2/prm44xx.h extern void omap44xx_prm_ocp_barrier(void); · line 774

Quoted 12 lines

?/**
?* omap4_device_set_state_off() - setup device off state ?* @enable: ? ?set to off or not.

arch/arm/mach-omap2/prm44xx.h +1 -0
index ee72ae6..fa76d9c 100644
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
 ?extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
 ?extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
 
+extern bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset);

we dont need to do this if we use arch_pwrdm->

Quoted 4 lines
arch/arm/mach-omap2/prm44xx.h +1 -0
+

?# endif

?#endif

---
Regards,
Nishanth Menon

#86 lore raw

PATCH v2 19/19 ARM: OMAP4: powerdomain: update mpu / core off counters during device off

Quoted 21 lines · Nishanth
Quoted 20 lines · Tero Kristo

Currently device off does not have any counters / timers of its own and it is impossible to track the time spent in this state. In device off, MPU / CORE powerdomains enter OSWR, so normally the RETENTION state times / counts are increased during device off.

This patch adds a new field to the powerdomain struct for context loss register, which is checked during pwrdm_post_transition to see if a device off type context loss has happened. If this is the case, the counters + timers for OFF state are touched instead of RETENTION.

---
 arch/arm/mach-omap2/omap-mpuss-lowpower.c   |    1 -
 arch/arm/mach-omap2/powerdomain.c           |    9 +++++++++
 arch/arm/mach-omap2/powerdomain.h           |    2 ++
 arch/arm/mach-omap2/powerdomains44xx_data.c |    2 ++
 arch/arm/mach-omap2/prm44xx.c               |   15 +++++++++++++++
 arch/arm/mach-omap2/prm44xx.h               |    2 ++
 6 files changed, 30 insertions(+), 1 deletions(-)
Quoted 13 lines

arch/arm/mach-omap2/omap-mpuss-lowpower.c int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) · line 407

Quoted 9 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -1
index 1f06f97..f187025 100644
@@ -404,7 +404,6 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
       if (omap4_device_prev_state_off()) {
               omap4_dpll_resume_off();
               omap4_cm_resume_off();
-               omap4_device_clear_prev_off_state();

We should probably delete the function in it's entirety - not just the call - the original implementation just clears L3 and this implementation seems superior.

Yeah, that can be done, I don't think it is used anymore after this change.

Quoted 17 lines
Quoted 17 lines
arch/arm/mach-omap2/omap-mpuss-lowpower.c +0 -0
       }
 
 sar_save_failed:
arch/arm/mach-omap2/powerdomain.c +5 -0
index 96ad3dbe..f13bb2c 100644
@@ -156,6 +156,15 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
               break;
       case PWRDM_STATE_PREV:
               prev = pwrdm_read_prev_pwrst(pwrdm);
+
+               /*
+                * If powerdomain has context offset defined, check if
+                * the domain has lost context (i.e. entered off)
+                */
Quoted 8 lines

arch/arm/mach-omap2/powerdomain.c static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag) · line 166

Quoted 3 lines
arch/arm/mach-omap2/powerdomain.c +3 -0
+               if (pwrdm->context_offs)
+                       if (omap4_pwrdm_lost_context_rff(pwrdm->prcm_offs,
+                                                        pwrdm->context_offs))

We should wrap this under pwrdm_lost_context(pwrdm) pwrdm_lost_context should call the arch_pwrdm->lost_context_rff as needed? the rest of the powerdomain.c does not use OMAP4 specific APIs.

Yes, that sounds like a good change, I'll change this.

Quoted 40 lines
Quoted 40 lines
arch/arm/mach-omap2/powerdomain.c +1 -0
+                               prev = PWRDM_POWER_OFF;
               if (pwrdm->state != prev)
                       pwrdm->state_counter[prev]++;
               if (prev == PWRDM_POWER_RET)
arch/arm/mach-omap2/powerdomain.h +2 -0
index 0d72a8a..a427645 100644
@@ -82,6 +82,7 @@ struct powerdomain;
 * @name: Powerdomain name
 * @voltdm: voltagedomain containing this powerdomain
 * @prcm_offs: the address offset from CM_BASE/PRM_BASE
+ * @context_offs: the address offset for the CONTEXT register
 * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs
 * @pwrsts: Possible powerdomain power states
 * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
@@ -106,6 +107,7 @@ struct powerdomain {
               struct voltagedomain *ptr;
       } voltdm;
       const s16 prcm_offs;
+       const s16 context_offs;
       const u8 pwrsts;
       const u8 pwrsts_logic_ret;
       const u8 flags;
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -0
index d8701ce..c4de02f 100644
@@ -36,6 +36,7 @@ static struct powerdomain core_44xx_pwrdm = {
       .voltdm           = { .name = "core" },
       .prcm_offs        = OMAP4430_PRM_CORE_INST,
       .prcm_partition   = OMAP4430_PRM_PARTITION,
+       .context_offs     = OMAP4_RM_L3_1_L3_1_CONTEXT_OFFSET,
       .pwrsts           = PWRSTS_RET_ON,
       .pwrsts_logic_ret = PWRSTS_OFF_RET,
       .banks            = 5,
@@ -205,6 +206,7 @@ static struct powerdomain mpu_44xx_pwrdm = {
       .voltdm           = { .name = "mpu" },
Quoted 8 lines

arch/arm/mach-omap2/powerdomains44xx_data.c static struct powerdomain mpu_44xx_pwrdm = { · line 212

Quoted 6 lines
arch/arm/mach-omap2/powerdomains44xx_data.c +1 -0
       .prcm_offs        = OMAP4430_PRM_MPU_INST,
       .prcm_partition   = OMAP4430_PRM_PARTITION,
+       .context_offs     = OMAP4_RM_MPU_MPU_CONTEXT_OFFSET,
       .pwrsts           = PWRSTS_RET_ON,
       .pwrsts_logic_ret = PWRSTS_OFF_RET,
       .banks            = 3,

Why are we not populating the rest of the CONTEXT_OFFSET registers?

Well, the thing is, other domains don't have any 'spare' context registers that are not needed by anything else. Like, all the per domain context registers are used by some hwmod. If we grab the register for this use, then the context lost count for that hwmod will break.

For PER domain, it might be possible to use RM_L4PER_L4_PER_CONTEXT though (it has two bit positions), but that is the only one missing... Other domains do go to OFF. L3_init domain doesn't have anything.

Quoted 18 lines
Quoted 18 lines
arch/arm/mach-omap2/prm44xx.c +9 -0
index 86c6c6b..de9132f 100644
@@ -289,6 +289,21 @@ static void __init omap44xx_prm_enable_io_wakeup(void)
                       OMAP4_PRM_IO_PMCTRL_OFFSET);
 }
 
+bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset)
+{
+       u32 val;
+
+       val = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst, offset);
+
+       if (val & OMAP4430_LOSTCONTEXT_RFF_MASK) {
+               omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, inst,
+                                            offset);
Quoted 8 lines

arch/arm/mach-omap2/prm44xx.c static void __init omap44xx_prm_enable_io_wakeup(void) · line 306

Quoted 6 lines
arch/arm/mach-omap2/prm44xx.c +6 -0
+               return true;
+       }
+
+       return false;
+}
+

could move to powerdomain4xx.c?

Yes, I'll do that.

-Tero

Quoted 22 lines

arch/arm/mach-omap2/prm44xx.h extern void omap44xx_prm_ocp_barrier(void); · line 774

Quoted 13 lines
arch/arm/mach-omap2/prm44xx.c +0 -0
 /**
 * omap4_device_set_state_off() - setup device off state
 * @enable:    set to off or not.
arch/arm/mach-omap2/prm44xx.h +1 -0
index ee72ae6..fa76d9c 100644
@@ -771,6 +771,8 @@ extern void omap44xx_prm_ocp_barrier(void);
 extern void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap44xx_prm_restore_irqen(u32 *saved_mask);
 
+extern bool omap4_pwrdm_lost_context_rff(s16 inst, s16 offset);

we dont need to do this if we use arch_pwrdm->

arch/arm/mach-omap2/prm44xx.h extern void omap44xx_prm_ocp_barrier(void); · line 778

Quoted 4 lines
arch/arm/mach-omap2/prm44xx.h +1 -0
+
 # endif
 
 #endif

---
Regards,
Nishanth Menon