xref: /rk3399_ARM-atf/plat/nvidia/tegra/common/tegra_sip_calls.c (revision c948f77136c42a92d0bb660543a3600c36dcf7f1)
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;
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 			/* clean up the high bits */
88 			x2 = (uint32_t)x2;
89 
90 			/*
91 			 * Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
92 			 * or falls outside of the valid DRAM range
93 			*/
94 			err = bl31_check_ns_address(x1, x2);
95 			if (err != 0) {
96 				SMC_RET1(handle, (uint64_t)err);
97 			}
98 
99 			/*
100 			 * Check if Video Memory is aligned to 1MB.
101 			 */
102 			if (((x1 & 0xFFFFFU) != 0U) || ((x2 & 0xFFFFFU) != 0U)) {
103 				ERROR("Unaligned Video Memory base address!\n");
104 				SMC_RET1(handle, -ENOTSUP);
105 			}
106 
107 			/*
108 			 * The GPU is the user of the Video Memory region. In order to
109 			 * transition to the new memory region smoothly, we program the
110 			 * new base/size ONLY if the GPU is in reset mode.
111 			 */
112 			regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
113 					      TEGRA_GPU_RESET_REG_OFFSET);
114 			if ((regval & GPU_RESET_BIT) == 0UL) {
115 				ERROR("GPU not in reset! Video Memory setup failed\n");
116 				SMC_RET1(handle, -ENOTSUP);
117 			}
118 
119 			/* new video memory carveout settings */
120 			tegra_memctrl_videomem_setup(x1, (uint32_t)x2);
121 
122 			SMC_RET1(handle, 0);
123 
124 		/*
125 		 * The NS world registers the address of its handler to be
126 		 * used for processing the FIQ. This is normally used by the
127 		 * NS FIQ debugger driver to detect system hangs by programming
128 		 * a watchdog timer to fire a FIQ interrupt.
129 		 */
130 		case TEGRA_SIP_FIQ_NS_ENTRYPOINT:
131 
132 			if (x1 == 0U) {
133 				SMC_RET1(handle, SMC_UNK);
134 			}
135 
136 			/*
137 			 * TODO: Check if x1 contains a valid DRAM address
138 			 */
139 
140 			/* store the NS world's entrypoint */
141 			tegra_fiq_set_ns_entrypoint(x1);
142 
143 			SMC_RET1(handle, 0);
144 
145 		/*
146 		 * The NS world's FIQ handler issues this SMC to get the NS EL1/EL0
147 		 * CPU context when the FIQ interrupt was triggered. This allows the
148 		 * NS world to understand the CPU state when the watchdog interrupt
149 		 * triggered.
150 		 */
151 		case TEGRA_SIP_FIQ_NS_GET_CONTEXT:
152 
153 			/* retrieve context registers when FIQ triggered */
154 			(void)tegra_fiq_get_intr_context();
155 
156 			SMC_RET0(handle);
157 
158 		case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND:
159 			/*
160 			 * System suspend fake mode is set if we are on VDK and we make
161 			 * a debug SIP call. This mode ensures that we excercise debug
162 			 * path instead of the regular code path to suit the pre-silicon
163 			 * platform needs. These include replacing the call to WFI by
164 			 * a warm reset request.
165 			 */
166 			if (tegra_platform_is_virt_dev_kit() != false) {
167 
168 				tegra_fake_system_suspend = 1;
169 				SMC_RET1(handle, 0);
170 			}
171 
172 			/*
173 			 * We return to the external world as if this SIP is not
174 			 * implemented in case, we are not running on VDK.
175 			 */
176 			break;
177 
178 		default:
179 			ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
180 			break;
181 		}
182 	}
183 
184 	SMC_RET1(handle, SMC_UNK);
185 }
186 
187 /* Define a runtime service descriptor for fast SMC calls */
188 DECLARE_RT_SVC(
189 	tegra_sip_fast,
190 
191 	(OEN_SIP_START),
192 	(OEN_SIP_END),
193 	(SMC_TYPE_FAST),
194 	(NULL),
195 	(tegra_sip_handler)
196 );
197