]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/sleep34xx.S
125b75affebbdf05525ef06c0ff7b18330d1648d
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / sleep34xx.S
1 /*
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>
30 #include <mach/pm.h>
31 #include <mach/control.h>
32
33 #include "prm.h"
34 #include "sdrc.h"
35
36 #define PM_PREPWSTST_CORE_V     OMAP34XX_PRM_REGADDR(CORE_MOD, \
37                                 OMAP3430_PM_PREPWSTST)
38 #define PM_PREPWSTST_MPU_V      OMAP34XX_PRM_REGADDR(MPU_MOD, \
39                                 OMAP3430_PM_PREPWSTST)
40 #define PM_PWSTCTRL_MPU_P       OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL)
41 #define SCRATCHPAD_MEM_OFFS     0x310 /* Move this as correct place is
42                                        * available */
43 #define SCRATCHPAD_BASE_P       OMAP343X_CTRL_REGADDR(\
44                                 OMAP343X_CONTROL_MEM_WKUP +\
45                                 SCRATCHPAD_MEM_OFFS)
46 #define SDRC_POWER_V            OMAP34XX_SDRC_REGADDR(SDRC_POWER)
47
48         .text
49 /* Function call to get the restore pointer for resume from OFF */
50 ENTRY(get_restore_pointer)
51         stmfd   sp!, {lr}     @ save registers on stack
52         adr     r0, restore
53         ldmfd   sp!, {pc}     @ restore regs and return
54 ENTRY(get_restore_pointer_sz)
55         .word   . - get_restore_pointer_sz
56 /*
57  * Forces OMAP into idle state
58  *
59  * omap34xx_suspend() - This bit of code just executes the WFI
60  * for normal idles.
61  *
62  * Note: This code get's copied to internal SRAM at boot. When the OMAP
63  *       wakes up it continues execution at the point it went to sleep.
64  */
65 ENTRY(omap34xx_cpu_suspend)
66         stmfd   sp!, {r0-r12, lr}               @ save registers on stack
67 loop:
68         /*b     loop*/  @Enable to debug by stepping through code
69         /* r0 contains restore pointer in sdram */
70         /* r1 contains information about saving context */
71         ldr     r4, sdrc_power          @ read the SDRC_POWER register
72         ldr     r5, [r4]                @ read the contents of SDRC_POWER
73         orr     r5, r5, #0x40           @ enable self refresh on idle req
74         str     r5, [r4]                @ write back to SDRC_POWER register
75
76         cmp     r1, #0x0
77         /* If context save is required, do that and execute wfi */
78         bne     save_context_wfi
79         /* Data memory barrier and Data sync barrier */
80         mov     r1, #0
81         mcr     p15, 0, r1, c7, c10, 4
82         mcr     p15, 0, r1, c7, c10, 5
83
84         wfi                             @ wait for interrupt
85
86         nop
87         nop
88         nop
89         nop
90         nop
91         nop
92         nop
93         nop
94         nop
95         nop
96         bl i_dll_wait
97
98         ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
99 restore:
100         /* b restore*/  @ Enable to debug restore code
101         /* Check what was the reason for mpu reset and store the reason in r9*/
102         /* 1 - Only L1 and logic lost */
103         /* 2 - Only L2 lost - In this case, we wont be here */
104         /* 3 - Both L1 and L2 lost */
105         ldr     r1, pm_pwstctrl_mpu
106         ldr     r2, [r1]
107         and     r2, r2, #0x3
108         cmp     r2, #0x0        @ Check if target power state was OFF or RET
109         moveq   r9, #0x3        @ MPU OFF => L1 and L2 lost
110         movne   r9, #0x1        @ Only L1 and L2 lost => avoid L2 invalidation
111         bne     logic_l1_restore
112         /* Execute smi to invalidate L2 cache */
113         mov r12, #0x1                         @ set up to invalide L2
114 smi:    .word 0xE1600070                @ Call SMI monitor (smieq)
115 logic_l1_restore:
116         mov     r1, #0
117         /* Invalidate all instruction caches to PoU
118          * and flush branch target cache */
119         mcr     p15, 0, r1, c7, c5, 0
120
121         ldr     r4, scratchpad_base
122         ldr     r3, [r4,#0xBC]
123         ldmia   r3!, {r4-r6}
124         mov     sp, r4
125         msr     spsr_cxsf, r5
126         mov     lr, r6
127
128         ldmia   r3!, {r4-r9}
129         /* Coprocessor access Control Register */
130         mcr p15, 0, r4, c1, c0, 2
131
132         /* TTBR0 */
133         MCR p15, 0, r5, c2, c0, 0
134         /* TTBR1 */
135         MCR p15, 0, r6, c2, c0, 1
136         /* Translation table base control register */
137         MCR p15, 0, r7, c2, c0, 2
138         /*domain access Control Register */
139         MCR p15, 0, r8, c3, c0, 0
140         /* data fault status Register */
141         MCR p15, 0, r9, c5, c0, 0
142
143         ldmia  r3!,{r4-r8}
144         /* instruction fault status Register */
145         MCR p15, 0, r4, c5, c0, 1
146         /*Data Auxiliary Fault Status Register */
147         MCR p15, 0, r5, c5, c1, 0
148         /*Instruction Auxiliary Fault Status Register*/
149         MCR p15, 0, r6, c5, c1, 1
150         /*Data Fault Address Register */
151         MCR p15, 0, r7, c6, c0, 0
152         /*Instruction Fault Address Register*/
153         MCR p15, 0, r8, c6, c0, 2
154         ldmia  r3!,{r4-r7}
155
156         /* user r/w thread and process ID */
157         MCR p15, 0, r4, c13, c0, 2
158         /* user ro thread and process ID */
159         MCR p15, 0, r5, c13, c0, 3
160         /*Privileged only thread and process ID */
161         MCR p15, 0, r6, c13, c0, 4
162         /* cache size selection */
163         MCR p15, 2, r7, c0, c0, 0
164         ldmia  r3!,{r4-r8}
165         /* Data TLB lockdown registers */
166         MCR p15, 0, r4, c10, c0, 0
167         /* Instruction TLB lockdown registers */
168         MCR p15, 0, r5, c10, c0, 1
169         /* Secure or Nonsecure Vector Base Address */
170         MCR p15, 0, r6, c12, c0, 0
171         /* FCSE PID */
172         MCR p15, 0, r7, c13, c0, 0
173         /* Context PID */
174         MCR p15, 0, r8, c13, c0, 1
175
176         ldmia  r3!,{r4-r5}
177         /* primary memory remap register */
178         MCR p15, 0, r4, c10, c2, 0
179         /*normal memory remap register */
180         MCR p15, 0, r5, c10, c2, 1
181
182         /* Restore registers for other modes from SDRAM */
183         /* Save current mode */
184         mrs     r7, cpsr
185
186         /* FIQ mode */
187         bic     r0, r7, #0x1F
188         orr     r0, r0, #0x11
189         msr     cpsr, r0
190         ldmia   r3!, {r8-r12}
191         /* load the SP and LR from SDRAM */
192         ldmia  r3!,{r4-r6}
193         mov    sp, r4   /*update the SP */
194         mov    lr, r5   /*update the LR */
195         msr    spsr, r6 /*update the SPSR*/
196
197         /* IRQ mode */
198         bic    r0, r7, #0x1F
199         orr    r0, r0, #0x12
200         msr    cpsr, r0 /*go into IRQ mode*/
201         ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM*/
202         mov    sp, r4   /*update the SP */
203         mov    lr, r5   /*update the LR */
204         msr    spsr, r6 /*update the SPSR */
205
206         /* ABORT mode */
207         bic    r0, r7, #0x1F
208         orr    r0, r0, #0x17
209         msr    cpsr, r0 /* go into ABORT mode */
210         ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM */
211         mov    sp, r4           /*update the SP */
212         mov    lr, r5           /*update the LR */
213         msr    spsr, r6         /*update the SPSR */
214
215         /* UNDEEF mode */
216         bic    r0, r7, #0x1F
217         orr    r0, r0, #0x1B
218         msr    cpsr, r0         /*go into UNDEF mode */
219         ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM */
220         mov    sp, r4           /*update the SP*/
221         mov    lr, r5           /*update the LR*/
222         msr    spsr, r6         /*update the SPSR*/
223
224         /* SYSTEM (USER) mode */
225         bic    r0, r7, #0x1F
226         orr    r0, r0, #0x1F
227         msr    cpsr, r0         /*go into USR mode */
228         ldmia  r3!,{r4-r6}      /*load the SP and LR from SDRAM*/
229         mov    sp, r4           /*update the SP */
230         mov    lr, r5           /*update the LR */
231         msr    spsr, r6         /*update the SPSR */
232         msr    cpsr, r7         /*back to original mode*/
233
234         /* Restore cpsr */
235         ldmia   r3!,{r4}        /*load CPSR from SDRAM*/
236         msr     cpsr, r4        /*store cpsr */
237
238         /* Enabling MMU here */
239         mrc     p15, 0, r7, c2, c0, 2 /* Read TTBRControl */
240         /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/
241         and     r7, #0x7
242         cmp     r7, #0x0
243         beq     usettbr0
244 ttbr_error:
245         /* More work needs to be done to support N[0:2] value other than 0
246         * So looping here so that the error can be detected
247         */
248         b       ttbr_error
249 usettbr0:
250         mrc     p15, 0, r2, c2, c0, 0
251         ldr     r5, ttbrbit_mask
252         and     r2, r5
253         mov     r4, pc
254         ldr     r5, table_index_mask
255         and     r4, r5 /* r4 = 31 to 20 bits of pc */
256         /* Extract the value to be written to table entry */
257         ldr     r1, table_entry
258         add     r1, r1, r4 /* r1 has value to be written to table entry*/
259         /* Getting the address of table entry to modify */
260         lsr     r4, #18
261         add     r2, r4 /* r2 has the location which needs to be modified */
262         /* Storing previous entry of location being modified */
263         ldr     r5, scratchpad_base
264         ldr     r4, [r2]
265         str     r4, [r5, #0xC0]
266         /* Modify the table entry */
267         str     r1, [r2]
268         /* Storing address of entry being modified
269          * - will be restored after enabling MMU */
270         ldr     r5, scratchpad_base
271         str     r2, [r5, #0xC4]
272
273         mov     r0, #0
274         mcr     p15, 0, r0, c7, c5, 4   @ Flush prefetch buffer
275         mcr     p15, 0, r0, c7, c5, 6   @ Invalidate branch predictor array
276         mcr     p15, 0, r0, c8, c5, 0   @ Invalidate instruction TLB
277         mcr     p15, 0, r0, c8, c6, 0   @ Invalidate data TLB
278         /* Restore control register  but dont enable caches here*/
279         /* Caches will be enabled after restoring MMU table entry */
280         ldmia   r3!, {r4}
281         /* Store previous value of control register in scratchpad */
282         str     r4, [r5, #0xC8]
283         ldr     r2, cache_pred_disable_mask
284         and     r4, r2
285         mcr     p15, 0, r4, c1, c0, 0
286
287         ldmfd   sp!, {r0-r12, pc}               @ restore regs and return
288 save_context_wfi:
289         /*b     save_context_wfi*/      @ enable to debug save code
290         mov     r8, r0 /* Store SDRAM address in r8 */
291         /* Check what that target sleep state is:stored in r1*/
292         /* 1 - Only L1 and logic lost */
293         /* 2 - Only L2 lost */
294         /* 3 - Both L1 and L2 lost */
295         cmp     r1, #0x2 /* Only L2 lost */
296         beq     clean_l2
297         cmp     r1, #0x1 /* L2 retained */
298         /* r9 stores whether to clean L2 or not*/
299         moveq   r9, #0x0 /* Dont Clean L2 */
300         movne   r9, #0x1 /* Clean L2 */
301 l1_logic_lost:
302         /* Store sp and spsr to SDRAM */
303         mov     r4, sp
304         mrs     r5, spsr
305         mov     r6, lr
306         stmia   r8!, {r4-r6}
307         /* Save all ARM registers */
308         /* Coprocessor access control register */
309         mrc     p15, 0, r6, c1, c0, 2
310         stmia   r8!, {r6}
311         /* TTBR0, TTBR1 and Translation table base control */
312         mrc     p15, 0, r4, c2, c0, 0
313         mrc     p15, 0, r5, c2, c0, 1
314         mrc     p15, 0, r6, c2, c0, 2
315         stmia   r8!, {r4-r6}
316         /* Domain access control register, data fault status register,
317         and instruction fault status register */
318         mrc     p15, 0, r4, c3, c0, 0
319         mrc     p15, 0, r5, c5, c0, 0
320         mrc     p15, 0, r6, c5, c0, 1
321         stmia   r8!, {r4-r6}
322         /* Data aux fault status register, instruction aux fault status,
323         datat fault address register and instruction fault address register*/
324         mrc     p15, 0, r4, c5, c1, 0
325         mrc     p15, 0, r5, c5, c1, 1
326         mrc     p15, 0, r6, c6, c0, 0
327         mrc     p15, 0, r7, c6, c0, 2
328         stmia   r8!, {r4-r7}
329         /* user r/w thread and process ID, user r/o thread and process ID,
330         priv only thread and process ID, cache size selection */
331         mrc     p15, 0, r4, c13, c0, 2
332         mrc     p15, 0, r5, c13, c0, 3
333         mrc     p15, 0, r6, c13, c0, 4
334         mrc     p15, 2, r7, c0, c0, 0
335         stmia   r8!, {r4-r7}
336         /* Data TLB lockdown, instruction TLB lockdown registers */
337         mrc     p15, 0, r5, c10, c0, 0
338         mrc     p15, 0, r6, c10, c0, 1
339         stmia   r8!, {r5-r6}
340         /* Secure or non secure vector base address, FCSE PID, Context PID*/
341         mrc     p15, 0, r4, c12, c0, 0
342         mrc     p15, 0, r5, c13, c0, 0
343         mrc     p15, 0, r6, c13, c0, 1
344         stmia   r8!, {r4-r6}
345         /* Primary remap, normal remap registers */
346         mrc     p15, 0, r4, c10, c2, 0
347         mrc     p15, 0, r5, c10, c2, 1
348         stmia   r8!,{r4-r5}
349         /* Store SP, LR, SPSR registers for SUP, FIQ, IRQ, ABORT and USER
350         modes into SDRAM */
351
352         /* move SDRAM address to r7 as r8 is banked in FIQ*/
353         mov     r7, r8
354
355         /* Save current mode */
356         mrs     r2, cpsr
357         /* FIQ mode */
358         bic     r0, r2, #0x1F
359         orr     r0, r0, #0x11
360         msr     cpsr, r0 /* go to FIQ mode */
361         stmia   r7!, {r8-r12}
362         mov     r4, r13 /* move SP into r4*/
363         mov     r5, r14
364         mrs     r6, spsr
365         stmia   r7!, {r4-r6}
366
367         /* IRQ mode */
368         bic     r0, r2, #0x1F
369         orr     r0, r0, #0x12
370         msr     cpsr, r0
371         mov     r4, r13
372         mov     r5, r14
373         mrs     r6, spsr
374         stmia   r7!, {r4-r6}
375
376         /* Abort mode */
377         bic     r0, r2, #0x1F
378         orr     r0, r0, #0x17
379         msr     cpsr, r0
380         mov     r4, r13
381         mov     r5, r14
382         mrs     r6, spsr
383         stmia   r7!, {r4-r6}
384
385         /* UNDEF mode */
386         bic     r0, r2, #0x1F
387         orr     r0, r0, #0x1B
388         msr     cpsr, r0
389         mov     r4, r13
390         mov     r5, r14
391         mrs     r6, spsr
392         stmia   r7!, {r4-r6}
393
394         /* System (USER mode) */
395         bic     r0, r2, #0x1F
396         orr     r0, r0, #0x1F
397         msr     cpsr, r0
398         mov     r4, r13
399         mov     r5, r14
400         mrs     r6, spsr
401         stmia   r7!, {r4-r6}
402
403         /* Back to original mode */
404         msr     cpsr, r2
405
406         /* Store current cpsr*/
407         stmia   r7!, {r2}
408
409         mrc     p15, 0, r4, c1, c0, 0
410         /* save control register */
411         stmia   r7!, {r4}
412 clean_caches:
413         /* Clean Data or unified cache to POU*/
414         /* How to invalidate only L1 cache???? - #FIX_ME# */
415         /* mcr  p15, 0, r11, c7, c11, 1 */
416         cmp     r9, #1 /* Check whether L2 inval is required or not*/
417         bne     skip_l2_inval
418 clean_l2:
419         /* read clidr */
420         mrc     p15, 1, r0, c0, c0, 1
421         /* extract loc from clidr */
422         ands    r3, r0, #0x7000000
423         /* left align loc bit field */
424         mov     r3, r3, lsr #23
425         /* if loc is 0, then no need to clean */
426         beq     finished
427         /* start clean at cache level 0 */
428         mov     r10, #0
429 loop1:
430         /* work out 3x current cache level */
431         add     r2, r10, r10, lsr #1
432         /* extract cache type bits from clidr*/
433         mov     r1, r0, lsr r2
434         /* mask of the bits for current cache only */
435         and     r1, r1, #7
436         /* see what cache we have at this level */
437         cmp     r1, #2
438         /* skip if no cache, or just i-cache */
439         blt     skip
440         /* select current cache level in cssr */
441         mcr     p15, 2, r10, c0, c0, 0
442         /* isb to sych the new cssr&csidr */
443         isb
444         /* read the new csidr */
445         mrc     p15, 1, r1, c0, c0, 0
446         /* extract the length of the cache lines */
447         and     r2, r1, #7
448         /* add 4 (line length offset) */
449         add     r2, r2, #4
450         ldr     r4, assoc_mask
451         /* find maximum number on the way size */
452         ands    r4, r4, r1, lsr #3
453         /* find bit position of way size increment */
454         clz     r5, r4
455         ldr     r7, numset_mask
456         /* extract max number of the index size*/
457         ands    r7, r7, r1, lsr #13
458 loop2:
459         mov     r9, r4
460         /* create working copy of max way size*/
461 loop3:
462         /* factor way and cache number into r11 */
463         orr     r11, r10, r9, lsl r5
464         /* factor index number into r11 */
465         orr     r11, r11, r7, lsl r2
466         /*clean & invalidate by set/way */
467         mcr     p15, 0, r11, c7, c10, 2
468         /* decrement the way*/
469         subs    r9, r9, #1
470         bge     loop3
471         /*decrement the index */
472         subs    r7, r7, #1
473         bge     loop2
474 skip:
475         add     r10, r10, #2
476         /* increment cache number */
477         cmp     r3, r10
478         bgt     loop1
479 finished:
480         /*swith back to cache level 0 */
481         mov     r10, #0
482         /* select current cache level in cssr */
483         mcr     p15, 2, r10, c0, c0, 0
484         isb
485 skip_l2_inval:
486         /* Data memory barrier and Data sync barrier */
487         mov     r1, #0
488         mcr     p15, 0, r1, c7, c10, 4
489         mcr     p15, 0, r1, c7, c10, 5
490
491         wfi                             @ wait for interrupt
492         nop
493         nop
494         nop
495         nop
496         nop
497         nop
498         nop
499         nop
500         nop
501         nop
502         bl i_dll_wait
503         /* restore regs and return */
504         ldmfd   sp!, {r0-r12, pc}
505
506 i_dll_wait:
507         ldr     r4, clk_stabilize_delay
508
509 i_dll_delay:
510         subs    r4, r4, #0x1
511         bne     i_dll_delay
512         ldr     r4, sdrc_power
513         ldr     r5, [r4]
514         bic     r5, r5, #0x40
515         str     r5, [r4]
516         bx      lr
517 pm_prepwstst_core:
518         .word   PM_PREPWSTST_CORE_V
519 pm_prepwstst_mpu:
520         .word   PM_PREPWSTST_MPU_V
521 pm_pwstctrl_mpu:
522         .word   PM_PWSTCTRL_MPU_P
523 scratchpad_base:
524         .word   SCRATCHPAD_BASE_P
525 sdrc_power:
526         .word SDRC_POWER_V
527 context_mem:
528         .word   0x803E3E14
529 clk_stabilize_delay:
530         .word 0x000001FF
531 assoc_mask:
532         .word   0x3ff
533 numset_mask:
534         .word   0x7fff
535 ttbrbit_mask:
536         .word   0xFFFFC000
537 table_index_mask:
538         .word   0xFFF00000
539 table_entry:
540         .word   0x00000C02
541 cache_pred_disable_mask:
542         .word   0xFFFFE7FB
543 ENTRY(omap34xx_cpu_suspend_sz)
544         .word   . - omap34xx_cpu_suspend