1 /*
2  * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <string.h>
9 
10 #include <arch_helpers.h>
11 #include <common/debug.h>
12 #include <lib/mmio.h>
13 
14 #include <mce.h>
15 #include <tegra194_private.h>
16 #include <tegra_def.h>
17 #include <tegra_private.h>
18 
19 extern uint64_t tegra_bl31_phys_base;
20 
21 #define MISCREG_AA64_RST_LOW		0x2004U
22 #define MISCREG_AA64_RST_HIGH		0x2008U
23 
24 #define CPU_RESET_MODE_AA64		1U
25 
26 /*******************************************************************************
27  * Setup secondary CPU vectors
28  ******************************************************************************/
plat_secondary_setup(void)29 void plat_secondary_setup(void)
30 {
31 	uint32_t addr_low, addr_high;
32 	plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
33 	uint64_t cpu_reset_handler_base, cpu_reset_handler_size, tzdram_addr;
34 	uint64_t src_len_bytes = BL_END - tegra_bl31_phys_base;
35 
36 	INFO("Setting up secondary CPU boot\n");
37 
38 	tzdram_addr = params_from_bl2->tzdram_base +
39 		      tegra194_get_cpu_reset_handler_size();
40 
41 	/*
42 	 * The BL31 code resides in the TZSRAM which loses state
43 	 * when we enter System Suspend. Copy the wakeup trampoline
44 	 * code to TZDRAM to help us exit from System Suspend.
45 	 */
46 	cpu_reset_handler_base = tegra194_get_cpu_reset_handler_base();
47 	cpu_reset_handler_size = tegra194_get_cpu_reset_handler_size();
48 	memcpy((void *)((uintptr_t)params_from_bl2->tzdram_base),
49 		(void *)((uintptr_t)cpu_reset_handler_base),
50 		cpu_reset_handler_size);
51 
52 	/* TZDRAM base will be used as the "resume" address */
53 	addr_low = (uint32_t)params_from_bl2->tzdram_base | CPU_RESET_MODE_AA64;
54 	addr_high = (uint32_t)((params_from_bl2->tzdram_base >> 32U) & 0x7ffU);
55 
56 	/* write lower 32 bits first, then the upper 11 bits */
57 	mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW, addr_low);
58 	assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_LOW) == addr_low);
59 	mmio_write_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH, addr_high);
60 	assert(mmio_read_32(TEGRA_MISC_BASE + MISCREG_AA64_RST_HIGH) == addr_high);
61 
62 	/* save reset vector to be used during SYSTEM_SUSPEND exit */
63 	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO,
64 			addr_low);
65 	assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO) == addr_low);
66 	mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
67 			addr_high);
68 	assert(mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI) == addr_high);
69 	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO,
70 						(uint32_t)tzdram_addr);
71 	assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_LO) == (uint32_t)tzdram_addr);
72 	mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI,
73 						(uint32_t)src_len_bytes);
74 	assert(mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV72_HI) == (uint32_t)src_len_bytes);
75 }
76