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