777 lines
14 KiB
ArmAsm
777 lines
14 KiB
ArmAsm
/*
|
|
* Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the license, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in teh hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
|
|
#define PM_INFO_PM_INFO_SIZE_OFFSET 0x0
|
|
#define PM_INFO_TTBR_OFFSET 0x4
|
|
#define PM_INFO_MMDC_V_OFFSET 0x8
|
|
#define PM_INFO_IOMUXC_V_OFFSET 0xc
|
|
#define PM_INFO_CCM_V_OFFSET 0x10
|
|
#define PM_INFO_L2_V_OFFSET 0x14
|
|
#define PM_INFO_ANATOP_V_OFFSET 0x18
|
|
#define PM_INFO_IO_NUM_OFFSET 0x1c
|
|
#define PM_INFO_IO_VAL_OFFSET 0x20
|
|
|
|
#define MX6Q_MMDC_MAPSR 0x404
|
|
#define MX6Q_MMDC_MPDGCTRL0 0x83c
|
|
|
|
.global mx6sl_lpm_wfi_start
|
|
.global mx6sl_lpm_wfi_end
|
|
|
|
.macro pll_do_wait_lock
|
|
1:
|
|
ldr r7, [r10, r8]
|
|
ands r7, #0x80000000
|
|
beq 1b
|
|
|
|
.endm
|
|
|
|
.macro ccm_do_wait
|
|
2:
|
|
ldr r7, [r10, #0x48]
|
|
cmp r7, #0x0
|
|
bne 2b
|
|
|
|
.endm
|
|
|
|
.macro ccm_enter_idle
|
|
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
/*
|
|
* if in audio_bus_freq_mode, skip to
|
|
* audio_mode low power setting.
|
|
*/
|
|
cmp r1, #0x1
|
|
beq audio_mode
|
|
/*
|
|
* Now set DDR rate to 1MHz.
|
|
* DDR is from bypassed PLL2 on periph2_clk2 path.
|
|
* Set the periph2_clk2_podf to divide by 8.
|
|
*/
|
|
ldr r6, [r10, #0x14]
|
|
orr r6, r6, #0x07
|
|
str r6, [r10, #0x14]
|
|
|
|
/* Now set MMDC PODF to divide by 3. */
|
|
ldr r6, [r10, #0x14]
|
|
bic r6, r6, #0x38
|
|
orr r6, r6, #0x10
|
|
str r6, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
|
|
/* Set the AHB to 3MHz. AXI to 3MHz. */
|
|
ldr r6, [r10, #0x14]
|
|
/*r12 stores the origin AHB podf value */
|
|
mov r12, r6
|
|
orr r6, r6, #0x1c00
|
|
orr r6, r6, #0x70000
|
|
str r6, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
|
|
/* Now set ARM to 24MHz.
|
|
* Move ARM to be sourced from step_clk
|
|
* after setting step_clk to 24MHz.
|
|
*/
|
|
ldr r6, [r10, #0x0c]
|
|
bic r6, r6, #0x100
|
|
str r6, [r10, #0xc]
|
|
/*Now pll1_sw_clk to step_clk */
|
|
ldr r6, [r10, #0x0c]
|
|
orr r6, r6, #0x4
|
|
str r6, [r10, #0x0c]
|
|
|
|
/* Bypass PLL1 and power it down */
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
ldr r6, =(1 << 16)
|
|
orr r6, r6, #0x1000
|
|
str r6, [r10, #0x04]
|
|
|
|
/*
|
|
* Set the ARM PODF to divide by 8.
|
|
* IPG is at 1.5MHz here, we need ARM to
|
|
* run at the 12:5 ratio (WAIT mode issue).
|
|
*/
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
ldr r11, [r10, #0x10]
|
|
ldr r6, =0x07
|
|
str r6, [r10, #0x10]
|
|
|
|
ccm_do_wait
|
|
|
|
b ccm_idle_done
|
|
|
|
audio_mode:
|
|
/*
|
|
* MMDC is sourced from pll2_200M.
|
|
* Set the mmdc_podf to div by 8
|
|
*/
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
ldr r6, [r10, #0x14]
|
|
orr r6, r6, #0x38
|
|
str r6, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
|
|
/*
|
|
* ARM is sourced from pll2_pfd2_400M here.
|
|
* switch ARM to bypassed PLL1
|
|
*/
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
ldr r6, [r10, #0x0c]
|
|
bic r6, r6, #0x4
|
|
str r6, [r10, #0xc]
|
|
|
|
/*
|
|
* set the arm_podf to divide by 3
|
|
* as IPG is at 4MHz, we cannot run
|
|
* arm clk above 9.6MHz when system
|
|
* enter WAIT mode
|
|
*/
|
|
ldr r11, [r10, #0x10]
|
|
ldr r6, =0x2
|
|
str r6, [r10, #0x10]
|
|
|
|
ccm_do_wait
|
|
|
|
ccm_idle_done:
|
|
|
|
.endm
|
|
|
|
.macro ccm_exit_idle
|
|
|
|
/*
|
|
* If in audio_bus_freq_mode, skip to
|
|
* audio_mode ccm restore.
|
|
*/
|
|
cmp r1, #0x1
|
|
beq audio_ccm_restore
|
|
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
/* Power up PLL1 and un-bypass it. */
|
|
ldr r6, =(1 << 12)
|
|
str r6, [r10, #0x08]
|
|
|
|
/* Wait for PLL1 to relock */
|
|
ldr r8, =0x0
|
|
pll_do_wait_lock
|
|
|
|
ldr r6, =(1 << 16)
|
|
str r6, [r10, #0x08]
|
|
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
/* Set PLL1_sw_clk back to PLL1 */
|
|
ldr r6, [r10, #0x0c]
|
|
bic r6, r6, #0x4
|
|
str r6, [r10, #0x0c]
|
|
|
|
/* Restore AHB/AXI back */
|
|
str r12, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
|
|
/* restore mmdc back to 24MHz*/
|
|
ldr r6, [r10, #0x14]
|
|
bic r6, r6, #0x3f
|
|
str r6, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
b ccm_exit_done
|
|
|
|
audio_ccm_restore:
|
|
/* move arm clk back to pll2_pfd2_400M */
|
|
ldr r6, [r10, #0xc]
|
|
orr r6, r6, #0x4
|
|
str r6, [r10, #0xc]
|
|
|
|
/* restore mmdc podf */
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
ldr r6, [r10, #0x14]
|
|
bic r6, r6, #0x38
|
|
orr r6, #0x8
|
|
str r6, [r10, #0x14]
|
|
|
|
ccm_do_wait
|
|
|
|
ccm_exit_done:
|
|
|
|
.endm
|
|
|
|
.macro check_pll_state
|
|
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
/*
|
|
* Check whether any PLL is enabled, as only when
|
|
* there is no PLLs enabled, 2p5 can be off and
|
|
* only enable the weak one. PLL1 will be powered
|
|
* down late, so no need to check PLL1 state.
|
|
*/
|
|
|
|
/* sys PLL2 */
|
|
ldr r6, [r10, #0x30]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
/* usb PLL3 */
|
|
ldr r6, [r10, #0x10]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
/* audio PLL4 */
|
|
ldr r6, [r10, #0x70]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
/* video PLL5 */
|
|
ldr r6, [r10, #0xa0]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
/* enet PLL6 */
|
|
ldr r6, [r10, #0xe0]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
/* usb host PLL7 */
|
|
ldr r6, [r10, #0x20]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 1f
|
|
|
|
ldr r4, =0x1
|
|
b check_done
|
|
1:
|
|
ldr r4, =0x0
|
|
|
|
check_done:
|
|
.endm
|
|
|
|
.macro anatop_enter_idle
|
|
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
cmp r4, #0x0
|
|
beq anatop_enter_done
|
|
|
|
/* Disable 1p1 brown out. */
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
ldr r6, [r10, #0x110]
|
|
bic r6, r6, #0x2
|
|
str r6, [r10, #0x110]
|
|
/*
|
|
* Set the OSC bias current to -37.5%
|
|
* to drop the power on VDDHIGH.
|
|
*/
|
|
ldr r6, [r10, #0x150]
|
|
orr r6, r6, #0xc000
|
|
str r6, [r10, #0x150]
|
|
|
|
/*
|
|
* if the usb VBUS wakeup is enabled, skip
|
|
* disable main 2p5.
|
|
*/
|
|
cmp r2, #0x1
|
|
beq anatop_enter_done
|
|
|
|
/* Enable the week 2p5 */
|
|
ldr r6, [r10, #0x130]
|
|
orr r6, r6, #0x40000
|
|
str r6, [r10, #0x130]
|
|
|
|
/* Disable main 2p5. */
|
|
ldr r6, [r10, #0x130]
|
|
bic r6, r6, #0x1
|
|
str r6, [r10, #0x130]
|
|
|
|
/*
|
|
* Cannot diable regular bandgap
|
|
* in LDO-enable mode. The bandgap
|
|
* is required for ARM-LDO to regulate
|
|
* the voltage.
|
|
*/
|
|
ldr r6, [r10, #0x140]
|
|
and r6, r6, #0x1f
|
|
cmp r6, #0x1f
|
|
bne anatop_enter_done
|
|
|
|
/* Enable low power bandgap */
|
|
ldr r6, [r10, #0x260]
|
|
orr r6, r6, #0x20
|
|
str r6, [r10, #0x260]
|
|
|
|
/*
|
|
* Turn off the bias current
|
|
* from the regular bandgap.
|
|
*/
|
|
ldr r6, [r10, #0x260]
|
|
orr r6, r6, #0x80
|
|
str r6, [r10, #0x260]
|
|
|
|
/*
|
|
* Clear the REFTTOP+SELFBIASOFF,
|
|
* self_bais circuit of the band gap.
|
|
* Per RM, should be cleared when
|
|
* band gap is powered down.
|
|
*/
|
|
ldr r6, [r10, #0x150]
|
|
bic r6, r6, #0x8
|
|
str r6, [r10, #0x150]
|
|
|
|
/* Power down the regular bandgap */
|
|
ldr r6, [r10, #0x150]
|
|
orr r6, r6, #0x1
|
|
str r6, [r10, #0x150]
|
|
anatop_enter_done:
|
|
|
|
.endm
|
|
|
|
.macro anatop_exit_idle
|
|
|
|
ldr r10, [r0, #PM_INFO_ANATOP_V_OFFSET]
|
|
cmp r4, #0x0
|
|
beq skip_anatop_restore
|
|
|
|
cmp r2, #0x1
|
|
beq ldo2p5_not_disabled
|
|
/*
|
|
* Regular bandgap will not be disabled
|
|
* in LDO-enabled mode as it is required
|
|
* for ARM-LDO to reguulate the voltage.
|
|
*/
|
|
ldr r6, [r10, #0x140]
|
|
and r6, r6, #0x1f
|
|
cmp r6, #0x1f
|
|
bne skip_bandgap_restore
|
|
|
|
/* Power up the regular bandgap */
|
|
ldr r6, [r10, #0x150]
|
|
bic r6, r6, #0x1
|
|
str r6, [r10, #0x150]
|
|
|
|
/* wait for bandgap stable */
|
|
3:
|
|
ldr r6, [r10, #0x150]
|
|
and r6, r6, #0x80
|
|
cmp r6, #0x80
|
|
bne 3b
|
|
|
|
/* now disable bandgap self-bias circuit */
|
|
ldr r6, [r10, #0x150]
|
|
orr r6, r6, #0x8
|
|
str r6, [r10, #0x150]
|
|
|
|
/* Turn on the bias current
|
|
* from the regular bandgap.
|
|
*/
|
|
ldr r6, [r10, #0x260]
|
|
bic r6, r6, #0x80
|
|
str r6, [r10, #0x260]
|
|
|
|
/* Disable the low power bandgap */
|
|
ldr r6, [r10, #0x260]
|
|
bic r6, r6, #0x20
|
|
str r6, [r10, #0x260]
|
|
|
|
skip_bandgap_restore:
|
|
/* Enable main 2p5. */
|
|
ldr r6, [r10, #0x130]
|
|
orr r6, r6, #0x1
|
|
str r6, [r10, #0x130]
|
|
|
|
/* Ensure the 2p5 is up */
|
|
5:
|
|
ldr r6, [r10, #0x130]
|
|
and r6, r6, #0x20000
|
|
cmp r6, #0x20000
|
|
bne 5b
|
|
|
|
/* Disable the weak 2p5 */
|
|
ldr r6, [r10, #0x130]
|
|
bic r6, r6, #0x40000
|
|
str r6, [r10, #0x130]
|
|
|
|
ldo2p5_not_disabled:
|
|
/*
|
|
* Set the OSC bias current to max
|
|
* value for normal operation.
|
|
*/
|
|
ldr r6, [r10, #0x150]
|
|
bic r6, r6, #0xc000
|
|
str r6, [r10, #0x150]
|
|
|
|
/* Enable 1p1 brown out, */
|
|
ldr r6, [r10, #0x110]
|
|
orr r6, r6, #0x2
|
|
str r6, [r10, #0x110]
|
|
|
|
skip_anatop_restore:
|
|
|
|
.endm
|
|
|
|
.macro disable_l1_dcache
|
|
|
|
/* disable d-cache */
|
|
mrc p15, 0, r7, c1, c0, 0
|
|
bic r7, r7, #(1 << 2)
|
|
mcr p15, 0, r7, c1, c0, 0
|
|
|
|
dsb
|
|
isb
|
|
|
|
.endm
|
|
|
|
.macro mmdc_enter_dvfs_mode
|
|
|
|
/* disable automatic power saving. */
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
orr r7, r7, #0x1
|
|
str r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
|
|
/* disable power down timer */
|
|
ldr r7, [r10, #0x04]
|
|
bic r7, r7, #0xff00
|
|
str r7, [r10, #0x04]
|
|
|
|
/* Make the DDR explicitly enter self-refresh. */
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
orr r7, r7, #(1 << 21)
|
|
str r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
|
|
poll_dvfs_set:
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
ands r7, r7, #(1 << 25)
|
|
beq poll_dvfs_set
|
|
|
|
/* set SBS step-by step mode */
|
|
ldr r7, [r10, #0x410]
|
|
orr r7, r7, #0x100
|
|
str r7, [r10, #0x410]
|
|
|
|
.endm
|
|
|
|
.macro resume_mmdc
|
|
/* restore MMDC IO */
|
|
ldr r10, [r0, #PM_INFO_IOMUXC_V_OFFSET]
|
|
|
|
ldr r6, [r0, #PM_INFO_IO_NUM_OFFSET]
|
|
ldr r7, =PM_INFO_IO_VAL_OFFSET
|
|
add r7, r7, r0
|
|
6:
|
|
ldr r8, [r7], #0x4
|
|
ldr r9, [r7], #0x4
|
|
str r9, [r10, r8]
|
|
subs r6, r6, #0x1
|
|
bne 6b
|
|
|
|
/*
|
|
* Need to reset the FIFO to avoid MMDC lockup
|
|
* caused because of floating/changing the
|
|
* configuration of many DDR IO pads.
|
|
*/
|
|
ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
|
|
/* reset read FIFO, RST_RD_FIFO */
|
|
ldr r7, =MX6Q_MMDC_MPDGCTRL0
|
|
ldr r6, [r10, r7]
|
|
orr r6, r6, #(1 << 31)
|
|
str r6, [r10, r7]
|
|
7:
|
|
ldr r6, [r10, r7]
|
|
ands r6, r6, #(1 << 31)
|
|
bne 7b
|
|
|
|
/* reset FIFO a second time */
|
|
ldr r7, =MX6Q_MMDC_MPDGCTRL0
|
|
ldr r6, [r10, r7]
|
|
orr r6, r6, #(1 << 31)
|
|
str r6, [r10, r7]
|
|
8:
|
|
ldr r6, [r10, r7]
|
|
ands r6, r6, #(1 <<31)
|
|
bne 8b
|
|
|
|
ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
|
|
/* Let DDR out of self-refresh */
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
bic r7, r7, #(1 << 21)
|
|
str r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
9:
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
ands r7, r7, #(1 << 25)
|
|
bne 9b
|
|
|
|
/* enable power down timer */
|
|
ldr r7, [r10, #0x04]
|
|
orr r7, r7, #0x5500
|
|
str r7, [r10, #0x04]
|
|
|
|
/* enable DDR auto power saving */
|
|
ldr r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
bic r7, r7, #0x1
|
|
str r7, [r10, #MX6Q_MMDC_MAPSR]
|
|
|
|
/* Clear SBS - unblock DDR accesses */
|
|
ldr r7, [r10, #0x410]
|
|
bic r7, r7, #0x100
|
|
str r7, [r10, #0x410]
|
|
|
|
.endm
|
|
|
|
.macro tlb_set_to_ocram
|
|
|
|
/* save ttbr */
|
|
mrc p15, 0, r7, c2, c0, 1
|
|
str r7, [r0, #PM_INFO_TTBR_OFFSET]
|
|
|
|
/*
|
|
* To ensure no page table walks occur in DDR, we
|
|
* have a another page table stored in IRAM that only
|
|
* contains entries pointing to IRAM, AIPS1 and AIPS2.
|
|
* we need to set the TTBR1 to the new IRAM TLB.
|
|
* Do the following steps:
|
|
* 1. Flush the Branch Target Address Cache (BTAC)
|
|
* 2. Set TTBR1 to point to the IRAM page table.
|
|
* 3. Disable page table walks in TTBR0 (PD0 = 1)
|
|
* 4. Set TTBR0.N=1, implying 0-2G is transslated by TTBR0
|
|
* and 2-4G is translated by TTBR1.
|
|
*/
|
|
|
|
ldr r6, =iram_tlb_phys_addr
|
|
ldr r7, [r6]
|
|
|
|
/* 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
|
|
|
|
dsb
|
|
isb
|
|
|
|
/* store the IRAM table in TTBR1 */
|
|
mcr p15, 0, r7, 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 tlb_back_to_ddr
|
|
|
|
/* Restore the TTBCR */
|
|
dsb
|
|
isb
|
|
|
|
/* 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
|
|
/* Flush the TLB */
|
|
ldr r6, =0x0
|
|
mcr p15, 0, r6, c8, c3, 0
|
|
|
|
dsb
|
|
isb
|
|
|
|
/* 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 ttbr */
|
|
ldr r7, [r0, #PM_INFO_TTBR_OFFSET]
|
|
mcr p15, 0, r7, c2, c0, 1
|
|
|
|
.endm
|
|
|
|
.extern iram_tlb_phys_addr
|
|
|
|
/*
|
|
* imx6sl_low_power_wfi code
|
|
* r0: wfi code base address
|
|
* r1: audio_bus_freq mode stat
|
|
* r2: vbus_ldo status
|
|
* r4: used for store the PLLs state
|
|
* r11: used for saving the ARM_PODF origin value
|
|
* r12: used for saving AHB_PODF origin value
|
|
*/
|
|
.align 3
|
|
ENTRY(imx6sl_low_power_idle)
|
|
|
|
mx6sl_lpm_wfi_start:
|
|
push {r4-r12}
|
|
|
|
tlb_set_to_ocram
|
|
disable_l1_dcache
|
|
|
|
#ifdef CONFIG_CACHE_L2X0
|
|
/* sync L2 */
|
|
ldr r10, [r0, #PM_INFO_L2_V_OFFSET]
|
|
/* Wait for background operations to complete. */
|
|
wait_for_l2_idle:
|
|
ldr r6, [r10, #0x730]
|
|
cmp r6, #0x0
|
|
bne wait_for_l2_idle
|
|
|
|
mov r6, #0x0
|
|
str r6, [r10, #0x730]
|
|
/* disable L2 */
|
|
str r6, [r10, #0x100]
|
|
|
|
dsb
|
|
isb
|
|
#endif
|
|
|
|
/* make sure MMDC in self-refresh */
|
|
ldr r10, [r0, #PM_INFO_MMDC_V_OFFSET]
|
|
mmdc_enter_dvfs_mode
|
|
/* save DDR IO settings and set to LPM mode*/
|
|
ldr r10, [r0, #PM_INFO_IOMUXC_V_OFFSET]
|
|
ldr r6, =0x0
|
|
ldr r7, [r0, #PM_INFO_IO_NUM_OFFSET]
|
|
ldr r8, =PM_INFO_IO_VAL_OFFSET
|
|
add r8, r8, r0
|
|
|
|
/* imx6sl's last 3 IOs need special setting */
|
|
sub r7, r7, #0x3
|
|
save_and_set_mmdc_io_lpm:
|
|
ldr r9, [r8], #0x4
|
|
ldr r5, [r10, r9]
|
|
str r6, [r10, r9]
|
|
str r5, [r8], #0x4
|
|
subs r7, r7, #0x1
|
|
bne save_and_set_mmdc_io_lpm
|
|
ldr r6, =0x1000
|
|
ldr r9, [r8], #0x4
|
|
ldr r5, [r10, r9]
|
|
str r5, [r8], #0x4
|
|
str r6, [r10, r9]
|
|
ldr r9, [r8], #0x4
|
|
ldr r5, [r10, r9]
|
|
str r6, [r10, r9]
|
|
str r5, [r8], #0x4
|
|
ldr r6, =0x80000
|
|
ldr r9, [r8], #0x4
|
|
ldr r5, [r10, r9]
|
|
str r6, [r10, r9]
|
|
str r5, [r8], #0x4
|
|
|
|
|
|
/* check the PLLs lock state */
|
|
check_pll_state
|
|
|
|
ccm_enter_idle
|
|
/* if in audio low power mode, no
|
|
* need to do anatop setting.
|
|
*/
|
|
cmp r1, #0x1
|
|
beq do_wfi
|
|
anatop_enter_idle
|
|
do_wfi:
|
|
wfi
|
|
/*
|
|
* Add these nops so that the
|
|
* prefetcher will not try to get
|
|
* any instrutions from DDR.
|
|
* The prefetch depth is about 23
|
|
* on A9, so adding 25 nops.
|
|
*/
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
nop
|
|
|
|
/*
|
|
* restore the ARM PODF first to speed
|
|
* up the restore procedure
|
|
*/
|
|
ldr r10, [r0, #PM_INFO_CCM_V_OFFSET]
|
|
/* Restore arm_clk_podf */
|
|
str r11, [r10, #0x10]
|
|
ccm_do_wait
|
|
|
|
/*
|
|
* if in audio low power mode, skip
|
|
* restore the anatop setting.
|
|
*/
|
|
cmp r1, #0x1
|
|
beq skip_analog_restore
|
|
anatop_exit_idle
|
|
|
|
skip_analog_restore:
|
|
ccm_exit_idle
|
|
resume_mmdc
|
|
|
|
/* enable d-cache */
|
|
mrc p15, 0, r7, c1, c0, 0
|
|
orr r7, r7, #(1 << 2)
|
|
mcr p15, 0, r7, c1, c0, 0
|
|
|
|
#ifdef CONFIG_CACHE_L2X0
|
|
ldr r10, [r0, #PM_INFO_L2_V_OFFSET]
|
|
mov r7, #0x1
|
|
/* enable L2 */
|
|
str r7, [r10, #0x100]
|
|
#endif
|
|
tlb_back_to_ddr
|
|
|
|
/* Restore register */
|
|
pop {r4 - r12}
|
|
mov pc, lr
|
|
|
|
/*
|
|
* Add ltorg here to ensure that all
|
|
* literals are stored here and are
|
|
* within the text space.
|
|
*/
|
|
.ltorg
|
|
mx6sl_lpm_wfi_end:
|