pm2: Power Management driver changes for 8x25
Current pm2.c driver supports low power mode functionality
only for single APPS processor targets. This patch adds extra
functionality to pm2.c driver to support multicore APPS
processor targets where MODEM is a master.
These changes makes pm2.c driver backward compatible to
older targets(eg: 7x27a & 7x30 etc) & multicore APPS
processors like 8x25.
Change-Id: I79b23b2a2052aa55f9a169886dea17180614dedb
Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org>
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index 7977d22..ff7a930 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -48,6 +48,7 @@
#ifdef CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN
#include <mach/msm_migrate_pages.h>
#endif
+#include <mach/socinfo.h>
#include "smd_private.h"
#include "smd_rpcrouter.h"
@@ -142,7 +143,6 @@
static char *msm_pm_sleep_mode_labels[MSM_PM_SLEEP_MODE_NR] = {
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND] = " ",
[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = "power_collapse",
- [MSM_PM_SLEEP_MODE_APPS_SLEEP] = "apps_sleep",
[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT] =
"ramp_down_and_wfi",
[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT] = "wfi",
@@ -682,8 +682,6 @@
MSM_PM_STAT_IDLE_WFI,
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE,
- MSM_PM_STAT_IDLE_SLEEP,
- MSM_PM_STAT_IDLE_FAILED_SLEEP,
MSM_PM_STAT_IDLE_POWER_COLLAPSE,
MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
MSM_PM_STAT_SUSPEND,
@@ -1008,6 +1006,13 @@
memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data));
+ if (cpu_is_msm8625()) {
+ /* Program the SPM */
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE,
+ false);
+ WARN_ON(ret);
+ }
+
msm_irq_enter_sleep1(true, from_idle, &msm_pm_smem_data->irq_mask);
msm_sirc_enter_sleep();
msm_gpio_enter_sleep(from_idle);
@@ -1210,6 +1215,13 @@
MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");
smd_sleep_exit();
+
+ if (cpu_is_msm8625()) {
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+ false);
+ WARN_ON(ret);
+ }
+
return 0;
power_collapse_early_exit:
@@ -1263,6 +1275,12 @@
smd_sleep_exit();
power_collapse_bail:
+ if (cpu_is_msm8625()) {
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
+ false);
+ WARN_ON(ret);
+ }
+
return ret;
}
@@ -1272,10 +1290,11 @@
* Return value:
* 0: success
*/
-static int msm_pm_power_collapse_standalone(void)
+static int msm_pm_power_collapse_standalone(bool from_idle)
{
int collapsed = 0;
int ret;
+ void *entry;
MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
KERN_INFO, "%s()\n", __func__);
@@ -1283,21 +1302,26 @@
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE, false);
WARN_ON(ret);
+ entry = (!smp_processor_id() || from_idle) ?
+ msm_pm_collapse_exit : msm_secondary_startup;
+
msm_pm_boot_config_before_pc(smp_processor_id(),
- virt_to_phys(msm_pm_collapse_exit));
+ virt_to_phys(entry));
#ifdef CONFIG_VFP
vfp_flush_context();
#endif
#ifdef CONFIG_CACHE_L2X0
- l2x0_suspend();
+ if (!cpu_is_msm8625())
+ l2x0_suspend();
#endif
collapsed = msm_pm_collapse();
#ifdef CONFIG_CACHE_L2X0
- l2x0_resume(collapsed);
+ if (!cpu_is_msm8625())
+ l2x0_resume(collapsed);
#endif
msm_pm_boot_config_after_pc(smp_processor_id());
@@ -1321,18 +1345,6 @@
}
/*
- * Apps-sleep the Apps processor. This function execute the handshake
- * protocol with Modem.
- *
- * Return value:
- * -ENOSYS: function not implemented yet
- */
-static int msm_pm_apps_sleep(uint32_t sleep_delay, uint32_t sleep_limit)
-{
- return -ENOSYS;
-}
-
-/*
* Bring the Apps processor to SWFI.
*
* Return value:
@@ -1353,7 +1365,9 @@
return -EIO;
}
- msm_pm_config_hw_before_swfi();
+ if (!cpu_is_msm8625())
+ msm_pm_config_hw_before_swfi();
+
msm_arch_idle();
if (ramp_acpu) {
@@ -1395,7 +1409,7 @@
int64_t t1;
static int64_t t2;
int exit_stat;
- #endif /* CONFIG_MSM_IDLE_STATS */
+ #endif
if (!atomic_read(&msm_pm_init_done))
return;
@@ -1412,19 +1426,19 @@
exit_stat = MSM_PM_STAT_IDLE_SPIN;
low_power = 0;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
for (i = 0; i < ARRAY_SIZE(allow); i++)
allow[i] = true;
- if ((timer_expiration < msm_pm_idle_sleep_min_time) ||
+ if (num_online_cpus() > 1 ||
+ (timer_expiration < msm_pm_idle_sleep_min_time) ||
#ifdef CONFIG_HAS_WAKELOCK
has_wake_lock(WAKE_LOCK_IDLE) ||
#endif
!msm_irq_idle_sleep_allowed()) {
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false;
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false;
- allow[MSM_PM_SLEEP_MODE_APPS_SLEEP] = false;
}
for (i = 0; i < ARRAY_SIZE(allow); i++) {
@@ -1493,32 +1507,15 @@
exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
msm_pm_sleep_limit = sleep_limit;
}
-#endif /* CONFIG_MSM_IDLE_STATS */
- } else if (allow[MSM_PM_SLEEP_MODE_APPS_SLEEP]) {
- uint32_t sleep_delay;
-
- sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
- timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
- if (sleep_delay == 0) /* 0 would mean infinite time */
- sleep_delay = 1;
-
- ret = msm_pm_apps_sleep(sleep_delay, sleep_limit);
- low_power = 0;
-
-#ifdef CONFIG_MSM_IDLE_STATS
- if (ret)
- exit_stat = MSM_PM_STAT_IDLE_FAILED_SLEEP;
- else
- exit_stat = MSM_PM_STAT_IDLE_SLEEP;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- ret = msm_pm_power_collapse_standalone();
+ ret = msm_pm_power_collapse_standalone(true);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = ret ?
MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE :
MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
ret = msm_pm_swfi(true);
if (ret)
@@ -1527,20 +1524,20 @@
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = ret ? MSM_PM_STAT_IDLE_SPIN : MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
msm_pm_swfi(false);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = MSM_PM_STAT_IDLE_WFI;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
} else {
while (!msm_irq_pending())
udelay(1);
low_power = 0;
#ifdef CONFIG_MSM_IDLE_STATS
exit_stat = MSM_PM_STAT_IDLE_SPIN;
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
}
msm_timer_exit_idle(low_power);
@@ -1548,13 +1545,14 @@
#ifdef CONFIG_MSM_IDLE_STATS
t2 = ktime_to_ns(ktime_get());
msm_pm_add_stat(exit_stat, t2 - t1);
-#endif /* CONFIG_MSM_IDLE_STATS */
+#endif
}
/*
* Suspend the Apps processor.
*
* Return value:
+ * -EPERM: Suspend happened by a not permitted core
* -EAGAIN: modem reset occurred or early exit from suspend
* -EBUSY: modem not ready for our suspend
* -EINVAL: invalid sleep mode
@@ -1566,13 +1564,20 @@
{
bool allow[MSM_PM_SLEEP_MODE_NR];
uint32_t sleep_limit = SLEEP_LIMIT_NONE;
- int ret;
+ int ret = -EPERM;
int i;
-
#ifdef CONFIG_MSM_IDLE_STATS
int64_t period = 0;
int64_t time = 0;
+#endif
+ /* Must executed by CORE0 */
+ if (smp_processor_id()) {
+ __WARN();
+ goto suspend_exit;
+ }
+
+#ifdef CONFIG_MSM_IDLE_STATS
time = msm_timer_get_sclk_time(&period);
#endif
@@ -1589,8 +1594,6 @@
allow[i] = false;
}
- ret = 0;
-
if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] ||
allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) {
#ifdef CONFIG_MSM_IDLE_STATS
@@ -1647,7 +1650,7 @@
msm_pm_add_stat(id, time);
#endif
} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
- ret = msm_pm_power_collapse_standalone();
+ ret = msm_pm_power_collapse_standalone(false);
} else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) {
ret = msm_pm_swfi(true);
if (ret)
@@ -1657,6 +1660,7 @@
msm_pm_swfi(false);
}
+suspend_exit:
MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND, KERN_INFO,
"%s(): return %d\n", __func__, ret);
@@ -1725,10 +1729,6 @@
};
-/******************************************************************************
- *
- *****************************************************************************/
-
/*
* Initialize the power management subsystem.
*
@@ -1837,15 +1837,6 @@
first_bucket_time =
CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
- stats[MSM_PM_STAT_IDLE_SLEEP].name = "idle-sleep";
- stats[MSM_PM_STAT_IDLE_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
- stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].name =
- "idle-failed-sleep";
- stats[MSM_PM_STAT_IDLE_FAILED_SLEEP].first_bucket_time =
- CONFIG_MSM_IDLE_STATS_FIRST_BUCKET;
-
stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].name =
"idle-power-collapse";
stats[MSM_PM_STAT_IDLE_POWER_COLLAPSE].first_bucket_time =