| /* |
| * Copyright (C) 2016 Freescale Semiconductor, Inc. |
| * Copyright 2017 NXP |
| * |
| * The code contained herein is licensed under the GNU General Public |
| * License. You may obtain a copy of the GNU General Public License |
| * Version 2 or later at the following locations: |
| * |
| * http://www.opensource.org/licenses/gpl-license.html |
| * http://www.gnu.org/copyleft/gpl.html |
| */ |
| |
| #include <linux/linkage.h> |
| #include <asm/asm-offsets.h> |
| #include "hardware.h" |
| |
| /* |
| * ==================== low level suspend ==================== |
| * |
| * Better to follow below rules to use ARM registers: |
| * r0: pm_info structure address; |
| * |
| * suspend ocram space layout: |
| * ======================== high address ====================== |
| * . |
| * . |
| * . |
| * ^ |
| * ^ |
| * ^ |
| * imx7ulp_suspend code |
| * PM_INFO structure(imx7ulp_cpu_pm_info) |
| * ======================== low address ======================= |
| */ |
| |
| /* |
| * Below offsets are based on struct imx7ulp_cpu_pm_info |
| * which defined in arch/arm/mach-imx/pm-imx7ulp.c, this |
| * structure contains necessary pm info for low level |
| * suspend related code. |
| */ |
| #define PM_INFO_M4_RESERVE0_OFFSET 0x0 |
| #define PM_INFO_M4_RESERVE1_OFFSET 0x4 |
| #define PM_INFO_M4_RESERVE2_OFFSET 0x8 |
| #define PM_INFO_PBASE_OFFSET 0xc |
| #define PM_INFO_RESUME_ADDR_OFFSET 0x10 |
| #define PM_INFO_PM_INFO_SIZE_OFFSET 0x14 |
| #define PM_INFO_PM_INFO_SIM_VBASE_OFFSET 0x18 |
| #define PM_INFO_PM_INFO_SCG1_VBASE_OFFSET 0x1c |
| #define PM_INFO_PM_INFO_MMDC_VBASE_OFFSET 0x20 |
| #define PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET 0x24 |
| #define PM_INFO_PM_INFO_SMC1_VBASE_OFFSET 0x28 |
| #define PM_INFO_PM_INFO_SCG1_VAL_OFFSET 0x2c |
| #define PM_INFO_MX7ULP_TTBR1_V_OFFSET 0x70 |
| #define PM_INFO_MX7ULP_GPIO_REG_OFFSET 0x74 |
| #define PM_INFO_IOMUX_NUM_OFFSET 0x94 |
| #define PM_INFO_IOMUX_VAL_OFFSET 0x98 |
| #define PM_INFO_SELECT_INPUT_NUM_OFFSET 0x268 |
| #define PM_INFO_SELECT_INPUT_VAL_OFFSET 0x26c |
| #define PM_INFO_MMDC_IO_NUM_OFFSET 0x3a4 |
| #define PM_INFO_MMDC_IO_VAL_OFFSET 0x3a8 |
| /* below offsets depends on MX7ULP_MAX_MMDC_IO_NUM(36) definition */ |
| #define PM_INFO_MMDC_NUM_OFFSET 0x5a8 |
| #define PM_INFO_MMDC_VAL_OFFSET 0x5ac |
| |
| #define DGO_CTRL0 0x50 |
| #define DGO_GPR3 0x60 |
| #define DGO_GPR4 0x64 |
| |
| #define MX7ULP_MMDC_MISC 0x18 |
| #define MX7ULP_MMDC_MAPSR 0x404 |
| #define MX7ULP_MMDC_MPDGCTRL0 0x83c |
| |
| #define SCG_RCCR 0x14 |
| #define SCG_DDRCCR 0x30 |
| #define SCG_NICCCR 0x40 |
| #define SCG_FIRCDIV 0x304 |
| #define SCG_APLLCSR 0x500 |
| #define SCG_APLLDIV 0x504 |
| #define SCG_APLLCFG 0x508 |
| #define SCG_APLLPFD 0x50c |
| #define SCG_APLLNUM 0x510 |
| #define SCG_APLLDENOM 0x514 |
| #define SCG_SPLLCSR 0x600 |
| #define SCG_SPLLDIV 0x604 |
| #define SCG_SPLLCFG 0x608 |
| #define SCG_SPLLPFD 0x60c |
| #define SCG_SPLLNUM 0x610 |
| #define SCG_SPLLDENOM 0x614 |
| #define SCG_SOSCDIV 0x104 |
| |
| #define PMC1_CTRL 0x24 |
| |
| #define GPIO_PDOR 0x0 |
| #define GPIO_PDDR 0x14 |
| #define GPIO_PORT_NUM 0x4 |
| #define GPIO_PORT_OFFSET 0x40 |
| |
| #define PMCTRL 0x10 |
| |
| #define IOMUX_OFFSET 0x0 |
| #define SELECT_INPUT_OFFSET 0x200 |
| |
| .align 3 |
| |
| .macro store_ttbr1 |
| |
| /* Store TTBR1 to pm_info->ttbr1 */ |
| mrc p15, 0, r7, c2, c0, 1 |
| str r7, [r0, #PM_INFO_MX7ULP_TTBR1_V_OFFSET] |
| |
| /* Disable Branch Prediction, Z bit in SCTLR. */ |
| mrc p15, 0, r6, c1, c0, 0 |
| bic r6, r6, #0x800 |
| mcr p15, 0, r6, c1, c0, 0 |
| |
| /* Flush the BTAC. */ |
| ldr r6, =0x0 |
| mcr p15, 0, r6, c7, c1, 6 |
| |
| ldr r6, =iram_tlb_phys_addr |
| ldr r6, [r6] |
| dsb |
| isb |
| |
| /* Store the IRAM table in TTBR1 */ |
| mcr p15, 0, r6, c2, c0, 1 |
| /* Read TTBCR and set PD0=1, N = 1 */ |
| mrc p15, 0, r6, c2, c0, 2 |
| orr r6, r6, #0x11 |
| mcr p15, 0, r6, c2, c0, 2 |
| |
| dsb |
| isb |
| |
| /* flush the TLB */ |
| ldr r6, =0x0 |
| mcr p15, 0, r6, c8, c3, 0 |
| |
| .endm |
| |
| .macro restore_ttbr1 |
| |
| /* Enable L1 data cache. */ |
| mrc p15, 0, r6, c1, c0, 0 |
| orr r6, r6, #0x4 |
| mcr p15, 0, r6, c1, c0, 0 |
| |
| dsb |
| isb |
| |
| /* Restore TTBCR */ |
| /* Read TTBCR and set PD0=0, N = 0 */ |
| mrc p15, 0, r6, c2, c0, 2 |
| bic r6, r6, #0x11 |
| mcr p15, 0, r6, c2, c0, 2 |
| dsb |
| isb |
| |
| /* flush the TLB */ |
| ldr r6, =0x0 |
| mcr p15, 0, r6, c8, c3, 0 |
| |
| /* Enable Branch Prediction, Z bit in SCTLR. */ |
| mrc p15, 0, r6, c1, c0, 0 |
| orr r6, r6, #0x800 |
| mcr p15, 0, r6, c1, c0, 0 |
| |
| /* Flush the Branch Target Address Cache (BTAC) */ |
| ldr r6, =0x0 |
| mcr p15, 0, r6, c7, c1, 6 |
| |
| /* Restore TTBR1, get the origin ttbr1 from pm info */ |
| ldr r7, [r0, #PM_INFO_MX7ULP_TTBR1_V_OFFSET] |
| mcr p15, 0, r7, c2, c0, 1 |
| |
| .endm |
| |
| .macro disable_l1_dcache |
| |
| /* |
| * Flush all data from the L1 data cache before disabling |
| * SCTLR.C bit. |
| */ |
| push {r0 - r10, lr} |
| ldr r7, =v7_flush_dcache_all |
| mov lr, pc |
| mov pc, r7 |
| pop {r0 - r10, lr} |
| |
| /* disable d-cache */ |
| mrc p15, 0, r7, c1, c0, 0 |
| bic r7, r7, #(1 << 2) |
| mcr p15, 0, r7, c1, c0, 0 |
| dsb |
| isb |
| |
| push {r0 - r10, lr} |
| ldr r7, =v7_flush_dcache_all |
| mov lr, pc |
| mov pc, r7 |
| pop {r0 - r10, lr} |
| |
| .endm |
| |
| .macro restore_mmdc_settings |
| |
| ldr r10, =MX7ULP_MMDC_IO_BASE_ADDR |
| ldr r11, =MX7ULP_MMDC_BASE_ADDR |
| |
| /* resume mmdc iomuxc settings */ |
| ldr r6, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] |
| ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET |
| add r7, r7, r0 |
| 11: |
| ldr r8, [r7], #0x4 |
| ldr r9, [r7], #0x4 |
| str r9, [r10, r8] |
| subs r6, r6, #0x1 |
| bne 11b |
| |
| /* restore MMDC settings */ |
| ldr r6, [r0, #PM_INFO_MMDC_NUM_OFFSET] |
| ldr r7, =PM_INFO_MMDC_VAL_OFFSET |
| add r7, r7, r0 |
| 1: |
| ldr r8, [r7], #0x4 |
| ldr r9, [r7], #0x4 |
| str r9, [r11, r8] |
| subs r6, r6, #0x1 |
| bne 1b |
| |
| /* let DDR enter self-refresh */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| orr r7, r7, #(1 << 20) |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| 2: |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| ands r7, r7, #(1 << 24) |
| beq 2b |
| |
| /* let DDR out of self-refresh */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| bic r7, r7, #(1 << 20) |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| 3: |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| ands r7, r7, #(1 << 24) |
| bne 3b |
| |
| /* kick off MMDC */ |
| ldr r4, =0x0 |
| str r4, [r11, #0x1c] |
| |
| /* let DDR out of self-refresh */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| bic r7, r7, #(1 << 20) |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| 4: |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| ands r7, r7, #(1 << 24) |
| bne 4b |
| |
| /* enable DDR auto power saving */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| bic r7, r7, #0x1 |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| |
| .endm |
| |
| ENTRY(imx7ulp_suspend) |
| push {r4-r12} |
| |
| /* |
| * The value of r0 is mapped the same in origin table and IRAM table, |
| * thus no need to care r0 here. |
| */ |
| ldr r1, [r0, #PM_INFO_PBASE_OFFSET] |
| ldr r2, [r0, #PM_INFO_RESUME_ADDR_OFFSET] |
| ldr r3, [r0, #PM_INFO_PM_INFO_SIZE_OFFSET] |
| |
| /* |
| * counting the resume address in iram |
| * to set it in SRC register. |
| */ |
| ldr r6, =imx7ulp_suspend |
| ldr r7, =resume |
| sub r7, r7, r6 |
| add r8, r1, r3 |
| add r9, r8, r7 |
| |
| ldr r11, [r0, #PM_INFO_PM_INFO_SIM_VBASE_OFFSET] |
| /* store physical resume addr and pm_info address. */ |
| str r9, [r11, #DGO_GPR3] |
| str r1, [r11, #DGO_GPR4] |
| ldr r7, [r11, #DGO_CTRL0] |
| orr r7, r7, #0xc |
| str r7, [r11, #DGO_CTRL0] |
| wait_dgo: |
| ldr r7, [r11, #DGO_CTRL0] |
| and r7, r7, #0x18000 |
| cmp r7, #0x18000 |
| bne wait_dgo |
| |
| ldr r7, [r11, #DGO_CTRL0] |
| orr r7, r7, #0x18000 |
| bic r7, r7, #0xc |
| str r7, [r11, #DGO_CTRL0] |
| |
| disable_l1_dcache |
| |
| store_ttbr1 |
| |
| ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_VBASE_OFFSET] |
| |
| /* |
| * put DDR explicitly into self-refresh and |
| * disable automatic power savings. |
| */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| orr r7, r7, #0x1 |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| |
| /* make the DDR explicitly enter self-refresh. */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| orr r7, r7, #(1 << 20) |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| |
| poll_dvfs_set: |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| ands r7, r7, #(1 << 24) |
| beq poll_dvfs_set |
| |
| /* put mmdc io into lpm */ |
| ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET] |
| ldr r10, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] |
| ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET |
| add r7, r7, r0 |
| mmdc_io_lpm: |
| ldr r8, [r7], #0x8 |
| mov r9, #0x0 |
| str r9, [r11, r8] |
| subs r10, r10, #0x1 |
| bne mmdc_io_lpm |
| |
| /* switch NIC clock to FIRC */ |
| ldr r10, [r0, #PM_INFO_PM_INFO_SCG1_VBASE_OFFSET] |
| ldr r7, [r10, #SCG_NICCCR] |
| bic r7, #(1 << 28) |
| str r7, [r10, #SCG_NICCCR] |
| |
| /* switch RUN clock to FIRC */ |
| ldr r7, [r10, #SCG_RCCR] |
| bic r7, #(0xf << 24) |
| orr r7, #(0x3 << 24) |
| str r7, [r10, #SCG_RCCR] |
| |
| /* turn off SPLL and SPFD */ |
| ldr r7, [r10, #SCG_SPLLPFD] |
| mov r8, r7 |
| orr r7, r7, #(0x1 << 31) |
| orr r7, r7, #(0x1 << 23) |
| orr r7, r7, #(0x1 << 15) |
| orr r7, r7, #(0x1 << 7) |
| str r7, [r10, #SCG_SPLLPFD] |
| |
| ldr r7, [r10, #SCG_SPLLCSR] |
| bic r7, r7, #0x1 |
| str r7, [r10, #SCG_SPLLCSR] |
| |
| /* turn off APLL and APFD */ |
| ldr r7, [r10, #SCG_APLLPFD] |
| mov r9, r7 |
| orr r7, r7, #(0x1 << 31) |
| orr r7, r7, #(0x1 << 23) |
| orr r7, r7, #(0x1 << 15) |
| orr r7, r7, #(0x1 << 7) |
| str r7, [r10, #SCG_APLLPFD] |
| |
| ldr r7, [r10, #SCG_APLLCSR] |
| bic r7, r7, #0x1 |
| str r7, [r10, #SCG_APLLCSR] |
| |
| /* Zzz, enter stop mode */ |
| wfi |
| nop |
| nop |
| nop |
| nop |
| |
| /* clear core0's entry and parameter */ |
| ldr r10, [r0, #PM_INFO_PM_INFO_SIM_VBASE_OFFSET] |
| mov r7, #0x0 |
| str r7, [r10, #DGO_GPR3] |
| str r7, [r10, #DGO_GPR4] |
| |
| /* enable SPLL and SPFD */ |
| ldr r10, [r0, #PM_INFO_PM_INFO_SCG1_VBASE_OFFSET] |
| ldr r7, [r10, #SCG_SPLLCSR] |
| orr r7, r7, #1 |
| str r7, [r10, #SCG_SPLLCSR] |
| wait_spll: |
| ldr r7, [r10, #SCG_SPLLCSR] |
| ands r7, r7, #(1 << 24) |
| beq wait_spll |
| |
| str r8, [r10, #SCG_SPLLPFD] |
| /* switch RUN clock to SPLL */ |
| ldr r7, [r10, #SCG_RCCR] |
| bic r7, #(0xf << 24) |
| orr r7, #(0x6 << 24) |
| str r7, [r10, #SCG_RCCR] |
| |
| /* enable APLL and APFD */ |
| ldr r7, [r10, #SCG_APLLCSR] |
| orr r7, r7, #1 |
| str r7, [r10, #SCG_APLLCSR] |
| wait_apll: |
| ldr r7, [r10, #SCG_APLLCSR] |
| ands r7, r7, #(1 << 24) |
| beq wait_apll |
| |
| str r9, [r10, #SCG_APLLPFD] |
| |
| /* switch NIC clock to DDR */ |
| ldr r7, [r10, #SCG_NICCCR] |
| orr r7, #(1 << 28) |
| str r7, [r10, #SCG_NICCCR] |
| |
| /* let mmdc io out of lpm */ |
| ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_IO_VBASE_OFFSET] |
| ldr r10, [r0, #PM_INFO_MMDC_IO_NUM_OFFSET] |
| ldr r7, =PM_INFO_MMDC_IO_VAL_OFFSET |
| add r7, r7, r0 |
| mmdc_io_exit_lpm: |
| ldr r8, [r7], #0x4 |
| ldr r9, [r7], #0x4 |
| str r9, [r11, r8] |
| subs r10, r10, #0x1 |
| bne mmdc_io_exit_lpm |
| |
| /* let DDR out of self-refresh */ |
| ldr r11, [r0, #PM_INFO_PM_INFO_MMDC_VBASE_OFFSET] |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| bic r7, r7, #(1 << 20) |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| poll_dvfs_clear: |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| ands r7, r7, #(1 << 24) |
| bne poll_dvfs_clear |
| |
| /* enable DDR auto power saving */ |
| ldr r7, [r11, #MX7ULP_MMDC_MAPSR] |
| bic r7, r7, #0x1 |
| str r7, [r11, #MX7ULP_MMDC_MAPSR] |
| |
| restore_ttbr1 |
| pop {r4-r12} |
| /* return to suspend finish */ |
| mov pc, lr |
| |
| resume: |
| /* invalidate L1 I-cache first */ |
| mov r6, #0x0 |
| mcr p15, 0, r6, c7, c5, 0 |
| mcr p15, 0, r6, c7, c5, 6 |
| /* enable the Icache and branch prediction */ |
| mov r6, #0x1800 |
| mcr p15, 0, r6, c1, c0, 0 |
| isb |
| |
| ldr r6, =MX7ULP_SIM_BASE_ADDR |
| ldr r0, [r6, #DGO_GPR4] |
| /* get physical resume address from pm_info. */ |
| ldr lr, [r0, #PM_INFO_RESUME_ADDR_OFFSET] |
| |
| ldr r11, =MX7ULP_SCG1_BASE_ADDR |
| /* enable spll and pfd0 */ |
| ldr r5, =PM_INFO_PM_INFO_SCG1_VAL_OFFSET |
| add r6, r5, #48 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLCFG] |
| |
| add r6, r5, #56 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLNUM] |
| |
| add r6, r5, #60 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLDENOM] |
| |
| add r6, r5, #40 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLCSR] |
| 5: |
| ldr r7, [r11, #SCG_SPLLCSR] |
| ands r7, r7, #0x1000000 |
| beq 5b |
| |
| add r6, r5, #44 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLDIV] |
| |
| add r6, r5, #52 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SPLLPFD] |
| |
| add r6, r5, #0 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_RCCR] |
| |
| /* enable apll and pfd0 */ |
| add r6, r5, #24 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLCFG] |
| |
| add r6, r5, #32 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLNUM] |
| |
| add r6, r5, #36 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLDENOM] |
| |
| add r6, r5, #16 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLCSR] |
| 6: |
| ldr r7, [r11, #SCG_APLLCSR] |
| ands r7, r7, #0x1000000 |
| beq 6b |
| |
| add r6, r5, #20 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLDIV] |
| |
| add r6, r5, #28 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_APLLPFD] |
| |
| /* set ddr ccr */ |
| add r6, r5, #4 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_DDRCCR] |
| |
| /* set nic sel */ |
| add r6, r5, #8 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_NICCCR] |
| |
| /* set firc div2 to get 48MHz */ |
| add r6, r5, #12 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_FIRCDIV] |
| |
| /* restore system OSC div */ |
| add r6, r5, #64 |
| ldr r7, [r0, r6] |
| str r7, [r11, #SCG_SOSCDIV] |
| |
| /* enable mmdc clock in pcc3 */ |
| ldr r11, =MX7ULP_PCC3_BASE_ADDR |
| ldr r7, [r11, #0xac] |
| orr r7, r7, #(1 << 30) |
| str r7, [r11, #0xac] |
| |
| /* enable GPIO clock in pcc2 */ |
| ldr r11, =MX7ULP_PCC2_BASE_ADDR |
| ldr r7, [r11, #0x3c] |
| orr r7, r7, #(1 << 30) |
| str r7, [r11, #0x3c] |
| |
| /* restore gpio settings */ |
| ldr r10, =MX7ULP_GPIOC_BASE_ADDR |
| ldr r7, =PM_INFO_MX7ULP_GPIO_REG_OFFSET |
| add r7, r7, r0 |
| ldr r6, =GPIO_PORT_NUM |
| 12: |
| ldr r9, [r7], #0x4 |
| str r9, [r10, #GPIO_PDOR] |
| ldr r9, [r7], #0x4 |
| str r9, [r10, #GPIO_PDDR] |
| add r10, r10, #GPIO_PORT_OFFSET |
| subs r6, r6, #0x1 |
| bne 12b |
| |
| /* restore iomuxc settings */ |
| ldr r10, =MX7ULP_IOMUXC1_BASE_ADDR |
| add r10, r10, #IOMUX_OFFSET |
| ldr r6, [r0, #PM_INFO_IOMUX_NUM_OFFSET] |
| ldr r7, =PM_INFO_IOMUX_VAL_OFFSET |
| add r7, r7, r0 |
| 13: |
| ldr r9, [r7], #0x4 |
| str r9, [r10], #0x4 |
| subs r6, r6, #0x1 |
| bne 13b |
| |
| /* restore select input settings */ |
| ldr r10, =MX7ULP_IOMUXC1_BASE_ADDR |
| add r10, r10, #SELECT_INPUT_OFFSET |
| ldr r6, [r0, #PM_INFO_SELECT_INPUT_NUM_OFFSET] |
| ldr r7, =PM_INFO_SELECT_INPUT_VAL_OFFSET |
| add r7, r7, r0 |
| 14: |
| ldr r9, [r7], #0x4 |
| str r9, [r10], #0x4 |
| subs r6, r6, #0x1 |
| bne 14b |
| |
| /* isoack */ |
| ldr r6, =MX7ULP_PMC1_BASE_ADDR |
| ldr r7, [r6, #PMC1_CTRL] |
| orr r7, r7, #(1 << 14) |
| str r7, [r6, #PMC1_CTRL] |
| |
| restore_mmdc_settings |
| |
| mov pc, lr |
| ENDPROC(imx7ulp_suspend) |
| |
| ENTRY(imx7ulp_cpu_resume) |
| bl v7_invalidate_l1 |
| b cpu_resume |
| ENDPROC(imx7ulp_cpu_resume) |