]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - arch/arm/mach-tegra/sleep-t30.S
ARM: Tegra: Add CONFIG_TEGRA_USE_SECURE_KERNEL
[linux-3.10.git] / arch / arm / mach-tegra / sleep-t30.S
index de1d37f787813a58209b26e9ee1cbc4002e6cb93..904cd34bb2861372fa1fbbd97f6ab8bb77a3b983 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -31,6 +31,7 @@
 
 #include "sleep.h"
 #include "clock.h"
+#include "reset.h"
 
 #define EMC_CFG                                0xc
 #define EMC_ADR_CFG                    0x10
 #define PMC_IO_DPD_REQ                 0x1b8
 #define PMC_IO_DPD_STATUS              0x1bc
 #define PMC_SCRATCH1_ECO       0x264
+#define PMC_POR_DPD_CTRL              0x264
+
+#define FLOW_IPC_STS                   0x500
+#define FLOW_IPC_STS_AP2BB_MSC_STS_0   (1 << 4)
 
 #define CLK_RESET_CCLK_BURST           0x20
 #define CLK_RESET_CCLK_DIVIDER         0x24
 
 #define MSELECT_CLKM                   (0x3 << 30)
 
+#define TEGRA_RTC_MSEC 0x10
+
 #if USE_PLL_LOCK_BITS
 #define LOCK_DELAY             PLL_POST_LOCK_DELAY
 #else
@@ -179,7 +186,7 @@ ENTRY(tegra30_cpu_shutdown)
        movw    r12, \
                FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
                FLOW_CTRL_CSR_ENABLE
-#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
        mov     r4, #(1 << 8)                   @ wfi bitmap
 #else
        mov     r4, #(1 << 4)                   @ wfe bitmap
@@ -211,7 +218,7 @@ delay_1:
 __cpu_reset_again:
        dsb
        .align 5
-#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
        wfi                                     @ CPU should be power gated here
 #else
        wfe                                     @ CPU should be power gated here
@@ -260,9 +267,35 @@ ENTRY(tegra3_sleep_core_finish)
        sub     r1, r1, r2
        mov32   r2, TEGRA_IRAM_CODE_AREA
        add     r1, r1, r2
+       mov     r11, #0
        b       tegra_turn_off_mmu
 ENDPROC(tegra3_sleep_core_finish)
 
+ENTRY(tegra3_stop_mc_clk_finish)
+       mov     r4, r0
+       bl      tegra_flush_cache
+       mov     r0, r4
+       bl      tegra_cpu_exit_coherency
+
+       /* preload all the address literals that are needed for the
+        * CPU power-gating process, to avoid loads from SDRAM (which are
+        * not supported once SDRAM is put into self-refresh.
+        * LP0 / LP1 use physical address, since the MMU needs to be
+        * disabled before putting SDRAM into self-refresh to avoid
+        * memory access due to page table walks */
+       mov32   r4, TEGRA_PMC_BASE
+       mov32   r5, TEGRA_CLK_RESET_BASE
+       mov32   r6, TEGRA_FLOW_CTRL_BASE
+       mov32   r7, TEGRA_TMRUS_BASE
+
+       mov32   r1, tegra3_stop_mc_clk
+       mov32   r2, tegra3_iram_start
+       sub     r1, r1, r2
+       mov32   r2, TEGRA_IRAM_CODE_AREA
+       add     r1, r1, r2
+       b       tegra_turn_off_mmu
+ENDPROC(tegra3_stop_mc_clk_finish)
+
 /*
  * tegra3_sleep_cpu_secondary_finish(unsigned long v2p)
  *
@@ -358,8 +391,14 @@ ENTRY(tegra3_lp1_reset)
        /* the CPU and system bus are running at 32KHz and executing from
         * IRAM when this code is executed; immediately switch to CLKM and
         * enable PLLP, PLLM, PLLC, and PLLX. */
