msm: idle-v7: SMP and AMP mode programming for 8x25 target
Program the Auxiliary Control Regiater(ACTLR.SMP) to switch
from Symmetric MultiProcessing Mode(SMP) to Asymmetric Multi
Processing Mode(AMP) while entering into the GDFS power mode.
This enables the CPU to be taken out of coherency by preventing
the CPU from receiving cache and TLB maintenance operations
broadcast by other CPUs in the system.
Change-Id: I74285e445e86cdb78a85705347550c762e47a0e2
Signed-off-by: Murali Nalajala <mnalajal@codeaurora.org>
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 515727c..0028286 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -26,6 +26,24 @@
#define SCM_CMD_TERMINATE_PC 0x2
#endif
+/* Switch between smp_to_amp/amp_to_smp configuration */
+.macro SET_SMP_COHERENCY, on = 0
+ldr r0, =target_type
+ldr r0, [r0]
+mov r1, #TARGET_IS_8625
+cmp r0, r1
+bne skip\@
+mrc p15, 0, r0, c1, c0, 1 /* read ACTLR register */
+.if \on
+orr r0, r0, #(1 << 6) /* Set the SMP bit in ACTLR */
+.else
+bic r0, r0, #(1 << 6) /* Clear the SMP bit */
+.endif
+mcr p15, 0, r0, c1, c0, 1 /* write ACTLR register */
+isb
+skip\@:
+.endm
+
ENTRY(msm_arch_idle)
wfi
#ifdef CONFIG_ARCH_MSM8X60
@@ -110,13 +128,13 @@
mcr p15, 0, r0, c1, c0, 0 /* disable d/i cache */
dsb
+ SET_SMP_COHERENCY OFF
wfi
mcr p15, 0, r4, c1, c0, 0 /* restore d/i cache */
isb
#endif
-
-
+ SET_SMP_COHERENCY ON
#if defined(CONFIG_MSM_FIQ_SUPPORT)
cpsie f
#endif
@@ -132,7 +150,6 @@
mul r2, r2, r1
add r0, r0, r2
#endif
-
ldmfd r0, {r4-r14} /* restore registers */
mov r0, #0 /* return power collapse failed */
bx lr
@@ -209,6 +226,8 @@
mcr p15, 0, r3, c7, c5, 6 /* BPIALL */
dsb
isb
+
+ SET_SMP_COHERENCY ON
#ifdef CONFIG_ARCH_MSM_KRAIT
mrc p15, 0, r1, c0, c0, 0
ldr r3, =0xff00fc00
@@ -269,6 +288,10 @@
msm_pm_boot_vector:
.space 4 * NR_CPUS
+ .globl target_type
+target_type:
+ .long 0x0
+
/*
* 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
diff --git a/arch/arm/mach-msm/idle.h b/arch/arm/mach-msm/idle.h
index df3045a..bfd632f 100644
--- a/arch/arm/mach-msm/idle.h
+++ b/arch/arm/mach-msm/idle.h
@@ -22,6 +22,10 @@
#define CPU_SAVED_STATE_SIZE (4 * 11 + 4 * 10)
#endif
+#define ON 1
+#define OFF 0
+#define TARGET_IS_8625 1
+
#ifndef __ASSEMBLY__
int msm_arch_idle(void);
@@ -35,6 +39,7 @@
void msm_pm_set_l2_flush_flag(unsigned int flag);
extern unsigned long msm_pm_pc_pgd;
extern unsigned long msm_pm_boot_vector[NR_CPUS];
+extern uint32_t target_type;
#else
static inline void msm_pm_set_l2_flush_flag(unsigned int flag)
{
diff --git a/arch/arm/mach-msm/pm2.c b/arch/arm/mach-msm/pm2.c
index d87d70f..a5e52be 100644
--- a/arch/arm/mach-msm/pm2.c
+++ b/arch/arm/mach-msm/pm2.c
@@ -1862,6 +1862,7 @@
unsigned int cpu;
#endif
int ret;
+ int val;
#ifdef CONFIG_CPU_V7
pgd_t *pc_pgd;
pmd_t *pmd;
@@ -1925,6 +1926,19 @@
return ret;
}
+ if (cpu_is_msm8625()) {
+ target_type = TARGET_IS_8625;
+ clean_caches((unsigned long)&target_type, sizeof(target_type),
+ virt_to_phys(&target_type));
+
+ /* Override the DBGNOPOWERDN for each cpu in
+ * MPA5_GDFS_CNT_VAL register
+ */
+ val = __raw_readl((MSM_CFG_CTL_BASE + 0x38));
+ val = val | 0x00030000;
+ __raw_writel(val, (MSM_CFG_CTL_BASE + 0x38));
+ }
+
#ifdef CONFIG_MSM_MEMORY_LOW_POWER_MODE
/* The wakeup_reason field is overloaded during initialization time
to signal Modem that Apps will control the low power modes of