1 /*
2 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <assert.h>
9 #include <errno.h>
10
11 #include <arch.h>
12 #include <arch_helpers.h>
13 #include <common/bl_common.h>
14 #include <common/debug.h>
15 #include <common/runtime_svc.h>
16 #include <lib/mmio.h>
17
18 #include <memctrl.h>
19 #include <tegra_platform.h>
20 #include <tegra_private.h>
21
22 /*******************************************************************************
23 * Common Tegra SiP SMCs
24 ******************************************************************************/
25 #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003
26 #define TEGRA_SIP_FIQ_NS_ENTRYPOINT 0x82000005
27 #define TEGRA_SIP_FIQ_NS_GET_CONTEXT 0x82000006
28
29 /*******************************************************************************
30 * This function is responsible for handling all SiP calls
31 ******************************************************************************/
tegra_sip_handler(uint32_t smc_fid,u_register_t x1,u_register_t x2,u_register_t x3,u_register_t x4,void * cookie,void * handle,u_register_t flags)32 uintptr_t tegra_sip_handler(uint32_t smc_fid,
33 u_register_t x1,
34 u_register_t x2,
35 u_register_t x3,
36 u_register_t x4,
37 void *cookie,
38 void *handle,
39 u_register_t flags)
40 {
41 uint32_t regval, local_x2_32 = (uint32_t)x2;
42 int32_t err;
43
44 /* Check if this is a SoC specific SiP */
45 err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
46 if (err == 0) {
47
48 SMC_RET1(handle, (uint64_t)err);
49
50 } else {
51
52 switch (smc_fid) {
53
54 case TEGRA_SIP_NEW_VIDEOMEM_REGION:
55 /* Check whether Video memory resize is enabled */
56 if (mmio_read_32(TEGRA_MC_BASE + MC_VIDEO_PROTECT_REG_CTRL)
57 != MC_VIDEO_PROTECT_WRITE_ACCESS_ENABLED) {
58 ERROR("Video Memory Resize isn't enabled! \n");
59 SMC_RET1(handle, (uint64_t)-ENOTSUP);
60 }
61
62 /*
63 * Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
64 * or falls outside of the valid DRAM range
65 */
66 err = bl31_check_ns_address(x1, local_x2_32);
67 if (err != 0) {
68 SMC_RET1(handle, (uint64_t)err);
69 }
70
71 /*
72 * Check if Video Memory is aligned to 1MB.
73 */
74 if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) {
75 ERROR("Unaligned Video Memory base address!\n");
76 SMC_RET1(handle, (uint64_t)-ENOTSUP);
77 }
78
79 /*
80 * The GPU is the user of the Video Memory region. In order to
81 * transition to the new memory region smoothly, we program the
82 * new base/size ONLY if the GPU is in reset mode.
83 */
84 regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
85 TEGRA_GPU_RESET_REG_OFFSET);
86 if ((regval & GPU_RESET_BIT) == 0U) {
87 ERROR("GPU not in reset! Video Memory setup failed\n");
88 SMC_RET1(handle, (uint64_t)-ENOTSUP);
89 }
90
91 /* new video memory carveout settings */
92 tegra_memctrl_videomem_setup(x1, local_x2_32);
93
94 /*
95 * Ensure again that GPU is still in reset after VPR resize
96 */
97 regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
98 TEGRA_GPU_RESET_REG_OFFSET);
99 if ((regval & GPU_RESET_BIT) == 0U) {
100 mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET,
101 GPU_SET_BIT);
102 }
103
104 SMC_RET1(handle, 0);
105
106 /*
107 * The NS world registers the address of its handler to be
108 * used for processing the FIQ. This is normally used by the
109 * NS FIQ debugger driver to detect system hangs by programming
110 * a watchdog timer to fire a FIQ interrupt.
111 */
112 case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
113
114 if (x1 == 0U) {
115 SMC_RET1(handle, SMC_UNK);
116 }
117
118 /*
119 * TODO: Check if x1 contains a valid DRAM address
120 */
121
122 /* store the NS world's entrypoint */
123 tegra_fiq_set_ns_entrypoint(x1);
124
125 SMC_RET1(handle, 0);
126
127 /*
128 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
129 * CPU context when the FIQ interrupt was triggered. This allows the
130 * NS world to understand the CPU state when the watchdog interrupt
131 * triggered.
132 */
133 case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
134
135 /* retrieve context registers when FIQ triggered */
136 (void)tegra_fiq_get_intr_context();
137
138 SMC_RET0(handle);
139
140 default:
141 ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
142 break;
143 }
144 }
145
146 SMC_RET1(handle, SMC_UNK);
147 }
148
149 /* Define a runtime service descriptor for fast SMC calls */
150 DECLARE_RT_SVC(
151 tegra_sip_fast,
152
153 (OEN_SIP_START),
154 (OEN_SIP_END),
155 (SMC_TYPE_FAST),
156 (NULL),
157 (tegra_sip_handler)
158 );
159