cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sleep-tegra20.S (10268B)


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