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