msm: pm2: Use a different kernel API to get the sleep length

Currently pm2 driver calls the "msm_timer_enter_idle" &
msm_timer_exit_idle" API's for all the power modes (i.e.
SWFI, GDFS/StandalonePC) to get next timer expiration &
time sync with modem respectively. Use these API's only
when the system decide to enter into a modem assisted PC
otherwise use a differnt API to get the sleep length.

Change-Id: Idf5d53518f75551bab432b3532c0eae1f61cdff1
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 feb7671..86a3a2f 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -28,6 +28,7 @@
 #include <linux/reboot.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
+#include <linux/tick.h>
 #include <linux/memory.h>
 #ifdef CONFIG_HAS_WAKELOCK
 #include <linux/wakelock.h>
@@ -1497,10 +1498,8 @@
 	bool allow[MSM_PM_SLEEP_MODE_NR];
 	uint32_t sleep_limit = SLEEP_LIMIT_NONE;
 
-	int latency_qos;
 	int64_t timer_expiration;
-
-	int low_power;
+	int latency_qos;
 	int ret;
 	int i;
 	unsigned int cpu;
@@ -1517,15 +1516,14 @@
 	cpu = smp_processor_id();
 
 	latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
-	timer_expiration = msm_timer_enter_idle();
+	/* get the next timer expiration */
+	timer_expiration = ktime_to_ns(tick_nohz_get_sleep_length());
 
 #ifdef CONFIG_MSM_IDLE_STATS
 	t1 = ktime_to_ns(ktime_get());
 	msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - t2);
 	msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, timer_expiration);
-
 	exit_stat = MSM_PM_STAT_IDLE_SPIN;
-	low_power = 0;
 #endif
 
 	for (i = 0; i < ARRAY_SIZE(allow); i++)
@@ -1581,10 +1579,16 @@
 
 	if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] ||
 		allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) {
+		/* Sync the timer with SCLK, it is needed only for modem
+		 * assissted pollapse case.
+		 */
+		int64_t next_timer_exp = msm_timer_enter_idle();
 		uint32_t sleep_delay;
+		bool low_power = false;
 
 		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
-			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
+			next_timer_exp, MSM_PM_SLEEP_TICK_LIMIT);
+
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
 
@@ -1599,6 +1603,7 @@
 
 		ret = msm_pm_power_collapse(true, sleep_delay, sleep_limit);
 		low_power = (ret != -EBUSY && ret != -ETIMEDOUT);
+		msm_timer_exit_idle(low_power);
 
 #ifdef CONFIG_MSM_IDLE_STATS
 		if (ret)
@@ -1610,7 +1615,6 @@
 #endif
 	} else if (allow[MSM_PM_SLEEP_MODE_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 :
@@ -1621,27 +1625,22 @@
 		if (ret)
 			while (!msm_pm_irq_extns->irq_pending())
 				udelay(1);
-		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = ret ? MSM_PM_STAT_IDLE_SPIN : MSM_PM_STAT_IDLE_WFI;
 #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
 	} else {
 		while (!msm_pm_irq_extns->irq_pending())
 			udelay(1);
-		low_power = 0;
 #ifdef CONFIG_MSM_IDLE_STATS
 		exit_stat = MSM_PM_STAT_IDLE_SPIN;
 #endif
 	}
 
-	msm_timer_exit_idle(low_power);
-
 #ifdef CONFIG_MSM_IDLE_STATS
 	t2 = ktime_to_ns(ktime_get());
 	msm_pm_add_stat(exit_stat, t2 - t1);