18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2014 Freescale Semiconductor, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/linkage.h>
78c2ecf20Sopenharmony_ci#include <asm/assembler.h>
88c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
98c2ecf20Sopenharmony_ci#include <asm/hardware/cache-l2x0.h>
108c2ecf20Sopenharmony_ci#include "hardware.h"
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/*
138c2ecf20Sopenharmony_ci * ==================== low level suspend ====================
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * Better to follow below rules to use ARM registers:
168c2ecf20Sopenharmony_ci * r0: pm_info structure address;
178c2ecf20Sopenharmony_ci * r1 ~ r4: for saving pm_info members;
188c2ecf20Sopenharmony_ci * r5 ~ r10: free registers;
198c2ecf20Sopenharmony_ci * r11: io base address.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * suspend ocram space layout:
228c2ecf20Sopenharmony_ci * ======================== high address ======================
238c2ecf20Sopenharmony_ci *                              .
248c2ecf20Sopenharmony_ci *                              .
258c2ecf20Sopenharmony_ci *                              .
268c2ecf20Sopenharmony_ci *                              ^
278c2ecf20Sopenharmony_ci *                              ^
288c2ecf20Sopenharmony_ci *                              ^
298c2ecf20Sopenharmony_ci *                      imx6_suspend code
308c2ecf20Sopenharmony_ci *              PM_INFO structure(imx6_cpu_pm_info)
318c2ecf20Sopenharmony_ci * ======================== low address =======================
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/*
358c2ecf20Sopenharmony_ci * Below offsets are based on struct imx6_cpu_pm_info
368c2ecf20Sopenharmony_ci * which defined in arch/arm/mach-imx/pm-imx6q.c, this
378c2ecf20Sopenharmony_ci * structure contains necessary pm info for low level
388c2ecf20Sopenharmony_ci * suspend related code.
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ci#define PM_INFO_PBASE_OFFSET			0x0
418c2ecf20Sopenharmony_ci#define PM_INFO_RESUME_ADDR_OFFSET		0x4
428c2ecf20Sopenharmony_ci#define PM_INFO_DDR_TYPE_OFFSET			0x8
438c2ecf20Sopenharmony_ci#define PM_INFO_PM_INFO_SIZE_OFFSET		0xC
448c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_MMDC_P_OFFSET		0x10
458c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_MMDC_V_OFFSET		0x14
468c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_SRC_P_OFFSET		0x18
478c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_SRC_V_OFFSET		0x1C
488c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_IOMUXC_P_OFFSET		0x20
498c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_IOMUXC_V_OFFSET		0x24
508c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_CCM_P_OFFSET		0x28
518c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_CCM_V_OFFSET		0x2C
528c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_GPC_P_OFFSET		0x30
538c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_GPC_V_OFFSET		0x34
548c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_L2_P_OFFSET		0x38
558c2ecf20Sopenharmony_ci#define PM_INFO_MX6Q_L2_V_OFFSET		0x3C
568c2ecf20Sopenharmony_ci#define PM_INFO_MMDC_IO_NUM_OFFSET		0x40
578c2ecf20Sopenharmony_ci#define PM_INFO_MMDC_IO_VAL_OFFSET		0x44
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define MX6Q_SRC_GPR1	0x20
608c2ecf20Sopenharmony_ci#define MX6Q_SRC_GPR2	0x24
618c2ecf20Sopenharmony_ci#define MX6Q_MMDC_MAPSR	0x404
628c2ecf20Sopenharmony_ci#define MX6Q_MMDC_MPDGCTRL0	0x83c
638c2ecf20Sopenharmony_ci#define MX6Q_GPC_IMR1	0x08
648c2ecf20Sopenharmony_ci#define MX6Q_GPC_IMR2	0x0c
658c2ecf20Sopenharmony_ci#define MX6Q_GPC_IMR3	0x10
668c2ecf20Sopenharmony_ci#define MX6Q_GPC_IMR4	0x14
678c2ecf20Sopenharmony_ci#define MX6Q_CCM_CCR	0x0
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	.align 3
708c2ecf20Sopenharmony_ci	.arm
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	.macro  sync_l2_cache
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/* sync L2 cache to drain L2's buffers to DRAM. */
758c2ecf20Sopenharmony_ci#ifdef CONFIG_CACHE_L2X0
768c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_L2_V_OFFSET]
778c2ecf20Sopenharmony_ci	teq	r11, #0
788c2ecf20Sopenharmony_ci	beq	6f
798c2ecf20Sopenharmony_ci	mov	r6, #0x0
808c2ecf20Sopenharmony_ci	str	r6, [r11, #L2X0_CACHE_SYNC]
818c2ecf20Sopenharmony_ci1:
828c2ecf20Sopenharmony_ci	ldr	r6, [r11, #L2X0_CACHE_SYNC]
838c2ecf20Sopenharmony_ci	ands	r6, r6, #0x1
848c2ecf20Sopenharmony_ci	bne	1b
858c2ecf20Sopenharmony_ci6:
868c2ecf20Sopenharmony_ci#endif
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	.endm
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	.macro	resume_mmdc
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	/* restore MMDC IO */
938c2ecf20Sopenharmony_ci	cmp	r5, #0x0
948c2ecf20Sopenharmony_ci	ldreq	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
958c2ecf20Sopenharmony_ci	ldrne	r11, [r0, #PM_INFO_MX6Q_IOMUXC_P_OFFSET]
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	ldr	r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
988c2ecf20Sopenharmony_ci	ldr	r7, =PM_INFO_MMDC_IO_VAL_OFFSET
998c2ecf20Sopenharmony_ci	add	r7, r7, r0
1008c2ecf20Sopenharmony_ci1:
1018c2ecf20Sopenharmony_ci	ldr	r8, [r7], #0x4
1028c2ecf20Sopenharmony_ci	ldr	r9, [r7], #0x4
1038c2ecf20Sopenharmony_ci	str	r9, [r11, r8]
1048c2ecf20Sopenharmony_ci	subs	r6, r6, #0x1
1058c2ecf20Sopenharmony_ci	bne	1b
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	cmp	r5, #0x0
1088c2ecf20Sopenharmony_ci	ldreq	r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
1098c2ecf20Sopenharmony_ci	ldrne	r11, [r0, #PM_INFO_MX6Q_MMDC_P_OFFSET]
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	cmp	r3, #IMX_DDR_TYPE_LPDDR2
1128c2ecf20Sopenharmony_ci	bne	4f
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	/* reset read FIFO, RST_RD_FIFO */
1158c2ecf20Sopenharmony_ci	ldr	r7, =MX6Q_MMDC_MPDGCTRL0
1168c2ecf20Sopenharmony_ci	ldr	r6, [r11, r7]
1178c2ecf20Sopenharmony_ci	orr     r6, r6, #(1 << 31)
1188c2ecf20Sopenharmony_ci	str	r6, [r11, r7]
1198c2ecf20Sopenharmony_ci2:
1208c2ecf20Sopenharmony_ci	ldr	r6, [r11, r7]
1218c2ecf20Sopenharmony_ci	ands	r6, r6, #(1 << 31)
1228c2ecf20Sopenharmony_ci	bne	2b
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	/* reset FIFO a second time */
1258c2ecf20Sopenharmony_ci	ldr	r6, [r11, r7]
1268c2ecf20Sopenharmony_ci	orr     r6, r6, #(1 << 31)
1278c2ecf20Sopenharmony_ci	str	r6, [r11, r7]
1288c2ecf20Sopenharmony_ci3:
1298c2ecf20Sopenharmony_ci	ldr	r6, [r11, r7]
1308c2ecf20Sopenharmony_ci	ands	r6, r6, #(1 << 31)
1318c2ecf20Sopenharmony_ci	bne	3b
1328c2ecf20Sopenharmony_ci4:
1338c2ecf20Sopenharmony_ci	/* let DDR out of self-refresh */
1348c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
1358c2ecf20Sopenharmony_ci	bic	r7, r7, #(1 << 21)
1368c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_MMDC_MAPSR]
1378c2ecf20Sopenharmony_ci5:
1388c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
1398c2ecf20Sopenharmony_ci	ands	r7, r7, #(1 << 25)
1408c2ecf20Sopenharmony_ci	bne	5b
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	/* enable DDR auto power saving */
1438c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
1448c2ecf20Sopenharmony_ci	bic	r7, r7, #0x1
1458c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_MMDC_MAPSR]
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	.endm
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ciENTRY(imx6_suspend)
1508c2ecf20Sopenharmony_ci	ldr	r1, [r0, #PM_INFO_PBASE_OFFSET]
1518c2ecf20Sopenharmony_ci	ldr	r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
1528c2ecf20Sopenharmony_ci	ldr	r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
1538c2ecf20Sopenharmony_ci	ldr	r4, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET]
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	/*
1568c2ecf20Sopenharmony_ci	 * counting the resume address in iram
1578c2ecf20Sopenharmony_ci	 * to set it in SRC register.
1588c2ecf20Sopenharmony_ci	 */
1598c2ecf20Sopenharmony_ci	ldr	r6, =imx6_suspend
1608c2ecf20Sopenharmony_ci	ldr	r7, =resume
1618c2ecf20Sopenharmony_ci	sub	r7, r7, r6
1628c2ecf20Sopenharmony_ci	add	r8, r1, r4
1638c2ecf20Sopenharmony_ci	add	r9, r8, r7
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	/*
1668c2ecf20Sopenharmony_ci	 * make sure TLB contain the addr we want,
1678c2ecf20Sopenharmony_ci	 * as we will access them after MMDC IO floated.
1688c2ecf20Sopenharmony_ci	 */
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
1718c2ecf20Sopenharmony_ci	ldr	r6, [r11, #0x0]
1728c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
1738c2ecf20Sopenharmony_ci	ldr	r6, [r11, #0x0]
1748c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
1758c2ecf20Sopenharmony_ci	ldr	r6, [r11, #0x0]
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/* use r11 to store the IO address */
1788c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_SRC_V_OFFSET]
1798c2ecf20Sopenharmony_ci	/* store physical resume addr and pm_info address. */
1808c2ecf20Sopenharmony_ci	str	r9, [r11, #MX6Q_SRC_GPR1]
1818c2ecf20Sopenharmony_ci	str	r1, [r11, #MX6Q_SRC_GPR2]
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	/* need to sync L2 cache before DSM. */
1848c2ecf20Sopenharmony_ci	sync_l2_cache
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_MMDC_V_OFFSET]
1878c2ecf20Sopenharmony_ci	/*
1888c2ecf20Sopenharmony_ci	 * put DDR explicitly into self-refresh and
1898c2ecf20Sopenharmony_ci	 * disable automatic power savings.
1908c2ecf20Sopenharmony_ci	 */
1918c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
1928c2ecf20Sopenharmony_ci	orr	r7, r7, #0x1
1938c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_MMDC_MAPSR]
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	/* make the DDR explicitly enter self-refresh. */
1968c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
1978c2ecf20Sopenharmony_ci	orr	r7, r7, #(1 << 21)
1988c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_MMDC_MAPSR]
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cipoll_dvfs_set:
2018c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_MMDC_MAPSR]
2028c2ecf20Sopenharmony_ci	ands	r7, r7, #(1 << 25)
2038c2ecf20Sopenharmony_ci	beq	poll_dvfs_set
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_IOMUXC_V_OFFSET]
2068c2ecf20Sopenharmony_ci	ldr	r6, =0x0
2078c2ecf20Sopenharmony_ci	ldr	r7, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET]
2088c2ecf20Sopenharmony_ci	ldr	r8, =PM_INFO_MMDC_IO_VAL_OFFSET
2098c2ecf20Sopenharmony_ci	add	r8, r8, r0
2108c2ecf20Sopenharmony_ci	/* LPDDR2's last 3 IOs need special setting */
2118c2ecf20Sopenharmony_ci	cmp	r3, #IMX_DDR_TYPE_LPDDR2
2128c2ecf20Sopenharmony_ci	subeq	r7, r7, #0x3
2138c2ecf20Sopenharmony_ciset_mmdc_io_lpm:
2148c2ecf20Sopenharmony_ci	ldr	r9, [r8], #0x8
2158c2ecf20Sopenharmony_ci	str	r6, [r11, r9]
2168c2ecf20Sopenharmony_ci	subs	r7, r7, #0x1
2178c2ecf20Sopenharmony_ci	bne	set_mmdc_io_lpm
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	cmp 	r3, #IMX_DDR_TYPE_LPDDR2
2208c2ecf20Sopenharmony_ci	bne	set_mmdc_io_lpm_done
2218c2ecf20Sopenharmony_ci	ldr	r6, =0x1000
2228c2ecf20Sopenharmony_ci	ldr	r9, [r8], #0x8
2238c2ecf20Sopenharmony_ci	str	r6, [r11, r9]
2248c2ecf20Sopenharmony_ci	ldr	r9, [r8], #0x8
2258c2ecf20Sopenharmony_ci	str	r6, [r11, r9]
2268c2ecf20Sopenharmony_ci	ldr	r6, =0x80000
2278c2ecf20Sopenharmony_ci	ldr	r9, [r8]
2288c2ecf20Sopenharmony_ci	str	r6, [r11, r9]
2298c2ecf20Sopenharmony_ciset_mmdc_io_lpm_done:
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/*
2328c2ecf20Sopenharmony_ci	 * mask all GPC interrupts before
2338c2ecf20Sopenharmony_ci	 * enabling the RBC counters to
2348c2ecf20Sopenharmony_ci	 * avoid the counter starting too
2358c2ecf20Sopenharmony_ci	 * early if an interupt is already
2368c2ecf20Sopenharmony_ci	 * pending.
2378c2ecf20Sopenharmony_ci	 */
2388c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
2398c2ecf20Sopenharmony_ci	ldr	r6, [r11, #MX6Q_GPC_IMR1]
2408c2ecf20Sopenharmony_ci	ldr	r7, [r11, #MX6Q_GPC_IMR2]
2418c2ecf20Sopenharmony_ci	ldr	r8, [r11, #MX6Q_GPC_IMR3]
2428c2ecf20Sopenharmony_ci	ldr	r9, [r11, #MX6Q_GPC_IMR4]
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	ldr	r10, =0xffffffff
2458c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_GPC_IMR1]
2468c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_GPC_IMR2]
2478c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_GPC_IMR3]
2488c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_GPC_IMR4]
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	/*
2518c2ecf20Sopenharmony_ci	 * enable the RBC bypass counter here
2528c2ecf20Sopenharmony_ci	 * to hold off the interrupts. RBC counter
2538c2ecf20Sopenharmony_ci	 * = 32 (1ms), Minimum RBC delay should be
2548c2ecf20Sopenharmony_ci	 * 400us for the analog LDOs to power down.
2558c2ecf20Sopenharmony_ci	 */
2568c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_CCM_V_OFFSET]
2578c2ecf20Sopenharmony_ci	ldr	r10, [r11, #MX6Q_CCM_CCR]
2588c2ecf20Sopenharmony_ci	bic	r10, r10, #(0x3f << 21)
2598c2ecf20Sopenharmony_ci	orr	r10, r10, #(0x20 << 21)
2608c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_CCM_CCR]
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* enable the counter. */
2638c2ecf20Sopenharmony_ci	ldr	r10, [r11, #MX6Q_CCM_CCR]
2648c2ecf20Sopenharmony_ci	orr	r10, r10, #(0x1 << 27)
2658c2ecf20Sopenharmony_ci	str	r10, [r11, #MX6Q_CCM_CCR]
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	/* unmask all the GPC interrupts. */
2688c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_GPC_V_OFFSET]
2698c2ecf20Sopenharmony_ci	str	r6, [r11, #MX6Q_GPC_IMR1]
2708c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_GPC_IMR2]
2718c2ecf20Sopenharmony_ci	str	r8, [r11, #MX6Q_GPC_IMR3]
2728c2ecf20Sopenharmony_ci	str	r9, [r11, #MX6Q_GPC_IMR4]
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	/*
2758c2ecf20Sopenharmony_ci	 * now delay for a short while (3usec)
2768c2ecf20Sopenharmony_ci	 * ARM is at 1GHz at this point
2778c2ecf20Sopenharmony_ci	 * so a short loop should be enough.
2788c2ecf20Sopenharmony_ci	 * this delay is required to ensure that
2798c2ecf20Sopenharmony_ci	 * the RBC counter can start counting in
2808c2ecf20Sopenharmony_ci	 * case an interrupt is already pending
2818c2ecf20Sopenharmony_ci	 * or in case an interrupt arrives just
2828c2ecf20Sopenharmony_ci	 * as ARM is about to assert DSM_request.
2838c2ecf20Sopenharmony_ci	 */
2848c2ecf20Sopenharmony_ci	ldr	r6, =2000
2858c2ecf20Sopenharmony_cirbc_loop:
2868c2ecf20Sopenharmony_ci	subs	r6, r6, #0x1
2878c2ecf20Sopenharmony_ci	bne	rbc_loop
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	/* Zzz, enter stop mode */
2908c2ecf20Sopenharmony_ci	wfi
2918c2ecf20Sopenharmony_ci	nop
2928c2ecf20Sopenharmony_ci	nop
2938c2ecf20Sopenharmony_ci	nop
2948c2ecf20Sopenharmony_ci	nop
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/*
2978c2ecf20Sopenharmony_ci	 * run to here means there is pending
2988c2ecf20Sopenharmony_ci	 * wakeup source, system should auto
2998c2ecf20Sopenharmony_ci	 * resume, we need to restore MMDC IO first
3008c2ecf20Sopenharmony_ci	 */
3018c2ecf20Sopenharmony_ci	mov	r5, #0x0
3028c2ecf20Sopenharmony_ci	resume_mmdc
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	/* return to suspend finish */
3058c2ecf20Sopenharmony_ci	ret	lr
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ciresume:
3088c2ecf20Sopenharmony_ci	/* invalidate L1 I-cache first */
3098c2ecf20Sopenharmony_ci	mov     r6, #0x0
3108c2ecf20Sopenharmony_ci	mcr     p15, 0, r6, c7, c5, 0
3118c2ecf20Sopenharmony_ci	mcr     p15, 0, r6, c7, c5, 6
3128c2ecf20Sopenharmony_ci	/* enable the Icache and branch prediction */
3138c2ecf20Sopenharmony_ci	mov     r6, #0x1800
3148c2ecf20Sopenharmony_ci	mcr     p15, 0, r6, c1, c0, 0
3158c2ecf20Sopenharmony_ci	isb
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* get physical resume address from pm_info. */
3188c2ecf20Sopenharmony_ci	ldr	lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET]
3198c2ecf20Sopenharmony_ci	/* clear core0's entry and parameter */
3208c2ecf20Sopenharmony_ci	ldr	r11, [r0, #PM_INFO_MX6Q_SRC_P_OFFSET]
3218c2ecf20Sopenharmony_ci	mov	r7, #0x0
3228c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_SRC_GPR1]
3238c2ecf20Sopenharmony_ci	str	r7, [r11, #MX6Q_SRC_GPR2]
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	ldr	r3, [r0, #PM_INFO_DDR_TYPE_OFFSET]
3268c2ecf20Sopenharmony_ci	mov	r5, #0x1
3278c2ecf20Sopenharmony_ci	resume_mmdc
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	ret	lr
3308c2ecf20Sopenharmony_ciENDPROC(imx6_suspend)
331