msm: Allow conditional L2 flush during power collapse
On existing targets, L2 is flushed every time any of the core executes a
power collapse. This adds latency into the enter path for idle power
collapse. This commit provides a API that would vote for a L2 flush
during power collapse.
Remove invalidating the L1/L2 cache during warmboot. On
Krait/Scorpion processors, the boot loaders code takes care of
invalidating the L1/L2 cache. On A5 processor, L1 is invalidated at reset.
And the L2 cache is invalidated later in the boot process using the L2
cache controller.
Change-Id: Ib63cfefafcc3aa887faa902a9856fbc5eb137075
Signed-off-by: Maheshkumar Sivasubramanian <msivasub@codeaurora.org>
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 20dbd39..a6e8fdb 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -91,7 +91,23 @@
#ifdef CONFIG_MSM_TRACE_ACROSS_PC
bl etm_save_reg_check
#endif
- bl v7_flush_dcache_all
+
+ ldr r0, =msm_pm_flush_l2_flag
+ ldr r0, [r0]
+ mov r1, #0
+ mcr p15, 2, r1, c0, c0, 0 /*CCSELR*/
+ mrc p15, 1, r1, c0, c0, 0 /*CCSIDR*/
+ mov r2, #1
+ and r1, r2, r1, ASR #30 /* Check if the cache is write back */
+ orr r1, r0, r1
+ cmp r1, #1
+ bne skip
+ bl v7_flush_dcache_all
+
+skip: ldr r0, =saved_state
+ ldr r1, =saved_state_end
+ sub r1, r1, r0
+ bl v7_flush_kern_dcache_area
mrc p15, 0, r4, c1, c0, 0 /* read current CR */
bic r0, r4, #(1 << 2) /* clear dcache bit */
@@ -234,8 +250,18 @@
ldr r2, =msm_pm_boot_vector
add r2, r2, r0, LSL #2 /* locate boot vector for our cpu */
str r1, [r2]
+ mov r0, r2
+ ldr r1, =4
+ stmfd sp!, {lr}
+ bl v7_flush_kern_dcache_area
+ ldmfd sp!, {lr}
bx lr
+ENTRY(msm_pm_set_l2_flush_flag)
+ ldr r1, =msm_pm_flush_l2_flag
+ str r0, [r1]
+ bx lr
+
.data
.globl msm_pm_pc_pgd
@@ -252,3 +278,11 @@
msm_pm_boot_vector:
.space 4 * NR_CPUS
+
+/*
+ * Default the l2 flush flag to 1 so that caches are flushed during power
+ * collapse unless the L2 driver decides to flush them only during L2
+ * Power collapse.
+ */
+msm_pm_flush_l2_flag:
+ .long 0x1
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index 138db45..753a47c 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -22,7 +22,14 @@
#ifdef CONFIG_CPU_V7
void msm_pm_boot_entry(void);
void msm_pm_write_boot_vector(unsigned int cpu, unsigned long address);
+void msm_pm_set_l2_flush_flag(unsigned int flag);
extern unsigned long msm_pm_pc_pgd;
+#else
+static inline void msm_pm_set_l2_flush_flag(unsigned int flag)
+{
+ /* empty */
+}
#endif
+
#endif
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index e6b91ee..0cc2272 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -28,6 +28,7 @@
#include "mpm.h"
#include "rpm_resources.h"
#include "spm.h"
+#include "idle.h"
/******************************************************************************
* Debug Definitions
@@ -513,6 +514,7 @@
BUG_ON(!msm_rpmrs_l2_counter_addr);
writel_relaxed(++msm_rpmrs_l2_reset_count,
msm_rpmrs_l2_counter_addr);
+ msm_pm_set_l2_flush_flag(1);
break;
case MSM_RPMRS_L2_CACHE_GDHS:
lpm = MSM_SPM_L2_MODE_GDHS;
@@ -537,6 +539,7 @@
bool notify_rpm, bool collapsed)
{
msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
+ msm_pm_set_l2_flush_flag(0);
if (!collapsed && (limits->l2_cache == MSM_RPMRS_L2_CACHE_HSFS_OPEN))
writel_relaxed(--msm_rpmrs_l2_reset_count,
msm_rpmrs_l2_counter_addr);
@@ -769,6 +772,7 @@
goto resource_sysfs_add_exit;
}
+ rc = 0;
resource_sysfs_add_exit:
if (rc) {
if (low_power_kobj)
@@ -1063,6 +1067,8 @@
msm_rpmrs_l2_counter_addr);
mb();
+ msm_pm_set_l2_flush_flag(0);
+
msm_rpmrs_l2_cache.beyond_limits =
msm_spm_l2_cache_beyond_limits;
msm_rpmrs_l2_cache.aggregate = NULL;