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);