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