18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2011, Google, Inc. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Colin Cross <ccross@android.com> 78c2ecf20Sopenharmony_ci * Gary King <gking@nvidia.com> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/linkage.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <soc/tegra/flowctrl.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <asm/assembler.h> 158c2ecf20Sopenharmony_ci#include <asm/proc-fns.h> 168c2ecf20Sopenharmony_ci#include <asm/cp15.h> 178c2ecf20Sopenharmony_ci#include <asm/cache.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "irammap.h" 208c2ecf20Sopenharmony_ci#include "reset.h" 218c2ecf20Sopenharmony_ci#include "sleep.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define EMC_CFG 0xc 248c2ecf20Sopenharmony_ci#define EMC_ADR_CFG 0x10 258c2ecf20Sopenharmony_ci#define EMC_NOP 0xdc 268c2ecf20Sopenharmony_ci#define EMC_SELF_REF 0xe0 278c2ecf20Sopenharmony_ci#define EMC_REQ_CTRL 0x2b0 288c2ecf20Sopenharmony_ci#define EMC_EMC_STATUS 0x2b4 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define CLK_RESET_CCLK_BURST 0x20 318c2ecf20Sopenharmony_ci#define CLK_RESET_CCLK_DIVIDER 0x24 328c2ecf20Sopenharmony_ci#define CLK_RESET_SCLK_BURST 0x28 338c2ecf20Sopenharmony_ci#define CLK_RESET_SCLK_DIVIDER 0x2c 348c2ecf20Sopenharmony_ci#define CLK_RESET_PLLC_BASE 0x80 358c2ecf20Sopenharmony_ci#define CLK_RESET_PLLM_BASE 0x90 368c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_BASE 0xa0 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define APB_MISC_XM2CFGCPADCTRL 0x8c8 398c2ecf20Sopenharmony_ci#define APB_MISC_XM2CFGDPADCTRL 0x8cc 408c2ecf20Sopenharmony_ci#define APB_MISC_XM2CLKCFGPADCTRL 0x8d0 418c2ecf20Sopenharmony_ci#define APB_MISC_XM2COMPPADCTRL 0x8d4 428c2ecf20Sopenharmony_ci#define APB_MISC_XM2VTTGENPADCTRL 0x8d8 438c2ecf20Sopenharmony_ci#define APB_MISC_XM2CFGCPADCTRL2 0x8e4 448c2ecf20Sopenharmony_ci#define APB_MISC_XM2CFGDPADCTRL2 0x8e8 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci.macro pll_enable, rd, r_car_base, pll_base 478c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_base] 488c2ecf20Sopenharmony_ci tst \rd, #(1 << 30) 498c2ecf20Sopenharmony_ci orreq \rd, \rd, #(1 << 30) 508c2ecf20Sopenharmony_ci streq \rd, [\r_car_base, #\pll_base] 518c2ecf20Sopenharmony_ci.endm 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci.macro emc_device_mask, rd, base 548c2ecf20Sopenharmony_ci ldr \rd, [\base, #EMC_ADR_CFG] 558c2ecf20Sopenharmony_ci tst \rd, #(0x3 << 24) 568c2ecf20Sopenharmony_ci moveq \rd, #(0x1 << 8) @ just 1 device 578c2ecf20Sopenharmony_ci movne \rd, #(0x3 << 8) @ 2 devices 588c2ecf20Sopenharmony_ci.endm 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * tegra20_hotplug_shutdown(void) 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * puts the current cpu in reset 658c2ecf20Sopenharmony_ci * should never return 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ciENTRY(tegra20_hotplug_shutdown) 688c2ecf20Sopenharmony_ci /* Put this CPU down */ 698c2ecf20Sopenharmony_ci cpu_id r0 708c2ecf20Sopenharmony_ci bl tegra20_cpu_shutdown 718c2ecf20Sopenharmony_ci ret lr @ should never get here 728c2ecf20Sopenharmony_ciENDPROC(tegra20_hotplug_shutdown) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* 758c2ecf20Sopenharmony_ci * tegra20_cpu_shutdown(int cpu) 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * r0 is cpu to reset 788c2ecf20Sopenharmony_ci * 798c2ecf20Sopenharmony_ci * puts the specified CPU in wait-for-event mode on the flow controller 808c2ecf20Sopenharmony_ci * and puts the CPU in reset 818c2ecf20Sopenharmony_ci * can be called on the current cpu or another cpu 828c2ecf20Sopenharmony_ci * if called on the current cpu, does not return 838c2ecf20Sopenharmony_ci * MUST NOT BE CALLED FOR CPU 0. 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * corrupts r0-r3, r12 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_ciENTRY(tegra20_cpu_shutdown) 888c2ecf20Sopenharmony_ci cmp r0, #0 898c2ecf20Sopenharmony_ci reteq lr @ must not be called for CPU 0 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci cpu_to_halt_reg r1, r0 928c2ecf20Sopenharmony_ci ldr r3, =TEGRA_FLOW_CTRL_VIRT 938c2ecf20Sopenharmony_ci mov r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME 948c2ecf20Sopenharmony_ci str r2, [r3, r1] @ put flow controller in wait event mode 958c2ecf20Sopenharmony_ci ldr r2, [r3, r1] 968c2ecf20Sopenharmony_ci isb 978c2ecf20Sopenharmony_ci dsb 988c2ecf20Sopenharmony_ci movw r1, 0x1011 998c2ecf20Sopenharmony_ci mov r1, r1, lsl r0 1008c2ecf20Sopenharmony_ci ldr r3, =TEGRA_CLK_RESET_VIRT 1018c2ecf20Sopenharmony_ci str r1, [r3, #0x340] @ put slave CPU in reset 1028c2ecf20Sopenharmony_ci isb 1038c2ecf20Sopenharmony_ci dsb 1048c2ecf20Sopenharmony_ci cpu_id r3 1058c2ecf20Sopenharmony_ci cmp r3, r0 1068c2ecf20Sopenharmony_ci beq . 1078c2ecf20Sopenharmony_ci ret lr 1088c2ecf20Sopenharmony_ciENDPROC(tegra20_cpu_shutdown) 1098c2ecf20Sopenharmony_ci#endif 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 1128c2ecf20Sopenharmony_ci/* 1138c2ecf20Sopenharmony_ci * tegra20_sleep_core_finish(unsigned long v2p) 1148c2ecf20Sopenharmony_ci * 1158c2ecf20Sopenharmony_ci * Enters suspend in LP0 or LP1 by turning off the mmu and jumping to 1168c2ecf20Sopenharmony_ci * tegra20_tear_down_core in IRAM 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ciENTRY(tegra20_sleep_core_finish) 1198c2ecf20Sopenharmony_ci mov r4, r0 1208c2ecf20Sopenharmony_ci /* Flush, disable the L1 data cache and exit SMP */ 1218c2ecf20Sopenharmony_ci mov r0, #TEGRA_FLUSH_CACHE_ALL 1228c2ecf20Sopenharmony_ci bl tegra_disable_clean_inv_dcache 1238c2ecf20Sopenharmony_ci mov r0, r4 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci mov32 r3, tegra_shut_off_mmu 1268c2ecf20Sopenharmony_ci add r3, r3, r0 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci mov32 r0, tegra20_tear_down_core 1298c2ecf20Sopenharmony_ci mov32 r1, tegra20_iram_start 1308c2ecf20Sopenharmony_ci sub r0, r0, r1 1318c2ecf20Sopenharmony_ci mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA 1328c2ecf20Sopenharmony_ci add r0, r0, r1 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret r3 1358c2ecf20Sopenharmony_ciENDPROC(tegra20_sleep_core_finish) 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/* 1388c2ecf20Sopenharmony_ci * tegra20_tear_down_cpu 1398c2ecf20Sopenharmony_ci * 1408c2ecf20Sopenharmony_ci * Switches the CPU cluster to PLL-P and enters sleep. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ciENTRY(tegra20_tear_down_cpu) 1438c2ecf20Sopenharmony_ci bl tegra_switch_cpu_to_pllp 1448c2ecf20Sopenharmony_ci b tegra20_enter_sleep 1458c2ecf20Sopenharmony_ciENDPROC(tegra20_tear_down_cpu) 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci/* START OF ROUTINES COPIED TO IRAM */ 1488c2ecf20Sopenharmony_ci .align L1_CACHE_SHIFT 1498c2ecf20Sopenharmony_ci .globl tegra20_iram_start 1508c2ecf20Sopenharmony_citegra20_iram_start: 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci/* 1538c2ecf20Sopenharmony_ci * tegra20_lp1_reset 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * reset vector for LP1 restore; copied into IRAM during suspend. 1568c2ecf20Sopenharmony_ci * Brings the system back up to a safe staring point (SDRAM out of 1578c2ecf20Sopenharmony_ci * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLP, 1588c2ecf20Sopenharmony_ci * system clock running on the same PLL that it suspended at), and 1598c2ecf20Sopenharmony_ci * jumps to tegra_resume to restore virtual addressing and PLLX. 1608c2ecf20Sopenharmony_ci * The physical address of tegra_resume expected to be stored in 1618c2ecf20Sopenharmony_ci * PMC_SCRATCH41. 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 1648c2ecf20Sopenharmony_ci */ 1658c2ecf20Sopenharmony_ciENTRY(tegra20_lp1_reset) 1668c2ecf20Sopenharmony_ci /* 1678c2ecf20Sopenharmony_ci * The CPU and system bus are running at 32KHz and executing from 1688c2ecf20Sopenharmony_ci * IRAM when this code is executed; immediately switch to CLKM and 1698c2ecf20Sopenharmony_ci * enable PLLM, PLLP, PLLC. 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ci mov32 r0, TEGRA_CLK_RESET_BASE 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci mov r1, #(1 << 28) 1748c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_SCLK_BURST] 1758c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_CCLK_BURST] 1768c2ecf20Sopenharmony_ci mov r1, #0 1778c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 1788c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLM_BASE 1818c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLP_BASE 1828c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLC_BASE 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci adr r2, tegra20_sdram_pad_address 1858c2ecf20Sopenharmony_ci adr r4, tegra20_sdram_pad_save 1868c2ecf20Sopenharmony_ci mov r5, #0 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci ldr r6, tegra20_sdram_pad_size 1898c2ecf20Sopenharmony_cipadload: 1908c2ecf20Sopenharmony_ci ldr r7, [r2, r5] @ r7 is the addr in the pad_address 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci ldr r1, [r4, r5] 1938c2ecf20Sopenharmony_ci str r1, [r7] @ restore the value in pad_save 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci add r5, r5, #4 1968c2ecf20Sopenharmony_ci cmp r6, r5 1978c2ecf20Sopenharmony_ci bne padload 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cipadload_done: 2008c2ecf20Sopenharmony_ci /* 255uS delay for PLL stabilization */ 2018c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 2028c2ecf20Sopenharmony_ci ldr r1, [r7] 2038c2ecf20Sopenharmony_ci add r1, r1, #0xff 2048c2ecf20Sopenharmony_ci wait_until r1, r7, r9 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci adr r4, tegra20_sclk_save 2078c2ecf20Sopenharmony_ci ldr r4, [r4] 2088c2ecf20Sopenharmony_ci str r4, [r0, #CLK_RESET_SCLK_BURST] 2098c2ecf20Sopenharmony_ci mov32 r4, ((1 << 28) | (4)) @ burst policy is PLLP 2108c2ecf20Sopenharmony_ci str r4, [r0, #CLK_RESET_CCLK_BURST] 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci mov32 r0, TEGRA_EMC_BASE 2138c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_CFG] 2148c2ecf20Sopenharmony_ci bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP 2158c2ecf20Sopenharmony_ci str r1, [r0, #EMC_CFG] 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci mov r1, #0 2188c2ecf20Sopenharmony_ci str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 2198c2ecf20Sopenharmony_ci mov r1, #1 2208c2ecf20Sopenharmony_ci str r1, [r0, #EMC_NOP] 2218c2ecf20Sopenharmony_ci str r1, [r0, #EMC_NOP] 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci emc_device_mask r1, r0 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciexit_selfrefresh_loop: 2268c2ecf20Sopenharmony_ci ldr r2, [r0, #EMC_EMC_STATUS] 2278c2ecf20Sopenharmony_ci ands r2, r2, r1 2288c2ecf20Sopenharmony_ci bne exit_selfrefresh_loop 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci mov r1, #0 @ unstall all transactions 2318c2ecf20Sopenharmony_ci str r1, [r0, #EMC_REQ_CTRL] 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci mov32 r0, TEGRA_PMC_BASE 2348c2ecf20Sopenharmony_ci ldr r0, [r0, #PMC_SCRATCH41] 2358c2ecf20Sopenharmony_ci ret r0 @ jump to tegra_resume 2368c2ecf20Sopenharmony_ciENDPROC(tegra20_lp1_reset) 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci/* 2398c2ecf20Sopenharmony_ci * tegra20_tear_down_core 2408c2ecf20Sopenharmony_ci * 2418c2ecf20Sopenharmony_ci * copied into and executed from IRAM 2428c2ecf20Sopenharmony_ci * puts memory in self-refresh for LP0 and LP1 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_citegra20_tear_down_core: 2458c2ecf20Sopenharmony_ci bl tegra20_sdram_self_refresh 2468c2ecf20Sopenharmony_ci bl tegra20_switch_cpu_to_clk32k 2478c2ecf20Sopenharmony_ci b tegra20_enter_sleep 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/* 2508c2ecf20Sopenharmony_ci * tegra20_switch_cpu_to_clk32k 2518c2ecf20Sopenharmony_ci * 2528c2ecf20Sopenharmony_ci * In LP0 and LP1 all PLLs will be turned off. Switch the CPU and system clock 2538c2ecf20Sopenharmony_ci * to the 32KHz clock. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_citegra20_switch_cpu_to_clk32k: 2568c2ecf20Sopenharmony_ci /* 2578c2ecf20Sopenharmony_ci * start by switching to CLKM to safely disable PLLs, then switch to 2588c2ecf20Sopenharmony_ci * CLKS. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci mov r0, #(1 << 28) 2618c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_BURST] 2628c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_CCLK_BURST] 2638c2ecf20Sopenharmony_ci mov r0, #0 2648c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_CCLK_DIVIDER] 2658c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_DIVIDER] 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* 2uS delay delay between changing SCLK and disabling PLLs */ 2688c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 2698c2ecf20Sopenharmony_ci ldr r1, [r7] 2708c2ecf20Sopenharmony_ci add r1, r1, #2 2718c2ecf20Sopenharmony_ci wait_until r1, r7, r9 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* disable PLLM, PLLP and PLLC */ 2748c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLM_BASE] 2758c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 2768c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLM_BASE] 2778c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLP_BASE] 2788c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 2798c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLP_BASE] 2808c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLC_BASE] 2818c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 2828c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLC_BASE] 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* switch to CLKS */ 2858c2ecf20Sopenharmony_ci mov r0, #0 /* brust policy = 32KHz */ 2868c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_BURST] 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci ret lr 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * tegra20_enter_sleep 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * uses flow controller to enter sleep state 2948c2ecf20Sopenharmony_ci * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 2958c2ecf20Sopenharmony_ci * executes from SDRAM with target state is LP2 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_citegra20_enter_sleep: 2988c2ecf20Sopenharmony_ci mov32 r6, TEGRA_FLOW_CTRL_BASE 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT 3018c2ecf20Sopenharmony_ci orr r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ 3028c2ecf20Sopenharmony_ci cpu_id r1 3038c2ecf20Sopenharmony_ci cpu_to_halt_reg r1, r1 3048c2ecf20Sopenharmony_ci str r0, [r6, r1] 3058c2ecf20Sopenharmony_ci dsb 3068c2ecf20Sopenharmony_ci ldr r0, [r6, r1] /* memory barrier */ 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cihalted: 3098c2ecf20Sopenharmony_ci dsb 3108c2ecf20Sopenharmony_ci wfe /* CPU should be power gated here */ 3118c2ecf20Sopenharmony_ci isb 3128c2ecf20Sopenharmony_ci b halted 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/* 3158c2ecf20Sopenharmony_ci * tegra20_sdram_self_refresh 3168c2ecf20Sopenharmony_ci * 3178c2ecf20Sopenharmony_ci * called with MMU off and caches disabled 3188c2ecf20Sopenharmony_ci * puts sdram in self refresh 3198c2ecf20Sopenharmony_ci * must be executed from IRAM 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_citegra20_sdram_self_refresh: 3228c2ecf20Sopenharmony_ci mov32 r1, TEGRA_EMC_BASE @ r1 reserved for emc base addr 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci mov r2, #3 3258c2ecf20Sopenharmony_ci str r2, [r1, #EMC_REQ_CTRL] @ stall incoming DRAM requests 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ciemcidle: 3288c2ecf20Sopenharmony_ci ldr r2, [r1, #EMC_EMC_STATUS] 3298c2ecf20Sopenharmony_ci tst r2, #4 3308c2ecf20Sopenharmony_ci beq emcidle 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci mov r2, #1 3338c2ecf20Sopenharmony_ci str r2, [r1, #EMC_SELF_REF] 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci emc_device_mask r2, r1 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ciemcself: 3388c2ecf20Sopenharmony_ci ldr r3, [r1, #EMC_EMC_STATUS] 3398c2ecf20Sopenharmony_ci and r3, r3, r2 3408c2ecf20Sopenharmony_ci cmp r3, r2 3418c2ecf20Sopenharmony_ci bne emcself @ loop until DDR in self-refresh 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci adr r2, tegra20_sdram_pad_address 3448c2ecf20Sopenharmony_ci adr r3, tegra20_sdram_pad_safe 3458c2ecf20Sopenharmony_ci adr r4, tegra20_sdram_pad_save 3468c2ecf20Sopenharmony_ci mov r5, #0 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci ldr r6, tegra20_sdram_pad_size 3498c2ecf20Sopenharmony_cipadsave: 3508c2ecf20Sopenharmony_ci ldr r0, [r2, r5] @ r0 is the addr in the pad_address 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci ldr r1, [r0] 3538c2ecf20Sopenharmony_ci str r1, [r4, r5] @ save the content of the addr 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci ldr r1, [r3, r5] 3568c2ecf20Sopenharmony_ci str r1, [r0] @ set the save val to the addr 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci add r5, r5, #4 3598c2ecf20Sopenharmony_ci cmp r6, r5 3608c2ecf20Sopenharmony_ci bne padsave 3618c2ecf20Sopenharmony_cipadsave_done: 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci mov32 r5, TEGRA_CLK_RESET_BASE 3648c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_SCLK_BURST] 3658c2ecf20Sopenharmony_ci adr r2, tegra20_sclk_save 3668c2ecf20Sopenharmony_ci str r0, [r2] 3678c2ecf20Sopenharmony_ci dsb 3688c2ecf20Sopenharmony_ci ret lr 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_citegra20_sdram_pad_address: 3718c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL 3728c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL 3738c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CLKCFGPADCTRL 3748c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2COMPPADCTRL 3758c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2VTTGENPADCTRL 3768c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGCPADCTRL2 3778c2ecf20Sopenharmony_ci .word TEGRA_APB_MISC_BASE + APB_MISC_XM2CFGDPADCTRL2 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_citegra20_sdram_pad_size: 3808c2ecf20Sopenharmony_ci .word tegra20_sdram_pad_size - tegra20_sdram_pad_address 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_citegra20_sdram_pad_safe: 3838c2ecf20Sopenharmony_ci .word 0x8 3848c2ecf20Sopenharmony_ci .word 0x8 3858c2ecf20Sopenharmony_ci .word 0x0 3868c2ecf20Sopenharmony_ci .word 0x8 3878c2ecf20Sopenharmony_ci .word 0x5500 3888c2ecf20Sopenharmony_ci .word 0x08080040 3898c2ecf20Sopenharmony_ci .word 0x0 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_citegra20_sclk_save: 3928c2ecf20Sopenharmony_ci .word 0x0 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_citegra20_sdram_pad_save: 3958c2ecf20Sopenharmony_ci .rept (tegra20_sdram_pad_size - tegra20_sdram_pad_address) / 4 3968c2ecf20Sopenharmony_ci .long 0 3978c2ecf20Sopenharmony_ci .endr 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci .ltorg 4008c2ecf20Sopenharmony_ci/* dummy symbol for end of IRAM */ 4018c2ecf20Sopenharmony_ci .align L1_CACHE_SHIFT 4028c2ecf20Sopenharmony_ci .globl tegra20_iram_end 4038c2ecf20Sopenharmony_citegra20_iram_end: 4048c2ecf20Sopenharmony_ci b . 4058c2ecf20Sopenharmony_ci#endif 406