[PATCH 06/12] arm: omap3: am35x: Add full PWRDM_POWER_INACTIVE support

Mark A. Greer mgreer at animalcreek.com
Wed Apr 11 15:05:41 EDT 2012


From: "Mark A. Greer" <mgreer at animalcreek.com>

The am35x family of SoCs only support PWRDM_POWER_ON
and PWRDM_POWER_INACTIVE power states. This causes
an issue in some areas of the OMAP3 power-related
code because of assumptions that PWRDM_POWER_RET
and/or PWRDM_POWER_OFF are always valid states.

To get am35x SoCs to work properly, add missing support
for PWRDM_POWER_INACTIVE and remove assumptions that
PWRDM_POWER_RET and PWRDM_POWER_OFF are always valid states.

Signed-off-by: Mark A. Greer <mgreer at animalcreek.com>
---
 arch/arm/mach-omap2/cpuidle34xx.c |   29 +++++++++++++++++++++++--
 arch/arm/mach-omap2/pm-debug.c    |    8 +++++--
 arch/arm/mach-omap2/pm34xx.c      |   43 +++++++++++++++++++++++--------------
 3 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 12cf81d..187872a 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -175,12 +175,23 @@ static int next_valid_state(struct cpuidle_device *dev,
 	struct cpuidle_state_usage *curr_usage = &dev->states_usage[index];
 	struct cpuidle_state *curr = &drv->states[index];
 	struct omap3_idle_statedata *cx = cpuidle_get_statedata(curr_usage);
-	u32 mpu_deepest_state = PWRDM_POWER_RET;
-	u32 core_deepest_state = PWRDM_POWER_RET;
+	u32 mpu_deepest_state;
+	u32 core_deepest_state;
 	int next_index = -1;
 
+	if (omap3_has_pwroff()) {
+		mpu_deepest_state = PWRDM_POWER_RET;
+		core_deepest_state = PWRDM_POWER_RET;
+	} else {
+		mpu_deepest_state = PWRDM_POWER_INACTIVE;
+		core_deepest_state = PWRDM_POWER_INACTIVE;
+	}
+
 	if (enable_off_mode) {
+		WARN_ON(!omap3_has_pwroff());
+
 		mpu_deepest_state = PWRDM_POWER_OFF;
+
 		/*
 		 * Erratum i583: valable for ES rev < Es1.2 on 3630.
 		 * CORE OFF mode is not supported in a stable form, restrict
@@ -311,6 +322,9 @@ void omap3_pm_init_cpuidle(struct cpuidle_params *cpuidle_board_params)
 			cpuidle_board_params[i].exit_latency;
 		cpuidle_params_table[i].target_residency =
 			cpuidle_board_params[i].target_residency;
+
+		WARN_ON(!omap3_has_pwroff() && (i >= 2) &&
+				cpuidle_params_table[i].valid);
 	}
 	return;
 }
@@ -349,6 +363,16 @@ static inline struct omap3_idle_statedata *_fill_cstate_usage(
 	return cx;
 }
 
+/* Only C1 & C2 C states valid when RET & OFF states aren't supported */
+static void omap3_cstate_valid_fixup(void)
+{
+	int idx;
+
+	if (!omap3_has_pwroff())
+		for (idx = 2; idx < OMAP3_NUM_STATES; idx++)
+			cpuidle_params_table[idx].valid = 0;
+}
+
 /**
  * omap3_idle_init - Init routine for OMAP3 idle
  *
@@ -366,6 +390,7 @@ int __init omap3_idle_init(void)
 	per_pd = pwrdm_lookup("per_pwrdm");
 	cam_pd = pwrdm_lookup("cam_pwrdm");
 
+	omap3_cstate_valid_fixup();
 
 	drv->safe_state_index = -1;
 	dev = &per_cpu(omap3_idle_dev, smp_processor_id());
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..339ed42 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -239,19 +239,23 @@ static int option_get(void *data, u64 *val)
 static int option_set(void *data, u64 val)
 {
 	u32 *option = data;
+	int ret = -EINVAL;
 
 	*option = val;
 
-	if (option == &enable_off_mode) {
+	if (omap3_has_pwroff() && (option == &enable_off_mode)) {
 		if (val)
 			omap_pm_enable_off_mode();
 		else
 			omap_pm_disable_off_mode();
+
 		if (cpu_is_omap34xx())
 			omap3_pm_off_mode_enable(val);
+
+		ret = 0;
 	}
 
-	return 0;
+	return ret;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index b7bbcee..00c4abe 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -279,6 +279,7 @@ void omap_sram_idle(void)
 	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
 	switch (mpu_next_state) {
 	case PWRDM_POWER_ON:
+	case PWRDM_POWER_INACTIVE:
 	case PWRDM_POWER_RET:
 		/* No need to save context */
 		save_state = 0;
@@ -614,6 +615,8 @@ void omap3_pm_off_mode_enable(int enable)
 	struct power_state *pwrst;
 	u32 state;
 
+	WARN_ON(!omap3_has_pwroff());
+
 	if (enable)
 		state = PWRDM_POWER_OFF;
 	else
@@ -668,7 +671,12 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 	if (!pwrst)
 		return -ENOMEM;
 	pwrst->pwrdm = pwrdm;
-	pwrst->next_state = PWRDM_POWER_RET;
+
+	if (omap3_has_pwroff())
+		pwrst->next_state = PWRDM_POWER_RET;
+	else
+		pwrst->next_state = PWRDM_POWER_INACTIVE;
+
 	list_add(&pwrst->node, &pwrst_list);
 
 	if (pwrdm_has_hdwr_sar(pwrdm))
@@ -781,25 +789,28 @@ static int __init omap3_pm_init(void)
 		omap3630_ctrl_disable_rta();
 
 	clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
-	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
-		omap3_secure_ram_storage =
-			kmalloc(0x803F, GFP_KERNEL);
-		if (!omap3_secure_ram_storage)
-			pr_err("Memory allocation failed when "
-			       "allocating for secure sram context\n");
 
-		local_irq_disable();
-		local_fiq_disable();
+	if (omap3_has_pwroff()) {
+		if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
+			omap3_secure_ram_storage =
+				kmalloc(0x803F, GFP_KERNEL);
+			if (!omap3_secure_ram_storage)
+				pr_err("Memory allocation failed when "
+				       "allocating for secure sram context\n");
 
-		omap_dma_global_context_save();
-		omap3_save_secure_ram_context();
-		omap_dma_global_context_restore();
+			local_irq_disable();
+			local_fiq_disable();
 
-		local_irq_enable();
-		local_fiq_enable();
-	}
+			omap_dma_global_context_save();
+			omap3_save_secure_ram_context();
+			omap_dma_global_context_restore();
+
+			local_irq_enable();
+			local_fiq_enable();
 
-	omap3_save_scratchpad_contents();
+			omap3_save_scratchpad_contents();
+		}
+	}
 	return ret;
 
 err3:
-- 
1.7.9.4




More information about the linux-arm-kernel mailing list