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(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 140