msm: pm-8x60: Merge msm_pm_idle_prepare into msm_pm_idle_enter

Modify LPM drivers to call msm_pm_idle_enter when idle. enter_sleep will
look at available time to sleep and the latencies of different low power
modes and decide the low power mode to enter. It returns the low power
mode enumeration back to cpuidle.

Change-Id: I56717f2ba7a748b38d53b418381a01159055e7bd
Signed-off-by: Priyanka Mathur <pmathur@codeaurora.org>
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index d2a58d7..e87c7b5 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -72,18 +72,19 @@
 	struct cpuidle_device *dev, struct cpuidle_driver *drv, int index)
 {
 	int ret = 0;
-	int i = 0;
+	int i;
 	enum msm_pm_sleep_mode pm_mode;
-	struct cpuidle_state_usage *st_usage = NULL;
 
 	cpu_pm_enter();
 
-	pm_mode = msm_pm_idle_prepare(dev, drv, index);
-	dev->last_residency = msm_pm_idle_enter(pm_mode);
+	pm_mode = msm_pm_idle_enter(dev, drv, index);
+
 	for (i = 0; i < dev->state_count; i++) {
-		st_usage = &dev->states_usage[i];
-		if ((enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage)
-		    == pm_mode) {
+		struct cpuidle_state_usage *st_usage = &dev->states_usage[i];
+		enum msm_pm_sleep_mode last_mode =
+			(enum msm_pm_sleep_mode)cpuidle_get_statedata(st_usage);
+
+		if (last_mode == pm_mode) {
 			ret = i;
 			break;
 		}
diff --git a/arch/arm/mach-msm/no-pm.c b/arch/arm/mach-msm/no-pm.c
index 0db6e68..a8d4fdb 100644
--- a/arch/arm/mach-msm/no-pm.c
+++ b/arch/arm/mach-msm/no-pm.c
@@ -37,15 +37,11 @@
 
 void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls) {}
 
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv, int index)
 {
 	return -ENOSYS;
 }
 
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode)
-{
-	return -ENOSYS;
-}
-
 void msm_pm_enable_retention(bool enable) {}
+
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 657f524..b52d284 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -445,8 +445,6 @@
 	}
 }
 
-static void *msm_pm_idle_rs_limits;
-
 static void msm_pm_swfi(void)
 {
 	msm_pm_config_hw_before_swfi();
@@ -724,8 +722,9 @@
 	}
 }
 
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
-		struct cpuidle_driver *drv, int index)
+static int msm_pm_idle_prepare(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int index,
+		void **msm_pm_idle_rs_limits)
 {
 	int i;
 	unsigned int power_usage = -1;
@@ -752,9 +751,9 @@
 		struct cpuidle_state_usage *st_usage = &dev->states_usage[i];
 		enum msm_pm_sleep_mode mode;
 		bool allow;
-		void *rs_limits = NULL;
 		uint32_t power;
 		int idx;
+		void *rs_limits = NULL;
 
 		mode = (enum msm_pm_sleep_mode) cpuidle_get_statedata(st_usage);
 		idx = MSM_PM_MODE(dev->cpu, mode);
@@ -806,10 +805,9 @@
 			power_usage = power;
 			modified_time_us = time_param.modified_time_us;
 			ret = mode;
+			*msm_pm_idle_rs_limits = rs_limits;
 		}
 
-		if (MSM_PM_SLEEP_MODE_POWER_COLLAPSE == mode)
-			msm_pm_idle_rs_limits = rs_limits;
 	}
 
 	if (modified_time_us && !dev->cpu)
