xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_sip_calls.c (revision 14928b88ab9f16aebd492f4d71779fd6f5ac91b2)
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 			SMC_RET1(handle, 0);
120 
121 		/*
122 		 * The NS world registers the address of its handler to be
123 		 * used for processing the FIQ. This is normally used by the
124 		 * NS FIQ debugger driver to detect system hangs by programming
125 		 * a watchdog timer to fire a FIQ interrupt.
126 		 */
127 		case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
128 
129 			if (x1 == 0U) {
130 				SMC_RET1(handle, SMC_UNK);
131 			}
132 
133 			/*
134 			 * TODO: Check if x1 contains a valid DRAM address
135 			 */
136 
137 			/* store the NS world's entrypoint */
138 			tegra_fiq_set_ns_entrypoint(x1);
139 
140 			SMC_RET1(handle, 0);
141 
142 		/*
143 		 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
144 		 * CPU context when the FIQ interrupt was triggered. This allows the
145 		 * NS world to understand the CPU state when the watchdog interrupt
146 		 * triggered.
147 		 */
148 		case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
149 
150 			/* retrieve context registers when FIQ triggered */
151 			(void)tegra_fiq_get_intr_context();
152 
153 			SMC_RET0(handle);
154 
155 		case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND:
156 			/*
157 			 * System suspend fake mode is set if we are on VDK and we make
158 			 * a debug SIP call. This mode ensures that we excercise debug
159 			 * path instead of the regular code path to suit the pre-silicon
160 			 * platform needs. These include replacing the call to WFI by
161 			 * a warm reset request.
162 			 */
163 			if (tegra_platform_is_virt_dev_kit() != false) {
164 
165 				tegra_fake_system_suspend = 1;
166 				SMC_RET1(handle, 0);
167 			}
168 
169 			/*
170 			 * We return to the external world as if this SIP is not
171 			 * implemented in case, we are not running on VDK.
172 			 */
173 			break;
174 
175 		default:
176 			ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
177 			break;
178 		}
179 	}
180 
181 	SMC_RET1(handle, SMC_UNK);
182 }
183 
184 /* Define a runtime service descriptor for fast SMC calls */
185 DECLARE_RT_SVC(
186 	tegra_sip_fast,
187 
188 	(OEN_SIP_START),
189 	(OEN_SIP_END),
190 	(SMC_TYPE_FAST),
191 	(NULL),
192 	(tegra_sip_handler)
193 );
194