OMAP3 PM: off-mode support for HS/EMU devices
[safe/jmp/linux-2.6] / 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 <plat/control.h>
31
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)
39 #define PM_PWSTCTRL_MPU_P       OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL
40 #define SRAM_BASE_P             0x40200000
41 #define CONTROL_STAT            0x480022F0
42 #define SCRATCHPAD_MEM_OFFS     0x310 /* Move this as correct place is
43                                        * available */
44 #define SCRATCHPAD_BASE_P       (OMAP343X_CTRL_BASE + 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 /* 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
90 /*
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  */
99 ENTRY(omap34xx_cpu_suspend)
100         stmfd   sp!, {r0-r12, lr}               @ save registers on stack
101 loop:
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
133 restore:
134         /* b restore*/  @ Enable to debug restore code
135         /* 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
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:
177         /* Execute smi to invalidate L2 cache */
178         mov r12, #0x1                         @ set up to invalide L2
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)
184 logic_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
261 ttbr_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
266 usettbr0:
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
305 save_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 */
318 l1_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}
374 clean_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
380 clean_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
391 loop1:
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
420 loop2:
421         mov     r9, r4
422         /* create working copy of max way size*/
423 loop3:
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
436 skip:
437         add     r10, r10, #2
438         /* increment cache number */
439         cmp     r3, r10
440         bgt     loop1
441 finished:
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
447 skip_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
468 i_dll_wait:
469         ldr     r4, clk_stabilize_delay
470
471 i_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
479 pm_prepwstst_core:
480         .word   PM_PREPWSTST_CORE_V
481 pm_prepwstst_mpu:
482         .word   PM_PREPWSTST_MPU_V
483 pm_pwstctrl_mpu:
484         .word   PM_PWSTCTRL_MPU_P
485 scratchpad_base:
486         .word   SCRATCHPAD_BASE_P
487 sdrc_power:
488         .word SDRC_POWER_V
489 clk_stabilize_delay:
490         .word 0x000001FF
491 assoc_mask:
492         .word   0x3ff
493 numset_mask:
494         .word   0x7fff
495 ttbrbit_mask:
496         .word   0xFFFFC000
497 table_index_mask:
498         .word   0xFFF00000
499 table_entry:
500         .word   0x00000C02
501 cache_pred_disable_mask:
502         .word   0xFFFFE7FB
503 control_stat:
504         .word   CONTROL_STAT
505 ENTRY(omap34xx_cpu_suspend_sz)
506         .word   . - omap34xx_cpu_suspend