blob: 5ed078ad110aa3bdcf054204d0ebd739061c6601 [file] [log] [blame]
Martin Fuzzey1579c7b2015-05-12 15:31:03 +02001/*
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(imx53_suspend_info)
37 * ======================== low address =======================
38 */
39
40/* Offsets of members of struct imx53_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
46ENTRY(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
571:
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
64skip_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 */
72wait_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
852:
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
96skip_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
1123:
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
119skip_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 */
127wait_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
136ENDPROC(imx53_suspend)
137
138ENTRY(imx53_suspend_sz)
139 .word . - imx53_suspend