xref: /optee_os/core/pta/qcom/pas/pta_qcom_pas.c (revision abca35a69f9bea0496cf05e025c3c36e6d5ea68b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2026, Qualcomm Technologies, Inc. and/or its subsidiaries.
4  */
5 
6 #include <initcall.h>
7 #include <kernel/pseudo_ta.h>
8 #include <kernel/user_ta.h>
9 #include <platform_config.h>
10 #include <pta_qcom_pas.h>
11 #include <string.h>
12 
13 #include "pas.h"
14 
15 #define PTA_NAME	"pta.qcom.pas"
16 
17 #define TA_PAS_UUID { 0xcff7d191, 0x7ca0, 0x4784, \
18 		{ 0xaf, 0x13, 0x48, 0x22, 0x3b, 0x9a, 0x4f, 0xbe} }
19 
20 static struct qcom_pas_data wpss_dsp_data = {
21 	.pas_id = PAS_ID_WPSS,
22 	.base.pa = WPSS_BASE,
23 	.size = WPSS_SIZE,
24 	.clk_group = QCOM_CLKS_WPSS,
25 };
26 
27 static struct qcom_pas_data turing_dsp_data = {
28 	.pas_id = PAS_ID_TURING,
29 	.base.pa = TURING_BASE,
30 	.size = TURING_SIZE,
31 	.clk_group = QCOM_CLKS_TURING,
32 };
33 
34 static struct qcom_pas_data lpass_dsp_data = {
35 	.pas_id = PAS_ID_QDSP6,
36 	.base.pa = LPASS_BASE,
37 	.size = LPASS_SIZE,
38 	.clk_group = QCOM_CLKS_LPASS,
39 };
40 
41 static struct qcom_pas_data venus_fw_data = {
42 	.pas_id = PAS_ID_VENUS,
43 	.base.pa = IRIS_BASE,
44 	.size = IRIS_SIZE,
45 };
46 
qcom_pas_is_supported(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])47 static TEE_Result qcom_pas_is_supported(uint32_t pt,
48 					TEE_Param params[TEE_NUM_PARAMS])
49 {
50 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
51 						TEE_PARAM_TYPE_NONE,
52 						TEE_PARAM_TYPE_NONE,
53 						TEE_PARAM_TYPE_NONE);
54 
55 	if (pt != exp_pt)
56 		return TEE_ERROR_BAD_PARAMETERS;
57 
58 	DMSG("invoked with pas_id: %d", params[0].value.a);
59 
60 	if (params[0].value.a != PAS_ID_WPSS &&
61 	    params[0].value.a != PAS_ID_QDSP6 &&
62 	    params[0].value.a != PAS_ID_VENUS &&
63 	    params[0].value.a != PAS_ID_TURING)
64 		return TEE_ERROR_NOT_SUPPORTED;
65 
66 	return TEE_SUCCESS;
67 }
68 
qcom_pas_capabilities(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])69 static TEE_Result qcom_pas_capabilities(uint32_t pt,
70 					TEE_Param params[TEE_NUM_PARAMS])
71 {
72 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
73 						TEE_PARAM_TYPE_VALUE_OUTPUT,
74 						TEE_PARAM_TYPE_NONE,
75 						TEE_PARAM_TYPE_NONE);
76 
77 	if (pt != exp_pt)
78 		return TEE_ERROR_BAD_PARAMETERS;
79 
80 	DMSG("invoked with pas_id: %d", params[0].value.a);
81 	/* Capabilities flags reserved for future use */
82 	params[1].value.a = 0;
83 
84 	return TEE_SUCCESS;
85 }
86 
qcom_pas_init_image(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])87 static TEE_Result qcom_pas_init_image(uint32_t pt,
88 				      TEE_Param params[TEE_NUM_PARAMS])
89 {
90 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
91 						TEE_PARAM_TYPE_MEMREF_INPUT,
92 						TEE_PARAM_TYPE_NONE,
93 						TEE_PARAM_TYPE_NONE);
94 
95 	if (pt != exp_pt)
96 		return TEE_ERROR_BAD_PARAMETERS;
97 
98 	DMSG("invoked with pas_id: %d", params[0].value.a);
99 
100 	if (params[0].value.a != PAS_ID_WPSS &&
101 	    params[0].value.a != PAS_ID_QDSP6 &&
102 	    params[0].value.a != PAS_ID_VENUS &&
103 	    params[0].value.a != PAS_ID_TURING)
104 		return TEE_ERROR_NOT_SUPPORTED;
105 
106 	return TEE_SUCCESS;
107 }
108 
qcom_pas_mem_setup(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])109 static TEE_Result qcom_pas_mem_setup(uint32_t pt,
110 				     TEE_Param params[TEE_NUM_PARAMS])
111 {
112 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
113 						TEE_PARAM_TYPE_VALUE_INPUT,
114 						TEE_PARAM_TYPE_NONE,
115 						TEE_PARAM_TYPE_NONE);
116 	struct qcom_pas_data *data = NULL;
117 
118 	if (pt != exp_pt)
119 		return TEE_ERROR_BAD_PARAMETERS;
120 
121 	DMSG("invoked with pas_id: %d", params[0].value.a);
122 
123 	switch (params[0].value.a) {
124 	case PAS_ID_WPSS:
125 		data = &wpss_dsp_data;
126 		break;
127 	case PAS_ID_TURING:
128 		data = &turing_dsp_data;
129 		break;
130 	case PAS_ID_QDSP6:
131 		data = &lpass_dsp_data;
132 		break;
133 	case PAS_ID_VENUS:
134 		data = &venus_fw_data;
135 		break;
136 	default:
137 		return TEE_ERROR_NOT_SUPPORTED;
138 	}
139 
140 	data->fw_size = params[0].value.b;
141 	data->fw_base = params[1].value.a;
142 	data->fw_base |= SHIFT_U64(params[1].value.b, 32);
143 
144 	/* Map the controller */
145 	if (!data->base.va) {
146 		data->base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_NSEC,
147 							      data->base.pa,
148 							      data->size);
149 		if (!data->base.va)
150 			return TEE_ERROR_GENERIC;
151 	}
152 
153 	return TEE_SUCCESS;
154 }
155 
qcom_pas_get_resource_table(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])156 static TEE_Result qcom_pas_get_resource_table(uint32_t pt,
157 					      TEE_Param params[TEE_NUM_PARAMS])
158 {
159 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
160 						TEE_PARAM_TYPE_MEMREF_INOUT,
161 						TEE_PARAM_TYPE_NONE,
162 						TEE_PARAM_TYPE_NONE);
163 
164 	if (pt != exp_pt)
165 		return TEE_ERROR_BAD_PARAMETERS;
166 
167 	DMSG("invoked with pas_id: %d", params[0].value.a);
168 
169 	if (params[0].value.a != PAS_ID_WPSS &&
170 	    params[0].value.a != PAS_ID_TURING &&
171 	    params[0].value.a != PAS_ID_QDSP6)
172 		return TEE_ERROR_NOT_SUPPORTED;
173 
174 	return pas_get_resource_table(params[0].value.a,
175 				      params[1].memref.buffer,
176 				      &params[1].memref.size);
177 }
178 
179 static TEE_Result
qcom_pas_set_remote_state(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS]__maybe_unused)180 qcom_pas_set_remote_state(uint32_t pt,
181 			  TEE_Param params[TEE_NUM_PARAMS]__maybe_unused)
182 {
183 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
184 						TEE_PARAM_TYPE_NONE,
185 						TEE_PARAM_TYPE_NONE,
186 						TEE_PARAM_TYPE_NONE);
187 
188 	if (pt != exp_pt)
189 		return TEE_ERROR_BAD_PARAMETERS;
190 
191 	DMSG("invoked with pas_id: %d", params[0].value.a);
192 
193 	if (params[0].value.a == PAS_ID_VENUS)
194 		return venus_fw_set_state(&venus_fw_data, params[0].value.b);
195 
196 	return TEE_ERROR_NOT_IMPLEMENTED;
197 }
198 
qcom_pas_auth_and_reset(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])199 static TEE_Result qcom_pas_auth_and_reset(uint32_t pt,
200 					  TEE_Param params[TEE_NUM_PARAMS])
201 {
202 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
203 						TEE_PARAM_TYPE_VALUE_INPUT,
204 						TEE_PARAM_TYPE_MEMREF_INPUT,
205 						TEE_PARAM_TYPE_NONE);
206 	TEE_Result res = TEE_SUCCESS;
207 
208 	if (pt != exp_pt)
209 		return TEE_ERROR_BAD_PARAMETERS;
210 
211 	DMSG("invoked with pas_id: %d", params[0].value.a);
212 
213 	switch (params[0].value.a) {
214 	case PAS_ID_WPSS:
215 		if (!wpss_dsp_data.fw_base)
216 			return TEE_ERROR_NO_DATA;
217 
218 		res = qcom_clock_enable(wpss_dsp_data.clk_group);
219 		if (res != TEE_SUCCESS) {
220 			EMSG("Failed to enable clocks: %d", res);
221 			return res;
222 		}
223 
224 		return wpss_fw_start(&wpss_dsp_data);
225 	case PAS_ID_TURING:
226 		if (!turing_dsp_data.fw_base)
227 			return TEE_ERROR_NO_DATA;
228 
229 		res = qcom_clock_enable(turing_dsp_data.clk_group);
230 		if (res != TEE_SUCCESS) {
231 			EMSG("Failed to enable clocks: %d", res);
232 			return res;
233 		}
234 
235 		return compute_fw_start(&turing_dsp_data);
236 	case PAS_ID_QDSP6:
237 		if (!lpass_dsp_data.fw_base)
238 			return TEE_ERROR_NO_DATA;
239 
240 		res = qcom_clock_enable(lpass_dsp_data.clk_group);
241 		if (res != TEE_SUCCESS) {
242 			EMSG("Failed to enable clocks: %d", res);
243 			return res;
244 		}
245 
246 		return lpass_fw_start(&lpass_dsp_data);
247 	case PAS_ID_VENUS:
248 		if (!venus_fw_data.fw_base)
249 			return TEE_ERROR_NO_DATA;
250 
251 		return venus_fw_start(&venus_fw_data);
252 	default:
253 		return TEE_ERROR_NOT_SUPPORTED;
254 	}
255 }
256 
257 static TEE_Result
qcom_pas_shutdown(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS]__maybe_unused)258 qcom_pas_shutdown(uint32_t pt,
259 		  TEE_Param params[TEE_NUM_PARAMS] __maybe_unused)
260 {
261 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
262 						TEE_PARAM_TYPE_NONE,
263 						TEE_PARAM_TYPE_NONE,
264 						TEE_PARAM_TYPE_NONE);
265 
266 	if (pt != exp_pt)
267 		return TEE_ERROR_BAD_PARAMETERS;
268 
269 	DMSG("invoked with pas_id: %d", params[0].value.a);
270 
271 	switch (params[0].value.a) {
272 	case PAS_ID_WPSS:
273 		return wpss_fw_shutdown(&wpss_dsp_data);
274 	case PAS_ID_TURING:
275 		return compute_fw_shutdown(&turing_dsp_data);
276 	case PAS_ID_QDSP6:
277 		return lpass_fw_shutdown(&lpass_dsp_data);
278 	case PAS_ID_VENUS:
279 		return venus_fw_shutdown(&venus_fw_data);
280 	default:
281 		return TEE_ERROR_NOT_SUPPORTED;
282 	}
283 
284 	return TEE_ERROR_NOT_IMPLEMENTED;
285 }
286 
pta_qcom_pas_invoke_command(void * session __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])287 static TEE_Result pta_qcom_pas_invoke_command(void *session __unused,
288 					      uint32_t cmd_id,
289 					      uint32_t param_types,
290 					      TEE_Param params[TEE_NUM_PARAMS])
291 {
292 	switch (cmd_id) {
293 	case PTA_QCOM_PAS_IS_SUPPORTED:
294 		return qcom_pas_is_supported(param_types, params);
295 	case PTA_QCOM_PAS_CAPABILITIES:
296 		return qcom_pas_capabilities(param_types, params);
297 	case PTA_QCOM_PAS_INIT_IMAGE:
298 		return qcom_pas_init_image(param_types, params);
299 	case PTA_QCOM_PAS_MEM_SETUP:
300 		return qcom_pas_mem_setup(param_types, params);
301 	case PTA_QCOM_PAS_GET_RESOURCE_TABLE:
302 		return qcom_pas_get_resource_table(param_types, params);
303 	case PTA_QCOM_PAS_AUTH_AND_RESET:
304 		return qcom_pas_auth_and_reset(param_types, params);
305 	case PTA_QCOM_PAS_SET_REMOTE_STATE:
306 		return qcom_pas_set_remote_state(param_types, params);
307 	case PTA_QCOM_PAS_SHUTDOWN:
308 		return qcom_pas_shutdown(param_types, params);
309 	default:
310 		return TEE_ERROR_NOT_IMPLEMENTED;
311 	}
312 }
313 
314 /*
315  * Pseudo Trusted Application entry points
316  */
317 static TEE_Result
pta_qcom_pas_open_session(uint32_t pt __unused,TEE_Param params[TEE_NUM_PARAMS]__unused,void ** sess_ctx __unused)318 pta_qcom_pas_open_session(uint32_t pt __unused,
319 			  TEE_Param params[TEE_NUM_PARAMS] __unused,
320 			  void **sess_ctx __unused)
321 {
322 	struct ts_session *s = ts_get_calling_session();
323 	struct ts_ctx *ctx = NULL;
324 	TEE_UUID ta_uuid = TA_PAS_UUID;
325 
326 	if (!s)
327 		return TEE_ERROR_ACCESS_DENIED;
328 
329 	ctx = s->ctx;
330 	if (memcmp(&ctx->uuid, &ta_uuid, sizeof(TEE_UUID)))
331 		return TEE_ERROR_ACCESS_DENIED;
332 
333 	return TEE_SUCCESS;
334 }
335 
336 /*
337  * TA_FLAG_CONCURRENT disabled:
338  *   concurrent operation must be supported by the client.
339  */
340 pseudo_ta_register(.uuid = PTA_QCOM_PAS_UUID, .name = PTA_NAME,
341 		   .flags = PTA_DEFAULT_FLAGS,
342 		   .invoke_command_entry_point = pta_qcom_pas_invoke_command,
343 		   .open_session_entry_point = pta_qcom_pas_open_session);
344