^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2011, Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Colin Cross <ccross@android.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Gary King <gking@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <soc/tegra/flowctrl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/assembler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/proc-fns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/cp15.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "irammap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "reset.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "sleep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define EMC_CFG 0xc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define EMC_ADR_CFG 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define EMC_NOP 0xdc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define EMC_SELF_REF 0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define EMC_REQ_CTRL 0x2b0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define EMC_EMC_STATUS 0x2b4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CLK_RESET_CCLK_BURST 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define CLK_RESET_CCLK_DIVIDER 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CLK_RESET_SCLK_BURST 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define CLK_RESET_SCLK_DIVIDER 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define CLK_RESET_PLLC_BASE 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define CLK_RESET_PLLM_BASE 0x90
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CLK_RESET_PLLP_BASE 0xa0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define APB_MISC_XM2CFGCPADCTRL 0x8c8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define APB_MISC_XM2CFGDPADCTRL 0x8cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define APB_MISC_XM2CLKCFGPADCTRL 0x8d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define APB_MISC_XM2COMPPADCTRL 0x8d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define APB_MISC_XM2VTTGENPADCTRL 0x8d8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define APB_MISC_XM2CFGCPADCTRL2 0x8e4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define APB_MISC_XM2CFGDPADCTRL2 0x8e8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .macro pll_enable, rd, r_car_base, pll_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ldr \rd, [\r_car_base, #\pll_base]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) tst \rd, #(1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) orreq \rd, \rd, #(1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) streq \rd, [\r_car_base, #\pll_base]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .macro emc_device_mask, rd, base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ldr \rd, [\base, #EMC_ADR_CFG]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) tst \rd, #(0x3 << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) moveq \rd, #(0x1 << 8) @ just 1 device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) movne \rd, #(0x3 << 8) @ 2 devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .endm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * tegra20_hotplug_shutdown(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * puts the current cpu in reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * should never return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ENTRY(tegra20_hotplug_shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Put this CPU down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cpu_id r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) bl tegra20_cpu_shutdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ret lr @ should never get here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) ENDPROC(tegra20_hotplug_shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * tegra20_cpu_shutdown(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * r0 is cpu to reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * puts the specified CPU in wait-for-event mode on the flow controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * and puts the CPU in reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * can be called on the current cpu or another cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * if called on the current cpu, does not return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * MUST NOT BE CALLED FOR CPU 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * corrupts r0-r3, r12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ENTRY(tegra20_cpu_shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) cmp r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) reteq lr @ must not be called for CPU 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) cpu_to_halt_reg r1, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) ldr r3, =TEGRA_FLOW_CTRL_VIRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) str r2, [r3, r1] @ put flow controller in wait event mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ldr r2, [r3, r1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) isb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) movw r1, 0x1011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) mov r1, r1, lsl r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ldr r3, =TEGRA_CLK_RESET_VIRT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) str r1, [r3, #0x340] @ put slave CPU in reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) isb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) cpu_id r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) cmp r3, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) beq .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ENDPROC(tegra20_cpu_shutdown)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * tegra20_sleep_core_finish(unsigned long v2p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * tegra20_tear_down_core in IRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ENTRY(tegra20_sleep_core_finish)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) mov r4, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* Flush, disable the L1 data cache and exit SMP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mov r0, #TEGRA_FLUSH_CACHE_ALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) bl tegra_disable_clean_inv_dcache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mov r0, r4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) mov32 r3, tegra_shut_off_mmu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) add r3, r3, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) mov32 r0, tegra20_tear_down_core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mov32 r1, tegra20_iram_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sub r0, r0, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) add r0, r0, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ret r3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ENDPROC(tegra20_sleep_core_finish)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * tegra20_tear_down_cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Switches the CPU cluster to PLL-P and enters sleep.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ENTRY(tegra20_tear_down_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) bl tegra_switch_cpu_to_pllp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) b tegra20_enter_sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ENDPROC(tegra20_tear_down_cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* START OF ROUTINES COPIED TO IRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .align L1_CACHE_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .globl tegra20_iram_start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) tegra20_iram_start:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * tegra20_lp1_reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * reset vector for LP1 restore; copied into IRAM during suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * Brings the system back up to a safe staring point (SDRAM out of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * system clock running on the same PLL that it suspended at), and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * jumps to tegra_resume to restore virtual addressing and PLLX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * The physical address of tegra_resume expected to be stored in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * PMC_SCRATCH41.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ENTRY(tegra20_lp1_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * The CPU and system bus are running at 32KHz and executing from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * IRAM when this code is executed; immediately switch to CLKM and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * enable PLLM, PLLP, PLLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) mov32 r0, TEGRA_CLK_RESET_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mov r1, #(1 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) str r1, [r0, #CLK_RESET_SCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) str r1, [r0, #CLK_RESET_CCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) mov r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) str r1, [r0, #CLK_RESET_CCLK_DIVIDER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) str r1, [r0, #CLK_RESET_SCLK_DIVIDER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) pll_enable r1, r0, CLK_RESET_PLLM_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pll_enable r1, r0, CLK_RESET_PLLP_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) pll_enable r1, r0, CLK_RESET_PLLC_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) adr r2, tegra20_sdram_pad_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) adr r4, tegra20_sdram_pad_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mov r5, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ldr r6, tegra20_sdram_pad_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) padload:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ldr r7, [r2, r5] @ r7 is the addr in the pad_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ldr r1, [r4, r5]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) str r1, [r7] @ restore the value in pad_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) add r5, r5, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) cmp r6, r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) bne padload
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) padload_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* 255uS delay for PLL stabilization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) mov32 r7, TEGRA_TMRUS_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ldr r1, [r7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) add r1, r1, #0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) wait_until r1, r7, r9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) adr r4, tegra20_sclk_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ldr r4, [r4]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) str r4, [r0, #CLK_RESET_SCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) str r4, [r0, #CLK_RESET_CCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mov32 r0, TEGRA_EMC_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ldr r1, [r0, #EMC_CFG]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) str r1, [r0, #EMC_CFG]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) mov r1, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) mov r1, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) str r1, [r0, #EMC_NOP]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) str r1, [r0, #EMC_NOP]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) emc_device_mask r1, r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) exit_selfrefresh_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ldr r2, [r0, #EMC_EMC_STATUS]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ands r2, r2, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) bne exit_selfrefresh_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mov r1, #0 @ unstall all transactions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) str r1, [r0, #EMC_REQ_CTRL]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) mov32 r0, TEGRA_PMC_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) ldr r0, [r0, #PMC_SCRATCH41]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ret r0 @ jump to tegra_resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ENDPROC(tegra20_lp1_reset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * tegra20_tear_down_core
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * copied into and executed from IRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * puts memory in self-refresh for LP0 and LP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) tegra20_tear_down_core:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) bl tegra20_sdram_self_refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bl tegra20_switch_cpu_to_clk32k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) b tegra20_enter_sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * tegra20_switch_cpu_to_clk32k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * to the 32KHz clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) tegra20_switch_cpu_to_clk32k:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * start by switching to CLKM to safely disable PLLs, then switch to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * CLKS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mov r0, #(1 << 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) str r0, [r5, #CLK_RESET_SCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) str r0, [r5, #CLK_RESET_CCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mov r0, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) str r0, [r5, #CLK_RESET_CCLK_DIVIDER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) str r0, [r5, #CLK_RESET_SCLK_DIVIDER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* 2uS delay delay between changing SCLK and disabling PLLs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) mov32 r7, TEGRA_TMRUS_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ldr r1, [r7]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) add r1, r1, #2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) wait_until r1, r7, r9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* disable PLLM, PLLP and PLLC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ldr r0, [r5, #CLK_RESET_PLLM_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) bic r0, r0, #(1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) str r0, [r5, #CLK_RESET_PLLM_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) ldr r0, [r5, #CLK_RESET_PLLP_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) bic r0, r0, #(1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) str r0, [r5, #CLK_RESET_PLLP_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ldr r0, [r5, #CLK_RESET_PLLC_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) bic r0, r0, #(1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) str r0, [r5, #CLK_RESET_PLLC_BASE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* switch to CLKS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) mov r0, #0 /* brust policy = 32KHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) str r0, [r5, #CLK_RESET_SCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * tegra20_enter_sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * uses flow controller to enter sleep state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * executes from SDRAM with target state is LP2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) tegra20_enter_sleep:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mov32 r6, TEGRA_FLOW_CTRL_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) cpu_id r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) cpu_to_halt_reg r1, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) str r0, [r6, r1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ldr r0, [r6, r1] /* memory barrier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) halted:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) wfe /* CPU should be power gated here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) isb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) b halted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * tegra20_sdram_self_refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * called with MMU off and caches disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * puts sdram in self refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * must be executed from IRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) tegra20_sdram_self_refresh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mov r2, #3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) emcidle:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ldr r2, [r1, #EMC_EMC_STATUS]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) tst r2, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) beq emcidle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) mov r2, #1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) str r2, [r1, #EMC_SELF_REF]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) emc_device_mask r2, r1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) emcself:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) ldr r3, [r1, #EMC_EMC_STATUS]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) and r3, r3, r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) cmp r3, r2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) bne emcself @ loop until DDR in self-refresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) adr r2, tegra20_sdram_pad_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) adr r3, tegra20_sdram_pad_safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) adr r4, tegra20_sdram_pad_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) mov r5, #0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ldr r6, tegra20_sdram_pad_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) padsave:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ldr r0, [r2, r5] @ r0 is the addr in the pad_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) ldr r1, [r0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) str r1, [r4, r5] @ save the content of the addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ldr r1, [r3, r5]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) str r1, [r0] @ set the save val to the addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) add r5, r5, #4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) cmp r6, r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) bne padsave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) padsave_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mov32 r5, TEGRA_CLK_RESET_BASE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ldr r0, [r5, #CLK_RESET_SCLK_BURST]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) adr r2, tegra20_sclk_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) str r0, [r2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) dsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret lr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) tegra20_sdram_pad_address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) tegra20_sdram_pad_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .word tegra20_sdram_pad_size - tegra20_sdram_pad_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) tegra20_sdram_pad_safe:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .word 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) .word 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) .word 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) .word 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .word 0x5500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .word 0x08080040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .word 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tegra20_sclk_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .word 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) tegra20_sdram_pad_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .long 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .endr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .ltorg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* dummy symbol for end of IRAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .align L1_CACHE_SHIFT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .globl tegra20_iram_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) tegra20_iram_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) b .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) #endif