diff options
author | Tero Kristo <tero.kristo@nokia.com> | 2008-10-13 06:15:00 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2009-11-11 17:42:25 -0500 |
commit | 27d59a4a2def42307349079f2e3538d96934c379 (patch) | |
tree | d581f0960d280dbe0f8c8ee03e111cadbfcf59db | |
parent | f2d1185824fd3ed631f3164daeff59d0b4e55d79 (diff) |
OMAP3 PM: off-mode support for HS/EMU devices
For HS/EMU devices, some additional resources need to be
saved/restored for off-mode support. Namely, saving the secure RAM
and a pointer to it in the scratchpad.
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
-rw-r--r-- | arch/arm/mach-omap2/control.c | 8 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm34xx.c | 43 | ||||
-rw-r--r-- | arch/arm/mach-omap2/sleep34xx.S | 75 |
4 files changed, 126 insertions, 3 deletions
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c index 3ea417d7a1b5..b84cff7087b0 100644 --- a/arch/arm/mach-omap2/control.c +++ b/arch/arm/mach-omap2/control.c | |||
@@ -85,6 +85,8 @@ struct omap3_scratchpad_sdrc_block { | |||
85 | u32 block_size; | 85 | u32 block_size; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | void *omap3_secure_ram_storage; | ||
89 | |||
88 | /* | 90 | /* |
89 | * This is used to store ARM registers in SDRAM before attempting | 91 | * This is used to store ARM registers in SDRAM before attempting |
90 | * an MPU OFF. The save and restore happens from the SRAM sleep code. | 92 | * an MPU OFF. The save and restore happens from the SRAM sleep code. |
@@ -209,7 +211,11 @@ void omap3_save_scratchpad_contents(void) | |||
209 | scratchpad_contents.boot_config_ptr = 0x0; | 211 | scratchpad_contents.boot_config_ptr = 0x0; |
210 | scratchpad_contents.public_restore_ptr = | 212 | scratchpad_contents.public_restore_ptr = |
211 | virt_to_phys(get_restore_pointer()); | 213 | virt_to_phys(get_restore_pointer()); |
212 | scratchpad_contents.secure_ram_restore_ptr = 0x0; | 214 | if (omap_type() == OMAP2_DEVICE_TYPE_GP) |
215 | scratchpad_contents.secure_ram_restore_ptr = 0x0; | ||
216 | else | ||
217 | scratchpad_contents.secure_ram_restore_ptr = | ||
218 | (u32) __pa(omap3_secure_ram_storage); | ||
213 | scratchpad_contents.sdrc_module_semaphore = 0x0; | 219 | scratchpad_contents.sdrc_module_semaphore = 0x0; |
214 | scratchpad_contents.prcm_block_offset = 0x2C; | 220 | scratchpad_contents.prcm_block_offset = 0x2C; |
215 | scratchpad_contents.sdrc_block_offset = 0x64; | 221 | scratchpad_contents.sdrc_block_offset = 0x64; |
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index 85b6face5392..45cafac716d1 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include <plat/powerdomain.h> | 14 | #include <plat/powerdomain.h> |
15 | 15 | ||
16 | extern void *omap3_secure_ram_storage; | ||
17 | |||
16 | extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm); | 18 | extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm); |
17 | extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); | 19 | extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state); |
18 | 20 | ||
@@ -36,6 +38,7 @@ extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, | |||
36 | void __iomem *sdrc_power); | 38 | void __iomem *sdrc_power); |
37 | extern void omap34xx_cpu_suspend(u32 *addr, int save_state); | 39 | extern void omap34xx_cpu_suspend(u32 *addr, int save_state); |
38 | extern void save_secure_ram_context(u32 *addr); | 40 | extern void save_secure_ram_context(u32 *addr); |
41 | extern void omap3_save_scratchpad_contents(void); | ||
39 | 42 | ||
40 | extern unsigned int omap24xx_idle_loop_suspend_sz; | 43 | extern unsigned int omap24xx_idle_loop_suspend_sz; |
41 | extern unsigned int omap34xx_suspend_sz; | 44 | extern unsigned int omap34xx_suspend_sz; |
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 54fea79b1720..ebb88f3aae31 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c | |||
@@ -63,6 +63,8 @@ static LIST_HEAD(pwrst_list); | |||
63 | 63 | ||
64 | static void (*_omap_sram_idle)(u32 *addr, int save_state); | 64 | static void (*_omap_sram_idle)(u32 *addr, int save_state); |
65 | 65 | ||
66 | static int (*_omap_save_secure_sram)(u32 *addr); | ||
67 | |||
66 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; | 68 | static struct powerdomain *mpu_pwrdm, *neon_pwrdm; |
67 | static struct powerdomain *core_pwrdm, *per_pwrdm; | 69 | static struct powerdomain *core_pwrdm, *per_pwrdm; |
68 | 70 | ||
@@ -110,6 +112,33 @@ static void omap3_core_restore_context(void) | |||
110 | omap_dma_global_context_restore(); | 112 | omap_dma_global_context_restore(); |
111 | } | 113 | } |
112 | 114 | ||
115 | static void omap3_save_secure_ram_context(u32 target_mpu_state) | ||
116 | { | ||
117 | u32 ret; | ||
118 | |||
119 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) { | ||
120 | /* Disable dma irq before calling secure rom code API */ | ||
121 | omap_dma_disable_irq(0); | ||
122 | omap_dma_disable_irq(1); | ||
123 | /* | ||
124 | * MPU next state must be set to POWER_ON temporarily, | ||
125 | * otherwise the WFI executed inside the ROM code | ||
126 | * will hang the system. | ||
127 | */ | ||
128 | pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON); | ||
129 | ret = _omap_save_secure_sram((u32 *) | ||
130 | __pa(omap3_secure_ram_storage)); | ||
131 | pwrdm_set_next_pwrst(mpu_pwrdm, target_mpu_state); | ||
132 | /* Following is for error tracking, it should not happen */ | ||
133 | if (ret) { | ||
134 | printk(KERN_ERR "save_secure_sram() returns %08x\n", | ||
135 | ret); | ||
136 | while (1) | ||
137 | ; | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | |||
113 | /* | 142 | /* |
114 | * PRCM Interrupt Handler Helper Function | 143 | * PRCM Interrupt Handler Helper Function |
115 | * | 144 | * |
@@ -308,6 +337,7 @@ static void omap_sram_idle(void) | |||
308 | if (core_next_state == PWRDM_POWER_OFF) { | 337 | if (core_next_state == PWRDM_POWER_OFF) { |
309 | omap3_core_save_context(); | 338 | omap3_core_save_context(); |
310 | omap3_prcm_save_context(); | 339 | omap3_prcm_save_context(); |
340 | omap3_save_secure_ram_context(mpu_next_state); | ||
311 | } | 341 | } |
312 | /* Enable IO-PAD wakeup */ | 342 | /* Enable IO-PAD wakeup */ |
313 | prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN); | 343 | prm_set_mod_reg_bits(OMAP3430_EN_IO, WKUP_MOD, PM_WKEN); |
@@ -901,6 +931,9 @@ void omap_push_sram_idle(void) | |||
901 | { | 931 | { |
902 | _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, | 932 | _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, |
903 | omap34xx_cpu_suspend_sz); | 933 | omap34xx_cpu_suspend_sz); |
934 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) | ||
935 | _omap_save_secure_sram = omap_sram_push(save_secure_ram_context, | ||
936 | save_secure_ram_context_sz); | ||
904 | } | 937 | } |
905 | 938 | ||
906 | static int __init omap3_pm_init(void) | 939 | static int __init omap3_pm_init(void) |
@@ -916,7 +949,6 @@ static int __init omap3_pm_init(void) | |||
916 | /* XXX prcm_setup_regs needs to be before enabling hw | 949 | /* XXX prcm_setup_regs needs to be before enabling hw |
917 | * supervised mode for powerdomains */ | 950 | * supervised mode for powerdomains */ |
918 | prcm_setup_regs(); | 951 | prcm_setup_regs(); |
919 | omap3_save_scratchpad_contents(); | ||
920 | 952 | ||
921 | ret = request_irq(INT_34XX_PRCM_MPU_IRQ, | 953 | ret = request_irq(INT_34XX_PRCM_MPU_IRQ, |
922 | (irq_handler_t)prcm_interrupt_handler, | 954 | (irq_handler_t)prcm_interrupt_handler, |
@@ -961,6 +993,15 @@ static int __init omap3_pm_init(void) | |||
961 | */ | 993 | */ |
962 | pwrdm_add_wkdep(per_pwrdm, core_pwrdm); | 994 | pwrdm_add_wkdep(per_pwrdm, core_pwrdm); |
963 | 995 | ||
996 | if (omap_type() != OMAP2_DEVICE_TYPE_GP) { | ||
997 | omap3_secure_ram_storage = | ||
998 | kmalloc(0x803F, GFP_KERNEL); | ||
999 | if (!omap3_secure_ram_storage) | ||
1000 | printk(KERN_ERR "Memory allocation failed when" | ||
1001 | "allocating for secure sram context\n"); | ||
1002 | } | ||
1003 | omap3_save_scratchpad_contents(); | ||
1004 | |||
964 | err1: | 1005 | err1: |
965 | return ret; | 1006 | return ret; |
966 | err2: | 1007 | err2: |
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S index f8d3834bf681..db75167bc52d 100644 --- a/arch/arm/mach-omap2/sleep34xx.S +++ b/arch/arm/mach-omap2/sleep34xx.S | |||
@@ -37,6 +37,8 @@ | |||
37 | #define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \ | 37 | #define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \ |
38 | OMAP3430_PM_PREPWSTST) | 38 | OMAP3430_PM_PREPWSTST) |
39 | #define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL | 39 | #define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL |
40 | #define SRAM_BASE_P 0x40200000 | ||
41 | #define CONTROL_STAT 0x480022F0 | ||
40 | #define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is | 42 | #define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is |
41 | * available */ | 43 | * available */ |
42 | #define SCRATCHPAD_BASE_P (OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\ | 44 | #define SCRATCHPAD_BASE_P (OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\ |
@@ -51,6 +53,40 @@ ENTRY(get_restore_pointer) | |||
51 | ldmfd sp!, {pc} @ restore regs and return | 53 | ldmfd sp!, {pc} @ restore regs and return |
52 | ENTRY(get_restore_pointer_sz) | 54 | ENTRY(get_restore_pointer_sz) |
53 | .word . - get_restore_pointer_sz | 55 | .word . - get_restore_pointer_sz |
56 | |||
57 | /* Function to call rom code to save secure ram context */ | ||
58 | ENTRY(save_secure_ram_context) | ||
59 | stmfd sp!, {r1-r12, lr} @ save registers on stack | ||
60 | save_secure_ram_debug: | ||
61 | /* b save_secure_ram_debug */ @ enable to debug save code | ||
62 | adr r3, api_params @ r3 points to parameters | ||
63 | str r0, [r3,#0x4] @ r0 has sdram address | ||
64 | ldr r12, high_mask | ||
65 | and r3, r3, r12 | ||
66 | ldr r12, sram_phy_addr_mask | ||
67 | orr r3, r3, r12 | ||
68 | mov r0, #25 @ set service ID for PPA | ||
69 | mov r12, r0 @ copy secure service ID in r12 | ||
70 | mov r1, #0 @ set task id for ROM code in r1 | ||
71 | mov r2, #7 @ set some flags in r2, r6 | ||
72 | mov r6, #0xff | ||
73 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
74 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier | ||
75 | .word 0xE1600071 @ call SMI monitor (smi #1) | ||
76 | nop | ||
77 | nop | ||
78 | nop | ||
79 | nop | ||
80 | ldmfd sp!, {r1-r12, pc} | ||
81 | sram_phy_addr_mask: | ||
82 | .word SRAM_BASE_P | ||
83 | high_mask: | ||
84 | .word 0xffff | ||
85 | api_params: | ||
86 | .word 0x4, 0x0, 0x0, 0x1, 0x1 | ||
87 | ENTRY(save_secure_ram_context_sz) | ||
88 | .word . - save_secure_ram_context | ||
89 | |||
54 | /* | 90 | /* |
55 | * Forces OMAP into idle state | 91 | * Forces OMAP into idle state |
56 | * | 92 | * |
@@ -107,9 +143,44 @@ restore: | |||
107 | moveq r9, #0x3 @ MPU OFF => L1 and L2 lost | 143 | moveq r9, #0x3 @ MPU OFF => L1 and L2 lost |
108 | movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation | 144 | movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation |
109 | bne logic_l1_restore | 145 | bne logic_l1_restore |
146 | ldr r0, control_stat | ||
147 | ldr r1, [r0] | ||
148 | and r1, #0x700 | ||
149 | cmp r1, #0x300 | ||
150 | beq l2_inv_gp | ||
151 | mov r0, #40 @ set service ID for PPA | ||
152 | mov r12, r0 @ copy secure Service ID in r12 | ||
153 | mov r1, #0 @ set task id for ROM code in r1 | ||
154 | mov r2, #4 @ set some flags in r2, r6 | ||
155 | mov r6, #0xff | ||
156 | adr r3, l2_inv_api_params @ r3 points to dummy parameters | ||
157 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
158 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier | ||
159 | .word 0xE1600071 @ call SMI monitor (smi #1) | ||
160 | /* Write to Aux control register to set some bits */ | ||
161 | mov r0, #42 @ set service ID for PPA | ||
162 | mov r12, r0 @ copy secure Service ID in r12 | ||
163 | mov r1, #0 @ set task id for ROM code in r1 | ||
164 | mov r2, #4 @ set some flags in r2, r6 | ||
165 | mov r6, #0xff | ||
166 | adr r3, write_aux_control_params @ r3 points to parameters | ||
167 | mcr p15, 0, r0, c7, c10, 4 @ data write barrier | ||
168 | mcr p15, 0, r0, c7, c10, 5 @ data memory barrier | ||
169 | .word 0xE1600071 @ call SMI monitor (smi #1) | ||
170 | |||
171 | b logic_l1_restore | ||
172 | l2_inv_api_params: | ||
173 | .word 0x1, 0x00 | ||
174 | write_aux_control_params: | ||
175 | .word 0x1, 0x72 | ||
176 | l2_inv_gp: | ||
110 | /* Execute smi to invalidate L2 cache */ | 177 | /* Execute smi to invalidate L2 cache */ |
111 | mov r12, #0x1 @ set up to invalide L2 | 178 | mov r12, #0x1 @ set up to invalide L2 |
112 | smi: .word 0xE1600070 @ Call SMI monitor (smieq) | 179 | smi: .word 0xE1600070 @ Call SMI monitor (smieq) |
180 | /* Write to Aux control register to set some bits */ | ||
181 | mov r0, #0x72 | ||
182 | mov r12, #0x3 | ||
183 | .word 0xE1600070 @ Call SMI monitor (smieq) | ||
113 | logic_l1_restore: | 184 | logic_l1_restore: |
114 | mov r1, #0 | 185 | mov r1, #0 |
115 | /* Invalidate all instruction caches to PoU | 186 | /* Invalidate all instruction caches to PoU |
@@ -429,5 +500,7 @@ table_entry: | |||
429 | .word 0x00000C02 | 500 | .word 0x00000C02 |
430 | cache_pred_disable_mask: | 501 | cache_pred_disable_mask: |
431 | .word 0xFFFFE7FB | 502 | .word 0xFFFFE7FB |
503 | control_stat: | ||
504 | .word CONTROL_STAT | ||
432 | ENTRY(omap34xx_cpu_suspend_sz) | 505 | ENTRY(omap34xx_cpu_suspend_sz) |
433 | .word . - omap34xx_cpu_suspend | 506 | .word . - omap34xx_cpu_suspend |