1 /*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <arch_helpers.h>
8 #include <assert.h>
9 #include <debug.h>
10 #include <denver.h>
11 #include <mmio.h>
12 #include <platform.h>
13 #include <pmc.h>
14 #include <psci.h>
15 #include <tegra_def.h>
16
17 #define SB_CSR 0x0
18 #define SB_CSR_NS_RST_VEC_WR_DIS (1 << 1)
19
20 /* AARCH64 CPU reset vector */
21 #define SB_AA64_RESET_LOW 0x30 /* width = 31:0 */
22 #define SB_AA64_RESET_HI 0x34 /* width = 11:0 */
23
24 /* AARCH32 CPU reset vector */
25 #define EVP_CPU_RESET_VECTOR 0x100
26
27 extern void tegra_secure_entrypoint(void);
28
29 /*
30 * For T132, CPUs reset to AARCH32, so the reset vector is first
31 * armv8_trampoline which does a warm reset to AARCH64 and starts
32 * execution at the address in SB_AA64_RESET_LOW/SB_AA64_RESET_HI.
33 */
34 __aligned(8) const uint32_t armv8_trampoline[] = {
35 0xE3A00003, /* mov r0, #3 */
36 0xEE0C0F50, /* mcr p15, 0, r0, c12, c0, 2 */
37 0xEAFFFFFE, /* b . */
38 };
39
40 /*******************************************************************************
41 * Setup secondary CPU vectors
42 ******************************************************************************/
plat_secondary_setup(void)43 void plat_secondary_setup(void)
44 {
45 uint32_t val;
46 uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint;
47
48 /*
49 * For T132, CPUs reset to AARCH32, so the reset vector is first
50 * armv8_trampoline, which does a warm reset to AARCH64 and starts
51 * execution at the address in SCRATCH34/SCRATCH35.
52 */
53 INFO("Setting up T132 CPU boot\n");
54
55 /* initial AARCH32 reset address */
56 tegra_pmc_write_32(PMC_SECURE_SCRATCH22,
57 (unsigned long)&armv8_trampoline);
58
59 /* set AARCH32 exception vector (read to flush) */
60 mmio_write_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR,
61 (unsigned long)&armv8_trampoline);
62 val = mmio_read_32(TEGRA_EVP_BASE + EVP_CPU_RESET_VECTOR);
63
64 /* setup secondary CPU vector */
65 mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_LOW,
66 (reset_addr & 0xFFFFFFFF) | 1);
67 val = reset_addr >> 32;
68 mmio_write_32(TEGRA_SB_BASE + SB_AA64_RESET_HI, val & 0x7FF);
69
70 /* configure PMC */
71 tegra_pmc_cpu_setup(reset_addr);
72 tegra_pmc_lock_cpu_vectors();
73 }
74