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