GNU Linux-libre 4.19.314-gnu1
[releases.git] / arch / arm / mach-imx / suspend-imx53.S
1 /*
2  * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
3  */
4 /*
5  * The code contained herein is licensed under the GNU General Public
6  * License. You may obtain a copy of the GNU General Public License
7  * Version 2 or later at the following locations:
8  *
9  * http://www.opensource.org/licenses/gpl-license.html
10  * http://www.gnu.org/copyleft/gpl.html
11  */
12
13 #include <linux/linkage.h>
14
15 #define M4IF_MCR0_OFFSET                        (0x008C)
16 #define M4IF_MCR0_FDVFS                         (0x1 << 11)
17 #define M4IF_MCR0_FDVACK                        (0x1 << 27)
18
19         .align 3
20
21 /*
22  * ==================== low level suspend ====================
23  *
24  * On entry
25  * r0: pm_info structure address;
26  *
27  * suspend ocram space layout:
28  * ======================== high address ======================
29  *                              .
30  *                              .
31  *                              .
32  *                              ^
33  *                              ^
34  *                              ^
35  *                      imx53_suspend code
36  *              PM_INFO structure(imx5_cpu_suspend_info)
37  * ======================== low address =======================
38  */
39
40 /* Offsets of members of struct imx5_cpu_suspend_info */
41 #define SUSPEND_INFO_MX53_M4IF_V_OFFSET         0x0
42 #define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET       0x4
43 #define SUSPEND_INFO_MX53_IO_COUNT_OFFSET       0x8
44 #define SUSPEND_INFO_MX53_IO_STATE_OFFSET       0xc
45
46 ENTRY(imx53_suspend)
47         stmfd   sp!, {r4,r5,r6,r7}
48
49         /* Save pad config */
50         ldr     r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
51         cmp     r1, #0
52         beq     skip_pad_conf_1
53
54         add     r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
55         ldr     r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
56
57 1:
58         ldr     r5, [r2], #12   /* IOMUXC register offset */
59         ldr     r6, [r3, r5]    /* current value */
60         str     r6, [r2], #4    /* save area */
61         subs    r1, r1, #1
62         bne     1b
63
64 skip_pad_conf_1:
65         /* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
66         ldr     r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
67         ldr     r2,[r1, #M4IF_MCR0_OFFSET]
68         orr     r2, r2, #M4IF_MCR0_FDVFS
69         str     r2,[r1, #M4IF_MCR0_OFFSET]
70
71         /* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
72 wait_sr_ack:
73         ldr     r2,[r1, #M4IF_MCR0_OFFSET]
74         ands    r2, r2, #M4IF_MCR0_FDVACK
75         beq     wait_sr_ack
76
77         /* Set pad config */
78         ldr     r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
79         cmp     r1, #0
80         beq     skip_pad_conf_2
81
82         add     r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
83         ldr     r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
84
85 2:
86         ldr     r5, [r2], #4    /* IOMUXC register offset */
87         ldr     r6, [r2], #4    /* clear */
88         ldr     r7, [r3, r5]
89         bic     r7, r7, r6
90         ldr     r6, [r2], #8    /* set */
91         orr     r7, r7, r6
92         str     r7, [r3, r5]
93         subs    r1, r1, #1
94         bne     2b
95
96 skip_pad_conf_2:
97         /* Zzz, enter stop mode */
98         wfi
99         nop
100         nop
101         nop
102         nop
103
104         /* Restore pad config */
105         ldr     r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
106         cmp     r1, #0
107         beq     skip_pad_conf_3
108
109         add     r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
110         ldr     r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
111
112 3:
113         ldr     r5, [r2], #12   /* IOMUXC register offset */
114         ldr     r6, [r2], #4    /* saved value */
115         str     r6, [r3, r5]
116         subs    r1, r1, #1
117         bne     3b
118
119 skip_pad_conf_3:
120         /* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
121         ldr     r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
122         ldr     r2,[r1, #M4IF_MCR0_OFFSET]
123         bic     r2, r2, #M4IF_MCR0_FDVFS
124         str     r2,[r1, #M4IF_MCR0_OFFSET]
125
126         /* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
127 wait_ar_ack:
128         ldr     r2,[r1, #M4IF_MCR0_OFFSET]
129         ands    r2, r2, #M4IF_MCR0_FDVACK
130         bne     wait_ar_ack
131
132         /* Restore registers */
133         ldmfd   sp!, {r4,r5,r6,r7}
134         mov     pc, lr
135
136 ENDPROC(imx53_suspend)
137
138 ENTRY(imx53_suspend_sz)
139         .word   . - imx53_suspend