]> nv-tegra.nvidia Code Review - linux-3.10.git/blobdiff - arch/arm/mach-tegra/sleep-t30.S
ARM: tegra14x: Fix sdram self-refresh entry/exit
[linux-3.10.git] / arch / arm / mach-tegra / sleep-t30.S
index d950ae838670892a907c9012849f06b32078fc26..7f1fa0cbb8bd046a34187a6eef657e324446f664 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,
 #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 CLK_RESET_PLLP_MISC            0xac
 #define CLK_RESET_PLLA_MISC            0xbc
 #define CLK_RESET_PLLX_MISC            0xe4
+#if !defined(CONFIG_ARCH_TEGRA_3x_SOC)
+#define CLK_RESET_PLLX_MISC3           0x518
+#define CLK_RESET_PLLM_MISC_IDDQ       5
+#define CLK_RESET_PLLC_MISC_IDDQ       26
+#define CLK_RESET_PLLX_MISC3_IDDQ      3
+#endif
 
 #define CLK_RESET_PLLP_OUTA            0xa4
 #define CLK_RESET_PLLP_OUTB            0xa8
 
 #define MSELECT_CLKM                   (0x3 << 30)
 
+#define TEGRA_RTC_MSEC 0x10
+
 #if USE_PLL_LOCK_BITS
 #define LOCK_DELAY             PLL_POST_LOCK_DELAY
 #else
