| /* |
| * Copyright (c) 2023, Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ |
| #define ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ |
| |
| #include <zephyr/device.h> |
| #include <zephyr/kernel.h> |
| #include <zephyr/arch/arm64/arm-smccc.h> |
| #include <zephyr/drivers/sip_svc/sip_svc_proto.h> |
| #include <zephyr/sip_svc/sip_svc_controller.h> |
| |
| #define DEV_API(dev) ((struct svc_driver_api *)(dev)->api) |
| |
| /** |
| * @brief Length of SVC conduit name. |
| * |
| */ |
| #define SVC_CONDUIT_NAME_LENGTH (4) |
| |
| /** |
| * @brief Callback API for executing the supervisory call |
| * See @a sip_supervisory_call() for argument description |
| */ |
| typedef void (*sip_supervisory_call_t)(const struct device *dev, unsigned long function_id, |
| unsigned long arg0, unsigned long arg1, unsigned long arg2, |
| unsigned long arg3, unsigned long arg4, unsigned long arg5, |
| unsigned long arg6, struct arm_smccc_res *res); |
| |
| /** |
| * @brief Callback API for validating function id for the supervisory call. |
| * See @a sip_svc_plat_func_id_valid() for argument description |
| */ |
| typedef bool (*sip_svc_plat_func_id_valid_t)(const struct device *dev, uint32_t command, |
| uint32_t func_id); |
| |
| /** |
| * @brief Callback API for generating the transaction id from client id. |
| * See @a sip_svc_plat_format_trans_id() for argument description |
| */ |
| typedef uint32_t (*sip_svc_plat_format_trans_id_t)(const struct device *dev, uint32_t client_idx, |
| uint32_t trans_idx); |
| |
| /** |
| * @brief Callback API for retrieving client transaction id from transaction id |
| * See @a sip_svc_plat_get_trans_idx() for argument description |
| */ |
| typedef uint32_t (*sip_svc_plat_get_trans_idx_t)(const struct device *dev, uint32_t trans_id); |
| |
| /** |
| * @brief Callback API for updating transaction id for request packet for lower layer |
| * See @a sip_svc_plat_update_trans_id() for argument description |
| */ |
| typedef void (*sip_svc_plat_update_trans_id_t)(const struct device *dev, |
| struct sip_svc_request *request, uint32_t trans_id); |
| |
| /** |
| * @brief Callback API for freeing command buffer in ASYNC packets |
| * See @a sip_svc_plat_free_async_memory() for argument description |
| */ |
| typedef void (*sip_svc_plat_free_async_memory_t)(const struct device *dev, |
| struct sip_svc_request *request); |
| |
| /** |
| * @brief Callback API to construct Polling packet for ASYNC transaction. |
| * See @a sip_svc_plat_async_res_req() for argument description |
| */ |
| typedef int (*sip_svc_plat_async_res_req_t)(const struct device *dev, unsigned long *a0, |
| unsigned long *a1, unsigned long *a2, unsigned long *a3, |
| unsigned long *a4, unsigned long *a5, unsigned long *a6, |
| unsigned long *a7, char *buf, size_t size); |
| |
| /** |
| * @brief Callback API to check the response of polling request |
| * See @a sip_svc_plat_async_res_res() for argument description |
| */ |
| typedef int (*sip_svc_plat_async_res_res_t)(const struct device *dev, struct arm_smccc_res *res, |
| char *buf, size_t *size, uint32_t *trans_id); |
| |
| /** |
| * @brief Callback API for retrieving error code from a supervisory call response. |
| * See @a sip_svc_plat_get_error_code() for argument description. |
| */ |
| typedef uint32_t (*sip_svc_plat_get_error_code_t)(const struct device *dev, |
| struct arm_smccc_res *res); |
| |
| /** |
| * @brief API structure for sip_svc driver. |
| * |
| */ |
| __subsystem struct svc_driver_api { |
| sip_supervisory_call_t sip_supervisory_call; |
| sip_svc_plat_func_id_valid_t sip_svc_plat_func_id_valid; |
| sip_svc_plat_format_trans_id_t sip_svc_plat_format_trans_id; |
| sip_svc_plat_get_trans_idx_t sip_svc_plat_get_trans_idx; |
| sip_svc_plat_update_trans_id_t sip_svc_plat_update_trans_id; |
| sip_svc_plat_free_async_memory_t sip_svc_plat_free_async_memory; |
| sip_svc_plat_async_res_req_t sip_svc_plat_async_res_req; |
| sip_svc_plat_async_res_res_t sip_svc_plat_async_res_res; |
| sip_svc_plat_get_error_code_t sip_svc_plat_get_error_code; |
| }; |
| |
| /** |
| * @brief supervisory call function which will execute the smc/hvc call |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param function_id Function identifier for the supervisory call. |
| * @param arg0 Argument 0 for supervisory call. |
| * @param arg1 Argument 1 for supervisory call. |
| * @param arg2 Argument 2 for supervisory call. |
| * @param arg3 Argument 3 for supervisory call. |
| * @param arg4 Argument 4 for supervisory call. |
| * @param arg5 Argument 5 for supervisory call. |
| * @param arg6 Argument 6 for supervisory call. |
| * @param res Pointer to response buffer for supervisory call. |
| */ |
| __syscall void sip_supervisory_call(const struct device *dev, unsigned long function_id, |
| unsigned long arg0, unsigned long arg1, unsigned long arg2, |
| unsigned long arg3, unsigned long arg4, unsigned long arg5, |
| unsigned long arg6, struct arm_smccc_res *res); |
| static inline void z_impl_sip_supervisory_call(const struct device *dev, unsigned long function_id, |
| unsigned long arg0, unsigned long arg1, |
| unsigned long arg2, unsigned long arg3, |
| unsigned long arg4, unsigned long arg5, |
| unsigned long arg6, struct arm_smccc_res *res) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_supervisory_call, "sip_supervisory_call shouldn't be NULL"); |
| __ASSERT(res, "response pointer shouldn't be NULL"); |
| |
| api->sip_supervisory_call(dev, function_id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, res); |
| } |
| |
| /** |
| * @brief Validate the function id for the supervisory call. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param command Command which specify if the call is SYNC or ASYNC. |
| * @param func_id Function identifier |
| * |
| * @retval true if command and function identifiers are valid. |
| * @retval false if command and function identifiers are invalid. |
| */ |
| __syscall bool sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command, |
| uint32_t func_id); |
| static inline bool z_impl_sip_svc_plat_func_id_valid(const struct device *dev, uint32_t command, |
| uint32_t func_id) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_func_id_valid, |
| "sip_svc_plat_func_id_valid func shouldn't be NULL"); |
| |
| return api->sip_svc_plat_func_id_valid(dev, command, func_id); |
| } |
| |
| /** |
| * @brief Formats and generates the transaction id from client id. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param client_idx client index. |
| * @param trans_idx transaction index. |
| * |
| * @retval transaction id, which is used for tracking each transaction. |
| */ |
| __syscall uint32_t sip_svc_plat_format_trans_id(const struct device *dev, uint32_t client_idx, |
| uint32_t trans_idx); |
| static inline uint32_t z_impl_sip_svc_plat_format_trans_id(const struct device *dev, |
| uint32_t client_idx, uint32_t trans_idx) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_format_trans_id, |
| "sip_svc_plat_format_trans_id func shouldn't be NULL"); |
| |
| return api->sip_svc_plat_format_trans_id(dev, client_idx, trans_idx); |
| } |
| |
| /** |
| * @brief Retrieve client transaction id from packet transaction id. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param trans_id transaction identifier if for a transaction. |
| * |
| * @retval client transaction id form Transaction id. |
| */ |
| __syscall uint32_t sip_svc_plat_get_trans_idx(const struct device *dev, uint32_t trans_id); |
| static inline uint32_t z_impl_sip_svc_plat_get_trans_idx(const struct device *dev, |
| uint32_t trans_id) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_get_trans_idx, |
| "sip_svc_plat_get_trans_idx func shouldn't be NULL"); |
| |
| return api->sip_svc_plat_get_trans_idx(dev, trans_id); |
| } |
| |
| /** |
| * @brief Update transaction id for sip_svc_request for lower layer. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param request Pointer to sip_svc_request structure. |
| * @param trans_id Transaction id. |
| */ |
| __syscall void sip_svc_plat_update_trans_id(const struct device *dev, |
| struct sip_svc_request *request, uint32_t trans_id); |
| static inline void z_impl_sip_svc_plat_update_trans_id(const struct device *dev, |
| struct sip_svc_request *request, |
| uint32_t trans_id) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_update_trans_id, |
| "sip_svc_plat_update_trans_id func shouldn't be NULL"); |
| __ASSERT(request, "request shouldn't be NULL"); |
| |
| return api->sip_svc_plat_update_trans_id(dev, request, trans_id); |
| } |
| |
| /** |
| * @brief Retrieve the error code from arm_smccc_res response. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param res Pointer to struct arm_smccc_res response. |
| * |
| * @retval 0 on success. |
| * @retval SIP_SVC_ID_INVALID on failure |
| */ |
| __syscall uint32_t sip_svc_plat_get_error_code(const struct device *dev, struct arm_smccc_res *res); |
| static inline uint32_t z_impl_sip_svc_plat_get_error_code(const struct device *dev, |
| struct arm_smccc_res *res) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_get_error_code, |
| "sip_svc_plat_get_error_code func shouldn't be NULL"); |
| __ASSERT(res, "res shouldn't be NULL"); |
| |
| return api->sip_svc_plat_get_error_code(dev, res); |
| } |
| |
| /** |
| * @brief Set arguments for polling supervisory call. For ASYNC polling of response. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param a0 Argument 0 for supervisory call. |
| * @param a1 Argument 1 for supervisory call. |
| * @param a2 Argument 2 for supervisory call. |
| * @param a3 Argument 3 for supervisory call. |
| * @param a4 Argument 4 for supervisory call. |
| * @param a5 Argument 5 for supervisory call. |
| * @param a6 Argument 6 for supervisory call. |
| * @param a7 Argument 7 for supervisory call. |
| * @param buf Pointer for response buffer. |
| * @param size Size of response buffer. |
| * |
| * @retval 0 on success |
| */ |
| __syscall int sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0, |
| unsigned long *a1, unsigned long *a2, unsigned long *a3, |
| unsigned long *a4, unsigned long *a5, unsigned long *a6, |
| unsigned long *a7, char *buf, size_t size); |
| static inline int z_impl_sip_svc_plat_async_res_req(const struct device *dev, unsigned long *a0, |
| unsigned long *a1, unsigned long *a2, |
| unsigned long *a3, unsigned long *a4, |
| unsigned long *a5, unsigned long *a6, |
| unsigned long *a7, char *buf, size_t size) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_async_res_req, |
| "sip_svc_plat_async_res_req func shouldn't be NULL"); |
| __ASSERT(a0, "a0 shouldn't be NULL"); |
| __ASSERT(a1, "a1 shouldn't be NULL"); |
| __ASSERT(a2, "a2 shouldn't be NULL"); |
| __ASSERT(a3, "a3 shouldn't be NULL"); |
| __ASSERT(a4, "a4 shouldn't be NULL"); |
| __ASSERT(a5, "a5 shouldn't be NULL"); |
| __ASSERT(a6, "a6 shouldn't be NULL"); |
| __ASSERT(a7, "a7 shouldn't be NULL"); |
| __ASSERT(((buf == NULL && size == 0) || (buf != NULL && size != 0)), |
| "buf and size should represent a buffer"); |
| return api->sip_svc_plat_async_res_req(dev, a0, a1, a2, a3, a4, a5, a6, a7, buf, size); |
| } |
| |
| /** |
| * @brief Check the response of polling supervisory call and retrieve the response |
| * size and transaction id. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param res Pointer to struct arm_smccc_res response. |
| * @param buf Pointer to response buffer. |
| * @param size Size of response in response buffer |
| * @param trans_id Transaction id of the response. |
| * |
| * @retval 0 on getting a valid polling response from supervisory call. |
| * @retval -EINPROGRESS on no valid polling response from supervisory call. |
| */ |
| __syscall int sip_svc_plat_async_res_res(const struct device *dev, struct arm_smccc_res *res, |
| char *buf, size_t *size, uint32_t *trans_id); |
| static inline int z_impl_sip_svc_plat_async_res_res(const struct device *dev, |
| struct arm_smccc_res *res, char *buf, |
| size_t *size, uint32_t *trans_id) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_async_res_res, |
| "sip_svc_plat_async_res_res func shouldn't be NULL"); |
| __ASSERT(res, "res shouldn't be NULL"); |
| __ASSERT(buf, "buf shouldn't be NULL"); |
| __ASSERT(size, "size shouldn't be NULL"); |
| __ASSERT(trans_id, "buf shouldn't be NULL"); |
| |
| return api->sip_svc_plat_async_res_res(dev, res, buf, size, trans_id); |
| } |
| |
| /** |
| * @brief Free the command buffer used for ASYNC packet after sending it to lower layers. |
| * |
| * @param dev Pointer to the device structure for the driver instance. |
| * @param request Pointer to sip_svc_request packet. |
| */ |
| __syscall void sip_svc_plat_free_async_memory(const struct device *dev, |
| struct sip_svc_request *request); |
| static inline void z_impl_sip_svc_plat_free_async_memory(const struct device *dev, |
| struct sip_svc_request *request) |
| { |
| __ASSERT(dev, "dev shouldn't be NULL"); |
| const struct svc_driver_api *api = DEV_API(dev); |
| |
| __ASSERT(api->sip_svc_plat_free_async_memory, |
| "sip_svc_plat_free_async_memory func shouldn't be NULL"); |
| __ASSERT(request, "request shouldn't be NULL"); |
| |
| api->sip_svc_plat_free_async_memory(dev, request); |
| } |
| |
| |
| #include <syscalls/sip_svc_driver.h> |
| |
| #endif /* ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ */ |