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;