123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
- */
- /*
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
- #include <linux/linkage.h>
- #define M4IF_MCR0_OFFSET (0x008C)
- #define M4IF_MCR0_FDVFS (0x1 << 11)
- #define M4IF_MCR0_FDVACK (0x1 << 27)
- .align 3
- /*
- * ==================== low level suspend ====================
- *
- * On entry
- * r0: pm_info structure address;
- *
- * suspend ocram space layout:
- * ======================== high address ======================
- * .
- * .
- * .
- * ^
- * ^
- * ^
- * imx53_suspend code
- * PM_INFO structure(imx53_suspend_info)
- * ======================== low address =======================
- */
- /* Offsets of members of struct imx53_suspend_info */
- #define SUSPEND_INFO_MX53_M4IF_V_OFFSET 0x0
- #define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET 0x4
- #define SUSPEND_INFO_MX53_IO_COUNT_OFFSET 0x8
- #define SUSPEND_INFO_MX53_IO_STATE_OFFSET 0xc
- ENTRY(imx53_suspend)
- stmfd sp!, {r4,r5,r6,r7}
- /* Save pad config */
- ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
- cmp r1, #0
- beq skip_pad_conf_1
- add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
- ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
- 1:
- ldr r5, [r2], #12 /* IOMUXC register offset */
- ldr r6, [r3, r5] /* current value */
- str r6, [r2], #4 /* save area */
- subs r1, r1, #1
- bne 1b
- skip_pad_conf_1:
- /* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
- ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
- ldr r2,[r1, #M4IF_MCR0_OFFSET]
- orr r2, r2, #M4IF_MCR0_FDVFS
- str r2,[r1, #M4IF_MCR0_OFFSET]
- /* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
- wait_sr_ack:
- ldr r2,[r1, #M4IF_MCR0_OFFSET]
- ands r2, r2, #M4IF_MCR0_FDVACK
- beq wait_sr_ack
- /* Set pad config */
- ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
- cmp r1, #0
- beq skip_pad_conf_2
- add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
- ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
- 2:
- ldr r5, [r2], #4 /* IOMUXC register offset */
- ldr r6, [r2], #4 /* clear */
- ldr r7, [r3, r5]
- bic r7, r7, r6
- ldr r6, [r2], #8 /* set */
- orr r7, r7, r6
- str r7, [r3, r5]
- subs r1, r1, #1
- bne 2b
- skip_pad_conf_2:
- /* Zzz, enter stop mode */
- wfi
- nop
- nop
- nop
- nop
- /* Restore pad config */
- ldr r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
- cmp r1, #0
- beq skip_pad_conf_3
- add r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
- ldr r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
- 3:
- ldr r5, [r2], #12 /* IOMUXC register offset */
- ldr r6, [r2], #4 /* saved value */
- str r6, [r3, r5]
- subs r1, r1, #1
- bne 3b
- skip_pad_conf_3:
- /* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
- ldr r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
- ldr r2,[r1, #M4IF_MCR0_OFFSET]
- bic r2, r2, #M4IF_MCR0_FDVFS
- str r2,[r1, #M4IF_MCR0_OFFSET]
- /* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
- wait_ar_ack:
- ldr r2,[r1, #M4IF_MCR0_OFFSET]
- ands r2, r2, #M4IF_MCR0_FDVACK
- bne wait_ar_ack
- /* Restore registers */
- ldmfd sp!, {r4,r5,r6,r7}
- mov pc, lr
- ENDPROC(imx53_suspend)
- ENTRY(imx53_suspend_sz)
- .word . - imx53_suspend
|