xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_sip_calls.c (revision 40d553cfde38d4f68449c62967cd1ce0d6478750)
1 /*
2  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <common/bl_common.h>
13 #include <common/debug.h>
14 #include <common/runtime_svc.h>
15 #include <lib/mmio.h>
16 
17 #include <memctrl.h>
18 #include <tegra_platform.h>
19 #include <tegra_private.h>
20 
21 /*******************************************************************************
22  * Common Tegra SiP SMCs
23  ******************************************************************************/
24 #define TEGRA_SIP_NEW_VIDEOMEM_REGION		0x82000003
25 #define TEGRA_SIP_FIQ_NS_ENTRYPOINT		0x82000005
26 #define TEGRA_SIP_FIQ_NS_GET_CONTEXT		0x82000006
27 #define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND	0xC2000007
28 
29 /*******************************************************************************
30  * Fake system suspend mode control var
31  ******************************************************************************/
32 extern uint8_t tegra_fake_system_suspend;
33 
34 /*******************************************************************************
35  * SoC specific SiP handler
36  ******************************************************************************/
37 #pragma weak plat_sip_handler
38 int32_t plat_sip_handler(uint32_t smc_fid,
39 		     uint64_t x1,
40 		     uint64_t x2,
41 		     uint64_t x3,
42 		     uint64_t x4,
43 		     const void *cookie,
44 		     void *handle,
45 		     uint64_t flags)
46 {
47 	/* unused parameters */
48 	(void)smc_fid;
49 	(void)x1;
50 	(void)x2;
51 	(void)x3;
52 	(void)x4;
53 	(void)cookie;
54 	(void)handle;
55 	(void)flags;
56 
57 	return -ENOTSUP;
58 }
59 
60 /*******************************************************************************
61  * This function is responsible for handling all SiP calls
62  ******************************************************************************/
63 uintptr_t tegra_sip_handler(uint32_t smc_fid,
64 			    u_register_t x1,
65 			    u_register_t x2,
66 			    u_register_t x3,
67 			    u_register_t x4,
68 			    void *cookie,
69 			    void *handle,
70 			    u_register_t flags)
71 {
72 	uint32_t regval, local_x2_32 = (uint32_t)x2;
73 	int32_t err;
74 
75 	/* Check if this is a SoC specific SiP */
76 	err = plat_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
77 	if (err == 0) {
78 
79 		SMC_RET1(handle, (uint64_t)err);
80 
81 	} else {
82 
83 		switch (smc_fid) {
84 
85 		case TEGRA_SIP_NEW_VIDEOMEM_REGION:
86 
87 			/*
88 			 * Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
89 			 * or falls outside of the valid DRAM range
90 			*/
91 			err = bl31_check_ns_address(x1, local_x2_32);
92 			if (err != 0) {
93 				SMC_RET1(handle, (uint64_t)err);
94 			}
95 
96 			/*
97 			 * Check if Video Memory is aligned to 1MB.
98 			 */
99 			if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) {
100 				ERROR("Unaligned Video Memory base address!\n");
101 				SMC_RET1(handle, (uint64_t)-ENOTSUP);
102 			}
103 
104 			/*
105 			 * The GPU is the user of the Video Memory region. In order to
106 			 * transition to the new memory region smoothly, we program the
107 			 * new base/size ONLY if the GPU is in reset mode.
108 			 */
109 			regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
110 					      TEGRA_GPU_RESET_REG_OFFSET);
111 			if ((regval & GPU_RESET_BIT) == 0U) {
112 				ERROR("GPU not in reset! Video Memory setup failed\n");
113 				SMC_RET1(handle, (uint64_t)-ENOTSUP);
114 			}
115 
116 			/* new video memory carveout settings */
117 			tegra_memctrl_videomem_setup(x1, local_x2_32);
118 
119 			/*
120 			 * Ensure again that GPU is still in reset after VPR resize
121 			 */
122 			regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
123 					      TEGRA_GPU_RESET_REG_OFFSET);
124 			if ((regval & GPU_RESET_BIT) == 0U) {
125 				mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_GPU_SET_OFFSET,
126 									GPU_SET_BIT);
127 			}
128 
129 			SMC_RET1(handle, 0);
130 
131 		/*
132 		 * The NS world registers the address of its handler to be
133 		 * used for processing the FIQ. This is normally used by the
134 		 * NS FIQ debugger driver to detect system hangs by programming
135 		 * a watchdog timer to fire a FIQ interrupt.
136 		 */
137 		case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
138 
139 			if (x1 == 0U) {
140 				SMC_RET1(handle, SMC_UNK);
141 			}
142 
143 			/*
144 			 * TODO: Check if x1 contains a valid DRAM address
145 			 */
146 
147 			/* store the NS world's entrypoint */
148 			tegra_fiq_set_ns_entrypoint(x1);
149 
150 			SMC_RET1(handle, 0);
151 
152 		/*
153 		 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
154 		 * CPU context when the FIQ interrupt was triggered. This allows the
155 		 * NS world to understand the CPU state when the watchdog interrupt
156 		 * triggered.
157 		 */
158 		case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
159 
160 			/* retrieve context registers when FIQ triggered */
161 			(void)tegra_fiq_get_intr_context();
162 
163 			SMC_RET0(handle);
164 
165 		case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND:
166 			/*
167 			 * System suspend fake mode is set if we are on VDK and we make
168 			 * a debug SIP call. This mode ensures that we excercise debug
169 			 * path instead of the regular code path to suit the pre-silicon
170 			 * platform needs. These include replacing the call to WFI by
171 			 * a warm reset request.
172 			 */
173 			if (tegra_platform_is_virt_dev_kit() != false) {
174 
175 				tegra_fake_system_suspend = 1;
176 				SMC_RET1(handle, 0);
177 			}
178 
179 			/*
180 			 * We return to the external world as if this SIP is not
181 			 * implemented in case, we are not running on VDK.
182 			 */
183 			break;
184 
185 		default:
186 			ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
187 			break;
188 		}
189 	}
190 
191 	SMC_RET1(handle, SMC_UNK);
192 }
193 
194 /* Define a runtime service descriptor for fast SMC calls */
195 DECLARE_RT_SVC(
196 	tegra_sip_fast,
197 
198 	(OEN_SIP_START),
199 	(OEN_SIP_END),
200 	(SMC_TYPE_FAST),
201 	(NULL),
202 	(tegra_sip_handler)
203 );
204