140 lines
3.4 KiB
ArmAsm
140 lines
3.4 KiB
ArmAsm
/*
|
|
* 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
|