From ebf48d711225e4aa428fc3f42409ae7ec8633d24 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Mon, 14 Feb 2022 11:46:49 -0800 Subject: [PATCH] drivers/ipm: Add IPM_CALLBACK_ASYNC mode Some IPM devices support asynchronous command processing, where acknowledgment of an IPM message can be delayed while handling happens in a context other than the ISR that invoked the callback. Expose this via a kconfig that can be selected by the driver, and add a new "complete" call (a zero-overhead stub on non-supporting devices) to signal the end of message handling. Signed-off-by: Andy Ross --- drivers/ipm/Kconfig | 8 ++++++++ include/drivers/ipm.h | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index 9fc0b957733..405e797fade 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -129,6 +129,14 @@ config IPM_STM32_HSEM_CPU help use to define the CPU ID used by HSEM +config IPM_CALLBACK_ASYNC + bool "Deliver callbacks asynchronously" + help + When selected, the driver supports "asynchronous" command + delivery. Commands will stay active after the ISR returns, + until the application expressly "completes" the command + later. + module = IPM module-str = ipm source "subsys/logging/Kconfig.template.log_config" diff --git a/include/drivers/ipm.h b/include/drivers/ipm.h index a415f0a0283..11c12459d0d 100644 --- a/include/drivers/ipm.h +++ b/include/drivers/ipm.h @@ -87,12 +87,23 @@ typedef void (*ipm_register_callback_t)(const struct device *port, */ typedef int (*ipm_set_enabled_t)(const struct device *ipmdev, int enable); +/** + * @typedef ipm_complete_t + * @brief Callback API upon command completion + * + * See @a ipm_complete() for argument definitions. + */ +typedef void (*ipm_complete_t)(const struct device *ipmdev); + __subsystem struct ipm_driver_api { ipm_send_t send; ipm_register_callback_t register_callback; ipm_max_data_size_get_t max_data_size_get; ipm_max_id_val_get_t max_id_val_get; ipm_set_enabled_t set_enabled; +#ifdef CONFIG_IPM_CALLBACK_ASYNC + ipm_complete_t complete; +#endif }; /** @@ -221,6 +232,34 @@ static inline int z_impl_ipm_set_enabled(const struct device *ipmdev, return api->set_enabled(ipmdev, enable); } +/** + * @brief Signal asynchronous command completion + * + * Some IPM backends have an ability to deliver a command + * asynchronously. The callback will be invoked in interrupt context, + * but the message (including the provided data pointer) will stay + * "active" and unacknowledged until later code (presumably in thread + * mode) calls ipm_complete(). + * + * This function is, obviously, a noop on drivers without async + * support. + * + * @param ipmdev Driver instance pointer. + */ +__syscall void ipm_complete(const struct device *ipmdev); + +static inline void z_impl_ipm_complete(const struct device *ipmdev) +{ +#ifdef CONFIG_IPM_CALLBACK_ASYNC + const struct ipm_driver_api *api = + (const struct ipm_driver_api *)ipmdev->api; + + if (api->complete != NULL) { + api->complete(ipmdev); + } +#endif +} + #ifdef __cplusplus } #endif