Line data Source code
1 0 : /*
2 : * Copyright (c) 2023, Intel Corporation.
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_
8 : #define ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_
9 :
10 : #include <zephyr/device.h>
11 : #include <zephyr/kernel.h>
12 : #include <zephyr/arch/arm64/arm-smccc.h>
13 : #include <zephyr/drivers/sip_svc/sip_svc_proto.h>
14 : #include <zephyr/sip_svc/sip_svc_controller.h>
15 :
16 0 : #define DEV_API(dev) ((struct svc_driver_api *)(dev)->api)
17 :
18 : /**
19 : * @brief Length of SVC conduit name.
20 : *
21 : */
22 1 : #define SVC_CONDUIT_NAME_LENGTH (4)
23 :
24 : /**
25 : * @brief Callback API for executing the supervisory call
26 : * See @a sip_supervisory_call() for argument description
27 : */
28 1 : typedef void (*sip_supervisory_call_t)(const struct device *dev, unsigned long function_id,
29 : unsigned long arg0, unsigned long arg1, unsigned long arg2,
30 : unsigned long arg3, unsigned long arg4, unsigned long arg5,
31 : unsigned long arg6, struct arm_smccc_res *res);
32 :
33 : /**
34 : * @brief Callback API for validating function id for the supervisory call.
35 : * See @a sip_svc_plat_func_id_valid() for argument description
36 : */
37 1 : typedef bool (*sip_svc_plat_func_id_valid_t)(const struct device *dev, uint32_t command,
38 : uint32_t func_id);
39 :
40 : /**
41 : * @brief Callback API for generating the transaction id from client id.
42 : * See @a sip_svc_plat_format_trans_id() for argument description
43 : */
44 1 : typedef uint32_t (*sip_svc_plat_format_trans_id_t)(const struct device *dev, uint32_t client_idx,
45 : uint32_t trans_idx);
46 :
47 : /**
48 : * @brief Callback API for retrieving client transaction id from transaction id
49 : * See @a sip_svc_plat_get_trans_idx() for argument description
50 : */
51 1 : typedef uint32_t (*sip_svc_plat_get_trans_idx_t)(const struct device *dev, uint32_t trans_id);
52 :
53 : /**
54 : * @brief Callback API for updating transaction id for request packet for lower layer
55 : * See @a sip_svc_plat_update_trans_id() for argument description
56 : */
57 1 : typedef void (*sip_svc_plat_update_trans_id_t)(const struct device *dev,
58 : struct sip_svc_request *request, uint32_t trans_id);
59 :
60 : /**
61 : * @brief Callback API for freeing command buffer in ASYNC packets
62 : * See @a sip_svc_plat_free_async_memory() for argument description
63 : */
64 1 : typedef void (*sip_svc_plat_free_async_memory_t)(const struct device *dev,
65 : struct sip_svc_request *request);
66 :
67 : /**
68 : * @brief Callback API to construct Polling packet for ASYNC transaction.
69 : * See @a sip_svc_plat_async_res_req() for argument description
70 : */
71 1 : typedef int (*sip_svc_plat_async_res_req_t)(const struct device *dev, unsigned long *a0,
72 : unsigned long *a1, unsigned long *a2, unsigned long *a3,
73 : unsigned long *a4, unsigned long *a5, unsigned long *a6,
74 : unsigned long *a7, char *buf, size_t size);
75 :
76 : /**
77 : * @brief Callback API to check the response of polling request
78 : * See @a sip_svc_plat_async_res_res() for argument description
79 : */
80 1 : typedef int (*sip_svc_plat_async_res_res_t)(const struct device *dev, struct arm_smccc_res *res,
81 : char *buf, size_t *size, uint32_t *trans_id);
82 :
83 : /**
84 : * @brief Callback API for retrieving error code from a supervisory call response.
85 : * See @a sip_svc_plat_get_error_code() for argument description.
86 : */
87 1 : typedef uint32_t (*sip_svc_plat_get_error_code_t)(const struct device *dev,
88 : struct arm_smccc_res *res);
89 :
90 : /**
91 : * @brief API structure for sip_svc driver.
92 : *
93 : */
94 1 : __subsystem struct svc_driver_api {
95 0 : sip_supervisory_call_t sip_supervisory_call;
96 0 : sip_svc_plat_func_id_valid_t sip_svc_plat_func_id_valid;
97 0 : sip_svc_plat_format_trans_id_t sip_svc_plat_format_trans_id;
98 0 : sip_svc_plat_get_trans_idx_t sip_svc_plat_get_trans_idx;
99 0 : sip_svc_plat_update_trans_id_t sip_svc_plat_update_trans_id;
100 0 : sip_svc_plat_free_async_memory_t sip_svc_plat_free_async_memory;
101 0 : sip_svc_plat_async_res_req_t sip_svc_plat_async_res_req;
102 0 : sip_svc_plat_async_res_res_t sip_svc_plat_async_res_res;
103 0 : sip_svc_plat_get_error_code_t sip_svc_plat_get_error_code;
104 : };
105 :
106 : /**
107 : * @brief supervisory call function which will execute the smc/hvc call
108 : *
109 : * @param dev Pointer to the device structure for the driver instance.
110 : * @param function_id Function identifier for the supervisory call.
111 : * @param arg0 Argument 0 for supervisory call.
112 : * @param arg1 Argument 1 for supervisory call.
113 : * @param arg2 Argument 2 for supervisory call.
114 : * @param arg3 Argument 3 for supervisory call.
115 : * @param arg4 Argument 4 for supervisory call.
116 : * @param arg5 Argument 5 for supervisory call.
117 : * @param arg6 Argument 6 for supervisory call.
118 : * @param res Pointer to response buffer for supervisory call.
119 : */
120 1 : __syscall void sip_supervisory_call(const struct device *dev, unsigned long function_id,
121 : unsigned long arg0, unsigned long arg1, unsigned long arg2,
122 : unsigned long arg3, unsigned long arg4, unsigned long arg5,
123 : unsigned long arg6, struct arm_smccc_res *res);
124 : static inline void z_impl_sip_supervisory_call(const struct device *dev, unsigned long function_id,
125 : unsigned long arg0, unsigned long arg1,
126 : unsigned long arg2, unsigned long arg3,
127 : unsigned long arg4, unsigned long arg5,
128 : unsigned long arg6, struct arm_smccc_res *res)
129 : {
130 : __ASSERT(dev, "dev shouldn't be NULL");
131 : const struct svc_driver_api *api = DEV_API(dev);
132 :
133 : __ASSERT(api->sip_supervisory_call, "sip_supervisory_call shouldn't be NULL");
134 : __ASSERT(res, "response pointer shouldn't be NULL");
135 :
136 : api->sip_supervisory_call(dev, function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res);
137 : }
138 :
139 : /**
140 : * @brief Validate the function id for the supervisory call.
141 : *
142 : * @param dev Pointer to the device structure for the driver instance.
143 : * @param command Command which specify if the call is SYNC or ASYNC.
144 : * @param func_id Function identifier
145 : *
146 : * @retval true if command and function identifiers are valid.
147 : * @retval false if command and function identifiers are invalid.
148 : */
149 1 : __syscall bool sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command,
150 : uint32_t func_id);
151 : static inline bool z_impl_sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command,
152 : uint32_t func_id)
153 : {
154 : __ASSERT(dev, "dev shouldn't be NULL");
155 : const struct svc_driver_api *api = DEV_API(dev);
156 :
157 : __ASSERT(api->sip_svc_plat_func_id_valid,
158 : "sip_svc_plat_func_id_valid func shouldn't be NULL");
159 :
160 : return api->sip_svc_plat_func_id_valid(dev, command, func_id);
161 : }
162 :
163 : /**
164 : * @brief Formats and generates the transaction id from client id.
165 : *
166 : * @param dev Pointer to the device structure for the driver instance.
167 : * @param client_idx client index.
168 : * @param trans_idx transaction index.
169 : *
170 : * @retval transaction id, which is used for tracking each transaction.
171 : */
172 1 : __syscall uint32_t sip_svc_plat_format_trans_id(const struct device *dev, uint32_t client_idx,
173 : uint32_t trans_idx);
174 : static inline uint32_t z_impl_sip_svc_plat_format_trans_id(const struct device *dev,
175 : uint32_t client_idx, uint32_t trans_idx)
176 : {
177 : __ASSERT(dev, "dev shouldn't be NULL");
178 : const struct svc_driver_api *api = DEV_API(dev);
179 :
180 : __ASSERT(api->sip_svc_plat_format_trans_id,
181 : "sip_svc_plat_format_trans_id func shouldn't be NULL");
182 :
183 : return api->sip_svc_plat_format_trans_id(dev, client_idx, trans_idx);
184 : }
185 :
186 : /**
187 : * @brief Retrieve client transaction id from packet transaction id.
188 : *
189 : * @param dev Pointer to the device structure for the driver instance.
190 : * @param trans_id transaction identifier if for a transaction.
191 : *
192 : * @retval client transaction id form Transaction id.
193 : */
194 1 : __syscall uint32_t sip_svc_plat_get_trans_idx(const struct device *dev, uint32_t trans_id);
195 : static inline uint32_t z_impl_sip_svc_plat_get_trans_idx(const struct device *dev,
196 : uint32_t trans_id)
197 : {
198 : __ASSERT(dev, "dev shouldn't be NULL");
199 : const struct svc_driver_api *api = DEV_API(dev);
200 :
201 : __ASSERT(api->sip_svc_plat_get_trans_idx,
202 : "sip_svc_plat_get_trans_idx func shouldn't be NULL");
203 :
204 : return api->sip_svc_plat_get_trans_idx(dev, trans_id);
205 : }
206 :
207 : /**
208 : * @brief Update transaction id for sip_svc_request for lower layer.
209 : *
210 : * @param dev Pointer to the device structure for the driver instance.
211 : * @param request Pointer to sip_svc_request structure.
212 : * @param trans_id Transaction id.
213 : */
214 1 : __syscall void sip_svc_plat_update_trans_id(const struct device *dev,
215 : struct sip_svc_request *request, uint32_t trans_id);
216 : static inline void z_impl_sip_svc_plat_update_trans_id(const struct device *dev,
217 : struct sip_svc_request *request,
218 : uint32_t trans_id)
219 : {
220 : __ASSERT(dev, "dev shouldn't be NULL");
221 : const struct svc_driver_api *api = DEV_API(dev);
222 :
223 : __ASSERT(api->sip_svc_plat_update_trans_id,
224 : "sip_svc_plat_update_trans_id func shouldn't be NULL");
225 : __ASSERT(request, "request shouldn't be NULL");
226 :
227 : api->sip_svc_plat_update_trans_id(dev, request, trans_id);
228 : }
229 :
230 : /**
231 : * @brief Retrieve the error code from arm_smccc_res response.
232 : *
233 : * @param dev Pointer to the device structure for the driver instance.
234 : * @param res Pointer to struct arm_smccc_res response.
235 : *
236 : * @retval 0 on success.
237 : * @retval SIP_SVC_ID_INVALID on failure
238 : */
239 1 : __syscall uint32_t sip_svc_plat_get_error_code(const struct device *dev, struct arm_smccc_res *res);
240 : static inline uint32_t z_impl_sip_svc_plat_get_error_code(const struct device *dev,
241 : struct arm_smccc_res *res)
242 : {
243 : __ASSERT(dev, "dev shouldn't be NULL");
244 : const struct svc_driver_api *api = DEV_API(dev);
245 :
246 : __ASSERT(api->sip_svc_plat_get_error_code,
247 : "sip_svc_plat_get_error_code func shouldn't be NULL");
248 : __ASSERT(res, "res shouldn't be NULL");
249 :
250 : return api->sip_svc_plat_get_error_code(dev, res);
251 : }
252 :
253 : /**
254 : * @brief Set arguments for polling supervisory call. For ASYNC polling of response.
255 : *
256 : * @param dev Pointer to the device structure for the driver instance.
257 : * @param a0 Argument 0 for supervisory call.
258 : * @param a1 Argument 1 for supervisory call.
259 : * @param a2 Argument 2 for supervisory call.
260 : * @param a3 Argument 3 for supervisory call.
261 : * @param a4 Argument 4 for supervisory call.
262 : * @param a5 Argument 5 for supervisory call.
263 : * @param a6 Argument 6 for supervisory call.
264 : * @param a7 Argument 7 for supervisory call.
265 : * @param buf Pointer for response buffer.
266 : * @param size Size of response buffer.
267 : *
268 : * @retval 0 on success
269 : */
270 1 : __syscall int sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0,
271 : unsigned long *a1, unsigned long *a2, unsigned long *a3,
272 : unsigned long *a4, unsigned long *a5, unsigned long *a6,
273 : unsigned long *a7, char *buf, size_t size);
274 : static inline int z_impl_sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0,
275 : unsigned long *a1, unsigned long *a2,
276 : unsigned long *a3, unsigned long *a4,
277 : unsigned long *a5, unsigned long *a6,
278 : unsigned long *a7, char *buf, size_t size)
279 : {
280 : __ASSERT(dev, "dev shouldn't be NULL");
281 : const struct svc_driver_api *api = DEV_API(dev);
282 :
283 : __ASSERT(api->sip_svc_plat_async_res_req,
284 : "sip_svc_plat_async_res_req func shouldn't be NULL");
285 : __ASSERT(a0, "a0 shouldn't be NULL");
286 : __ASSERT(a1, "a1 shouldn't be NULL");
287 : __ASSERT(a2, "a2 shouldn't be NULL");
288 : __ASSERT(a3, "a3 shouldn't be NULL");
289 : __ASSERT(a4, "a4 shouldn't be NULL");
290 : __ASSERT(a5, "a5 shouldn't be NULL");
291 : __ASSERT(a6, "a6 shouldn't be NULL");
292 : __ASSERT(a7, "a7 shouldn't be NULL");
293 : __ASSERT(((buf == NULL && size == 0) || (buf != NULL && size != 0)),
294 : "buf and size should represent a buffer");
295 : return api->sip_svc_plat_async_res_req(dev, a0, a1, a2, a3, a4, a5, a6, a7, buf, size);
296 : }
297 :
298 : /**
299 : * @brief Check the response of polling supervisory call and retrieve the response
300 : * size and transaction id.
301 : *
302 : * @param dev Pointer to the device structure for the driver instance.
303 : * @param res Pointer to struct arm_smccc_res response.
304 : * @param buf Pointer to response buffer.
305 : * @param size Size of response in response buffer
306 : * @param trans_id Transaction id of the response.
307 : *
308 : * @retval 0 on getting a valid polling response from supervisory call.
309 : * @retval -EINPROGRESS on no valid polling response from supervisory call.
310 : */
311 1 : __syscall int sip_svc_plat_async_res_res(const struct device *dev, struct arm_smccc_res *res,
312 : char *buf, size_t *size, uint32_t *trans_id);
313 : static inline int z_impl_sip_svc_plat_async_res_res(const struct device *dev,
314 : struct arm_smccc_res *res, char *buf,
315 : size_t *size, uint32_t *trans_id)
316 : {
317 : __ASSERT(dev, "dev shouldn't be NULL");
318 : const struct svc_driver_api *api = DEV_API(dev);
319 :
320 : __ASSERT(api->sip_svc_plat_async_res_res,
321 : "sip_svc_plat_async_res_res func shouldn't be NULL");
322 : __ASSERT(res, "res shouldn't be NULL");
323 : __ASSERT(buf, "buf shouldn't be NULL");
324 : __ASSERT(size, "size shouldn't be NULL");
325 : __ASSERT(trans_id, "buf shouldn't be NULL");
326 :
327 : return api->sip_svc_plat_async_res_res(dev, res, buf, size, trans_id);
328 : }
329 :
330 : /**
331 : * @brief Free the command buffer used for ASYNC packet after sending it to lower layers.
332 : *
333 : * @param dev Pointer to the device structure for the driver instance.
334 : * @param request Pointer to sip_svc_request packet.
335 : */
336 1 : __syscall void sip_svc_plat_free_async_memory(const struct device *dev,
337 : struct sip_svc_request *request);
338 : static inline void z_impl_sip_svc_plat_free_async_memory(const struct device *dev,
339 : struct sip_svc_request *request)
340 : {
341 : __ASSERT(dev, "dev shouldn't be NULL");
342 : const struct svc_driver_api *api = DEV_API(dev);
343 :
344 : __ASSERT(api->sip_svc_plat_free_async_memory,
345 : "sip_svc_plat_free_async_memory func shouldn't be NULL");
346 : __ASSERT(request, "request shouldn't be NULL");
347 :
348 : api->sip_svc_plat_free_async_memory(dev, request);
349 : }
350 :
351 :
352 : #include <zephyr/syscalls/sip_svc_driver.h>
353 :
354 : #endif /* ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ */
|