18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2012, NVIDIA Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/linkage.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <soc/tegra/flowctrl.h> 98c2ecf20Sopenharmony_ci#include <soc/tegra/fuse.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h> 128c2ecf20Sopenharmony_ci#include <asm/assembler.h> 138c2ecf20Sopenharmony_ci#include <asm/cache.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "irammap.h" 168c2ecf20Sopenharmony_ci#include "sleep.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define EMC_CFG 0xc 198c2ecf20Sopenharmony_ci#define EMC_ADR_CFG 0x10 208c2ecf20Sopenharmony_ci#define EMC_TIMING_CONTROL 0x28 218c2ecf20Sopenharmony_ci#define EMC_NOP 0xdc 228c2ecf20Sopenharmony_ci#define EMC_SELF_REF 0xe0 238c2ecf20Sopenharmony_ci#define EMC_MRW 0xe8 248c2ecf20Sopenharmony_ci#define EMC_FBIO_CFG5 0x104 258c2ecf20Sopenharmony_ci#define EMC_AUTO_CAL_CONFIG 0x2a4 268c2ecf20Sopenharmony_ci#define EMC_AUTO_CAL_INTERVAL 0x2a8 278c2ecf20Sopenharmony_ci#define EMC_AUTO_CAL_STATUS 0x2ac 288c2ecf20Sopenharmony_ci#define EMC_REQ_CTRL 0x2b0 298c2ecf20Sopenharmony_ci#define EMC_CFG_DIG_DLL 0x2bc 308c2ecf20Sopenharmony_ci#define EMC_EMC_STATUS 0x2b4 318c2ecf20Sopenharmony_ci#define EMC_ZCAL_INTERVAL 0x2e0 328c2ecf20Sopenharmony_ci#define EMC_ZQ_CAL 0x2ec 338c2ecf20Sopenharmony_ci#define EMC_XM2VTTGENPADCTRL 0x310 348c2ecf20Sopenharmony_ci#define EMC_XM2VTTGENPADCTRL2 0x314 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define PMC_CTRL 0x0 378c2ecf20Sopenharmony_ci#define PMC_CTRL_SIDE_EFFECT_LP0 (1 << 14) /* enter LP0 when CPU pwr gated */ 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define PMC_PLLP_WB0_OVERRIDE 0xf8 408c2ecf20Sopenharmony_ci#define PMC_IO_DPD_REQ 0x1b8 418c2ecf20Sopenharmony_ci#define PMC_IO_DPD_STATUS 0x1bc 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define CLK_RESET_CCLK_BURST 0x20 448c2ecf20Sopenharmony_ci#define CLK_RESET_CCLK_DIVIDER 0x24 458c2ecf20Sopenharmony_ci#define CLK_RESET_SCLK_BURST 0x28 468c2ecf20Sopenharmony_ci#define CLK_RESET_SCLK_DIVIDER 0x2c 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define CLK_RESET_PLLC_BASE 0x80 498c2ecf20Sopenharmony_ci#define CLK_RESET_PLLC_MISC 0x8c 508c2ecf20Sopenharmony_ci#define CLK_RESET_PLLM_BASE 0x90 518c2ecf20Sopenharmony_ci#define CLK_RESET_PLLM_MISC 0x9c 528c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_BASE 0xa0 538c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_MISC 0xac 548c2ecf20Sopenharmony_ci#define CLK_RESET_PLLA_BASE 0xb0 558c2ecf20Sopenharmony_ci#define CLK_RESET_PLLA_MISC 0xbc 568c2ecf20Sopenharmony_ci#define CLK_RESET_PLLX_BASE 0xe0 578c2ecf20Sopenharmony_ci#define CLK_RESET_PLLX_MISC 0xe4 588c2ecf20Sopenharmony_ci#define CLK_RESET_PLLX_MISC3 0x518 598c2ecf20Sopenharmony_ci#define CLK_RESET_PLLX_MISC3_IDDQ 3 608c2ecf20Sopenharmony_ci#define CLK_RESET_PLLM_MISC_IDDQ 5 618c2ecf20Sopenharmony_ci#define CLK_RESET_PLLC_MISC_IDDQ 26 628c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_RESHIFT 0x528 638c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_RESHIFT_DEFAULT 0x3b 648c2ecf20Sopenharmony_ci#define CLK_RESET_PLLP_RESHIFT_ENABLE 0x3 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define CLK_RESET_CLK_SOURCE_MSELECT 0x3b4 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define MSELECT_CLKM (0x3 << 30) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define LOCK_DELAY 50 /* safety delay after lock is detected */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define TEGRA30_POWER_HOTPLUG_SHUTDOWN (1 << 27) /* Hotplug shutdown */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci.macro emc_device_mask, rd, base 758c2ecf20Sopenharmony_ci ldr \rd, [\base, #EMC_ADR_CFG] 768c2ecf20Sopenharmony_ci tst \rd, #0x1 778c2ecf20Sopenharmony_ci moveq \rd, #(0x1 << 8) @ just 1 device 788c2ecf20Sopenharmony_ci movne \rd, #(0x3 << 8) @ 2 devices 798c2ecf20Sopenharmony_ci.endm 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci.macro emc_timing_update, rd, base 828c2ecf20Sopenharmony_ci mov \rd, #1 838c2ecf20Sopenharmony_ci str \rd, [\base, #EMC_TIMING_CONTROL] 848c2ecf20Sopenharmony_ci1001: 858c2ecf20Sopenharmony_ci ldr \rd, [\base, #EMC_EMC_STATUS] 868c2ecf20Sopenharmony_ci tst \rd, #(0x1<<23) @ wait EMC_STATUS_TIMING_UPDATE_STALLED is clear 878c2ecf20Sopenharmony_ci bne 1001b 888c2ecf20Sopenharmony_ci.endm 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci.macro pll_enable, rd, r_car_base, pll_base, pll_misc 918c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_base] 928c2ecf20Sopenharmony_ci tst \rd, #(1 << 30) 938c2ecf20Sopenharmony_ci orreq \rd, \rd, #(1 << 30) 948c2ecf20Sopenharmony_ci streq \rd, [\r_car_base, #\pll_base] 958c2ecf20Sopenharmony_ci /* Enable lock detector */ 968c2ecf20Sopenharmony_ci .if \pll_misc 978c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_misc] 988c2ecf20Sopenharmony_ci bic \rd, \rd, #(1 << 18) 998c2ecf20Sopenharmony_ci str \rd, [\r_car_base, #\pll_misc] 1008c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_misc] 1018c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_misc] 1028c2ecf20Sopenharmony_ci orr \rd, \rd, #(1 << 18) 1038c2ecf20Sopenharmony_ci str \rd, [\r_car_base, #\pll_misc] 1048c2ecf20Sopenharmony_ci .endif 1058c2ecf20Sopenharmony_ci.endm 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci.macro pll_locked, rd, r_car_base, pll_base 1088c2ecf20Sopenharmony_ci1: 1098c2ecf20Sopenharmony_ci ldr \rd, [\r_car_base, #\pll_base] 1108c2ecf20Sopenharmony_ci tst \rd, #(1 << 27) 1118c2ecf20Sopenharmony_ci beq 1b 1128c2ecf20Sopenharmony_ci.endm 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci.macro pll_iddq_exit, rd, car, iddq, iddq_bit 1158c2ecf20Sopenharmony_ci ldr \rd, [\car, #\iddq] 1168c2ecf20Sopenharmony_ci bic \rd, \rd, #(1<<\iddq_bit) 1178c2ecf20Sopenharmony_ci str \rd, [\car, #\iddq] 1188c2ecf20Sopenharmony_ci.endm 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci.macro pll_iddq_entry, rd, car, iddq, iddq_bit 1218c2ecf20Sopenharmony_ci ldr \rd, [\car, #\iddq] 1228c2ecf20Sopenharmony_ci orr \rd, \rd, #(1<<\iddq_bit) 1238c2ecf20Sopenharmony_ci str \rd, [\car, #\iddq] 1248c2ecf20Sopenharmony_ci.endm 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP) 1278c2ecf20Sopenharmony_ci/* 1288c2ecf20Sopenharmony_ci * tegra30_hotplug_shutdown(void) 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * Powergates the current CPU. 1318c2ecf20Sopenharmony_ci * Should never return. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ciENTRY(tegra30_hotplug_shutdown) 1348c2ecf20Sopenharmony_ci /* Powergate this CPU */ 1358c2ecf20Sopenharmony_ci mov r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN 1368c2ecf20Sopenharmony_ci bl tegra30_cpu_shutdown 1378c2ecf20Sopenharmony_ci ret lr @ should never get here 1388c2ecf20Sopenharmony_ciENDPROC(tegra30_hotplug_shutdown) 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* 1418c2ecf20Sopenharmony_ci * tegra30_cpu_shutdown(unsigned long flags) 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * Puts the current CPU in wait-for-event mode on the flow controller 1448c2ecf20Sopenharmony_ci * and powergates it -- flags (in R0) indicate the request type. 1458c2ecf20Sopenharmony_ci * 1468c2ecf20Sopenharmony_ci * r10 = SoC ID 1478c2ecf20Sopenharmony_ci * corrupts r0-r4, r10-r12 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ciENTRY(tegra30_cpu_shutdown) 1508c2ecf20Sopenharmony_ci cpu_id r3 1518c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_VIRT, r10 1528c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 1538c2ecf20Sopenharmony_ci bne _no_cpu0_chk @ It's not Tegra30 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci cmp r3, #0 1568c2ecf20Sopenharmony_ci reteq lr @ Must never be called for CPU 0 1578c2ecf20Sopenharmony_ci_no_cpu0_chk: 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci ldr r12, =TEGRA_FLOW_CTRL_VIRT 1608c2ecf20Sopenharmony_ci cpu_to_csr_reg r1, r3 1618c2ecf20Sopenharmony_ci add r1, r1, r12 @ virtual CSR address for this CPU 1628c2ecf20Sopenharmony_ci cpu_to_halt_reg r2, r3 1638c2ecf20Sopenharmony_ci add r2, r2, r12 @ virtual HALT_EVENTS address for this CPU 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* 1668c2ecf20Sopenharmony_ci * Clear this CPU's "event" and "interrupt" flags and power gate 1678c2ecf20Sopenharmony_ci * it when halting but not before it is in the "WFE" state. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci movw r12, \ 1708c2ecf20Sopenharmony_ci FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \ 1718c2ecf20Sopenharmony_ci FLOW_CTRL_CSR_ENABLE 1728c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 1738c2ecf20Sopenharmony_ci moveq r4, #(1 << 4) @ wfe bitmap 1748c2ecf20Sopenharmony_ci movne r4, #(1 << 8) @ wfi bitmap 1758c2ecf20Sopenharmony_ci ARM( orr r12, r12, r4, lsl r3 ) 1768c2ecf20Sopenharmony_ci THUMB( lsl r4, r4, r3 ) 1778c2ecf20Sopenharmony_ci THUMB( orr r12, r12, r4 ) 1788c2ecf20Sopenharmony_ci str r12, [r1] 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* Halt this CPU. */ 1818c2ecf20Sopenharmony_ci mov r3, #0x400 1828c2ecf20Sopenharmony_cidelay_1: 1838c2ecf20Sopenharmony_ci subs r3, r3, #1 @ delay as a part of wfe war. 1848c2ecf20Sopenharmony_ci bge delay_1; 1858c2ecf20Sopenharmony_ci cpsid a @ disable imprecise aborts. 1868c2ecf20Sopenharmony_ci ldr r3, [r1] @ read CSR 1878c2ecf20Sopenharmony_ci str r3, [r1] @ clear CSR 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci tst r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN 1908c2ecf20Sopenharmony_ci beq flow_ctrl_setting_for_lp2 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* flow controller set up for hotplug */ 1938c2ecf20Sopenharmony_ci mov r3, #FLOW_CTRL_WAITEVENT @ For hotplug 1948c2ecf20Sopenharmony_ci b flow_ctrl_done 1958c2ecf20Sopenharmony_ciflow_ctrl_setting_for_lp2: 1968c2ecf20Sopenharmony_ci /* flow controller set up for LP2 */ 1978c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 1988c2ecf20Sopenharmony_ci moveq r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT @ For LP2 1998c2ecf20Sopenharmony_ci movne r3, #FLOW_CTRL_WAITEVENT 2008c2ecf20Sopenharmony_ci orrne r3, r3, #FLOW_CTRL_HALT_GIC_IRQ 2018c2ecf20Sopenharmony_ci orrne r3, r3, #FLOW_CTRL_HALT_GIC_FIQ 2028c2ecf20Sopenharmony_ciflow_ctrl_done: 2038c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 2048c2ecf20Sopenharmony_ci str r3, [r2] 2058c2ecf20Sopenharmony_ci ldr r0, [r2] 2068c2ecf20Sopenharmony_ci b wfe_war 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci__cpu_reset_again: 2098c2ecf20Sopenharmony_ci dsb 2108c2ecf20Sopenharmony_ci .align 5 2118c2ecf20Sopenharmony_ci wfeeq @ CPU should be power gated here 2128c2ecf20Sopenharmony_ci wfine 2138c2ecf20Sopenharmony_ciwfe_war: 2148c2ecf20Sopenharmony_ci b __cpu_reset_again 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * 38 nop's, which fills rest of wfe cache line and 2188c2ecf20Sopenharmony_ci * 4 more cachelines with nop 2198c2ecf20Sopenharmony_ci */ 2208c2ecf20Sopenharmony_ci .rept 38 2218c2ecf20Sopenharmony_ci nop 2228c2ecf20Sopenharmony_ci .endr 2238c2ecf20Sopenharmony_ci b . @ should never get here 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciENDPROC(tegra30_cpu_shutdown) 2268c2ecf20Sopenharmony_ci#endif 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 2298c2ecf20Sopenharmony_ci/* 2308c2ecf20Sopenharmony_ci * tegra30_sleep_core_finish(unsigned long v2p) 2318c2ecf20Sopenharmony_ci * 2328c2ecf20Sopenharmony_ci * Enters suspend in LP0 or LP1 by turning off the MMU and jumping to 2338c2ecf20Sopenharmony_ci * tegra30_tear_down_core in IRAM 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_ciENTRY(tegra30_sleep_core_finish) 2368c2ecf20Sopenharmony_ci mov r4, r0 2378c2ecf20Sopenharmony_ci /* Flush, disable the L1 data cache and exit SMP */ 2388c2ecf20Sopenharmony_ci mov r0, #TEGRA_FLUSH_CACHE_ALL 2398c2ecf20Sopenharmony_ci bl tegra_disable_clean_inv_dcache 2408c2ecf20Sopenharmony_ci mov r0, r4 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* 2438c2ecf20Sopenharmony_ci * Preload all the address literals that are needed for the 2448c2ecf20Sopenharmony_ci * CPU power-gating process, to avoid loading from SDRAM which 2458c2ecf20Sopenharmony_ci * are not supported once SDRAM is put into self-refresh. 2468c2ecf20Sopenharmony_ci * LP0 / LP1 use physical address, since the MMU needs to be 2478c2ecf20Sopenharmony_ci * disabled before putting SDRAM into self-refresh to avoid 2488c2ecf20Sopenharmony_ci * memory access due to page table walks. 2498c2ecf20Sopenharmony_ci */ 2508c2ecf20Sopenharmony_ci mov32 r4, TEGRA_PMC_BASE 2518c2ecf20Sopenharmony_ci mov32 r5, TEGRA_CLK_RESET_BASE 2528c2ecf20Sopenharmony_ci mov32 r6, TEGRA_FLOW_CTRL_BASE 2538c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci mov32 r3, tegra_shut_off_mmu 2568c2ecf20Sopenharmony_ci add r3, r3, r0 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci mov32 r0, tegra30_tear_down_core 2598c2ecf20Sopenharmony_ci mov32 r1, tegra30_iram_start 2608c2ecf20Sopenharmony_ci sub r0, r0, r1 2618c2ecf20Sopenharmony_ci mov32 r1, TEGRA_IRAM_LPx_RESUME_AREA 2628c2ecf20Sopenharmony_ci add r0, r0, r1 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci ret r3 2658c2ecf20Sopenharmony_ciENDPROC(tegra30_sleep_core_finish) 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/* 2688c2ecf20Sopenharmony_ci * tegra30_pm_secondary_cpu_suspend(unsigned long unused_arg) 2698c2ecf20Sopenharmony_ci * 2708c2ecf20Sopenharmony_ci * Enters LP2 on secondary CPU by exiting coherency and powergating the CPU. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_ciENTRY(tegra30_pm_secondary_cpu_suspend) 2738c2ecf20Sopenharmony_ci mov r7, lr 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* Flush and disable the L1 data cache */ 2768c2ecf20Sopenharmony_ci mov r0, #TEGRA_FLUSH_CACHE_LOUIS 2778c2ecf20Sopenharmony_ci bl tegra_disable_clean_inv_dcache 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Powergate this CPU. */ 2808c2ecf20Sopenharmony_ci mov r0, #0 @ power mode flags (!hotplug) 2818c2ecf20Sopenharmony_ci bl tegra30_cpu_shutdown 2828c2ecf20Sopenharmony_ci mov r0, #1 @ never return here 2838c2ecf20Sopenharmony_ci ret r7 2848c2ecf20Sopenharmony_ciENDPROC(tegra30_pm_secondary_cpu_suspend) 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci/* 2878c2ecf20Sopenharmony_ci * tegra30_tear_down_cpu 2888c2ecf20Sopenharmony_ci * 2898c2ecf20Sopenharmony_ci * Switches the CPU to enter sleep. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ciENTRY(tegra30_tear_down_cpu) 2928c2ecf20Sopenharmony_ci mov32 r6, TEGRA_FLOW_CTRL_BASE 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci b tegra30_enter_sleep 2958c2ecf20Sopenharmony_ciENDPROC(tegra30_tear_down_cpu) 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* START OF ROUTINES COPIED TO IRAM */ 2988c2ecf20Sopenharmony_ci .align L1_CACHE_SHIFT 2998c2ecf20Sopenharmony_ci .globl tegra30_iram_start 3008c2ecf20Sopenharmony_citegra30_iram_start: 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci/* 3038c2ecf20Sopenharmony_ci * tegra30_lp1_reset 3048c2ecf20Sopenharmony_ci * 3058c2ecf20Sopenharmony_ci * reset vector for LP1 restore; copied into IRAM during suspend. 3068c2ecf20Sopenharmony_ci * Brings the system back up to a safe staring point (SDRAM out of 3078c2ecf20Sopenharmony_ci * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLX, 3088c2ecf20Sopenharmony_ci * system clock running on the same PLL that it suspended at), and 3098c2ecf20Sopenharmony_ci * jumps to tegra_resume to restore virtual addressing. 3108c2ecf20Sopenharmony_ci * The physical address of tegra_resume expected to be stored in 3118c2ecf20Sopenharmony_ci * PMC_SCRATCH41. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_LPx_RESUME_AREA. 3148c2ecf20Sopenharmony_ci */ 3158c2ecf20Sopenharmony_ciENTRY(tegra30_lp1_reset) 3168c2ecf20Sopenharmony_ci /* 3178c2ecf20Sopenharmony_ci * The CPU and system bus are running at 32KHz and executing from 3188c2ecf20Sopenharmony_ci * IRAM when this code is executed; immediately switch to CLKM and 3198c2ecf20Sopenharmony_ci * enable PLLP, PLLM, PLLC, PLLA and PLLX. 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ci mov32 r0, TEGRA_CLK_RESET_BASE 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci mov r1, #(1 << 28) 3248c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_SCLK_BURST] 3258c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_CCLK_BURST] 3268c2ecf20Sopenharmony_ci mov r1, #0 3278c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_CCLK_DIVIDER] 3288c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_SCLK_DIVIDER] 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_BASE, r10 3318c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 3328c2ecf20Sopenharmony_ci beq _no_pll_iddq_exit 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci pll_iddq_exit r1, r0, CLK_RESET_PLLM_MISC, CLK_RESET_PLLM_MISC_IDDQ 3358c2ecf20Sopenharmony_ci pll_iddq_exit r1, r0, CLK_RESET_PLLC_MISC, CLK_RESET_PLLC_MISC_IDDQ 3368c2ecf20Sopenharmony_ci pll_iddq_exit r1, r0, CLK_RESET_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 3398c2ecf20Sopenharmony_ci ldr r1, [r7] 3408c2ecf20Sopenharmony_ci add r1, r1, #2 3418c2ecf20Sopenharmony_ci wait_until r1, r7, r3 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /* enable PLLM via PMC */ 3448c2ecf20Sopenharmony_ci mov32 r2, TEGRA_PMC_BASE 3458c2ecf20Sopenharmony_ci ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE] 3468c2ecf20Sopenharmony_ci orr r1, r1, #(1 << 12) 3478c2ecf20Sopenharmony_ci str r1, [r2, #PMC_PLLP_WB0_OVERRIDE] 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLM_BASE, 0 3508c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLC_BASE, 0 3518c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLX_BASE, 0 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci b _pll_m_c_x_done 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci_no_pll_iddq_exit: 3568c2ecf20Sopenharmony_ci /* enable PLLM via PMC */ 3578c2ecf20Sopenharmony_ci mov32 r2, TEGRA_PMC_BASE 3588c2ecf20Sopenharmony_ci ldr r1, [r2, #PMC_PLLP_WB0_OVERRIDE] 3598c2ecf20Sopenharmony_ci orr r1, r1, #(1 << 12) 3608c2ecf20Sopenharmony_ci str r1, [r2, #PMC_PLLP_WB0_OVERRIDE] 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLM_BASE, CLK_RESET_PLLM_MISC 3638c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLC_BASE, CLK_RESET_PLLC_MISC 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci_pll_m_c_x_done: 3668c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLP_BASE, CLK_RESET_PLLP_MISC 3678c2ecf20Sopenharmony_ci pll_enable r1, r0, CLK_RESET_PLLA_BASE, CLK_RESET_PLLA_MISC 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci pll_locked r1, r0, CLK_RESET_PLLM_BASE 3708c2ecf20Sopenharmony_ci pll_locked r1, r0, CLK_RESET_PLLP_BASE 3718c2ecf20Sopenharmony_ci pll_locked r1, r0, CLK_RESET_PLLA_BASE 3728c2ecf20Sopenharmony_ci pll_locked r1, r0, CLK_RESET_PLLC_BASE 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci /* 3758c2ecf20Sopenharmony_ci * CPUFreq driver could select other PLL for CPU. PLLX will be 3768c2ecf20Sopenharmony_ci * enabled by the Tegra30 CLK driver on an as-needed basis, see 3778c2ecf20Sopenharmony_ci * tegra30_cpu_clock_resume(). 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 3808c2ecf20Sopenharmony_ci cmp r1, #TEGRA30 3818c2ecf20Sopenharmony_ci beq 1f 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci pll_locked r1, r0, CLK_RESET_PLLX_BASE 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci ldr r1, [r0, #CLK_RESET_PLLP_BASE] 3868c2ecf20Sopenharmony_ci bic r1, r1, #(1<<31) @ disable PllP bypass 3878c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_PLLP_BASE] 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci mov r1, #CLK_RESET_PLLP_RESHIFT_DEFAULT 3908c2ecf20Sopenharmony_ci str r1, [r0, #CLK_RESET_PLLP_RESHIFT] 3918c2ecf20Sopenharmony_ci1: 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 3948c2ecf20Sopenharmony_ci ldr r1, [r7] 3958c2ecf20Sopenharmony_ci add r1, r1, #LOCK_DELAY 3968c2ecf20Sopenharmony_ci wait_until r1, r7, r3 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci adr r5, tegra_sdram_pad_save 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci ldr r4, [r5, #0x18] @ restore CLK_SOURCE_MSELECT 4018c2ecf20Sopenharmony_ci str r4, [r0, #CLK_RESET_CLK_SOURCE_MSELECT] 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci ldr r4, [r5, #0x1C] @ restore SCLK_BURST 4048c2ecf20Sopenharmony_ci str r4, [r0, #CLK_RESET_SCLK_BURST] 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci movw r4, #:lower16:((1 << 28) | (0x4)) @ burst policy is PLLP 4078c2ecf20Sopenharmony_ci movt r4, #:upper16:((1 << 28) | (0x4)) 4088c2ecf20Sopenharmony_ci str r4, [r0, #CLK_RESET_CCLK_BURST] 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* Restore pad power state to normal */ 4118c2ecf20Sopenharmony_ci ldr r1, [r5, #0x14] @ PMC_IO_DPD_STATUS 4128c2ecf20Sopenharmony_ci mvn r1, r1 4138c2ecf20Sopenharmony_ci bic r1, r1, #(1 << 31) 4148c2ecf20Sopenharmony_ci orr r1, r1, #(1 << 30) 4158c2ecf20Sopenharmony_ci str r1, [r2, #PMC_IO_DPD_REQ] @ DPD_OFF 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 4188c2ecf20Sopenharmony_ci movweq r0, #:lower16:TEGRA_EMC_BASE @ r0 reserved for emc base 4198c2ecf20Sopenharmony_ci movteq r0, #:upper16:TEGRA_EMC_BASE 4208c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 4218c2ecf20Sopenharmony_ci movweq r0, #:lower16:TEGRA_EMC0_BASE 4228c2ecf20Sopenharmony_ci movteq r0, #:upper16:TEGRA_EMC0_BASE 4238c2ecf20Sopenharmony_ci cmp r10, #TEGRA124 4248c2ecf20Sopenharmony_ci movweq r0, #:lower16:TEGRA124_EMC_BASE 4258c2ecf20Sopenharmony_ci movteq r0, #:upper16:TEGRA124_EMC_BASE 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ciexit_self_refresh: 4288c2ecf20Sopenharmony_ci ldr r1, [r5, #0xC] @ restore EMC_XM2VTTGENPADCTRL 4298c2ecf20Sopenharmony_ci str r1, [r0, #EMC_XM2VTTGENPADCTRL] 4308c2ecf20Sopenharmony_ci ldr r1, [r5, #0x10] @ restore EMC_XM2VTTGENPADCTRL2 4318c2ecf20Sopenharmony_ci str r1, [r0, #EMC_XM2VTTGENPADCTRL2] 4328c2ecf20Sopenharmony_ci ldr r1, [r5, #0x8] @ restore EMC_AUTO_CAL_INTERVAL 4338c2ecf20Sopenharmony_ci str r1, [r0, #EMC_AUTO_CAL_INTERVAL] 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci /* Relock DLL */ 4368c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_CFG_DIG_DLL] 4378c2ecf20Sopenharmony_ci orr r1, r1, #(1 << 30) @ set DLL_RESET 4388c2ecf20Sopenharmony_ci str r1, [r0, #EMC_CFG_DIG_DLL] 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci emc_timing_update r1, r0 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 4438c2ecf20Sopenharmony_ci movweq r1, #:lower16:TEGRA_EMC1_BASE 4448c2ecf20Sopenharmony_ci movteq r1, #:upper16:TEGRA_EMC1_BASE 4458c2ecf20Sopenharmony_ci cmpeq r0, r1 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_AUTO_CAL_CONFIG] 4488c2ecf20Sopenharmony_ci orr r1, r1, #(1 << 31) @ set AUTO_CAL_ACTIVE 4498c2ecf20Sopenharmony_ci orreq r1, r1, #(1 << 27) @ set slave mode for channel 1 4508c2ecf20Sopenharmony_ci str r1, [r0, #EMC_AUTO_CAL_CONFIG] 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ciemc_wait_auto_cal_onetime: 4538c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_AUTO_CAL_STATUS] 4548c2ecf20Sopenharmony_ci tst r1, #(1 << 31) @ wait until AUTO_CAL_ACTIVE is cleared 4558c2ecf20Sopenharmony_ci bne emc_wait_auto_cal_onetime 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_CFG] 4588c2ecf20Sopenharmony_ci bic r1, r1, #(1 << 31) @ disable DRAM_CLK_STOP_PD 4598c2ecf20Sopenharmony_ci str r1, [r0, #EMC_CFG] 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci mov r1, #0 4628c2ecf20Sopenharmony_ci str r1, [r0, #EMC_SELF_REF] @ take DRAM out of self refresh 4638c2ecf20Sopenharmony_ci mov r1, #1 4648c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 4658c2ecf20Sopenharmony_ci streq r1, [r0, #EMC_NOP] 4668c2ecf20Sopenharmony_ci streq r1, [r0, #EMC_NOP] 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci emc_device_mask r1, r0 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ciexit_selfrefresh_loop: 4718c2ecf20Sopenharmony_ci ldr r2, [r0, #EMC_EMC_STATUS] 4728c2ecf20Sopenharmony_ci ands r2, r2, r1 4738c2ecf20Sopenharmony_ci bne exit_selfrefresh_loop 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci lsr r1, r1, #8 @ devSel, bit0:dev0, bit1:dev1 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci mov32 r7, TEGRA_TMRUS_BASE 4788c2ecf20Sopenharmony_ci ldr r2, [r0, #EMC_FBIO_CFG5] 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci and r2, r2, #3 @ check DRAM_TYPE 4818c2ecf20Sopenharmony_ci cmp r2, #2 4828c2ecf20Sopenharmony_ci beq emc_lpddr2 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci /* Issue a ZQ_CAL for dev0 - DDR3 */ 4858c2ecf20Sopenharmony_ci mov32 r2, 0x80000011 @ DEV_SELECTION=2, LENGTH=LONG, CMD=1 4868c2ecf20Sopenharmony_ci str r2, [r0, #EMC_ZQ_CAL] 4878c2ecf20Sopenharmony_ci ldr r2, [r7] 4888c2ecf20Sopenharmony_ci add r2, r2, #10 4898c2ecf20Sopenharmony_ci wait_until r2, r7, r3 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci tst r1, #2 4928c2ecf20Sopenharmony_ci beq zcal_done 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* Issue a ZQ_CAL for dev1 - DDR3 */ 4958c2ecf20Sopenharmony_ci mov32 r2, 0x40000011 @ DEV_SELECTION=1, LENGTH=LONG, CMD=1 4968c2ecf20Sopenharmony_ci str r2, [r0, #EMC_ZQ_CAL] 4978c2ecf20Sopenharmony_ci ldr r2, [r7] 4988c2ecf20Sopenharmony_ci add r2, r2, #10 4998c2ecf20Sopenharmony_ci wait_until r2, r7, r3 5008c2ecf20Sopenharmony_ci b zcal_done 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ciemc_lpddr2: 5038c2ecf20Sopenharmony_ci /* Issue a ZQ_CAL for dev0 - LPDDR2 */ 5048c2ecf20Sopenharmony_ci mov32 r2, 0x800A00AB @ DEV_SELECTION=2, MA=10, OP=0xAB 5058c2ecf20Sopenharmony_ci str r2, [r0, #EMC_MRW] 5068c2ecf20Sopenharmony_ci ldr r2, [r7] 5078c2ecf20Sopenharmony_ci add r2, r2, #1 5088c2ecf20Sopenharmony_ci wait_until r2, r7, r3 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci tst r1, #2 5118c2ecf20Sopenharmony_ci beq zcal_done 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci /* Issue a ZQ_CAL for dev0 - LPDDR2 */ 5148c2ecf20Sopenharmony_ci mov32 r2, 0x400A00AB @ DEV_SELECTION=1, MA=10, OP=0xAB 5158c2ecf20Sopenharmony_ci str r2, [r0, #EMC_MRW] 5168c2ecf20Sopenharmony_ci ldr r2, [r7] 5178c2ecf20Sopenharmony_ci add r2, r2, #1 5188c2ecf20Sopenharmony_ci wait_until r2, r7, r3 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cizcal_done: 5218c2ecf20Sopenharmony_ci mov r1, #0 @ unstall all transactions 5228c2ecf20Sopenharmony_ci str r1, [r0, #EMC_REQ_CTRL] 5238c2ecf20Sopenharmony_ci ldr r1, [r5, #0x4] @ restore EMC_ZCAL_INTERVAL 5248c2ecf20Sopenharmony_ci str r1, [r0, #EMC_ZCAL_INTERVAL] 5258c2ecf20Sopenharmony_ci ldr r1, [r5, #0x0] @ restore EMC_CFG 5268c2ecf20Sopenharmony_ci str r1, [r0, #EMC_CFG] 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci emc_timing_update r1, r0 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Tegra114 had dual EMC channel, now config the other one */ 5318c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 5328c2ecf20Sopenharmony_ci bne __no_dual_emc_chanl 5338c2ecf20Sopenharmony_ci mov32 r1, TEGRA_EMC1_BASE 5348c2ecf20Sopenharmony_ci cmp r0, r1 5358c2ecf20Sopenharmony_ci movne r0, r1 5368c2ecf20Sopenharmony_ci addne r5, r5, #0x20 5378c2ecf20Sopenharmony_ci bne exit_self_refresh 5388c2ecf20Sopenharmony_ci__no_dual_emc_chanl: 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci mov32 r0, TEGRA_PMC_BASE 5418c2ecf20Sopenharmony_ci ldr r0, [r0, #PMC_SCRATCH41] 5428c2ecf20Sopenharmony_ci ret r0 @ jump to tegra_resume 5438c2ecf20Sopenharmony_ciENDPROC(tegra30_lp1_reset) 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci .align L1_CACHE_SHIFT 5468c2ecf20Sopenharmony_citegra30_sdram_pad_address: 5478c2ecf20Sopenharmony_ci .word TEGRA_EMC_BASE + EMC_CFG @0x0 5488c2ecf20Sopenharmony_ci .word TEGRA_EMC_BASE + EMC_ZCAL_INTERVAL @0x4 5498c2ecf20Sopenharmony_ci .word TEGRA_EMC_BASE + EMC_AUTO_CAL_INTERVAL @0x8 5508c2ecf20Sopenharmony_ci .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL @0xc 5518c2ecf20Sopenharmony_ci .word TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL2 @0x10 5528c2ecf20Sopenharmony_ci .word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14 5538c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18 5548c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c 5558c2ecf20Sopenharmony_citegra30_sdram_pad_address_end: 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_citegra114_sdram_pad_address: 5588c2ecf20Sopenharmony_ci .word TEGRA_EMC0_BASE + EMC_CFG @0x0 5598c2ecf20Sopenharmony_ci .word TEGRA_EMC0_BASE + EMC_ZCAL_INTERVAL @0x4 5608c2ecf20Sopenharmony_ci .word TEGRA_EMC0_BASE + EMC_AUTO_CAL_INTERVAL @0x8 5618c2ecf20Sopenharmony_ci .word TEGRA_EMC0_BASE + EMC_XM2VTTGENPADCTRL @0xc 5628c2ecf20Sopenharmony_ci .word TEGRA_EMC0_BASE + EMC_XM2VTTGENPADCTRL2 @0x10 5638c2ecf20Sopenharmony_ci .word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14 5648c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18 5658c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c 5668c2ecf20Sopenharmony_ci .word TEGRA_EMC1_BASE + EMC_CFG @0x20 5678c2ecf20Sopenharmony_ci .word TEGRA_EMC1_BASE + EMC_ZCAL_INTERVAL @0x24 5688c2ecf20Sopenharmony_ci .word TEGRA_EMC1_BASE + EMC_AUTO_CAL_INTERVAL @0x28 5698c2ecf20Sopenharmony_ci .word TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL @0x2c 5708c2ecf20Sopenharmony_ci .word TEGRA_EMC1_BASE + EMC_XM2VTTGENPADCTRL2 @0x30 5718c2ecf20Sopenharmony_citegra114_sdram_pad_adress_end: 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_citegra124_sdram_pad_address: 5748c2ecf20Sopenharmony_ci .word TEGRA124_EMC_BASE + EMC_CFG @0x0 5758c2ecf20Sopenharmony_ci .word TEGRA124_EMC_BASE + EMC_ZCAL_INTERVAL @0x4 5768c2ecf20Sopenharmony_ci .word TEGRA124_EMC_BASE + EMC_AUTO_CAL_INTERVAL @0x8 5778c2ecf20Sopenharmony_ci .word TEGRA124_EMC_BASE + EMC_XM2VTTGENPADCTRL @0xc 5788c2ecf20Sopenharmony_ci .word TEGRA124_EMC_BASE + EMC_XM2VTTGENPADCTRL2 @0x10 5798c2ecf20Sopenharmony_ci .word TEGRA_PMC_BASE + PMC_IO_DPD_STATUS @0x14 5808c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT @0x18 5818c2ecf20Sopenharmony_ci .word TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST @0x1c 5828c2ecf20Sopenharmony_citegra124_sdram_pad_address_end: 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_citegra30_sdram_pad_size: 5858c2ecf20Sopenharmony_ci .word tegra30_sdram_pad_address_end - tegra30_sdram_pad_address 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_citegra114_sdram_pad_size: 5888c2ecf20Sopenharmony_ci .word tegra114_sdram_pad_adress_end - tegra114_sdram_pad_address 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci .type tegra_sdram_pad_save, %object 5918c2ecf20Sopenharmony_citegra_sdram_pad_save: 5928c2ecf20Sopenharmony_ci .rept (tegra114_sdram_pad_adress_end - tegra114_sdram_pad_address) / 4 5938c2ecf20Sopenharmony_ci .long 0 5948c2ecf20Sopenharmony_ci .endr 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci/* 5978c2ecf20Sopenharmony_ci * tegra30_tear_down_core 5988c2ecf20Sopenharmony_ci * 5998c2ecf20Sopenharmony_ci * copied into and executed from IRAM 6008c2ecf20Sopenharmony_ci * puts memory in self-refresh for LP0 and LP1 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_citegra30_tear_down_core: 6038c2ecf20Sopenharmony_ci bl tegra30_sdram_self_refresh 6048c2ecf20Sopenharmony_ci bl tegra30_switch_cpu_to_clk32k 6058c2ecf20Sopenharmony_ci b tegra30_enter_sleep 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci/* 6088c2ecf20Sopenharmony_ci * tegra30_switch_cpu_to_clk32k 6098c2ecf20Sopenharmony_ci * 6108c2ecf20Sopenharmony_ci * In LP0 and LP1 all PLLs will be turned off. Switching the CPU and System CLK 6118c2ecf20Sopenharmony_ci * to the 32KHz clock. 6128c2ecf20Sopenharmony_ci * r4 = TEGRA_PMC_BASE 6138c2ecf20Sopenharmony_ci * r5 = TEGRA_CLK_RESET_BASE 6148c2ecf20Sopenharmony_ci * r6 = TEGRA_FLOW_CTRL_BASE 6158c2ecf20Sopenharmony_ci * r7 = TEGRA_TMRUS_BASE 6168c2ecf20Sopenharmony_ci * r10= SoC ID 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_citegra30_switch_cpu_to_clk32k: 6198c2ecf20Sopenharmony_ci /* 6208c2ecf20Sopenharmony_ci * start by jumping to CLKM to safely disable PLLs, then jump to 6218c2ecf20Sopenharmony_ci * CLKS. 6228c2ecf20Sopenharmony_ci */ 6238c2ecf20Sopenharmony_ci mov r0, #(1 << 28) 6248c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_BURST] 6258c2ecf20Sopenharmony_ci /* 2uS delay delay between changing SCLK and CCLK */ 6268c2ecf20Sopenharmony_ci ldr r1, [r7] 6278c2ecf20Sopenharmony_ci add r1, r1, #2 6288c2ecf20Sopenharmony_ci wait_until r1, r7, r9 6298c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_CCLK_BURST] 6308c2ecf20Sopenharmony_ci mov r0, #0 6318c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_CCLK_DIVIDER] 6328c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_DIVIDER] 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci /* switch the clock source of mselect to be CLK_M */ 6358c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT] 6368c2ecf20Sopenharmony_ci orr r0, r0, #MSELECT_CLKM 6378c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_CLK_SOURCE_MSELECT] 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci /* 2uS delay delay between changing SCLK and disabling PLLs */ 6408c2ecf20Sopenharmony_ci ldr r1, [r7] 6418c2ecf20Sopenharmony_ci add r1, r1, #2 6428c2ecf20Sopenharmony_ci wait_until r1, r7, r9 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* disable PLLM via PMC in LP1 */ 6458c2ecf20Sopenharmony_ci ldr r0, [r4, #PMC_PLLP_WB0_OVERRIDE] 6468c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 12) 6478c2ecf20Sopenharmony_ci str r0, [r4, #PMC_PLLP_WB0_OVERRIDE] 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci /* disable PLLP, PLLA, PLLC and PLLX */ 6508c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_BASE, r1 6518c2ecf20Sopenharmony_ci cmp r1, #TEGRA30 6528c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLP_BASE] 6538c2ecf20Sopenharmony_ci orrne r0, r0, #(1 << 31) @ enable PllP bypass on fast cluster 6548c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 6558c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLP_BASE] 6568c2ecf20Sopenharmony_ci beq 1f 6578c2ecf20Sopenharmony_ci mov r0, #CLK_RESET_PLLP_RESHIFT_ENABLE 6588c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLP_RESHIFT] 6598c2ecf20Sopenharmony_ci1: 6608c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLA_BASE] 6618c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 6628c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLA_BASE] 6638c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLC_BASE] 6648c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 6658c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLC_BASE] 6668c2ecf20Sopenharmony_ci ldr r0, [r5, #CLK_RESET_PLLX_BASE] 6678c2ecf20Sopenharmony_ci bic r0, r0, #(1 << 30) 6688c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_PLLX_BASE] 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 6718c2ecf20Sopenharmony_ci beq _no_pll_in_iddq 6728c2ecf20Sopenharmony_ci pll_iddq_entry r1, r5, CLK_RESET_PLLX_MISC3, CLK_RESET_PLLX_MISC3_IDDQ 6738c2ecf20Sopenharmony_ci_no_pll_in_iddq: 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci /* 6768c2ecf20Sopenharmony_ci * Switch to clk_s (32KHz); bits 28:31=0 6778c2ecf20Sopenharmony_ci * Enable burst on CPU IRQ; bit 24=1 6788c2ecf20Sopenharmony_ci * Set IRQ burst clock source to clk_m; bits 10:8=0 6798c2ecf20Sopenharmony_ci */ 6808c2ecf20Sopenharmony_ci mov r0, #(1 << 24) 6818c2ecf20Sopenharmony_ci str r0, [r5, #CLK_RESET_SCLK_BURST] 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci ret lr 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci/* 6868c2ecf20Sopenharmony_ci * tegra30_enter_sleep 6878c2ecf20Sopenharmony_ci * 6888c2ecf20Sopenharmony_ci * uses flow controller to enter sleep state 6898c2ecf20Sopenharmony_ci * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1 6908c2ecf20Sopenharmony_ci * executes from SDRAM with target state is LP2 6918c2ecf20Sopenharmony_ci * r6 = TEGRA_FLOW_CTRL_BASE 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_citegra30_enter_sleep: 6948c2ecf20Sopenharmony_ci cpu_id r1 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci cpu_to_csr_reg r2, r1 6978c2ecf20Sopenharmony_ci ldr r0, [r6, r2] 6988c2ecf20Sopenharmony_ci orr r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG 6998c2ecf20Sopenharmony_ci orr r0, r0, #FLOW_CTRL_CSR_ENABLE 7008c2ecf20Sopenharmony_ci str r0, [r6, r2] 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_BASE, r10 7038c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 7048c2ecf20Sopenharmony_ci mov r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT 7058c2ecf20Sopenharmony_ci orreq r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ 7068c2ecf20Sopenharmony_ci orrne r0, r0, #FLOW_CTRL_HALT_LIC_IRQ | FLOW_CTRL_HALT_LIC_FIQ 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci cpu_to_halt_reg r2, r1 7098c2ecf20Sopenharmony_ci str r0, [r6, r2] 7108c2ecf20Sopenharmony_ci dsb 7118c2ecf20Sopenharmony_ci ldr r0, [r6, r2] /* memory barrier */ 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 7148c2ecf20Sopenharmony_cihalted: 7158c2ecf20Sopenharmony_ci isb 7168c2ecf20Sopenharmony_ci dsb 7178c2ecf20Sopenharmony_ci wfine /* CPU should be power gated here */ 7188c2ecf20Sopenharmony_ci wfeeq 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci /* !!!FIXME!!! Implement halt failure handler */ 7218c2ecf20Sopenharmony_ci b halted 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci/* 7248c2ecf20Sopenharmony_ci * tegra30_sdram_self_refresh 7258c2ecf20Sopenharmony_ci * 7268c2ecf20Sopenharmony_ci * called with MMU off and caches disabled 7278c2ecf20Sopenharmony_ci * must be executed from IRAM 7288c2ecf20Sopenharmony_ci * r4 = TEGRA_PMC_BASE 7298c2ecf20Sopenharmony_ci * r5 = TEGRA_CLK_RESET_BASE 7308c2ecf20Sopenharmony_ci * r6 = TEGRA_FLOW_CTRL_BASE 7318c2ecf20Sopenharmony_ci * r7 = TEGRA_TMRUS_BASE 7328c2ecf20Sopenharmony_ci * r10= SoC ID 7338c2ecf20Sopenharmony_ci */ 7348c2ecf20Sopenharmony_citegra30_sdram_self_refresh: 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci adr r8, tegra_sdram_pad_save 7378c2ecf20Sopenharmony_ci tegra_get_soc_id TEGRA_APB_MISC_BASE, r10 7388c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 7398c2ecf20Sopenharmony_ci adreq r2, tegra30_sdram_pad_address 7408c2ecf20Sopenharmony_ci ldreq r3, tegra30_sdram_pad_size 7418c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 7428c2ecf20Sopenharmony_ci adreq r2, tegra114_sdram_pad_address 7438c2ecf20Sopenharmony_ci ldreq r3, tegra114_sdram_pad_size 7448c2ecf20Sopenharmony_ci cmp r10, #TEGRA124 7458c2ecf20Sopenharmony_ci adreq r2, tegra124_sdram_pad_address 7468c2ecf20Sopenharmony_ci ldreq r3, tegra30_sdram_pad_size 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci mov r9, #0 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_cipadsave: 7518c2ecf20Sopenharmony_ci ldr r0, [r2, r9] @ r0 is the addr in the pad_address 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci ldr r1, [r0] 7548c2ecf20Sopenharmony_ci str r1, [r8, r9] @ save the content of the addr 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci add r9, r9, #4 7578c2ecf20Sopenharmony_ci cmp r3, r9 7588c2ecf20Sopenharmony_ci bne padsave 7598c2ecf20Sopenharmony_cipadsave_done: 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci dsb 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 7648c2ecf20Sopenharmony_ci ldreq r0, =TEGRA_EMC_BASE @ r0 reserved for emc base addr 7658c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 7668c2ecf20Sopenharmony_ci ldreq r0, =TEGRA_EMC0_BASE 7678c2ecf20Sopenharmony_ci cmp r10, #TEGRA124 7688c2ecf20Sopenharmony_ci ldreq r0, =TEGRA124_EMC_BASE 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_cienter_self_refresh: 7718c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 7728c2ecf20Sopenharmony_ci mov r1, #0 7738c2ecf20Sopenharmony_ci str r1, [r0, #EMC_ZCAL_INTERVAL] 7748c2ecf20Sopenharmony_ci str r1, [r0, #EMC_AUTO_CAL_INTERVAL] 7758c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_CFG] 7768c2ecf20Sopenharmony_ci bic r1, r1, #(1 << 28) 7778c2ecf20Sopenharmony_ci bicne r1, r1, #(1 << 29) 7788c2ecf20Sopenharmony_ci str r1, [r0, #EMC_CFG] @ disable DYN_SELF_REF 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci emc_timing_update r1, r0 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci ldr r1, [r7] 7838c2ecf20Sopenharmony_ci add r1, r1, #5 7848c2ecf20Sopenharmony_ci wait_until r1, r7, r2 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ciemc_wait_auto_cal: 7878c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_AUTO_CAL_STATUS] 7888c2ecf20Sopenharmony_ci tst r1, #(1 << 31) @ wait until AUTO_CAL_ACTIVE is cleared 7898c2ecf20Sopenharmony_ci bne emc_wait_auto_cal 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci mov r1, #3 7928c2ecf20Sopenharmony_ci str r1, [r0, #EMC_REQ_CTRL] @ stall incoming DRAM requests 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ciemcidle: 7958c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_EMC_STATUS] 7968c2ecf20Sopenharmony_ci tst r1, #4 7978c2ecf20Sopenharmony_ci beq emcidle 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci mov r1, #1 8008c2ecf20Sopenharmony_ci str r1, [r0, #EMC_SELF_REF] 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci emc_device_mask r1, r0 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ciemcself: 8058c2ecf20Sopenharmony_ci ldr r2, [r0, #EMC_EMC_STATUS] 8068c2ecf20Sopenharmony_ci and r2, r2, r1 8078c2ecf20Sopenharmony_ci cmp r2, r1 8088c2ecf20Sopenharmony_ci bne emcself @ loop until DDR in self-refresh 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci /* Put VTTGEN in the lowest power mode */ 8118c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_XM2VTTGENPADCTRL] 8128c2ecf20Sopenharmony_ci mov32 r2, 0xF8F8FFFF @ clear XM2VTTGEN_DRVUP and XM2VTTGEN_DRVDN 8138c2ecf20Sopenharmony_ci and r1, r1, r2 8148c2ecf20Sopenharmony_ci str r1, [r0, #EMC_XM2VTTGENPADCTRL] 8158c2ecf20Sopenharmony_ci ldr r1, [r0, #EMC_XM2VTTGENPADCTRL2] 8168c2ecf20Sopenharmony_ci cmp r10, #TEGRA30 8178c2ecf20Sopenharmony_ci orreq r1, r1, #7 @ set E_NO_VTTGEN 8188c2ecf20Sopenharmony_ci orrne r1, r1, #0x3f 8198c2ecf20Sopenharmony_ci str r1, [r0, #EMC_XM2VTTGENPADCTRL2] 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci emc_timing_update r1, r0 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci /* Tegra114 had dual EMC channel, now config the other one */ 8248c2ecf20Sopenharmony_ci cmp r10, #TEGRA114 8258c2ecf20Sopenharmony_ci bne no_dual_emc_chanl 8268c2ecf20Sopenharmony_ci mov32 r1, TEGRA_EMC1_BASE 8278c2ecf20Sopenharmony_ci cmp r0, r1 8288c2ecf20Sopenharmony_ci movne r0, r1 8298c2ecf20Sopenharmony_ci bne enter_self_refresh 8308c2ecf20Sopenharmony_cino_dual_emc_chanl: 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci ldr r1, [r4, #PMC_CTRL] 8338c2ecf20Sopenharmony_ci tst r1, #PMC_CTRL_SIDE_EFFECT_LP0 8348c2ecf20Sopenharmony_ci bne pmc_io_dpd_skip 8358c2ecf20Sopenharmony_ci /* 8368c2ecf20Sopenharmony_ci * Put DDR_DATA, DISC_ADDR_CMD, DDR_ADDR_CMD, POP_ADDR_CMD, POP_CLK 8378c2ecf20Sopenharmony_ci * and COMP in the lowest power mode when LP1. 8388c2ecf20Sopenharmony_ci */ 8398c2ecf20Sopenharmony_ci mov32 r1, 0x8EC00000 8408c2ecf20Sopenharmony_ci str r1, [r4, #PMC_IO_DPD_REQ] 8418c2ecf20Sopenharmony_cipmc_io_dpd_skip: 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci dsb 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci ret lr 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci .ltorg 8488c2ecf20Sopenharmony_ci/* dummy symbol for end of IRAM */ 8498c2ecf20Sopenharmony_ci .align L1_CACHE_SHIFT 8508c2ecf20Sopenharmony_ci .global tegra30_iram_end 8518c2ecf20Sopenharmony_citegra30_iram_end: 8528c2ecf20Sopenharmony_ci b . 8538c2ecf20Sopenharmony_ci#endif 854