@@ -173,7 +185,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
@@ -205,7 +217,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
@@ -315,9 +327,15 @@ tegra3_iram_start:
        orreq   \rd, \rd, #(1<<30)
        streq   \rd, [\car, #\base]
 #if USE_PLL_LOCK_BITS
+       .if     \misc
+       ldr     \rd, [\car, #\misc]
+       bic     \rd, \rd, #(1<<18)
+       str     \rd, [\car, #\misc]
+       ldr     \rd, [\car, #\misc]
        ldr     \rd, [\car, #\misc]
        orr     \rd, \rd, #(1<<18)
        str     \rd, [\car, #\misc]
+       .endif
 #endif
 .endm
 
@@ -330,10 +348,22 @@ tegra3_iram_start:
 #endif
 .endm
 
+.macro pll_iddq_exit, rd, car, iddq, iddq_bit
+       ldr     \rd, [\car, #\iddq]
+       bic     \rd, \rd, #(1<<\iddq_bit)
+       str     \rd, [\car, #\iddq]
+.endm
+
+.macro pll_iddq_entry, rd, car, iddq, iddq_bit
+       ldr     \rd, [\car, #\iddq]
+       orr     \rd, \rd, #(1<<\iddq_bit)
+       str     \rd, [\car, #\iddq]
+.endm
+
 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, PLLA and PLLX. */
+        * enable PLLP, PLLM, PLLC, and PLLX. */
        mov32   r0, TEGRA_CLK_RESET_BASE
 #ifndef CONFIG_TRUSTED_FOUNDATIONS
        /* secure code handles 32KHz to CLKM/OSC clock switch */
@@ -344,6 +374,8 @@ ENTRY(tegra3_lp1_reset)
        str     r1, [r0, #CLK_RESET_SCLK_DIVIDER]
        str     r1, [r0, #CLK_RESET_CCLK_DIVIDER]
 #endif
+
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
        /* enable PLLM via PMC */
        mov32   r2, TEGRA_PMC_BASE
        ldr     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
@@ -351,14 +383,32 @@ ENTRY(tegra3_lp1_reset)
        str     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
 
        pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC
-       pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
-       pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC
        pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC
        pll_enable r1, r0, CLK_RESET_PLLX_BASE, CLK_RESET_PLLX_MISC
+#else
+       pll_iddq_exit r1, r0, CLK_RESET_PLLM_MISC, CLK_RESET_PLLM_MISC_IDDQ
+       pll_iddq_exit r1, r0, CLK_RESET_PLLC_MISC, CLK_RESET_PLLC_MISC_IDDQ
+       pll_iddq_exit r1, r0, CLK_RESET_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ
+
+       mov32   r7, TEGRA_TMRUS_BASE
+       ldr     r1, [r7]
+       add     r1, r1, #2
+       wait_until r1, r7, r3
+
+       /* enable PLLM via PMC */
+       mov32   r2, TEGRA_PMC_BASE
+       ldr     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
+       orr     r1, r1, #(1<<12)
+       str     r1, [r2, #PMC_PLLP_WB0_OVERRIDE]
+
+       pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0
+       pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0
+       pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0
+#endif
+       pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC
 
        pll_locked r1, r0, CLK_RESET_PLLM_BASE
        pll_locked r1, r0, CLK_RESET_PLLP_BASE
-       pll_locked r1, r0, CLK_RESET_PLLA_BASE
        pll_locked r1, r0, CLK_RESET_PLLC_BASE
        pll_locked r1, r0, CLK_RESET_PLLX_BASE
 
@@ -367,7 +417,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]
@@ -455,13 +510,19 @@ 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_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
        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]
@@ -475,8 +536,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:
@@ -555,11 +623,19 @@ 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
        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:
@@ -581,9 +657,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
@@ -600,17 +707,155 @@ lp1_register_core_highvolt:
        .word   0
 #endif
 
-/*
- * tegra3_tear_down_core
+/* 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]
+       ldr     r3, [r4, #PMC_SCRATCH37]
+
+       tst     r0, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON
+       moveq   r0, #0
+       beq     tegra148_lp0_entry
+       andnes  r3, r3, #TEGRA_POWER_LP1_AUDIO
+       bne     lp1bb_entry
+
+/* lp0_delayed_entry
+ *
+ * If BB has a paging request, a 30msec timeout has to be done before the
+ * PMC_IPC_STS register is queried again
+ */
+lp0_delayed_entry:
+        /* Use RTC MS timer
+        */
+       mov32   r8, TEGRA_RTC_BASE
+       ldr     r0, [r8, #TEGRA_RTC_MSEC]
+       add     r0, r0, #30
+timer_loop:
+       ldr     r1, [r8, #TEGRA_RTC_MSEC]
+       subs    r1,r1, r0
+       ble     timer_loop
+       ldr     r0, [r4, #PMC_IPC_STS]
+       tst     r0, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON
+       moveq   r0, #1
+       bne     lp1bb_entry
+
+/* R0 contains info whether delay timeout has already taken place or not */
+tegra148_lp0_entry:
+
+       /* 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_I2C_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]
+
+       /* Check PMC_IPC_STS[mem_req] and PMC_IPC_STS[mem_req_soon]
+        * once again. If both 0 then go to LP0 entry
+        */
+       ldr     r3, [r4, #PMC_IPC_STS]
+       tst     r3, #PMC_IPC_STS_MEM_REQ | PMC_IPC_STS_MEM_REQ_SOON
+       beq     tegra3_lp0_tear_down_core
+
+       /* Check if delay has happened. If yes, then set PMC_IPC_SET[mem_sts]
+        * and then go to LP1BB, else go to delay */
+       cmp     r0, #1
+       bne     lp0_delayed_entry
+       ldr     r1, [r4, #PMC_IPC_SET]
+       orr     r1, r1, #PMC_IPC_SET_MEM_STS
+       str     r1, [r4, #PMC_IPC_SET]
+       b       lp1bb_entry
+
+
+/* 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:
+
+       /* 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]
+       bic     r0, r0, #PMC_WAKE2_BB_MEM_REQ
+       str     r0, [r4, #PMC_WAKE2_LEVEL]
+
+       /* Wait for a few ticks for this to stabilize */
+       ldr     r0, =0x300
+wait_stable:
+       subs    r0, r0, #1
+       bne     wait_stable
+
+       /* Program the auto_wake_lvl regsiters */
+       ldr     r0, [r4, #PMC_AUTO_WAKE_LVL]
+       orr     r0, r0, #1
+       str     r0, [r4, #PMC_AUTO_WAKE_LVL]
+
+       ldr     r0, =0x300
+wait_stable2:
+       subs    r0, r0, #1
+       bne     wait_stable2
+
+       /* 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]
+
+       /* Configure the EVP reset vector */
+       ldr     r0, [r4, #PMC_SCRATCH41]
+       ldr     r8, =TEGRA_EXCEPTION_VECTORS_BASE
+       str     r0, [r8, #0x100]
+
+       /* 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]
+
+       bl      tegra148_lp1bb_clear_warmboot_flag
+       bl      tegra3_cpu_clk32k
+       b       tegra3_enter_sleep
+#endif
+
+/* 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:
        bl      tegra3_sdram_self_refresh
        bl      tegra3_cpu_clk32k
        b       tegra3_enter_sleep
 
+/*
+ * tegra148_lp1bb_clear_warmboot_flag
+ * Clears warmboot0 flag, and clears SIDE_EFFECT_BIT.
+ * Called by lp1bb_entry.
+ */
+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
+
 /*
  * tegra3_cpu_clk32k
  *
@@ -639,6 +884,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:
@@ -709,6 +960,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]
@@ -724,14 +980,12 @@ lp1_volt_skip:
        add     r1, r1, #2
        wait_until r1, r7, r9
 
-       /* switch to CLKS */
-       mov     r0, #0  /* burst policy = 32KHz */
-       str     r0, [r5, #CLK_RESET_SCLK_BURST]
-
+#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:
@@ -753,7 +1007,18 @@ powerdown_pll_cx:
        ldr     r0, [r5, #CLK_RESET_PLLX_BASE]
        bic     r0, r0, #(1<<30)
        str     r0, [r5, #CLK_RESET_PLLX_BASE]
+#if !defined(CONFIG_ARCH_TEGRA_3x_SOC)
+       /*
+        * 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_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ
+#endif
 
+       /* switch to CLKS */
+       mov     r0, #0  /* burst policy = 32KHz */
+       str     r0, [r5, #CLK_RESET_SCLK_BURST]
        mov     pc, lr
 
 /*
@@ -779,7 +1044,7 @@ tegra3_enter_sleep:
        orr     r0, r0, #FLOW_CTRL_CSR_ENABLE
        str     r0, [r6, r2]
 
-#if defined(CONFIG_ARCH_TEGRA_11x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_11x_SOC) || defined(CONFIG_ARCH_TEGRA_14x_SOC)
        tst     r0, #FLOW_CTRL_IMMEDIATE_WAKE
        movne   r0, #FLOW_CTRL_WAITEVENT
        moveq   r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
@@ -827,31 +1092,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
@@ -889,11 +1166,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