@@ -822,11 +820,27 @@
 	return ret;
 }
 
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode)
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
+	struct cpuidle_driver *drv, int index)
 {
 	int64_t time;
-	int exit_stat;
 	bool collapsed = 1;
+	int exit_stat = -1;
+	enum msm_pm_sleep_mode sleep_mode;
+	void *msm_pm_idle_rs_limits = NULL;
+	int sleep_delay = 1;
+	int ret = -ENODEV;
+	int64_t timer_expiration = 0;
+	int notify_rpm = false;
+	bool timer_halted = false;
+
+	sleep_mode = msm_pm_idle_prepare(dev, drv, index,
+		&msm_pm_idle_rs_limits);
+
+	if (!msm_pm_idle_rs_limits) {
+		sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
+		goto cpuidle_enter_bail;
+	}
 
 	if (MSM_PM_DEBUG_IDLE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: mode %d\n",
@@ -834,6 +848,22 @@
 
 	time = ktime_to_ns(ktime_get());
 
+	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
+		notify_rpm = true;
+		timer_expiration = msm_pm_timer_enter_idle();
+
+		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;
+	}
+
+	if (pm_sleep_ops.enter_sleep)
+		ret = pm_sleep_ops.enter_sleep(sleep_delay,
+			msm_pm_idle_rs_limits, true, notify_rpm);
+	if (ret)
+		goto cpuidle_enter_bail;
+
 	switch (sleep_mode) {
 	case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
 		msm_pm_swfi();
@@ -850,41 +880,16 @@
 		exit_stat = MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE;
 		break;
 
-	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE: {
-		int64_t timer_expiration = 0;
-		bool timer_halted = false;
-		uint32_t sleep_delay;
-		int ret = -ENODEV;
-		int notify_rpm =
-			(sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE);
-		timer_expiration = msm_pm_timer_enter_idle();
-
-		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;
-
+	case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
 		if (MSM_PM_DEBUG_IDLE_CLK & msm_pm_debug_mask)
 			clock_debug_print_enabled();
 
-		if (pm_sleep_ops.enter_sleep)
-			ret =
-			pm_sleep_ops.enter_sleep(sleep_delay,
-					msm_pm_idle_rs_limits,
-					true, notify_rpm);
-		if (!ret) {
-			collapsed = msm_pm_power_collapse(true);
-			timer_halted = true;
+		collapsed = msm_pm_power_collapse(true);
+		timer_halted = true;
 
-			if (pm_sleep_ops.exit_sleep)
-				pm_sleep_ops.exit_sleep(
-					msm_pm_idle_rs_limits,
-						true, notify_rpm, collapsed);
-		}
-		msm_pm_timer_exit_idle(timer_halted);
 		exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE;
+		msm_pm_timer_exit_idle(timer_halted);
 		break;
-	}
 
 	case MSM_PM_SLEEP_MODE_NOT_SELECTED:
 		goto cpuidle_enter_bail;
@@ -896,16 +901,24 @@
 		break;
 	}
 
-	time = ktime_to_ns(ktime_get()) - time;
-	msm_pm_add_stat(exit_stat, time);
-	msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode,
-				collapsed);
+	if (pm_sleep_ops.exit_sleep)
+		pm_sleep_ops.exit_sleep(msm_pm_idle_rs_limits, true,
+				notify_rpm, collapsed);
 
+	time = ktime_to_ns(ktime_get()) - time;
+	msm_pm_ftrace_lpm_exit(smp_processor_id(), sleep_mode, collapsed);
+	if (exit_stat >= 0)
+		msm_pm_add_stat(exit_stat, time);
 	do_div(time, 1000);
-	return (int) time;
+	dev->last_residency = (int) time;
+	return sleep_mode;
 
 cpuidle_enter_bail:
-	return 0;
+	dev->last_residency = 0;
+	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE)
+		msm_pm_timer_exit_idle(timer_halted);
+	sleep_mode = MSM_PM_SLEEP_MODE_NOT_SELECTED;
+	return sleep_mode;
 }
 
 void msm_pm_cpu_enter_lowpower(unsigned int cpu)
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index ed6bb9e..af0744c 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -119,10 +119,9 @@
 };
 
 void msm_pm_set_platform_data(struct msm_pm_platform_data *data, int count);
-int msm_pm_idle_prepare(struct cpuidle_device *dev,
+enum msm_pm_sleep_mode msm_pm_idle_enter(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv, int index);
 void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls);
-int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
 void msm_pm_cpu_enter_lowpower(unsigned int cpu);
 void __init msm_pm_set_tz_retention_flag(unsigned int flag);
 void msm_pm_enable_retention(bool enable);