18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci/*
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/linkage.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#define M4IF_MCR0_OFFSET			(0x008C)
118c2ecf20Sopenharmony_ci#define M4IF_MCR0_FDVFS				(0x1 << 11)
128c2ecf20Sopenharmony_ci#define M4IF_MCR0_FDVACK			(0x1 << 27)
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci	.align 3
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/*
178c2ecf20Sopenharmony_ci * ==================== low level suspend ====================
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * On entry
208c2ecf20Sopenharmony_ci * r0: pm_info structure address;
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * suspend ocram space layout:
238c2ecf20Sopenharmony_ci * ======================== high address ======================
248c2ecf20Sopenharmony_ci *                              .
258c2ecf20Sopenharmony_ci *                              .
268c2ecf20Sopenharmony_ci *                              .
278c2ecf20Sopenharmony_ci *                              ^
288c2ecf20Sopenharmony_ci *                              ^
298c2ecf20Sopenharmony_ci *                              ^
308c2ecf20Sopenharmony_ci *                      imx53_suspend code
318c2ecf20Sopenharmony_ci *              PM_INFO structure(imx5_cpu_suspend_info)
328c2ecf20Sopenharmony_ci * ======================== low address =======================
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci/* Offsets of members of struct imx5_cpu_suspend_info */
368c2ecf20Sopenharmony_ci#define SUSPEND_INFO_MX53_M4IF_V_OFFSET		0x0
378c2ecf20Sopenharmony_ci#define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET	0x4
388c2ecf20Sopenharmony_ci#define SUSPEND_INFO_MX53_IO_COUNT_OFFSET	0x8
398c2ecf20Sopenharmony_ci#define SUSPEND_INFO_MX53_IO_STATE_OFFSET	0xc
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ciENTRY(imx53_suspend)
428c2ecf20Sopenharmony_ci	stmfd	sp!, {r4,r5,r6,r7}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	/* Save pad config */
458c2ecf20Sopenharmony_ci	ldr	r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
468c2ecf20Sopenharmony_ci	cmp	r1, #0
478c2ecf20Sopenharmony_ci	beq	skip_pad_conf_1
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	add	r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
508c2ecf20Sopenharmony_ci	ldr	r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci1:
538c2ecf20Sopenharmony_ci	ldr	r5, [r2], #12	/* IOMUXC register offset */
548c2ecf20Sopenharmony_ci	ldr	r6, [r3, r5]	/* current value */
558c2ecf20Sopenharmony_ci	str	r6, [r2], #4	/* save area */
568c2ecf20Sopenharmony_ci	subs	r1, r1, #1
578c2ecf20Sopenharmony_ci	bne	1b
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ciskip_pad_conf_1:
608c2ecf20Sopenharmony_ci	/* Set FDVFS bit of M4IF_MCR0 to request DDR to enter self-refresh */
618c2ecf20Sopenharmony_ci	ldr	r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
628c2ecf20Sopenharmony_ci	ldr	r2,[r1, #M4IF_MCR0_OFFSET]
638c2ecf20Sopenharmony_ci	orr	r2, r2, #M4IF_MCR0_FDVFS
648c2ecf20Sopenharmony_ci	str	r2,[r1, #M4IF_MCR0_OFFSET]
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	/* Poll FDVACK bit of M4IF_MCR to wait for DDR to enter self-refresh */
678c2ecf20Sopenharmony_ciwait_sr_ack:
688c2ecf20Sopenharmony_ci	ldr	r2,[r1, #M4IF_MCR0_OFFSET]
698c2ecf20Sopenharmony_ci	ands	r2, r2, #M4IF_MCR0_FDVACK
708c2ecf20Sopenharmony_ci	beq	wait_sr_ack
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/* Set pad config */
738c2ecf20Sopenharmony_ci	ldr	r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
748c2ecf20Sopenharmony_ci	cmp	r1, #0
758c2ecf20Sopenharmony_ci	beq	skip_pad_conf_2
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	add	r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
788c2ecf20Sopenharmony_ci	ldr	r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci2:
818c2ecf20Sopenharmony_ci	ldr	r5, [r2], #4	/* IOMUXC register offset */
828c2ecf20Sopenharmony_ci	ldr	r6, [r2], #4	/* clear */
838c2ecf20Sopenharmony_ci	ldr	r7, [r3, r5]
848c2ecf20Sopenharmony_ci	bic	r7, r7, r6
858c2ecf20Sopenharmony_ci	ldr	r6, [r2], #8	/* set */
868c2ecf20Sopenharmony_ci	orr	r7, r7, r6
878c2ecf20Sopenharmony_ci	str	r7, [r3, r5]
888c2ecf20Sopenharmony_ci	subs	r1, r1, #1
898c2ecf20Sopenharmony_ci	bne	2b
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ciskip_pad_conf_2:
928c2ecf20Sopenharmony_ci	/* Zzz, enter stop mode */
938c2ecf20Sopenharmony_ci	wfi
948c2ecf20Sopenharmony_ci	nop
958c2ecf20Sopenharmony_ci	nop
968c2ecf20Sopenharmony_ci	nop
978c2ecf20Sopenharmony_ci	nop
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* Restore pad config */
1008c2ecf20Sopenharmony_ci	ldr	r1, [r0, #SUSPEND_INFO_MX53_IO_COUNT_OFFSET]
1018c2ecf20Sopenharmony_ci	cmp	r1, #0
1028c2ecf20Sopenharmony_ci	beq	skip_pad_conf_3
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	add	r2, r0, #SUSPEND_INFO_MX53_IO_STATE_OFFSET
1058c2ecf20Sopenharmony_ci	ldr	r3, [r0, #SUSPEND_INFO_MX53_IOMUXC_V_OFFSET]
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci3:
1088c2ecf20Sopenharmony_ci	ldr	r5, [r2], #12	/* IOMUXC register offset */
1098c2ecf20Sopenharmony_ci	ldr	r6, [r2], #4	/* saved value */
1108c2ecf20Sopenharmony_ci	str	r6, [r3, r5]
1118c2ecf20Sopenharmony_ci	subs	r1, r1, #1
1128c2ecf20Sopenharmony_ci	bne	3b
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ciskip_pad_conf_3:
1158c2ecf20Sopenharmony_ci	/* Clear FDVFS bit of M4IF_MCR0 to request DDR to exit self-refresh */
1168c2ecf20Sopenharmony_ci	ldr	r1, [r0, #SUSPEND_INFO_MX53_M4IF_V_OFFSET]
1178c2ecf20Sopenharmony_ci	ldr	r2,[r1, #M4IF_MCR0_OFFSET]
1188c2ecf20Sopenharmony_ci	bic	r2, r2, #M4IF_MCR0_FDVFS
1198c2ecf20Sopenharmony_ci	str	r2,[r1, #M4IF_MCR0_OFFSET]
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	/* Poll FDVACK bit of M4IF_MCR to wait for DDR to exit self-refresh */
1228c2ecf20Sopenharmony_ciwait_ar_ack:
1238c2ecf20Sopenharmony_ci	ldr	r2,[r1, #M4IF_MCR0_OFFSET]
1248c2ecf20Sopenharmony_ci	ands	r2, r2, #M4IF_MCR0_FDVACK
1258c2ecf20Sopenharmony_ci	bne	wait_ar_ack
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/* Restore registers */
1288c2ecf20Sopenharmony_ci	ldmfd	sp!, {r4,r5,r6,r7}
1298c2ecf20Sopenharmony_ci	mov	pc, lr
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ciENDPROC(imx53_suspend)
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciENTRY(imx53_suspend_sz)
1348c2ecf20Sopenharmony_ci        .word   . - imx53_suspend
135