diff options
author | root <root@artemis.panaceas.org> | 2015-12-25 04:40:36 +0000 |
---|---|---|
committer | root <root@artemis.panaceas.org> | 2015-12-25 04:40:36 +0000 |
commit | 849369d6c66d3054688672f97d31fceb8e8230fb (patch) | |
tree | 6135abc790ca67dedbe07c39806591e70eda81ce /arch/arm/mach-mx6/mx6_suspend.S | |
download | linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.tar.gz linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.tar.bz2 linux-3.0.35-kobo-849369d6c66d3054688672f97d31fceb8e8230fb.zip |
initial_commit
Diffstat (limited to 'arch/arm/mach-mx6/mx6_suspend.S')
-rw-r--r-- | arch/arm/mach-mx6/mx6_suspend.S | 1713 |
1 files changed, 1713 insertions, 0 deletions
diff --git a/arch/arm/mach-mx6/mx6_suspend.S b/arch/arm/mach-mx6/mx6_suspend.S new file mode 100644 index 00000000..30388ead --- /dev/null +++ b/arch/arm/mach-mx6/mx6_suspend.S @@ -0,0 +1,1713 @@ +/* + * Copyright (C) 2010-2012 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 the 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. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <linux/linkage.h> +#include <mach/hardware.h> +#include <asm/memory.h> +#include <asm/hardware/cache-l2x0.h> +#include "src-reg.h" + +#define ARM_CTRL_DCACHE (1 << 2) +#define ARM_CTRL_ICACHE (1 << 12) +#define ARM_AUXCR_L2EN (1 << 1) +#define TTRBIT_MASK 0xffffc000 +#define TABLE_INDEX_MASK 0xfff00000 +#define TABLE_ENTRY 0x00000c02 +#define CACHE_DISABLE_MASK 0xfffffffb +#define MMDC_MAPSR_OFFSET 0x404 +#define MMDC_MAPSR_PSS (1 << 4) +#define MMDC_MAPSR_PSD (1 << 0) +/* + * The code size is limited to 5K, as we may need to store + * this code * along with the low power WFI and DDR freq + * change code within 8K of IRAM. + */ +#define IRAM_SUSPEND_SIZE MX6_SUSPEND_CODE_SIZE + +.extern iram_tlb_phys_addr +.extern suspend_iram_base +.extern suspend_iram_phys_addr + +/************************************************************* +mx6_suspend: + +Suspend the processor (eg, wait for interrupt). +Set the DDR into Self Refresh +IRQs are already disabled. + +The following code contain both standby and +dormant mode for MX6, decided by the parameter +passed in r0: +see define in include/linux/suspend.h +1 -> cpu enter stop mode; +3 -> cpu enter dormant mode. +r1: iram_paddr +r2: suspend_iram_base +*************************************************************/ + .macro mx6sl_standy_saving_set + + /* Move periph_clk to OSC_CLK. */ + ldr r1, =CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* Ensure the periph_clk2_sel to OSC clk. */ + ldr r0, [r1, #0x18] + bic r0, r0, #0x3000 + orr r0, r0, #0x1000 + str r0, [r1, #0x18] + + ldr r0, [r1, #0x14] + orr r0, r0, #0x2000000 + str r0, [r1, #0x14] + +periph_clk_switch: + ldr r0, [r1, #0x48] + cmp r0, #0 + bne periph_clk_switch + + /* Set the divider to divider by 8 */ + ldr r0, [r1, #0x14] + orr r0, r0, #0x70000 + orr r0, r0, #0x1c00 + str r0, [r1, #0x14] + +ahb_podf: + ldr r0, [r1, #0x48] + cmp r0, #0 + bne ahb_podf + + /* Move DDR clk to PLL3 clock. + */ + /* First set the divider to 2. */ + ldr r0, [r1, #0x14] + orr r0, r0, #0x1 + str r0, [r1, #0x14] + + ldr r0, [r1, #0x18] + bic r0, r0, #0x100000 + str r0, [r1, #0x18] + + ldr r0, [r1, #0x14] + orr r0, r0, #0x4000000 + str r0, [r1, #0x14] + +ddr_switch: + ldr r0, [r1, #0x48] + cmp r0, #0 + bne ddr_switch + + /* Set DDR clock to divide by 8. */ + ldr r0, [r1, #0x14] + orr r0, r0, #0x38 + str r0, [r1, #0x14] + +mmdc_div: + ldr r0, [r1, #0x48] + cmp r0, #0 + bne mmdc_div + + /* Now Switch ARM to run from + * step_clk sourced from OSC. + */ + ldr r0, [r1, #0xc] + bic r0, r1, #0x100 + str r0, [r1, #0x0c] + + /* Now switch PLL1_SW_CLK to step_clk. */ + ldr r0, [r1, #0x0c] + orr r0, r0, #0x4 + str r0, [r1, #0x0c] + + ldr r1, =ANATOP_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* Need to clock gate the 528 PFDs before + * powering down PLL2. + * Only the PLL2_PFD2_400M should be ON + * as it feeds the MMDC/AHB + */ + ldr r0, [r1, #0x100] + orr r0, r0, #0x800000 + str r0, [r1, #0x100] + + /* Now bypass PLL1 and PLL2. */ + ldr r0, =0x10000 + str r0, [r1, #0x4] + str r0, [r1, #0x34] + + /* Now do all the analog savings. */ + + /* Disable 1p1 brown out. */ + ldr r0, [r1, #0x110] + bic r0, r0, #0x2 + str r0, [r1, #0x110] + + /* Enable the weak 2P5 */ + ldr r0, [r1, #0x130] + orr r0, r0, #0x40000 + str r0, [r1, #0x130] + + /*Disable main 2p5. */ + ldr r0, [r1, #0x130] + bic r0, r0, #0x1 + str r0, [r1, #0x130] + + + /* Set the OSC bias current to -37.5% + * to drop the power on VDDHIGH. + */ + ldr r0, [r1, #0x150] + orr r0, r0, #0xC000 + str r0, [r1, #0x150] + .endm + + .macro mx6sl_standby_savings_restore + + /* Set the OSC bias current to max + * value for normal operation. + */ + ldr r6, [r1, #0x150] + bic r6, r6, #0xC000 + str r6, [r1, #0x150] + + /*Enable main 2p5. */ + ldr r6, [r1, #0x130] + orr r6, r6, #0x1 + str r6, [r1, #0x130] + + /* Ensure the 2P5 is up. */ +loop_2p5: + ldr r6, [r1, #0x130] + and r6, r6, #0x20000 + cmp r6, #0x20000 + bne loop_2p5 + + /* Disable the weak 2P5 */ + ldr r6, [r1, #0x130] + bic r6, r6, #0x40000 + str r6, [r1, #0x130] + + /* Enable 1p1 brown out. */ + ldr r6, [r1, #0x110] + orr r6, r6, #0x2 + str r6, [r1, #0x110] + + /* Unbypass PLLs and + * wait for relock. + */ + ldr r6, =(1 << 16) + str r6, [r1, #0x08] + str r6, [r1, #0x38] + +wait_for_pll_lock: + ldr r6, [r1, #0x0] + and r6, r6, #0x80000000 + cmp r6, #0x80000000 + bne wait_for_pll_lock + +wait_for_pll2_lock: + ldr r6, [r1, #0x30] + and r6, r6, #0x80000000 + cmp r6, #0x80000000 + bne wait_for_pll2_lock + + /* Set PLL1_sw_clk back to PLL1. */ + ldr r6, [r3, #0x0c] + bic r6, r6, #0x4 + str r6, [r3, #0xc] + + /* Need to enable the 528 PFDs after + * powering up PLL2. + * Only the PLL2_PFD2_400M should be ON + * as it feeds the MMDC. Rest should have + * been managed by clock code. + */ + ldr r6, [r1, #0x100] + bic r6, r6, #0x800000 + str r6, [r1, #0x100] + + /* Move periph_clk back + * to PLL2_PFD2_400. + */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x2000000 + str r6, [r3, #0x14] + +periph_clk_switch1: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne periph_clk_switch1 + + /* Set the dividers to default value. */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x70000 + bic r6, r6, #0x1c00 + orr r6, r6, #0x10800 + str r6, [r3, #0x14] + +ahb_podf1: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne ahb_podf1 + + /* Move MMDC back to PLL2_PFD2_400 */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x4000000 + str r6, [r3, #0x14] + +mmdc_loop2: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne mmdc_loop2 + + /* Set DDR clock to divide by 1. */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x38 + str r6, [r3, #0x14] + +mmdc_div1: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne mmdc_div1 + + .endm + + .macro mx6sl_standby_pg_savings_restore + + /* Set the OSC bias current to max + * value for normal operation. + */ + ldr r6, [r1, #0x150] + bic r6, r6, #0xC000 + str r6, [r1, #0x150] + + /*Enable main 2p5. */ + ldr r6, [r1, #0x130] + orr r6, r6, #0x1 + str r6, [r1, #0x130] + + /* Ensure the 2P5 is up. */ +loop_2p5_1: + ldr r6, [r1, #0x130] + and r6, r6, #0x20000 + cmp r6, #0x20000 + bne loop_2p5_1 + + /* Disable the weak 2P5 */ + ldr r6, [r1, #0x130] + bic r6, r6, #0x40000 + str r6, [r1, #0x130] + + /* Enable 1p1 brown out. */ + ldr r6, [r1, #0x110] + orr r6, r6, #0x2 + str r6, [r1, #0x110] + + /* Unbypass PLLs and + * wait for relock. + */ + ldr r6, =(1 << 16) + str r6, [r1, #0x08] + str r6, [r1, #0x38] + +wait_for_pll_lock1: + ldr r6, [r1, #0x0] + and r6, r6, #0x80000000 + cmp r6, #0x80000000 + bne wait_for_pll_lock1 + + /* Set PLL1_sw_clk back to PLL1. */ + ldr r6, [r3, #0x0c] + bic r6, r6, #0x4 + str r6, [r3, #0xc] + + /* Need to enable the 528 PFDs after + * powering up PLL2. + * Only the PLL2_PFD2_400M should be ON + * as it feeds the MMDC. Rest should have + * been managed by clock code. + */ + ldr r6, [r1, #0x100] + bic r6, r6, #0x800000 + str r6, [r1, #0x100] + + /* Move DDR clock back to PLL2_PFD2_400 */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x4000000 + str r6, [r3, #0x14] + +mmdc_loop3: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne mmdc_loop3 + + /* Set DDR clock to divide by 1. */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x38 + str r6, [r3, #0x14] + +mmdc_div2: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne mmdc_div2 + + /* Move periph_clk back + * to PLL2_PFD2_400. + */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x2000000 + str r6, [r3, #0x14] + +periph_clk_switch2: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne periph_clk_switch2 + + /* Set the dividers to default value. */ + ldr r6, [r3, #0x14] + bic r6, r6, #0x70000 + bic r6, r6, #0x1c00 + orr r6, r6, #0x10800 + str r6, [r3, #0x14] + +ahb_podf2: + ldr r6, [r3, #0x48] + cmp r6, #0 + bne ahb_podf2 + + .endm + + .macro sl_ddr_io_save + + ldr r4, [r1, #0x30c] /* DRAM_DQM0 */ + ldr r5, [r1, #0x310] /* DRAM_DQM1 */ + ldr r6, [r1, #0x314] /* DRAM_DQM2 */ + ldr r7, [r1, #0x318] /* DRAM_DQM3 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x5c4] /* GPR_B0DS */ + ldr r5, [r1, #0x5cc] /* GPR_B1DS */ + ldr r6, [r1, #0x5d4] /* GPR_B2DS */ + ldr r7, [r1, #0x5d8] /* GPR_B3DS */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x300] /* DRAM_CAS */ + ldr r5, [r1, #0x31c] /* DRAM_RAS */ + ldr r6, [r1, #0x338] /* DRAM_SDCLK_0 */ + ldr r7, [r1, #0x5ac] /* GPR_ADDS*/ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x5b0] /* DDRMODE_CTL */ + ldr r5, [r1, #0x5c0] /* DDRMODE */ + ldr r6, [r1, #0x33c] /* DRAM_SODT0*/ + ldr r7, [r1, #0x340] /* DRAM_SODT1*/ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x330] /* DRAM_SDCKE0 */ + ldr r5, [r1, #0x334] /* DRAM_SDCKE1 */ + ldr r6, [r1, #0x320] /* DRAM_RESET */ + stmfd r0!, {r4-r6} + + .endm + + .macro sl_ddr_io_restore + + ldmea r0!, {r4-r7} + str r4, [r1, #0x30c] /* DRAM_DQM0 */ + str r5, [r1, #0x310] /* DRAM_DQM1 */ + str r6, [r1, #0x314] /* DRAM_DQM2 */ + str r7, [r1, #0x318] /* DRAM_DQM3 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x5c4] /* GPR_B0DS */ + str r5, [r1, #0x5cc] /* GPR_B1DS */ + str r6, [r1, #0x5d4] /* GPR_B2DS */ + str r7, [r1, #0x5d8] /* GPR_B3DS */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x300] /* DRAM_CAS */ + str r5, [r1, #0x31c] /* DRAM_RAS */ + str r6, [r1, #0x338] /* DRAM_SDCLK_0 */ + str r7, [r1, #0x5ac] /* GPR_ADDS*/ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x5b0] /* DDRMODE_CTL */ + str r5, [r1, #0x5c0] /* DDRMODE */ + str r6, [r1, #0x33c] /* DRAM_SODT0*/ + str r7, [r1, #0x340] /* DRAM_SODT1*/ + + ldmea r0!, {r4-r6} + str r4, [r1, #0x330] /* DRAM_SDCKE0 */ + str r5, [r1, #0x334] /* DRAM_SDCKE1 */ + str r6, [r1, #0x320] /* DRAM_RESET */ + + .endm + + .macro sl_ddr_io_set_lpm + + mov r0, #0 + str r0, [r1, #0x30c] /* DRAM_DQM0 */ + str r0, [r1, #0x310] /* DRAM_DQM1 */ + str r0, [r1, #0x314] /* DRAM_DQM2 */ + str r0, [r1, #0x318] /* DRAM_DQM3 */ + + str r0, [r1, #0x5c4] /* GPR_B0DS */ + str r0, [r1, #0x5cc] /* GPR_B1DS */ + str r0, [r1, #0x5d4] /* GPR_B2DS */ + str r0, [r1, #0x5d8] /* GPR_B3DS */ + + str r0, [r1, #0x300] /* DRAM_CAS */ + str r0, [r1, #0x31c] /* DRAM_RAS */ + str r0, [r1, #0x338] /* DRAM_SDCLK_0 */ + str r0, [r1, #0x5ac] /* GPR_ADDS*/ + + str r0, [r1, #0x5b0] /* DDRMODE_CTL */ + str r0, [r1, #0x5c0] /* DDRMODE */ + str r0, [r1, #0x33c] /* DRAM_SODT0*/ + str r0, [r1, #0x340] /* DRAM_SODT1*/ + + mov r0, #0x80000 + str r0, [r1, #0x320] /* DRAM_RESET */ + mov r0, #0x1000 + str r0, [r1, #0x330] /* DRAM_SDCKE0 */ + str r0, [r1, #0x334] /* DRAM_SDCKE1 */ + + .endm + + .macro dl_ddr_io_save + + ldr r4, [r1, #0x470] /* DRAM_DQM0 */ + ldr r5, [r1, #0x474] /* DRAM_DQM1 */ + ldr r6, [r1, #0x478] /* DRAM_DQM2 */ + ldr r7, [r1, #0x47c] /* DRAM_DQM3 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x480] /* DRAM_DQM4 */ + ldr r5, [r1, #0x484] /* DRAM_DQM5 */ + ldr r6, [r1, #0x488] /* DRAM_DQM6 */ + ldr r7, [r1, #0x48c] /* DRAM_DQM7 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x464] /* DRAM_CAS */ + ldr r5, [r1, #0x490] /* DRAM_RAS */ + ldr r6, [r1, #0x4ac] /* DRAM_SDCLK_0 */ + ldr r7, [r1, #0x4b0] /* DRAM_SDCLK_1 */ + stmfd r0!, {r4-r7} + + ldr r5, [r1, #0x750] /* DDRMODE_CTL */ + ldr r6, [r1, #0x760] /* DDRMODE */ + stmfd r0!, {r5-r6} + + ldr r4, [r1, #0x4bc] /* DRAM_SDQS0 */ + ldr r5, [r1, #0x4c0] /* DRAM_SDQS1 */ + ldr r6, [r1, #0x4c4] /* DRAM_SDQS2 */ + ldr r7, [r1, #0x4c8] /* DRAM_SDQS3 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x4cc] /* DRAM_SDQS4 */ + ldr r5, [r1, #0x4d0] /* DRAM_SDQS5 */ + ldr r6, [r1, #0x4d4] /* DRAM_SDQS6 */ + ldr r7, [r1, #0x4d8] /* DRAM_SDQS7 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x764] /* GPR_B0DS */ + ldr r5, [r1, #0x770] /* GPR_B1DS */ + ldr r6, [r1, #0x778] /* GPR_B2DS */ + ldr r7, [r1, #0x77c] /* GPR_B3DS */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x780] /* GPR_B4DS */ + ldr r5, [r1, #0x784] /* GPR_B5DS */ + ldr r6, [r1, #0x78c] /* GPR_B6DS */ + ldr r7, [r1, #0x748] /* GPR_B7DS */ + stmfd r0!, {r4-r7} + + ldr r5, [r1, #0x74c] /* GPR_ADDS*/ + ldr r6, [r1, #0x4b4] /* DRAM_SODT0*/ + ldr r7, [r1, #0x4b8] /* DRAM_SODT1*/ + stmfd r0!, {r5-r7} + + .endm + + .macro dl_ddr_io_restore + + ldmea r0!, {r4-r7} + str r4, [r1, #0x470] /* DRAM_DQM0 */ + str r5, [r1, #0x474] /* DRAM_DQM1 */ + str r6, [r1, #0x478] /* DRAM_DQM2 */ + str r7, [r1, #0x47c] /* DRAM_DQM3 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x480] /* DRAM_DQM4 */ + str r5, [r1, #0x484] /* DRAM_DQM5 */ + str r6, [r1, #0x488] /* DRAM_DQM6 */ + str r7, [r1, #0x48c] /* DRAM_DQM7 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x464] /* DRAM_CAS */ + str r5, [r1, #0x490] /* DRAM_RAS */ + str r6, [r1, #0x4ac] /* DRAM_SDCLK_0 */ + str r7, [r1, #0x4b0] /* DRAM_SDCLK_1 */ + + ldmea r0!, {r5-r6} + str r5, [r1, #0x750] /* DDRMODE_CTL */ + str r6, [r1, #0x760] /* DDRMODE */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x4bc] /* DRAM_SDQS0 */ + str r5, [r1, #0x4c0] /* DRAM_SDQS1 */ + str r6, [r1, #0x4c4] /* DRAM_SDQS2 */ + str r7, [r1, #0x4c8] /* DRAM_SDQS3 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x4cc] /* DRAM_SDQS4 */ + str r5, [r1, #0x4d0] /* DRAM_SDQS5 */ + str r6, [r1, #0x4d4] /* DRAM_SDQS6 */ + str r7, [r1, #0x4d8] /* DRAM_SDQS7 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x764] /* GPR_B0DS */ + str r5, [r1, #0x770] /* GPR_B1DS */ + str r6, [r1, #0x778] /* GPR_B2DS */ + str r7, [r1, #0x77c] /* GPR_B3DS */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x780] /* GPR_B4DS */ + str r5, [r1, #0x784] /* GPR_B5DS */ + str r6, [r1, #0x78c] /* GPR_B6DS */ + str r7, [r1, #0x748] /* GPR_B7DS */ + + ldmea r0!, {r5-r7} + str r5, [r1, #0x74c] /* GPR_ADDS*/ + str r6, [r1, #0x4b4] /* DRAM_SODT0*/ + str r7, [r1, #0x4b8] /* DRAM_SODT1*/ + + .endm + + .macro dl_ddr_io_set_lpm + + mov r0, #0 + str r0, [r1, #0x470] /* DRAM_DQM0 */ + str r0, [r1, #0x474] /* DRAM_DQM1 */ + str r0, [r1, #0x478] /* DRAM_DQM2 */ + str r0, [r1, #0x47c] /* DRAM_DQM3 */ + + str r0, [r1, #0x480] /* DRAM_DQM4 */ + str r0, [r1, #0x484] /* DRAM_DQM5 */ + str r0, [r1, #0x488] /* DRAM_DQM6 */ + str r0, [r1, #0x48c] /* DRAM_DQM7 */ + + str r0, [r1, #0x464] /* DRAM_CAS */ + str r0, [r1, #0x490] /* DRAM_RAS */ + str r0, [r1, #0x4ac] /* DRAM_SDCLK_0 */ + str r0, [r1, #0x4b0] /* DRAM_SDCLK_1 */ + + str r0, [r1, #0x750] /* DDRMODE_CTL */ + str r0, [r1, #0x760] /* DDRMODE */ + + str r0, [r1, #0x4bc] /* DRAM_SDQS0 */ + str r0, [r1, #0x4c0] /* DRAM_SDQS1 */ + str r0, [r1, #0x4c4] /* DRAM_SDQS2 */ + str r0, [r1, #0x4c8] /* DRAM_SDQS3 */ + + str r0, [r1, #0x4cc] /* DRAM_SDQS4 */ + str r0, [r1, #0x4d0] /* DRAM_SDQS5 */ + str r0, [r1, #0x4d4] /* DRAM_SDQS6 */ + str r0, [r1, #0x4d8] /* DRAM_SDQS7 */ + + str r0, [r1, #0x764] /* GPR_B0DS */ + str r0, [r1, #0x770] /* GPR_B1DS */ + str r0, [r1, #0x778] /* GPR_B2DS */ + str r0, [r1, #0x77c] /* GPR_B3DS */ + + str r0, [r1, #0x780] /* GPR_B4DS */ + str r0, [r1, #0x784] /* GPR_B5DS */ + str r0, [r1, #0x78c] /* GPR_B6DS */ + str r0, [r1, #0x748] /* GPR_B7DS */ + + str r0, [r1, #0x74c] /* GPR_ADDS*/ + str r0, [r1, #0x4b4] /* DRAM_SODT0*/ + str r0, [r1, #0x4b8] /* DRAM_SODT1*/ + + .endm + + .macro dq_ddr_io_save + + ldr r4, [r1, #0x5ac] /* DRAM_DQM0 */ + ldr r5, [r1, #0x5b4] /* DRAM_DQM1 */ + ldr r6, [r1, #0x528] /* DRAM_DQM2 */ + ldr r7, [r1, #0x520] /* DRAM_DQM3 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x514] /* DRAM_DQM4 */ + ldr r5, [r1, #0x510] /* DRAM_DQM5 */ + ldr r6, [r1, #0x5bc] /* DRAM_DQM6 */ + ldr r7, [r1, #0x5c4] /* DRAM_DQM7 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x56c] /* DRAM_CAS */ + ldr r5, [r1, #0x578] /* DRAM_RAS */ + ldr r6, [r1, #0x588] /* DRAM_SDCLK_0 */ + ldr r7, [r1, #0x594] /* DRAM_SDCLK_1 */ + stmfd r0!, {r4-r7} + + ldr r5, [r1, #0x750] /* DDRMODE_CTL */ + ldr r6, [r1, #0x774] /* DDRMODE */ + stmfd r0!, {r5-r6} + + ldr r4, [r1, #0x5a8] /* DRAM_SDQS0 */ + ldr r5, [r1, #0x5b0] /* DRAM_SDQS1 */ + ldr r6, [r1, #0x524] /* DRAM_SDQS2 */ + ldr r7, [r1, #0x51c] /* DRAM_SDQS3 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x518] /* DRAM_SDQS4 */ + ldr r5, [r1, #0x50c] /* DRAM_SDQS5 */ + ldr r6, [r1, #0x5b8] /* DRAM_SDQS6 */ + ldr r7, [r1, #0x5c0] /* DRAM_SDQS7 */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x784] /* GPR_B0DS */ + ldr r5, [r1, #0x788] /* GPR_B1DS */ + ldr r6, [r1, #0x794] /* GPR_B2DS */ + ldr r7, [r1, #0x79c] /* GPR_B3DS */ + stmfd r0!, {r4-r7} + + ldr r4, [r1, #0x7a0] /* GPR_B4DS */ + ldr r5, [r1, #0x7a4] /* GPR_B5DS */ + ldr r6, [r1, #0x7a8] /* GPR_B6DS */ + ldr r7, [r1, #0x748] /* GPR_B7DS */ + stmfd r0!, {r4-r7} + + ldr r5, [r1, #0x74c] /* GPR_ADDS*/ + ldr r6, [r1, #0x59c] /* DRAM_SODT0*/ + ldr r7, [r1, #0x5a0] /* DRAM_SODT1*/ + stmfd r0!, {r5-r7} + + .endm + + .macro dq_ddr_io_restore + + ldmea r0!, {r4-r7} + str r4, [r1, #0x5ac] /* DRAM_DQM0 */ + str r5, [r1, #0x5b4] /* DRAM_DQM1 */ + str r6, [r1, #0x528] /* DRAM_DQM2 */ + str r7, [r1, #0x520] /* DRAM_DQM3 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x514] /* DRAM_DQM4 */ + str r5, [r1, #0x510] /* DRAM_DQM5 */ + str r6, [r1, #0x5bc] /* DRAM_DQM6 */ + str r7, [r1, #0x5c4] /* DRAM_DQM7 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x56c] /* DRAM_CAS */ + str r5, [r1, #0x578] /* DRAM_RAS */ + str r6, [r1, #0x588] /* DRAM_SDCLK_0 */ + str r7, [r1, #0x594] /* DRAM_SDCLK_1 */ + + ldmea r0!, {r5-r6} + str r5, [r1, #0x750] /* DDRMODE_CTL */ + str r6, [r1, #0x774] /* DDRMODE */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x5a8] /* DRAM_SDQS0 */ + str r5, [r1, #0x5b0] /* DRAM_SDQS1 */ + str r6, [r1, #0x524] /* DRAM_SDQS2 */ + str r7, [r1, #0x51c] /* DRAM_SDQS3 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x518] /* DRAM_SDQS4 */ + str r5, [r1, #0x50c] /* DRAM_SDQS5 */ + str r6, [r1, #0x5b8] /* DRAM_SDQS6 */ + str r7, [r1, #0x5c0] /* DRAM_SDQS7 */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x784] /* GPR_B0DS */ + str r5, [r1, #0x788] /* GPR_B1DS */ + str r6, [r1, #0x794] /* GPR_B2DS */ + str r7, [r1, #0x79c] /* GPR_B3DS */ + + ldmea r0!, {r4-r7} + str r4, [r1, #0x7a0] /* GPR_B4DS */ + str r5, [r1, #0x7a4] /* GPR_B5DS */ + str r6, [r1, #0x7a8] /* GPR_B6DS */ + str r7, [r1, #0x748] /* GPR_B7DS */ + + ldmea r0!, {r5-r7} + str r5, [r1, #0x74c] /* GPR_ADDS*/ + str r6, [r1, #0x59c] /* DRAM_SODT0*/ + str r7, [r1, #0x5a0] /* DRAM_SODT1*/ + + .endm + + .macro dq_ddr_io_set_lpm + + mov r0, #0 + str r0, [r1, #0x5ac] /* DRAM_DQM0 */ + str r0, [r1, #0x5b4] /* DRAM_DQM1 */ + str r0, [r1, #0x528] /* DRAM_DQM2 */ + str r0, [r1, #0x520] /* DRAM_DQM3 */ + + str r0, [r1, #0x514] /* DRAM_DQM4 */ + str r0, [r1, #0x510] /* DRAM_DQM5 */ + str r0, [r1, #0x5bc] /* DRAM_DQM6 */ + str r0, [r1, #0x5c4] /* DRAM_DQM7 */ + + str r0, [r1, #0x56c] /* DRAM_CAS */ + str r0, [r1, #0x578] /* DRAM_RAS */ + str r0, [r1, #0x588] /* DRAM_SDCLK_0 */ + str r0, [r1, #0x594] /* DRAM_SDCLK_1 */ + + str r0, [r1, #0x750] /* DDRMODE_CTL */ + str r0, [r1, #0x774] /* DDRMODE */ + + str r0, [r1, #0x5a8] /* DRAM_SDQS0 */ + str r0, [r1, #0x5b0] /* DRAM_SDQS1 */ + str r0, [r1, #0x524] /* DRAM_SDQS2 */ + str r0, [r1, #0x51c] /* DRAM_SDQS3 */ + + str r0, [r1, #0x518] /* DRAM_SDQS4 */ + str r0, [r1, #0x50c] /* DRAM_SDQS5 */ + str r0, [r1, #0x5b8] /* DRAM_SDQS6 */ + str r0, [r1, #0x5c0] /* DRAM_SDQS7 */ + + str r0, [r1, #0x784] /* GPR_B0DS */ + str r0, [r1, #0x788] /* GPR_B1DS */ + str r0, [r1, #0x794] /* GPR_B2DS */ + str r0, [r1, #0x79c] /* GPR_B3DS */ + + str r0, [r1, #0x7a0] /* GPR_B4DS */ + str r0, [r1, #0x7a4] /* GPR_B5DS */ + str r0, [r1, #0x7a8] /* GPR_B6DS */ + str r0, [r1, #0x748] /* GPR_B7DS */ + + str r0, [r1, #0x74c] /* GPR_ADDS*/ + str r0, [r1, #0x59c] /* DRAM_SODT0*/ + str r0, [r1, #0x5a0] /* DRAM_SODT1*/ + + .endm + +/****************************************************************** +Invalidate l1 dcache, r0-r4, r6, r7 used +******************************************************************/ + .macro invalidate_l1_dcache + + mov r0, #0 + mcr p15, 2, r0, c0, c0, 0 + mrc p15, 1, r0, c0, c0, 0 + + ldr r1, =0x7fff + and r2, r1, r0, lsr #13 + + ldr r1, =0x3ff + + and r3, r1, r0, lsr #3 @ NumWays - 1 + add r2, r2, #1 @ NumSets + + and r0, r0, #0x7 + add r0, r0, #4 @ SetShift + + clz r1, r3 @ WayShift + add r4, r3, #1 @ NumWays +1: + sub r2, r2, #1 @ NumSets-- + mov r3, r4 @ Temp = NumWays +2: + subs r3, r3, #1 @ Temp-- + mov r7, r3, lsl r1 + mov r6, r2, lsl r0 + orr r7, r7, r6 + mcr p15, 0, r7, c7, c6, 2 + bgt 2b + cmp r2, #0 + bgt 1b + dsb + isb + + .endm + +/****************************************************************** +Flush and disable L1 dcache +******************************************************************/ + .macro flush_disable_l1_dcache + + /* + * Flush all data from the L1 data cache before disabling + * SCTLR.C bit. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Clear the SCTLR.C bit to prevent further data cache + * allocation. Clearing SCTLR.C would make all the data accesses + * strongly ordered and would not hit the cache. + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + isb + + /* + * Invalidate L1 data cache. Even though only invalidate is + * necessary exported flush API is used here. Doing clean + * on already clean cache would be almost NOP. + */ + push {r0-r12, lr} + ldr r0, =v7_flush_dcache_all + mov lr, pc + mov pc, r0 + pop {r0-r12, lr} + + /* + * Execute an ISB instruction to ensure that all of the + * CP15 register changes have been committed. + */ + isb + + /* + * Execute a barrier instruction to ensure that all cache, + * TLB and branch predictor maintenance operations issued + * by any CPU in the cluster have completed. + */ + dsb + dmb + + .endm + +/****************************************************************** +Clean L2 cache +******************************************************************/ + .macro clean_l2_cache + /* Clean L2 cache to write the dirty data into DRAM to make + sure the data alignment between DRAM and L2 cache. + */ +#ifdef CONFIG_CACHE_L2X0 + /* Clean L2 cache here */ + ldr r1, =L2_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + /* Make way to 0xFFFF 16 ways */ + mov r0, #0x10000 + sub r0, r0, #0x1 + /* 0x7BC is L2X0_CLEAN_WAY */ + mov r4, #0x700 + orr r4, #0xBC + str r0, [r1, r4] +3: + ldr r5, [r1, r4] + ands r5, r5, r0 + bne 3b +4: + mov r5, #0x0 + /* 0x730 is L2X0_CACHE_SYNC */ + mov r4, #0x700 + orr r4, #0x30 + str r5, [r1, r4] +5: + ldr r5, [r1, r4] + ands r5, r5, #0x1 + bne 5b +#endif + .endm + + .align 3 +ENTRY(mx6_suspend) + stmfd sp!, {r0-r12} @ Save registers +/************************************************************* +suspend mode entry +*************************************************************/ + mov r12, r3 /* Save CPU type to r12*/ + mov r11, r0 /* Save the state in r11 */ + + cmp r12, #MXC_CPU_MX6SL + beq dormant + + cmp r0, #0x1 + bne dormant /* dormant mode */ + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + /* Need to clean L2 dcache*/ + clean_l2_cache + + /* Disable L2 cache */ +#ifdef CONFIG_CACHE_L2X0 + ldr r2, =L2_BASE_ADDR + add r2, r2, #PERIPBASE_VIRT + mov r4, #0x0 + str r4, [r2, #L2X0_CTRL] +#endif + + wfi + + nop + nop + nop + nop + + /* Invalidate L1 I-cache first */ + mov r1, #0x0 + mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache + + /* Need to invalidate L1 dcache, as the power is dropped */ + invalidate_l1_dcache + + /* Enable L1 dcache first */ + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 2) @ Disable the C bit + mcr p15, 0, r0, c1, c0, 0 + + /* Enable L2 cache here */ +#ifdef CONFIG_CACHE_L2X0 + ldr r2, =L2_BASE_ADDR + add r2, r2, #PERIPBASE_VIRT + mov r4, #0x1 + str r4, [r2, #L2X0_CTRL] +#endif + +/*********************************************************** +never run to here +************************************************************/ + b out /* exit standby */ + /* Place the literal pool here so that + * literals are within 4KB range + */ + .ltorg +/************************************************************ +dormant entry, data save in stack, save sp in the src_gpr2 +************************************************************/ +dormant: + mov r3, r1 + mov r0, r1 + add r0, r0, #IRAM_SUSPEND_SIZE /* 8K */ + ldr r4, =SRC_BASE_ADDR + add r4, r4, #PERIPBASE_VIRT + str r0, [r4, #SRC_GPR2_OFFSET] /* set src_gpr2 */ +/************************************************************ +saved register and context as below: + ddr_iomux set + sp + spsr + lr + CPACR + TTBR0 + TTBR1 + TTBCR + DACR + PRRR + NMRR + ACTLR + Context ID + User r/w thread ID + Secure or NS VBAR + CPSR + SCTLR +************************************************************/ + /* save mmdc iomux setting, stack is from the tail of + iram_suspend base */ + + mov r0, r2 /* get suspend_iram_base */ + add r0, r0, #IRAM_SUSPEND_SIZE /* 5K */ + + mov r4, r12 @ Store cpu type + stmfd r0!, {r4} + mov r4, r11 @ Store state entered + stmfd r0!, {r4} + + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + cmp r12, #MXC_CPU_MX6Q + bne dl_io_save + dq_ddr_io_save + b ddr_io_save_done +dl_io_save: + cmp r12, #MXC_CPU_MX6DL + bne sl_io_save + dl_ddr_io_save + b ddr_io_save_done +sl_io_save: + sl_ddr_io_save + +ddr_io_save_done: +#ifdef CONFIG_CACHE_L2X0 + ldr r1, =L2_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + ldr r4, [r1, #L2X0_CTRL] + ldr r5, [r1, #L2X0_AUX_CTRL] + ldr r6, [r1, #L2X0_TAG_LATENCY_CTRL] + ldr r7, [r1, #L2X0_DATA_LATENCY_CTRL] + stmfd r0!, {r4-r7} + + ldr r4, [r1, #L2X0_PREFETCH_CTRL] + ldr r5, [r1, #L2X0_POWER_CTRL] + stmfd r0!, {r4-r5} +#endif + + mov r4, sp @ Store sp + mrs r5, spsr @ Store spsr + mov r6, lr @ Store lr + stmfd r0!, {r4-r6} + + /* c1 and c2 registers */ + mrc p15, 0, r4, c1, c0, 2 @ CPACR + mrc p15, 0, r5, c2, c0, 0 @ TTBR0 + mrc p15, 0, r6, c2, c0, 1 @ TTBR1 + mrc p15, 0, r7, c2, c0, 2 @ TTBCR + stmfd r0!, {r4-r7} + + /* c3 and c10 registers */ + mrc p15, 0, r4, c3, c0, 0 @ DACR + mrc p15, 0, r5, c10, c2, 0 @ PRRR + mrc p15, 0, r6, c10, c2, 1 @ NMRR + mrc p15, 0, r7, c1, c0, 1 @ ACTLR + stmfd r0!,{r4-r7} + + /* c12, c13 and CPSR registers */ + mrc p15, 0, r4, c13, c0, 1 @ Context ID + mrc p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + mrs r7, cpsr @ Store CPSR + stmfd r0!, {r4-r7} + + /* c1 control register */ + mrc p15, 0, r4, c1, c0, 0 @ SCTLR + stmfd r0!, {r4} + + /* Need to flush and disable L1 dcache*/ + flush_disable_l1_dcache + + /* Need to clean L2 dcache*/ + clean_l2_cache + + /* + * 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 IRAM page table. + * 3. Disable page table walks in TTBR0 (PD0 = 1) + * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0 + * and 2-4G is translated by TTBR1. + */ + /* 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 + +/**************************************************************** +set ddr iomux to low power mode +****************************************************************/ + ldr r1, =MMDC_P0_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* Put DDR explicitly into self-refresh. */ + /* Disable Automatic power savings. */ + ldr r0, [r1, #0x404] + orr r0, r0, #0x01 + str r0, [r1, #0x404] + + /* Make the DDR explicitly enter self-refresh. */ + ldr r0, [r1, #0x404] + orr r0, r0, #0x200000 + str r0, [r1, #0x404] + +poll_dvfs_set_1: + ldr r0, [r1, #0x404] + and r0, r0, #0x2000000 + cmp r0, #0x2000000 + bne poll_dvfs_set_1 + + /* set mmdc iomux to low power mode */ + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + cmp r12, #MXC_CPU_MX6Q + bne dl_io_set_lpm + dq_ddr_io_set_lpm + b ddr_io_set_lpm_done +dl_io_set_lpm: + cmp r12, #MXC_CPU_MX6DL + bne sl_io_set_lpm + dl_ddr_io_set_lpm + b ddr_io_set_lpm_done +sl_io_set_lpm: + sl_ddr_io_set_lpm + +ddr_io_set_lpm_done: + /* Do Analog Power Optimizations + * for MX6SL in standby mode. + */ + cmp r12, #MXC_CPU_MX6SL + bne no_analog_savings + cmp r11, #1 + bne no_analog_savings + + /* We are here because on + * MX6SL, we want to lower + * the power in Standby mode. + */ + mx6sl_standy_saving_set + +no_analog_savings: + +/**************************************************************** +save resume pointer into SRC_GPR1 +****************************************************************/ + ldr r0, =mx6_suspend + ldr r1, =resume + sub r1, r1, r0 + add r3, r3, r1 + ldr r1, =SRC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + str r3, [r1, #SRC_GPR1_OFFSET] + + /* Mask all GPC interrupts before + * enabling the RBC counters to + * avoid the counter starting too + * early if an interupt is already + * pending. + */ + ldr r3, =GPC_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT + ldr r4, [r3, #0x08] + ldr r5, [r3, #0x0c] + ldr r6, [r3, #0x10] + ldr r7, [r3, #0x14] + + ldr r8, =0xffffffff + str r8, [r3, #0x08] + str r8, [r3, #0x0c] + str r8, [r3, #0x10] + str r8, [r3, #0x14] + + /* Enable the RBC bypass counter here + * to hold off the interrupts. + * RBC counter = 32 (1ms) + * Minimum RBC delay should be + * 400us for the analog LDOs to + * power down. + */ + ldr r1, =CCM_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r8, [r1, #0x0] + ldr r0, =0x7E00000 + bic r8, r8, r0 + ldr r0, =0x4000000 + orr r8, r8, r0 + str r8, [r1, #0x0] + + /* Enable the counter. */ + ldr r8, [r1, #0x0] + orr r8, r8, #0x8000000 + str r8, [r1, #0x0] + + /* Unmask all the GPC interrupts. */ + str r4, [r3, #0x08] + str r5, [r3, #0x0c] + str r6, [r3, #0x10] + str r7, [r3, #0x14] + + + /* Now delay for a short while (3usec) + * ARM is at 1GHz at this point + * so a short loop should be enough. + * This delay is required to ensure that + * the RBC counter can start counting in case an + * interrupt is already pending or in case an interrupt + * arrives just as ARM is about to assert DSM_request. + */ + ldr r4, =2000 +rbc_loop: + sub r4, r4, #0x1 + cmp r4, #0x0 + bne rbc_loop + + /*if internal ldo(VDDARM) bypassed,analog bypass it for DSM(0x1e) and + *restore it when resume(0x1f). + */ + ldr r1, =ANATOP_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r4, [r1, #0x140] + and r4, r4, #0x1f + cmp r4, #0x1f + bne ldo_check_done1 +ldo_analog_bypass: + ldr r4, [r1, #0x140] + bic r4, r4, #0x1f + orr r4, r4, #0x1e + str r4, [r1, #0x140] +ldo_check_done1: +/**************************************************************** +execute a wfi instruction to let SOC go into stop mode. +****************************************************************/ + wfi + + nop + nop + nop + nop + +/**************************************************************** +if go here, means there is a wakeup irq pending, we should resume +system immediately. +****************************************************************/ + /*restore it with 0x1f if use ldo bypass mode.*/ + ldr r1, =ANATOP_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + ldr r3, [r1, #0x140] + and r3, r3, #0x1f + cmp r3, #0x1e + bne ldo_check_done2 +ldo_bypass_restore: + ldr r3, [r1, #0x140] + orr r3, r3, #0x1f + str r3, [r1, #0x140] +ldo_check_done2: + /* + * Get the address of IRAM stack + */ + ldr r0, =SRC_BASE_ADDR + add r0, r0, #PERIPBASE_VIRT + ldr r0, [r0, #SRC_GPR2_OFFSET] + + add r0, r0, #PERIPBASE_VIRT + ldmea r0!, {r12} @ get cpu type to make ddr io + @ offset right + + ldmea r0!, {r11} @ standby or mem + + cmp r12, #MXC_CPU_MX6SL + bne no_analog_restore + + cmp r11, #0x1 + bne no_analog_restore + + ldr r3, =CCM_BASE_ADDR + add r3, r3, #PERIPBASE_VIRT + + /* Restore the analog settings. */ + mx6sl_standby_savings_restore + +no_analog_restore: + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + cmp r12, #MXC_CPU_MX6Q + bne dl_io_restore + dq_ddr_io_restore + b ddr_io_restore_done +dl_io_restore: + cmp r12, #MXC_CPU_MX6DL + bne sl_io_restore + dl_ddr_io_restore + b ddr_io_restore_done +sl_io_restore: + sl_ddr_io_restore + ldr r1, =MMDC_P0_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* reset read FIFO, RST_RD_FIFO */ + ldr r7, =0x83c + ldr r6, [r1, r7] + orr r6, r6, #0x80000000 + str r6, [r1, r7] +fifo_reset1_wait: + ldr r6, [r1, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne fifo_reset1_wait + + /* reset FIFO a second time */ + ldr r6, [r1, r7] + orr r6, r6, #0x80000000 + str r6, [r1, r7] +fifo_reset2_wait: + ldr r6, [r1, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne fifo_reset2_wait + +ddr_io_restore_done: + ldr r1, =MMDC_P0_BASE_ADDR + add r1, r1, #PERIPBASE_VIRT + + /* Ensure DDR exits self-refresh. */ + ldr r6, [r1, #0x404] + bic r6, r6, #0x200000 + str r6, [r1, #0x404] + +poll_dvfs_clear_1: + ldr r6, [r1, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + beq poll_dvfs_clear_1 + + /* Enable Automatic power savings. */ + ldr r6, [r1, #0x404] + bic r6, r6, #0x01 + str r6, [r1, #0x404] + + /* Add enough nops so that the + * prefetcher will not get instructions + * from DDR before its IO pads + * are restored. + */ + 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 + + mrc p15, 0, r1, c1, c0, 0 + orr r1, r1, #(1 << 2) @ Enable the C bit + mcr p15, 0, r1, c1, c0, 0 + + /* Restore 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 + dsb + isb + + /* flush the TLB */ + ldr r6, =0x0 + mcr p15, 0, r6, c8, c3, 0 + + b out /* exit standby */ + .ltorg + +/**************************************************************** +when SOC exit stop mode, arm core restart from here, currently +are running with MMU off. +****************************************************************/ +resume: + /*restore it with 0x1f if use ldo bypass mode.*/ + ldr r1, =ANATOP_BASE_ADDR + ldr r3, [r1, #0x140] + and r3, r3, #0x1f + cmp r3, #0x1e + bne ldo_check_done3 + ldr r3, [r1, #0x140] + orr r3, r3, #0x1f + str r3, [r1, #0x140] +ldo_check_done3: + /* Invalidate L1 I-cache first */ + mov r1, #0x0 + mcr p15, 0, r1, c7, c5, 0 @ Invalidate I-Cache + mcr p15, 0, r1, c7, c5, 0 @ invalidate Icache to PoU + mcr p15, 0, r1, c7, c5, 6 @ invalidate branch predictor + mov r1, #0x1800 + mcr p15, 0, r1, c1, c0, 0 @ enable the Icache and branch prediction + isb @ as soon as possible + + /* Need to invalidate L1 dcache */ + invalidate_l1_dcache + + ldr r0, =SRC_BASE_ADDR + str r1, [r0, #SRC_GPR1_OFFSET] /* clear SRC_GPR1 */ + ldr r0, [r0, #SRC_GPR2_OFFSET] + + ldmea r0!, {r12} @ get cpu type + + ldmea r0!, {r11} @ standby or mem + + cmp r12, #MXC_CPU_MX6SL + bne no_analog_restore1 + + cmp r11, #0x1 + bne no_analog_restore1 + + ldr r1, =ANATOP_BASE_ADDR + ldr r3, =CCM_BASE_ADDR + + /* Restore the analog settings. */ + mx6sl_standby_pg_savings_restore + +no_analog_restore1: + /* Restore DDR IO */ + ldr r1, =MX6Q_IOMUXC_BASE_ADDR + + cmp r12, #MXC_CPU_MX6Q + bne dl_io_dsm_restore + dq_ddr_io_restore + b ddr_io_restore_dsm_done +dl_io_dsm_restore: + cmp r12, #MXC_CPU_MX6DL + bne sl_io_dsm_restore + dl_ddr_io_restore + b ddr_io_restore_dsm_done +sl_io_dsm_restore: + sl_ddr_io_restore + ldr r1, =MMDC_P0_BASE_ADDR + /* reset read FIFO, RST_RD_FIFO */ + ldr r7, =0x83c + ldr r6, [r1, r7] + orr r6, r6, #0x80000000 + str r6, [r1, r7] +dsm_fifo_reset1_wait: + ldr r6, [r1, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne dsm_fifo_reset1_wait + + /* reset FIFO a second time */ + ldr r6, [r1, r7] + orr r6, r6, #0x80000000 + str r6, [r1, r7] +dsm_fifo_reset2_wait: + ldr r6, [r1, r7] + and r6, r6, #0x80000000 + cmp r6, #0 + bne dsm_fifo_reset2_wait + +ddr_io_restore_dsm_done: + ldr r1, =MMDC_P0_BASE_ADDR + + /* Ensure DDR exits self-refresh. */ + ldr r6, [r1, #0x404] + bic r6, r6, #0x200000 + str r6, [r1, #0x404] + +poll_dvfs_clear_2: + ldr r6, [r1, #0x404] + and r6, r6, #0x2000000 + cmp r6, #0x2000000 + beq poll_dvfs_clear_2 + + /* Enable Automatic power savings. */ + ldr r6, [r1, #0x404] + bic r6, r6, #0x01 + str r6, [r1, #0x404] + +#ifdef CONFIG_CACHE_L2X0 + ldr r2, =L2_BASE_ADDR + ldmea r0!, {r4-r7} + /* L2 will be enabled after L1 is enabled */ + mov r4, #0x0 + str r4, [r2, #L2X0_CTRL] + str r5, [r2, #L2X0_AUX_CTRL] + str r6, [r2, #L2X0_TAG_LATENCY_CTRL] + str r7, [r2, #L2X0_DATA_LATENCY_CTRL] + + ldmea r0!, {r4-r5} + str r4, [r2, #L2X0_PREFETCH_CTRL] + str r5, [r2, #L2X0_POWER_CTRL] +#endif + + /* Restore cp15 registers and cpu type */ + ldmea r0!, {r4-r6} + mov sp, r4 @ Restore sp + msr spsr_cxsf, r5 @ Restore spsr + mov lr, r6 @ Restore lr + + /* c1 and c2 registers */ + ldmea r0!, {r4-r7} + mcr p15, 0, r4, c1, c0, 2 @ CPACR + mcr p15, 0, r5, c2, c0, 0 @ TTBR0 + mcr p15, 0, r6, c2, c0, 1 @ TTBR1 + mcr p15, 0, r7, c2, c0, 2 @ TTBCR + + /* c3 and c10 registers */ + ldmea r0!,{r4-r7} + mcr p15, 0, r4, c3, c0, 0 @ DACR + mcr p15, 0, r5, c10, c2, 0 @ PRRR + mcr p15, 0, r6, c10, c2, 1 @ NMRR + mcr p15, 0, r7, c1, c0, 1 @ ACTLR + + /* c12, c13 and CPSR registers */ + ldmea r0!,{r4-r7} + mcr p15, 0, r4, c13, c0, 1 @ Context ID + mcr p15, 0, r5, c13, c0, 2 @ User r/w thread ID + mrc p15, 0, r6, c12, c0, 0 @ Secure or NS VBAR + msr cpsr, r7 @ store cpsr + + /* + * Enabling MMU here. Page entry needs to be altered + * to create temporary 1:1 map and then resore the entry + * ones MMU is enabled + */ + mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl + and r7, #0x7 @ Extract N (0:2) to decide + cmp r7, #0x0 @ TTBR0/TTBR1 + beq use_ttbr0 +ttbr_error: + b ttbr_error @ Only N = 0 supported +use_ttbr0: + mrc p15, 0, r2, c2, c0, 0 @ Read TTBR0 + ldr r5, =TTRBIT_MASK + and r2, r5 + mov r4, pc + ldr r5, =TABLE_INDEX_MASK + and r4, r5 @ r4 = 31 to 20 bits of pc + ldr r1, =TABLE_ENTRY + add r1, r1, r4 @ r1 has value of table entry + lsr r4, #18 @ Address of table entry + add r2, r4 @ r2 - location to be modified + + /* Storing previous entry of location being modified */ + ldr r4, [r2] + mov r9, r4 + str r1, [r2] + + /* + * Storing address of entry being modified + * It will be restored after enabling MMU + */ + mov r10, r2 + + mov r1, #0 + mcr p15, 0, r1, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r1, c8, c5, 0 @ Invalidate ITLB + mcr p15, 0, r1, c8, c6, 0 @ Invalidate DTLB + + /* + * Restore control register but don't enable Data caches here. + * Caches will be enabled after restoring MMU table entry. + */ + ldmea r0!, {r4} + mov r11, r4 + ldr r2, =CACHE_DISABLE_MASK + and r4, r4, r2 + mcr p15, 0, r4, c1, c0, 0 + isb + dsb + ldr r1, =mmu_on_label + bx r1 +mmu_on_label: + +/************************************************************ +restore control register to enable cache +************************************************************/ + mov r0, r11 + mcr p15, 0, r0, c1, c0, 0 @ with caches enabled. + dsb + isb + +#ifdef CONFIG_CACHE_L2X0 + /* Enable L2 cache here */ + ldr r2, =L2_BASE_ADDR + add r2, r2, #PERIPBASE_VIRT + mov r4, #0x1 + str r4, [r2, #L2X0_CTRL] +#endif + + mov r8, lr + push {r0-r3, r12} + + /* Set up the per-CPU stacks */ + bl cpu_init + pop {r0-r3, r12} + + /* + * Restore the MMU table entry that was modified for + * enabling MMU. + */ + ldr r4, =PAGE_OFFSET + + cmp r12, #MXC_CPU_MX6SL + bne dq_dl_phy_offset + ldr r5, =MX6SL_PHYS_OFFSET + b get_phy_offset_done +dq_dl_phy_offset: + ldr r5, =MX6_PHYS_OFFSET +get_phy_offset_done: + + sub r4, r4, r5 + add r4, r4, r10 + str r9, [r4] + + mov r0, #0 + mcr p15, 0, r0, c7, c1, 6 @ flush TLB and issue barriers + mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r0, c7, c5, 6 @ Invalidate BTB + mcr p15, 0, r0, c8, c5, 0 @ Invalidate ITLB + mcr p15, 0, r0, c8, c6, 0 @ Invalidate DTLB + dsb + isb + +/*********************************************************** +return back to mx6_suspend_enter for dormant +***********************************************************/ + mov lr, r8 + ldmfd sp!, {r0-r12} + mov pc, lr +/************************************************ +return back to mx6_suspend_enter for suspend +*************************************************/ +out: + ldmfd sp!, {r0-r12} + mov pc, lr + + .type mx6_do_suspend, #object +ENTRY(mx6_do_suspend) + .word mx6_suspend + .size mx6_suspend, . - mx6_suspend |