msm: pm-8x60: Decrement L2 reset counter on failed power collapses

The L2 reset counter must be decremented to prevent TZ from invalidating
L2 when Power collapse fails because of a pending interrupt.

Signed-off-by: Maheshkumar Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 91cbcad..9a445a5 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -625,11 +625,11 @@
 	msm_arch_idle();
 }
 
-static void msm_pm_spm_power_collapse(
+static bool msm_pm_spm_power_collapse(
 	struct msm_pm_device *dev, bool from_idle, bool notify_rpm)
 {
 	void *entry;
-	int collapsed = 0;
+	bool collapsed = 0;
 	int ret;
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
@@ -670,24 +670,28 @@
 
 	ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
 	WARN_ON(ret);
+	return collapsed;
 }
 
-static void msm_pm_power_collapse_standalone(bool from_idle)
+static bool msm_pm_power_collapse_standalone(bool from_idle)
 {
 	struct msm_pm_device *dev = &__get_cpu_var(msm_pm_devices);
 	unsigned int avsdscr_setting;
+	bool collapsed;
 
 	avsdscr_setting = avs_get_avsdscr();
 	avs_disable();
-	msm_pm_spm_power_collapse(dev, from_idle, false);
+	collapsed = msm_pm_spm_power_collapse(dev, from_idle, false);
 	avs_reset_delays(avsdscr_setting);
+	return collapsed;
 }
 
-static void msm_pm_power_collapse(bool from_idle)
+static bool msm_pm_power_collapse(bool from_idle)
 {
 	struct msm_pm_device *dev = &__get_cpu_var(msm_pm_devices);
 	unsigned long saved_acpuclk_rate;
 	unsigned int avsdscr_setting;
+	bool collapsed;
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: idle %d\n",
@@ -709,7 +713,7 @@
 		pr_info("CPU%u: %s: change clock rate (old rate = %lu)\n",
 			dev->cpu, __func__, saved_acpuclk_rate);
 
-	msm_pm_spm_power_collapse(dev, from_idle, true);
+	collapsed = msm_pm_spm_power_collapse(dev, from_idle, true);
 
 	if (MSM_PM_DEBUG_CLOCK & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: restore clock rate to %lu\n",
@@ -725,6 +729,7 @@
 
 	if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
 		pr_info("CPU%u: %s: return\n", dev->cpu, __func__);
+	return collapsed;
 }
 
 static irqreturn_t msm_pm_rpm_wakeup_interrupt(int irq, void *dev_id)
@@ -884,6 +889,7 @@
 		int ret;
 		int notify_rpm =
 			(sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE);
+		int collapsed;
 
 		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
 			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
@@ -893,11 +899,11 @@
 		ret = msm_rpmrs_enter_sleep(
 			sleep_delay, msm_pm_idle_rs_limits, true, notify_rpm);
 		if (!ret) {
-			msm_pm_power_collapse(true);
+			collapsed = msm_pm_power_collapse(true);
 			timer_halted = true;
 
 			msm_rpmrs_exit_sleep(msm_pm_idle_rs_limits, true,
-					notify_rpm);
+					notify_rpm, collapsed);
 		}
 
 		msm_timer_exit_idle((int) timer_halted);
@@ -986,8 +992,9 @@
 			ret = msm_rpmrs_enter_sleep(
 				msm_pm_max_sleep_time, rs_limits, false, true);
 			if (!ret) {
-				msm_pm_power_collapse(false);
-				msm_rpmrs_exit_sleep(rs_limits, false, true);
+				int collapsed = msm_pm_power_collapse(false);
+				msm_rpmrs_exit_sleep(rs_limits, false, true,
+						collapsed);
 			}
 		} else {
 			pr_err("%s: cannot find the lowest power limit\n",
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 20239d6..b7508f7 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -530,11 +530,23 @@
 
 	return rc;
 }
+static void msm_rpmrs_L2_restore(struct msm_rpmrs_limits *limits,
+		bool notify_rpm, bool collapsed)
+{
+	msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
+	if (!collapsed && (limits->l2_cache == MSM_RPMRS_L2_CACHE_HSFS_OPEN))
+		writel_relaxed(--msm_rpmrs_l2_reset_count,
+				msm_rpmrs_l2_counter_addr);
+}
 #else
 static int msm_rpmrs_flush_L2(struct msm_rpmrs_limits *limits, int notify_rpm)
 {
 	return 0;
 }
+static void msm_rpmrs_L2_restore(struct msm_rpmrs_limits *limits,
+		bool notify_rpm, bool collapsed)
+{
+}
 #endif
 
 static int msm_rpmrs_flush_buffer(
@@ -868,12 +880,12 @@
 	return rc;
 }
 
-void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
-		bool from_idle, bool notify_rpm)
+void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
+		bool notify_rpm, bool collapsed)
 {
 
 	/* Disable L2 for now, we dont want L2 to do retention by default */
-	msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
+	msm_rpmrs_L2_restore(limits, notify_rpm, collapsed);
 
 	if (msm_rpmrs_use_mpm(limits))
 		msm_mpm_exit_sleep(from_idle);
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index db6249e..d90aa4c 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -102,8 +102,8 @@
 
 int msm_rpmrs_enter_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
 		bool from_idle, bool notify_rpm);
-void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
-		bool from_idle, bool notify_rpm);
+void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits, bool from_idle,
+		bool notify_rpm, bool collapsed);
 
 int msm_rpmrs_levels_init(struct msm_rpmrs_level *levels, int size);