+
+       ldr     r8, [r12, #RESET_DATA(MASK_MC_CLK)]
+       tst     r8, r11         @ if memory clock stopped
+       mov32   r2, TEGRA_PMC_BASE
+       bne     emc_exit_selfrefresh
+
        mov32   r0, TEGRA_CLK_RESET_BASE
-#ifndef CONFIG_TRUSTED_FOUNDATIONS
+#if !defined(CONFIG_TEGRA_USE_SECURE_KERNEL)
        /* secure code handles 32KHz to CLKM/OSC clock switch */
        mov     r1, #(1<<28)
        str     r1, [r0, #CLK_RESET_SCLK_BURST]
@@ -411,7 +450,12 @@ ENTRY(tegra3_lp1_reset)
        add     r1, r1, #LOCK_DELAY
        wait_until r1, r7, r3
 
-       add     r5, pc, #tegra3_sdram_pad_save-(.+8)    @ r5 reserved for pad base
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       add     r5, pc, #tegra3_sdram_pad_save-(.+8)    @ r5 --> saved data
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       add     r5, pc, #tegra11_sdram_pad_save-(.+8)   @ r5 --> saved data
+#endif
 
        ldr     r4, [r5, #0x18]
        str     r4, [r0, #CLK_RESET_CLK_SOURCE_MSELECT]
@@ -499,13 +543,85 @@ powerup_l2_done:
        str     r0, [r2, #PMC_REMOVE_CLAMPING_CMD]
 #endif
 
-       mov32   r0, TEGRA_EMC_BASE                      @ r0 reserved for emc base
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+
+       /* If we are waking up from LP1, unconditionally continue
+        * resume.
+        */
+       mov32   r4, TEGRA_PMC_BASE
+       ldr     r0, [r4, #PMC_LP_STATE_SCRATCH_REG]
+       mov     r0, r0, lsr #PMC_LP_STATE_BIT_OFFSET
+       and     r0, r0, #PMC_LP_STATE_BIT_MASK
+       cmp     r0, #PMC_LP_STATE_LP1
+       beq     lp1_exit_resume
+
+       /* If we are waking up from LP1BB, see the wake source.
+        * If it was mem_req=0, then go into LP1.
+        * Otherwise wake to active.
+        */
+       ldr     r0, [r4, #PMC_WAKE2_STATUS]
+       tst     r0, #PMC_WAKE2_BB_MEM_REQ
+
+       /* If it isn't mem_req=0, continue with resume, just
+        * skip self refresh routine
+        */
+       beq     self_refresh_skip
+
+       /* If it is mem_req=0, check to see if there was another
+        * wake event, if yes, continue with wake to active
+        */
+       ldr     r1, [r4, #PMC_WAKE_STATUS]
+
+       /* Mask out other wake events from WAKE2_STATUS */
+       bic     r0, r0, #PMC_WAKE2_BB_MEM_REQ
+       orrs    r1, r1, r0
+
+       /* If there were any other wake events, wake to active */
+       bne     self_refresh_skip
+
+       /* Since the wake was mem_req, we need to enter LP1 */
+       mov32   r5, TEGRA_CLK_RESET_BASE
+       mov32   r6, TEGRA_FLOW_CTRL_BASE
+       mov32   r7, TEGRA_TMRUS_BASE
+
+       /* Write PMC_IPC_CLR[mem_sts] = 1 */
+       ldr     r1, [r4, #PMC_IPC_CLR]
+       orr     r1, r1, #PMC_IPC_CLR_MEM_STS
+       str     r1, [r4, #PMC_IPC_CLR]
+
+       /* Set lp state variable */
+       mov     r0, #PMC_LP_STATE_LP1
+       str     r0, lp_enter_state
+       bl      tegra148_set_lp_state
+
+       /* Set mem_req=1 interrupt */
+       bl      tegra148_set_mem_req_interrupt
+
+       /* Legacy LP1 entry routine */
+       bl      tegra3_sdram_self_refresh
+       bl      tegra3_cpu_clk32k
+       b       tegra3_enter_sleep
+
+lp1_exit_resume:
+#endif
+
+emc_exit_selfrefresh:
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       mov32   r0, TEGRA_EMC_BASE              @ r0 reserved for emc base
+       add     r5, pc, #tegra3_sdram_pad_save-(.+8)    @ r5 --> saved data
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       mov32   r0, TEGRA_EMC0_BASE             @ r0 reserved for emc base
+       add     r5, pc, #tegra11_sdram_pad_save-(.+8)   @ r5 --> saved data
+#endif
 
        ldr     r1, [r5, #0x14] @ PMC_IO_DPD_STATUS
        mvn     r1, r1
        bic     r1, r1, #(0x1<<31)
        orr     r1, r1, #(0x1<<30)
        str     r1, [r2, #PMC_IO_DPD_REQ]
+
+exit_self_refresh:
        ldr     r1, [r5, #0xC]
        str     r1, [r0, #EMC_XM2VTTGENPADCTRL]
        ldr     r1, [r5, #0x10]
@@ -519,8 +635,15 @@ powerup_l2_done:
 
        emc_timing_update r1, r0
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       mov32   r1, TEGRA_EMC1_BASE
+       cmp     r0, r1
+#endif
        ldr     r1, [r0, #EMC_AUTO_CAL_CONFIG]
        orr     r1, r1, #(0x1<<31)              @ set AUTO_CAL_ACTIVE
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       orreq   r1, r1, #(0x1<<27)              @ set slave mode for channel 1
+#endif
        str     r1, [r0, #EMC_AUTO_CAL_CONFIG]
 
 emc_wait_audo_cal_onetime:
@@ -599,11 +722,30 @@ zcal_done:
        ldr     r1, [r5, #0x0]
        str     r1, [r0, #EMC_CFG]
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       mov32   r1, TEGRA_EMC1_BASE
+       cmp     r0, r1
+       movne   r0, r1
+       addne   r5, r5, #0x20
+       bne     exit_self_refresh
+#endif
+
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       /* In the LP1 case, we need to set the Memory status from
+        * AP to BB, so that memory transactions can take place
+        */
+       mov32   r4, TEGRA_PMC_BASE
+       ldr     r1, [r4, #PMC_IPC_SET]
+       orr     r1, r1, #PMC_IPC_SET_MEM_STS
+       str     r1, [r4, #PMC_IPC_SET]
+self_refresh_skip:
+#endif
        mov32   r0, TEGRA_PMC_BASE
        ldr     r0, [r0, #PMC_SCRATCH41]
        mov     pc, r0
 ENDPROC(tegra3_lp1_reset)
 
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)|| defined(CONFIG_ARCH_TEGRA_14x_SOC)
        .align  L1_CACHE_SHIFT
        .type   tegra3_sdram_pad_save, %object
 tegra3_sdram_pad_save:
@@ -625,9 +767,40 @@ tegra3_sdram_pad_address:
        .word   TEGRA_PMC_BASE + PMC_IO_DPD_STATUS                      @0x14
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT     @0x18
        .word   TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST             @0x1c
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       .align  L1_CACHE_SHIFT
+       .type   tegra11_sdram_pad_save, %object
+tegra11_sdram_pad_save:
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
+       .word   0
 
-tegra3_sdram_pad_size:
-       .word   tegra3_sdram_pad_address - tegra3_sdram_pad_save
+tegra11_sdram_pad_address:
+       .word   TEGRA_EMC0_BASE + EMC_CFG                               @0x0
+       .word   TEGRA_EMC0_BASE + EMC_ZCAL_INTERVAL                     @0x4
+       .word   TEGRA_EMC0_BASE + EMC_AUTO_CAL_INTERVAL                 @0x8
+       .word   TEGRA_EMC0_BASE + EMC_XM2VTTGENPADCTRL                  @0xc
+       .word   TEGRA_EMC0_BASE + EMC_XM2VTTGENPADCTRL2                 @0x10
+       .word   TEGRA_PMC_BASE + PMC_IO_DPD_STATUS                      @0x14
+       .word   TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT     @0x18
+       .word   TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST             @0x1c
+       .word   TEGRA_EMC1_BASE + EMC_CFG                               @0x20
+       .word   TEGRA_EMC1_BASE + EMC_ZCAL_INTERVAL                     @0x24
+       .word   TEGRA_EMC1_BASE + EMC_AUTO_CAL_INTERVAL                 @0x28
+       .word   TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL                  @0x2c
+       .word   TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL2                 @0x30
+#endif
 
 #ifdef CONFIG_TEGRA_LP1_950
        .globl lp1_register_pmuslave_addr
@@ -644,17 +817,152 @@ lp1_register_core_highvolt:
        .word   0
 #endif
 
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+lp_enter_state:
+       .word   0
+#endif
+
+/* tegra3_tear_down_core
+ *
+ * LP0 entry check conditions w.r.t BB take place here
+ */
+tegra3_tear_down_core:
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       /* Checking for BB-idle or Paging case */
+       ldr     r0, [r4, #PMC_IPC_STS]
+       tst     r0, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON
+       movne   r0, #PMC_LP_STATE_LP1BB
+
+       /* Write PMC_IPC_CLR[mem_sts] = 1 */
+       ldr     r1, [r4, #PMC_IPC_CLR]
+       orr     r1, r1, #PMC_IPC_CLR_MEM_STS
+       str     r1, [r4, #PMC_IPC_CLR]
+
+       /* Clear FLOW_IPC_STS[AP2BB_MSC_STS[0]] */
+       ldr     r1, [r6, #FLOW_IPC_STS]
+       bic     r1, #FLOW_IPC_STS_AP2BB_MSC_STS_0
+       str     r1, [r6, #FLOW_IPC_STS]
+
+       cmp     r0, #PMC_LP_STATE_LP1BB
+       bne     tegra3_lp0_tear_down_core
+       ldr     r1, [r4, #PMC_IPC_SET]
+       orr     r1, r1, #PMC_IPC_SET_MEM_STS
+       str     r1, [r4, #PMC_IPC_SET]
+
+/* lp1bb_entry
+ * Set up mem_req active low to be a wake event.
+ * Configure the EVP reset vector.
+ * Set up LIC to accept pmc wake events as interrupts.
+ * Clear previously set warmboot and side_effect bits
+ * Invoke remaining LP routines.
+ */
+lp1bb_entry:
+       bl      tegra148_lp1bb_clear_warmboot_flag
+       mov     r0, #PMC_LP_STATE_LP1BB
+       str     r0, lp_enter_state
+       bl      tegra148_set_lp_state
+       bl      tegra148_set_mem_req_interrupt
+       bl      tegra3_cpu_clk32k
+       b       tegra3_enter_sleep
+
+/* Based on LP state being entered, sets mem_req=0
+ * or mem_req=1 as a wake interrupt
+ */
+tegra148_set_mem_req_interrupt:
+       /* Clear the PMC_CTRL2_WAKE_DET_EN bit */
+       ldr     r0, [r4, #PMC_CTRL2]
+       bic     r0, r0, #PMC_CTRL2_WAKE_DET_EN
+       str     r0, [r4, #PMC_CTRL2]
+
+       /* Program the wake_level2 registers */
+       ldr     r0, [r4, #PMC_WAKE2_LEVEL]
+       ldr     r1, lp_enter_state
+       cmp     r1, #PMC_LP_STATE_LP1BB
+       biceq   r0, r0, #PMC_WAKE2_BB_MEM_REQ
+       orrne   r0, r0, #PMC_WAKE2_BB_MEM_REQ
+       str     r0, [r4, #PMC_WAKE2_LEVEL]
+
+       /* Wait for 1ms for write to take effect */
+       mov32   r7, TEGRA_TMRUS_BASE
+       wait_for_us r1, r7, r9
+       add r1, r1, #100
+       wait_until r1, r7, r9
+
+       /* Program the auto_wake_lvl regsiters */
+       ldr     r0, [r4, #PMC_AUTO_WAKE_LVL]
+       orr     r0, r0, #1
+       str     r0, [r4, #PMC_AUTO_WAKE_LVL]
+
+       /* Wait for 1ms for write to take effect */
+       mov32   r7, TEGRA_TMRUS_BASE
+       wait_for_us r1, r7, r9
+       add r1, r1, #100
+       wait_until r1, r7, r9
+
+       /* Configure mem_req active low to be wake event */
+       ldr     r0, [r4, #PMC_WAKE2_MASK]
+       orr     r0, r0, #PMC_WAKE2_BB_MEM_REQ
+       str     r0, [r4, #PMC_WAKE2_MASK]
+
+       ldr     r0, [r4, #PMC_CTRL2]
+       orr     r0, r0, #PMC_CTRL2_WAKE_DET_EN
+       str     r0, [r4, #PMC_CTRL2]
+
+       /* Set up the LIC to accept pmc_wake events as interrupts */
+       ldr     r8, =TEGRA_TERTIARY_ICTLR_BASE
+       ldr     r0, =TRI_ICTLR_PMC_WAKE_INT
+       str     r0, [r8, #TRI_ICTLR_CPU_IER_SET]
+       mov     pc, lr
+
 /*
- * tegra3_tear_down_core
+ * tegra148_lp1bb_clear_warmboot_flag
+ * Clears side effect bit in case it was set during
+ * suspend entry. Also clears Warmboot0 flag.
+ */
+tegra148_lp1bb_clear_warmboot_flag:
+       ldr     r0, [r4, #PMC_SCRATCH0]
+       bic     r0, r0, #1
+       str     r0, [r4, #PMC_SCRATCH0]
+       ldr     r0, [r4, #PMC_CTRL]
+       bic     r0, r0, #PMC_CTRL_SIDE_EFFECT_LP0
+       str     r0, [r4, #PMC_CTRL]
+       mov     pc, lr
+
+/* Based on value of lp_enter_state, update LP state
+ * scratch register
+ */
+tegra148_set_lp_state:
+       ldr     r0, lp_enter_state
+       mov     r0, r0, lsl #PMC_LP_STATE_BIT_OFFSET
+       ldr     r1, [r4, #PMC_LP_STATE_SCRATCH_REG]
+       mov     r2, #PMC_LP_STATE_BIT_MASK
+       bic     r1, r2, lsl #PMC_LP_STATE_BIT_OFFSET
+       orr     r1, r0
+       str     r1, [r4, #PMC_LP_STATE_SCRATCH_REG]
+       mov     pc, lr
+
+/* tegra3_lp0_tear_down_core
  *
  * copied into and executed from IRAM
  * puts memory in self-refresh for LP0 and LP1
  */
-tegra3_tear_down_core:
+tegra3_lp0_tear_down_core:
+       ldr     r0, [r4, #PMC_CTRL]
+       tst     r0, #PMC_CTRL_SIDE_EFFECT_LP0
+       moveq   r0, #PMC_LP_STATE_LP1
+       movne   r0, #PMC_LP_STATE_LP0
+       str     r0, lp_enter_state
+       bleq    tegra148_set_mem_req_interrupt
+       bl      tegra148_set_lp_state
+#endif
        bl      tegra3_sdram_self_refresh
        bl      tegra3_cpu_clk32k
        b       tegra3_enter_sleep
 
+tegra3_stop_mc_clk:
+       bl      tegra3_sdram_self_refresh
+       b       tegra3_enter_sleep
+
 /*
  * tegra3_cpu_clk32k
  *
@@ -683,6 +991,12 @@ tegra3_cpu_clk32k:
        str r1, [r4, #PMC_SCRATCH1_ECO]
 #endif
 
+#if defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       ldr r1, [r4, #PMC_POR_DPD_CTRL]
+       orr r1, r1, #0x47
+       str r1, [r4, #PMC_POR_DPD_CTRL]
+#endif
+
        mov     pc, lr
 
 lp1_clocks_prepare:
@@ -753,6 +1067,11 @@ lp1_volt_skip:
         * to clks */
        mov     r0, #(1 << 28)
        str     r0, [r5, #CLK_RESET_SCLK_BURST]
+       /* 2 us delay between changing sclk and cclk */
+       wait_for_us r1, r7, r9
+       add     r1, r1, #2
+       wait_until r1, r7, r9
+       mov     r0, #(1 << 28)
        str     r0, [r5, #CLK_RESET_CCLK_BURST]
        mov     r0, #0
        str     r0, [r5, #CLK_RESET_CCLK_DIVIDER]
@@ -768,10 +1087,12 @@ lp1_volt_skip:
        add     r1, r1, #2
        wait_until r1, r7, r9
 
+#if !defined(CONFIG_ARCH_TEGRA_14x_SOC)
        /* disable PLLM via PMC in LP1 */
        ldr     r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
        bic     r0, r0, #(1 << 12)
        str     r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
+#endif
        b       powerdown_pll_pcx
 
 powerdown_pll_pcx:
@@ -795,10 +1116,10 @@ powerdown_pll_cx:
        str     r0, [r5, #CLK_RESET_PLLX_BASE]
 #if !defined(CONFIG_ARCH_TEGRA_3x_SOC)
        /*
-        * FIXME: put PLLM into IDDQ (need additional testing)
+        * FIXME: put PLLM/C into IDDQ (need additional testing)
         * pll_iddq_entry r1, r5, CLK_RESET_PLLM_MISC, CLK_RESET_PLLM_MISC_IDDQ
+        * pll_iddq_entry r1, r5, CLK_RESET_PLLC_MISC, CLK_RESET_PLLC_MISC_IDDQ
         */
-       pll_iddq_entry r1, r5, CLK_RESET_PLLC_MISC, CLK_RESET_PLLC_MISC_IDDQ
        pll_iddq_entry r1, r5, CLK_RESET_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ
 #endif
 
@@ -878,31 +1199,43 @@ halted:
 
 tegra3_sdram_self_refresh:
 
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
        adr     r2, tegra3_sdram_pad_address
        adr     r8, tegra3_sdram_pad_save
-       mov     r9, #0
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       adr     r2, tegra11_sdram_pad_address
+       adr     r8, tegra11_sdram_pad_save
+#endif
+       mov     r9, r2
 
 padsave:
-       ldr     r0, [r2, r9]                    @ r0 is emc register address
+       ldr     r0, [r2], #4                    @ r0 is emc register address
 
        ldr     r1, [r0]
-       str     r1, [r8, r9]                    @ save emc register
+       str     r1, [r8], #4                    @ save emc register
 
-       add     r9, r9, #4
-       ldr     r0, tegra3_sdram_pad_size
-       cmp     r0, r9
+       cmp     r8, r9
        bne     padsave
 padsave_done:
 
        dsb
 
-       mov32   r0, TEGRA_EMC_BASE                      @ r0 reserved for emc base
-
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       mov32   r0, TEGRA_EMC_BASE              @ r0 reserved for emc base
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       mov32   r0, TEGRA_EMC0_BASE             @ r0 reserved for emc base
+#endif
+enter_self_refresh:
        mov     r1, #0
        str     r1, [r0, #EMC_ZCAL_INTERVAL]
        str     r1, [r0, #EMC_AUTO_CAL_INTERVAL]
        ldr     r1, [r0, #EMC_CFG]
        bic     r1, r1, #(1<<28)
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       bic     r1, r1, #(1<<29)
+#endif
        str     r1, [r0, #EMC_CFG]              @ disable DYN_SELF_REF
 
        emc_timing_update r1, r0
@@ -940,11 +1273,23 @@ emcself:
        and     r1, r1, r2
        str     r1, [r0, #EMC_XM2VTTGENPADCTRL]
        ldr     r1, [r0, #EMC_XM2VTTGENPADCTRL2]
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
        orr     r1, r1, #7                      @ set E_NO_VTTGEN
+#endif
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
+       orr     r1, r1, #0x3f                   @ set E_NO_VTTGEN
+#endif
        str     r1, [r0, #EMC_XM2VTTGENPADCTRL2]
 
        emc_timing_update r1, r0
 
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+       mov32   r1, TEGRA_EMC1_BASE
+       cmp     r0, r1
+       movne   r0, r1
+       bne     enter_self_refresh
+#endif
+
        ldr     r1, [r4, #PMC_CTRL]
        tst     r1, #PMC_CTRL_SIDE_EFFECT_LP0
        bne     pmc_io_dpd_skip