aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/include/mach/omap-secure.h5
-rw-r--r--arch/arm/mach-omap2/omap-mpuss-lowpower.c41
-rw-r--r--arch/arm/mach-omap2/omap4-sar-layout.h4
-rw-r--r--arch/arm/mach-omap2/sleep44xx.S95
4 files changed, 144 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/include/mach/omap-secure.h b/arch/arm/mach-omap2/include/mach/omap-secure.h
index 5f0763dd5664..c90a43589abe 100644
--- a/arch/arm/mach-omap2/include/mach/omap-secure.h
+++ b/arch/arm/mach-omap2/include/mach/omap-secure.h
@@ -37,8 +37,13 @@
37 37
38/* Secure Monitor mode APIs */ 38/* Secure Monitor mode APIs */
39#define OMAP4_MON_SCU_PWR_INDEX 0x108 39#define OMAP4_MON_SCU_PWR_INDEX 0x108
40#define OMAP4_MON_L2X0_DBG_CTRL_INDEX 0x100
41#define OMAP4_MON_L2X0_CTRL_INDEX 0x102
42#define OMAP4_MON_L2X0_AUXCTRL_INDEX 0x109
43#define OMAP4_MON_L2X0_PREFETCH_INDEX 0x113
40 44
41/* Secure PPA(Primary Protected Application) APIs */ 45/* Secure PPA(Primary Protected Application) APIs */
46#define OMAP4_PPA_L2_POR_INDEX 0x23
42#define OMAP4_PPA_CPU_ACTRL_SMP_INDEX 0x25 47#define OMAP4_PPA_CPU_ACTRL_SMP_INDEX 0x25
43 48
44#ifndef __ASSEMBLER__ 49#ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index f9bb2b3d977b..907a048fe5e9 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -49,6 +49,7 @@
49#include <asm/system.h> 49#include <asm/system.h>
50#include <asm/pgalloc.h> 50#include <asm/pgalloc.h>
51#include <asm/suspend.h> 51#include <asm/suspend.h>
52#include <asm/hardware/cache-l2x0.h>
52 53
53#include <plat/omap44xx.h> 54#include <plat/omap44xx.h>
54 55
@@ -63,10 +64,12 @@ struct omap4_cpu_pm_info {
63 struct powerdomain *pwrdm; 64 struct powerdomain *pwrdm;
64 void __iomem *scu_sar_addr; 65 void __iomem *scu_sar_addr;
65 void __iomem *wkup_sar_addr; 66 void __iomem *wkup_sar_addr;
67 void __iomem *l2x0_sar_addr;
66}; 68};
67 69
68static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); 70static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info);
69static struct powerdomain *mpuss_pd; 71static struct powerdomain *mpuss_pd;
72static void __iomem *sar_base;
70 73
71/* 74/*
72 * Program the wakeup routine address for the CPU0 and CPU1 75 * Program the wakeup routine address for the CPU0 and CPU1
@@ -135,6 +138,36 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
135 __raw_writel(scu_pwr_st, pm_info->scu_sar_addr); 138 __raw_writel(scu_pwr_st, pm_info->scu_sar_addr);
136} 139}
137 140
141/*
142 * Store the CPU cluster state for L2X0 low power operations.
143 */
144static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state)
145{
146 struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
147
148 __raw_writel(save_state, pm_info->l2x0_sar_addr);
149}
150
151/*
152 * Save the L2X0 AUXCTRL and POR value to SAR memory. Its used to
153 * in every restore MPUSS OFF path.
154 */
155#ifdef CONFIG_CACHE_L2X0
156static void save_l2x0_context(void)
157{
158 u32 val;
159 void __iomem *l2x0_base = omap4_get_l2cache_base();
160
161 val = __raw_readl(l2x0_base + L2X0_AUX_CTRL);
162 __raw_writel(val, sar_base + L2X0_AUXCTRL_OFFSET);
163 val = __raw_readl(l2x0_base + L2X0_PREFETCH_CTRL);
164 __raw_writel(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET);
165}
166#else
167static void save_l2x0_context(void)
168{}
169#endif
170
138/** 171/**
139 * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function 172 * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
140 * The purpose of this function is to manage low power programming 173 * The purpose of this function is to manage low power programming
@@ -182,6 +215,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
182 set_cpu_next_pwrst(cpu, power_state); 215 set_cpu_next_pwrst(cpu, power_state);
183 set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume)); 216 set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
184 scu_pwrst_prepare(cpu, power_state); 217 scu_pwrst_prepare(cpu, power_state);
218 l2x0_pwrst_prepare(cpu, save_state);
185 219
186 /* 220 /*
187 * Call low level function with targeted low power state. 221 * Call low level function with targeted low power state.
@@ -239,17 +273,19 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
239int __init omap4_mpuss_init(void) 273int __init omap4_mpuss_init(void)
240{ 274{
241 struct omap4_cpu_pm_info *pm_info; 275 struct omap4_cpu_pm_info *pm_info;
242 void __iomem *sar_base = omap4_get_sar_ram_base();
243 276
244 if (omap_rev() == OMAP4430_REV_ES1_0) { 277 if (omap_rev() == OMAP4430_REV_ES1_0) {
245 WARN(1, "Power Management not supported on OMAP4430 ES1.0\n"); 278 WARN(1, "Power Management not supported on OMAP4430 ES1.0\n");
246 return -ENODEV; 279 return -ENODEV;
247 } 280 }
248 281
282 sar_base = omap4_get_sar_ram_base();
283
249 /* Initilaise per CPU PM information */ 284 /* Initilaise per CPU PM information */
250 pm_info = &per_cpu(omap4_pm_info, 0x0); 285 pm_info = &per_cpu(omap4_pm_info, 0x0);
251 pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; 286 pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
252 pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; 287 pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
288 pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
253 pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); 289 pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
254 if (!pm_info->pwrdm) { 290 if (!pm_info->pwrdm) {
255 pr_err("Lookup failed for CPU0 pwrdm\n"); 291 pr_err("Lookup failed for CPU0 pwrdm\n");
@@ -265,6 +301,7 @@ int __init omap4_mpuss_init(void)
265 pm_info = &per_cpu(omap4_pm_info, 0x1); 301 pm_info = &per_cpu(omap4_pm_info, 0x1);
266 pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; 302 pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
267 pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; 303 pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
304 pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
268 pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); 305 pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm");
269 if (!pm_info->pwrdm) { 306 if (!pm_info->pwrdm) {
270 pr_err("Lookup failed for CPU1 pwrdm\n"); 307 pr_err("Lookup failed for CPU1 pwrdm\n");
@@ -290,6 +327,8 @@ int __init omap4_mpuss_init(void)
290 else 327 else
291 __raw_writel(0, sar_base + OMAP_TYPE_OFFSET); 328 __raw_writel(0, sar_base + OMAP_TYPE_OFFSET);
292 329
330 save_l2x0_context();
331
293 return 0; 332 return 0;
294} 333}
295 334
diff --git a/arch/arm/mach-omap2/omap4-sar-layout.h b/arch/arm/mach-omap2/omap4-sar-layout.h
index aa14a8dd2505..fe5b545ad443 100644
--- a/arch/arm/mach-omap2/omap4-sar-layout.h
+++ b/arch/arm/mach-omap2/omap4-sar-layout.h
@@ -23,6 +23,10 @@
23#define SCU_OFFSET0 0xd00 23#define SCU_OFFSET0 0xd00
24#define SCU_OFFSET1 0xd04 24#define SCU_OFFSET1 0xd04
25#define OMAP_TYPE_OFFSET 0xd10 25#define OMAP_TYPE_OFFSET 0xd10
26#define L2X0_SAVE_OFFSET0 0xd14
27#define L2X0_SAVE_OFFSET1 0xd18
28#define L2X0_AUXCTRL_OFFSET 0xd1c
29#define L2X0_PREFETCH_CTRL_OFFSET 0xd20
26 30
27/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */ 31/* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
28#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04 32#define CPU0_WAKEUP_NS_PA_ADDR_OFFSET 0xa04
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index e5521945ba8e..3154b63def35 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -32,6 +32,9 @@
32ppa_zero_params: 32ppa_zero_params:
33 .word 0x0 33 .word 0x0
34 34
35ppa_por_params:
36 .word 1, 0
37
35/* 38/*
36 * ============================= 39 * =============================
37 * == CPU suspend finisher == 40 * == CPU suspend finisher ==
@@ -132,6 +135,54 @@ skip_scu_gp_set:
132 mcrne p15, 0, r0, c1, c0, 1 135 mcrne p15, 0, r0, c1, c0, 1
133 isb 136 isb
134 dsb 137 dsb
138#ifdef CONFIG_CACHE_L2X0
139 /*
140 * Clean and invalidate the L2 cache.
141 * Common cache-l2x0.c functions can't be used here since it
142 * uses spinlocks. We are out of coherency here with data cache
143 * disabled. The spinlock implementation uses exclusive load/store
144 * instruction which can fail without data cache being enabled.
145 * OMAP4 hardware doesn't support exclusive monitor which can
146 * overcome exclusive access issue. Because of this, CPU can
147 * lead to deadlock.
148 */
149 bl omap4_get_sar_ram_base
150 mov r8, r0
151 mrc p15, 0, r5, c0, c0, 5 @ Read MPIDR
152 ands r5, r5, #0x0f
153 ldreq r0, [r8, #L2X0_SAVE_OFFSET0] @ Retrieve L2 state from SAR
154 ldrne r0, [r8, #L2X0_SAVE_OFFSET1] @ memory.
155 cmp r0, #3
156 bne do_WFI
157#ifdef CONFIG_PL310_ERRATA_727915
158 mov r0, #0x03
159 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
160 DO_SMC
161#endif
162 bl omap4_get_l2cache_base
163 mov r2, r0
164 ldr r0, =0xffff
165 str r0, [r2, #L2X0_CLEAN_INV_WAY]
166wait:
167 ldr r0, [r2, #L2X0_CLEAN_INV_WAY]
168 ldr r1, =0xffff
169 ands r0, r0, r1
170 bne wait
171#ifdef CONFIG_PL310_ERRATA_727915
172 mov r0, #0x00
173 mov r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
174 DO_SMC
175#endif
176l2x_sync:
177 bl omap4_get_l2cache_base
178 mov r2, r0
179 mov r0, #0x0
180 str r0, [r2, #L2X0_CACHE_SYNC]
181sync:
182 ldr r0, [r2, #L2X0_CACHE_SYNC]
183 ands r0, r0, #0x1
184 bne sync
185#endif
135 186
136do_WFI: 187do_WFI:
137 bl omap_do_wfi 188 bl omap_do_wfi
@@ -225,6 +276,50 @@ enable_smp_bit:
225 mcreq p15, 0, r0, c1, c0, 1 276 mcreq p15, 0, r0, c1, c0, 1
226 isb 277 isb
227skip_ns_smp_enable: 278skip_ns_smp_enable:
279#ifdef CONFIG_CACHE_L2X0
280 /*
281 * Restore the L2 AUXCTRL and enable the L2 cache.
282 * OMAP4_MON_L2X0_AUXCTRL_INDEX = Program the L2X0 AUXCTRL
283 * OMAP4_MON_L2X0_CTRL_INDEX = Enable the L2 using L2X0 CTRL
284 * register r0 contains value to be programmed.
285 * L2 cache is already invalidate by ROM code as part
286 * of MPUSS OFF wakeup path.
287 */
288 ldr r2, =OMAP44XX_L2CACHE_BASE
289 ldr r0, [r2, #L2X0_CTRL]
290 and r0, #0x0f
291 cmp r0, #1
292 beq skip_l2en @ Skip if already enabled
293 ldr r3, =OMAP44XX_SAR_RAM_BASE
294 ldr r1, [r3, #OMAP_TYPE_OFFSET]
295 cmp r1, #0x1 @ Check for HS device
296 bne set_gp_por
297 ldr r0, =OMAP4_PPA_L2_POR_INDEX
298 ldr r1, =OMAP44XX_SAR_RAM_BASE
299 ldr r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
300 adr r3, ppa_por_params
301 str r4, [r3, #0x04]
302 mov r1, #0x0 @ Process ID
303 mov r2, #0x4 @ Flag
304 mov r6, #0xff
305 mov r12, #0x00 @ Secure Service ID
306 DO_SMC
307 b set_aux_ctrl
308set_gp_por:
309 ldr r1, =OMAP44XX_SAR_RAM_BASE
310 ldr r0, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
311 ldr r12, =OMAP4_MON_L2X0_PREFETCH_INDEX @ Setup L2 PREFETCH
312 DO_SMC
313set_aux_ctrl:
314 ldr r1, =OMAP44XX_SAR_RAM_BASE
315 ldr r0, [r1, #L2X0_AUXCTRL_OFFSET]
316 ldr r12, =OMAP4_MON_L2X0_AUXCTRL_INDEX @ Setup L2 AUXCTRL
317 DO_SMC
318 mov r0, #0x1
319 ldr r12, =OMAP4_MON_L2X0_CTRL_INDEX @ Enable L2 cache
320 DO_SMC
321skip_l2en:
322#endif
228 323
229 b cpu_resume @ Jump to generic resume 324 b cpu_resume @ Jump to generic resume
230ENDPROC(omap4_cpu_resume) 325ENDPROC(omap4_cpu_resume)