blob: db75167bc52d92e582acb261dfc64b23a8dae790 [file] [log] [blame]
Kevin Hilman8bd22942009-05-28 10:56:16 -07001/*
2 * linux/arch/arm/mach-omap2/sleep.S
3 *
4 * (C) Copyright 2007
5 * Texas Instruments
6 * Karthik Dasu <karthik-dp@ti.com>
7 *
8 * (C) Copyright 2004
9 * Texas Instruments, <www.ti.com>
10 * Richard Woodruff <r-woodruff2@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27#include <linux/linkage.h>
28#include <asm/assembler.h>
29#include <mach/io.h>
Tony Lindgrence491cf2009-10-20 09:40:47 -070030#include <plat/control.h>
Kevin Hilman8bd22942009-05-28 10:56:16 -070031
32#include "prm.h"
33#include "sdrc.h"
34
35#define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \
36 OMAP3430_PM_PREPWSTST)
37#define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \
38 OMAP3430_PM_PREPWSTST)
Rajendra Nayak61255ab2008-09-26 17:49:56 +053039#define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL
Tero Kristo27d59a42008-10-13 13:15:00 +030040#define SRAM_BASE_P 0x40200000
41#define CONTROL_STAT 0x480022F0
Kevin Hilman8bd22942009-05-28 10:56:16 -070042#define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is
43 * available */
Rajendra Nayak61255ab2008-09-26 17:49:56 +053044#define SCRATCHPAD_BASE_P (OMAP343X_CTRL_BASE + OMAP343X_CONTROL_MEM_WKUP\
45 + SCRATCHPAD_MEM_OFFS)
Kevin Hilman8bd22942009-05-28 10:56:16 -070046#define SDRC_POWER_V OMAP34XX_SDRC_REGADDR(SDRC_POWER)
47
48 .text
49/* Function call to get the restore pointer for resume from OFF */
50ENTRY(get_restore_pointer)
51 stmfd sp!, {lr} @ save registers on stack
52 adr r0, restore
53 ldmfd sp!, {pc} @ restore regs and return
54ENTRY(get_restore_pointer_sz)
55 .word . - get_restore_pointer_sz
Tero Kristo27d59a42008-10-13 13:15:00 +030056
57/* Function to call rom code to save secure ram context */
58ENTRY(save_secure_ram_context)
59 stmfd sp!, {r1-r12, lr} @ save registers on stack
60save_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}
81sram_phy_addr_mask:
82 .word SRAM_BASE_P
83high_mask:
84 .word 0xffff
85api_params:
86 .word 0x4, 0x0, 0x0, 0x1, 0x1
87ENTRY(save_secure_ram_context_sz)
88 .word . - save_secure_ram_context
89
Kevin Hilman8bd22942009-05-28 10:56:16 -070090/*
91 * Forces OMAP into idle state
92 *
93 * omap34xx_suspend() - This bit of code just executes the WFI
94 * for normal idles.
95 *
96 * Note: This code get's copied to internal SRAM at boot. When the OMAP
97 * wakes up it continues execution at the point it went to sleep.
98 */
99ENTRY(omap34xx_cpu_suspend)
100 stmfd sp!, {r0-r12, lr} @ save registers on stack
101loop:
102 /*b loop*/ @Enable to debug by stepping through code
103 /* r0 contains restore pointer in sdram */
104 /* r1 contains information about saving context */
105 ldr r4, sdrc_power @ read the SDRC_POWER register
106 ldr r5, [r4] @ read the contents of SDRC_POWER
107 orr r5, r5, #0x40 @ enable self refresh on idle req
108 str r5, [r4] @ write back to SDRC_POWER register
109
110 cmp r1, #0x0
111 /* If context save is required, do that and execute wfi */
112 bne save_context_wfi
113 /* Data memory barrier and Data sync barrier */
114 mov r1, #0
115 mcr p15, 0, r1, c7, c10, 4
116 mcr p15, 0, r1, c7, c10, 5
117
118 wfi @ wait for interrupt
119
120 nop
121 nop
122 nop
123 nop
124 nop
125 nop
126 nop
127 nop
128 nop
129 nop
130 bl i_dll_wait
131
132 ldmfd sp!, {r0-r12, pc} @ restore regs and return
133restore:
Rajendra Nayak61255ab2008-09-26 17:49:56 +0530134 /* b restore*/ @ Enable to debug restore code
Kevin Hilman8bd22942009-05-28 10:56:16 -0700135 /* Check what was the reason for mpu reset and store the reason in r9*/
136 /* 1 - Only L1 and logic lost */
137 /* 2 - Only L2 lost - In this case, we wont be here */
138 /* 3 - Both L1 and L2 lost */
139 ldr r1, pm_pwstctrl_mpu
140 ldr r2, [r1]
141 and r2, r2, #0x3
142 cmp r2, #0x0 @ Check if target power state was OFF or RET
143 moveq r9, #0x3 @ MPU OFF => L1 and L2 lost
144 movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation
145 bne logic_l1_restore
Tero Kristo27d59a42008-10-13 13:15:00 +0300146 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
172l2_inv_api_params:
173 .word 0x1, 0x00
174write_aux_control_params:
175 .word 0x1, 0x72
176l2_inv_gp:
Kevin Hilman8bd22942009-05-28 10:56:16 -0700177 /* Execute smi to invalidate L2 cache */
178 mov r12, #0x1 @ set up to invalide L2
Tero Kristo27d59a42008-10-13 13:15:00 +0300179smi: .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)
Kevin Hilman8bd22942009-05-28 10:56:16 -0700184logic_l1_restore:
185 mov r1, #0
186 /* Invalidate all instruction caches to PoU
187 * and flush branch target cache */
188 mcr p15, 0, r1, c7, c5, 0
189
190 ldr r4, scratchpad_base
191 ldr r3, [r4,#0xBC]
192 ldmia r3!, {r4-r6}
193 mov sp, r4
194 msr spsr_cxsf, r5
195 mov lr, r6
196
197 ldmia r3!, {r4-r9}
198 /* Coprocessor access Control Register */
199 mcr p15, 0, r4, c1, c0, 2
200
201 /* TTBR0 */
202 MCR p15, 0, r5, c2, c0, 0
203 /* TTBR1 */
204 MCR p15, 0, r6, c2, c0, 1
205 /* Translation table base control register */
206 MCR p15, 0, r7, c2, c0, 2
207 /*domain access Control Register */
208 MCR p15, 0, r8, c3, c0, 0
209 /* data fault status Register */
210 MCR p15, 0, r9, c5, c0, 0
211
212 ldmia r3!,{r4-r8}
213 /* instruction fault status Register */
214 MCR p15, 0, r4, c5, c0, 1
215 /*Data Auxiliary Fault Status Register */
216 MCR p15, 0, r5, c5, c1, 0
217 /*Instruction Auxiliary Fault Status Register*/
218 MCR p15, 0, r6, c5, c1, 1
219 /*Data Fault Address Register */
220 MCR p15, 0, r7, c6, c0, 0
221 /*Instruction Fault Address Register*/
222 MCR p15, 0, r8, c6, c0, 2
223 ldmia r3!,{r4-r7}
224
225 /* user r/w thread and process ID */
226 MCR p15, 0, r4, c13, c0, 2
227 /* user ro thread and process ID */
228 MCR p15, 0, r5, c13, c0, 3
229 /*Privileged only thread and process ID */
230 MCR p15, 0, r6, c13, c0, 4
231 /* cache size selection */
232 MCR p15, 2, r7, c0, c0, 0
233 ldmia r3!,{r4-r8}
234 /* Data TLB lockdown registers */
235 MCR p15, 0, r4, c10, c0, 0
236 /* Instruction TLB lockdown registers */
237 MCR p15, 0, r5, c10, c0, 1
238 /* Secure or Nonsecure Vector Base Address */
239 MCR p15, 0, r6, c12, c0, 0
240 /* FCSE PID */
241 MCR p15, 0, r7, c13, c0, 0
242 /* Context PID */
243 MCR p15, 0, r8, c13, c0, 1
244
245 ldmia r3!,{r4-r5}
246 /* primary memory remap register */
247 MCR p15, 0, r4, c10, c2, 0
248 /*normal memory remap register */
249 MCR p15, 0, r5, c10, c2, 1
250
251 /* Restore cpsr */
252 ldmia r3!,{r4} /*load CPSR from SDRAM*/
253 msr cpsr, r4 /*store cpsr */
254
255 /* Enabling MMU here */
256 mrc p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
257 /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
258 and r7, #0x7
259 cmp r7, #0x0
260 beq usettbr0
261ttbr_error:
262 /* More work needs to be done to support N[0:2] value other than 0
263 * So looping here so that the error can be detected
264 */
265 b ttbr_error
266usettbr0:
267 mrc p15, 0, r2, c2, c0, 0
268 ldr r5, ttbrbit_mask
269 and r2, r5
270 mov r4, pc
271 ldr r5, table_index_mask
272 and r4, r5 /* r4 = 31 to 20 bits of pc */
273 /* Extract the value to be written to table entry */
274 ldr r1, table_entry
275 add r1, r1, r4 /* r1 has value to be written to table entry*/
276 /* Getting the address of table entry to modify */
277 lsr r4, #18
278 add r2, r4 /* r2 has the location which needs to be modified */
279 /* Storing previous entry of location being modified */
280 ldr r5, scratchpad_base
281 ldr r4, [r2]
282 str r4, [r5, #0xC0]
283 /* Modify the table entry */
284 str r1, [r2]
285 /* Storing address of entry being modified
286 * - will be restored after enabling MMU */
287 ldr r5, scratchpad_base
288 str r2, [r5, #0xC4]
289
290 mov r0, #0
291 mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
292 mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array
293 mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB
294 mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB
295 /* Restore control register but dont enable caches here*/
296 /* Caches will be enabled after restoring MMU table entry */
297 ldmia r3!, {r4}
298 /* Store previous value of control register in scratchpad */
299 str r4, [r5, #0xC8]
300 ldr r2, cache_pred_disable_mask
301 and r4, r2
302 mcr p15, 0, r4, c1, c0, 0
303
304 ldmfd sp!, {r0-r12, pc} @ restore regs and return
305save_context_wfi:
306 /*b save_context_wfi*/ @ enable to debug save code
307 mov r8, r0 /* Store SDRAM address in r8 */
308 /* Check what that target sleep state is:stored in r1*/
309 /* 1 - Only L1 and logic lost */
310 /* 2 - Only L2 lost */
311 /* 3 - Both L1 and L2 lost */
312 cmp r1, #0x2 /* Only L2 lost */
313 beq clean_l2
314 cmp r1, #0x1 /* L2 retained */
315 /* r9 stores whether to clean L2 or not*/
316 moveq r9, #0x0 /* Dont Clean L2 */
317 movne r9, #0x1 /* Clean L2 */
318l1_logic_lost:
319 /* Store sp and spsr to SDRAM */
320 mov r4, sp
321 mrs r5, spsr
322 mov r6, lr
323 stmia r8!, {r4-r6}
324 /* Save all ARM registers */
325 /* Coprocessor access control register */
326 mrc p15, 0, r6, c1, c0, 2
327 stmia r8!, {r6}
328 /* TTBR0, TTBR1 and Translation table base control */
329 mrc p15, 0, r4, c2, c0, 0
330 mrc p15, 0, r5, c2, c0, 1
331 mrc p15, 0, r6, c2, c0, 2
332 stmia r8!, {r4-r6}
333 /* Domain access control register, data fault status register,
334 and instruction fault status register */
335 mrc p15, 0, r4, c3, c0, 0
336 mrc p15, 0, r5, c5, c0, 0
337 mrc p15, 0, r6, c5, c0, 1
338 stmia r8!, {r4-r6}
339 /* Data aux fault status register, instruction aux fault status,
340 datat fault address register and instruction fault address register*/
341 mrc p15, 0, r4, c5, c1, 0
342 mrc p15, 0, r5, c5, c1, 1
343 mrc p15, 0, r6, c6, c0, 0
344 mrc p15, 0, r7, c6, c0, 2
345 stmia r8!, {r4-r7}
346 /* user r/w thread and process ID, user r/o thread and process ID,
347 priv only thread and process ID, cache size selection */
348 mrc p15, 0, r4, c13, c0, 2
349 mrc p15, 0, r5, c13, c0, 3
350 mrc p15, 0, r6, c13, c0, 4
351 mrc p15, 2, r7, c0, c0, 0
352 stmia r8!, {r4-r7}
353 /* Data TLB lockdown, instruction TLB lockdown registers */
354 mrc p15, 0, r5, c10, c0, 0
355 mrc p15, 0, r6, c10, c0, 1
356 stmia r8!, {r5-r6}
357 /* Secure or non secure vector base address, FCSE PID, Context PID*/
358 mrc p15, 0, r4, c12, c0, 0
359 mrc p15, 0, r5, c13, c0, 0
360 mrc p15, 0, r6, c13, c0, 1
361 stmia r8!, {r4-r6}
362 /* Primary remap, normal remap registers */
363 mrc p15, 0, r4, c10, c2, 0
364 mrc p15, 0, r5, c10, c2, 1
365 stmia r8!,{r4-r5}
366
367 /* Store current cpsr*/
368 mrs r2, cpsr
369 stmia r8!, {r2}
370
371 mrc p15, 0, r4, c1, c0, 0
372 /* save control register */
373 stmia r8!, {r4}
374clean_caches:
375 /* Clean Data or unified cache to POU*/
376 /* How to invalidate only L1 cache???? - #FIX_ME# */
377 /* mcr p15, 0, r11, c7, c11, 1 */
378 cmp r9, #1 /* Check whether L2 inval is required or not*/
379 bne skip_l2_inval
380clean_l2:
381 /* read clidr */
382 mrc p15, 1, r0, c0, c0, 1
383 /* extract loc from clidr */
384 ands r3, r0, #0x7000000
385 /* left align loc bit field */
386 mov r3, r3, lsr #23
387 /* if loc is 0, then no need to clean */
388 beq finished
389 /* start clean at cache level 0 */
390 mov r10, #0
391loop1:
392 /* work out 3x current cache level */
393 add r2, r10, r10, lsr #1
394 /* extract cache type bits from clidr*/
395 mov r1, r0, lsr r2
396 /* mask of the bits for current cache only */
397 and r1, r1, #7
398 /* see what cache we have at this level */
399 cmp r1, #2
400 /* skip if no cache, or just i-cache */
401 blt skip
402 /* select current cache level in cssr */
403 mcr p15, 2, r10, c0, c0, 0
404 /* isb to sych the new cssr&csidr */
405 isb
406 /* read the new csidr */
407 mrc p15, 1, r1, c0, c0, 0
408 /* extract the length of the cache lines */
409 and r2, r1, #7
410 /* add 4 (line length offset) */
411 add r2, r2, #4
412 ldr r4, assoc_mask
413 /* find maximum number on the way size */
414 ands r4, r4, r1, lsr #3
415 /* find bit position of way size increment */
416 clz r5, r4
417 ldr r7, numset_mask
418 /* extract max number of the index size*/
419 ands r7, r7, r1, lsr #13
420loop2:
421 mov r9, r4
422 /* create working copy of max way size*/
423loop3:
424 /* factor way and cache number into r11 */
425 orr r11, r10, r9, lsl r5
426 /* factor index number into r11 */
427 orr r11, r11, r7, lsl r2
428 /*clean & invalidate by set/way */
429 mcr p15, 0, r11, c7, c10, 2
430 /* decrement the way*/
431 subs r9, r9, #1
432 bge loop3
433 /*decrement the index */
434 subs r7, r7, #1
435 bge loop2
436skip:
437 add r10, r10, #2
438 /* increment cache number */
439 cmp r3, r10
440 bgt loop1
441finished:
442 /*swith back to cache level 0 */
443 mov r10, #0
444 /* select current cache level in cssr */
445 mcr p15, 2, r10, c0, c0, 0
446 isb
447skip_l2_inval:
448 /* Data memory barrier and Data sync barrier */
449 mov r1, #0
450 mcr p15, 0, r1, c7, c10, 4
451 mcr p15, 0, r1, c7, c10, 5
452
453 wfi @ wait for interrupt
454 nop
455 nop
456 nop
457 nop
458 nop
459 nop
460 nop
461 nop
462 nop
463 nop
464 bl i_dll_wait
465 /* restore regs and return */
466 ldmfd sp!, {r0-r12, pc}
467
468i_dll_wait:
469 ldr r4, clk_stabilize_delay
470
471i_dll_delay:
472 subs r4, r4, #0x1
473 bne i_dll_delay
474 ldr r4, sdrc_power
475 ldr r5, [r4]
476 bic r5, r5, #0x40
477 str r5, [r4]
478 bx lr
479pm_prepwstst_core:
480 .word PM_PREPWSTST_CORE_V
481pm_prepwstst_mpu:
482 .word PM_PREPWSTST_MPU_V
483pm_pwstctrl_mpu:
484 .word PM_PWSTCTRL_MPU_P
485scratchpad_base:
486 .word SCRATCHPAD_BASE_P
487sdrc_power:
488 .word SDRC_POWER_V
Kevin Hilman8bd22942009-05-28 10:56:16 -0700489clk_stabilize_delay:
490 .word 0x000001FF
491assoc_mask:
492 .word 0x3ff
493numset_mask:
494 .word 0x7fff
495ttbrbit_mask:
496 .word 0xFFFFC000
497table_index_mask:
498 .word 0xFFF00000
499table_entry:
500 .word 0x00000C02
501cache_pred_disable_mask:
502 .word 0xFFFFE7FB
Tero Kristo27d59a42008-10-13 13:15:00 +0300503control_stat:
504 .word CONTROL_STAT
Kevin Hilman8bd22942009-05-28 10:56:16 -0700505ENTRY(omap34xx_cpu_suspend_sz)
506 .word . - omap34xx_cpu_suspend