LCOV - code coverage report
Current view: top level - zephyr/drivers - ipm.h Hit Total Coverage
Test: new.info Lines: 14 20 70.0 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Generic low-level inter-processor mailbox communication API.
       5             :  */
       6             : 
       7             : /*
       8             :  * Copyright (c) 2015 Intel Corporation
       9             :  *
      10             :  * SPDX-License-Identifier: Apache-2.0
      11             :  */
      12             : 
      13             : #ifndef ZEPHYR_INCLUDE_DRIVERS_IPM_H_
      14             : #define ZEPHYR_INCLUDE_DRIVERS_IPM_H_
      15             : 
      16             : /**
      17             :  * @brief IPM Interface
      18             :  * @defgroup ipm_interface IPM Interface
      19             :  * @since 1.0
      20             :  * @version 1.0.0
      21             :  * @ingroup io_interfaces
      22             :  * @{
      23             :  */
      24             : 
      25             : #include <zephyr/kernel.h>
      26             : #include <zephyr/device.h>
      27             : 
      28             : #ifdef __cplusplus
      29             : extern "C" {
      30             : #endif
      31             : 
      32             : /**
      33             :  * @typedef ipm_callback_t
      34             :  * @brief Callback API for incoming IPM messages
      35             :  *
      36             :  * These callbacks execute in interrupt context. Therefore, use only
      37             :  * interrupt-safe APIS. Registration of callbacks is done via
      38             :  * @a ipm_register_callback
      39             :  *
      40             :  * @param ipmdev Driver instance
      41             :  * @param user_data Pointer to some private data provided at registration
      42             :  *        time.
      43             :  * @param id Message type identifier.
      44             :  * @param data Message data pointer. The correct amount of data to read out
      45             :  *        must be inferred using the message id/upper level protocol.
      46             :  */
      47           1 : typedef void (*ipm_callback_t)(const struct device *ipmdev, void *user_data,
      48             :                                uint32_t id, volatile void *data);
      49             : 
      50             : /**
      51             :  * @typedef ipm_send_t
      52             :  * @brief Callback API to send IPM messages
      53             :  *
      54             :  * See @a ipm_send() for argument definitions.
      55             :  */
      56           1 : typedef int (*ipm_send_t)(const struct device *ipmdev, int wait, uint32_t id,
      57             :                           const void *data, int size);
      58             : /**
      59             :  * @typedef ipm_max_data_size_get_t
      60             :  * @brief Callback API to get maximum data size
      61             :  *
      62             :  * See @a ipm_max_data_size_get() for argument definitions.
      63             :  */
      64           1 : typedef int (*ipm_max_data_size_get_t)(const struct device *ipmdev);
      65             : 
      66             : /**
      67             :  * @typedef ipm_max_id_val_get_t
      68             :  * @brief Callback API to get the ID's maximum value
      69             :  *
      70             :  * See @a ipm_max_id_val_get() for argument definitions.
      71             :  */
      72           1 : typedef uint32_t (*ipm_max_id_val_get_t)(const struct device *ipmdev);
      73             : 
      74             : /**
      75             :  * @typedef ipm_register_callback_t
      76             :  * @brief Callback API upon registration
      77             :  *
      78             :  * See @a ipm_register_callback() for argument definitions.
      79             :  */
      80           1 : typedef void (*ipm_register_callback_t)(const struct device *port,
      81             :                                         ipm_callback_t cb,
      82             :                                         void *user_data);
      83             : 
      84             : /**
      85             :  * @typedef ipm_set_enabled_t
      86             :  * @brief Callback API upon enablement of interrupts
      87             :  *
      88             :  * See @a ipm_set_enabled() for argument definitions.
      89             :  */
      90           1 : typedef int (*ipm_set_enabled_t)(const struct device *ipmdev, int enable);
      91             : 
      92             : /**
      93             :  * @typedef ipm_complete_t
      94             :  * @brief Callback API upon command completion
      95             :  *
      96             :  * See @a ipm_complete() for argument definitions.
      97             :  */
      98           1 : typedef void (*ipm_complete_t)(const struct device *ipmdev);
      99             : 
     100           0 : __subsystem struct ipm_driver_api {
     101           0 :         ipm_send_t send;
     102           0 :         ipm_register_callback_t register_callback;
     103           0 :         ipm_max_data_size_get_t max_data_size_get;
     104           0 :         ipm_max_id_val_get_t max_id_val_get;
     105           0 :         ipm_set_enabled_t set_enabled;
     106             : #ifdef CONFIG_IPM_CALLBACK_ASYNC
     107             :         ipm_complete_t complete;
     108             : #endif
     109             : };
     110             : 
     111             : /**
     112             :  * @brief Try to send a message over the IPM device.
     113             :  *
     114             :  * A message is considered consumed once the remote interrupt handler
     115             :  * finishes. If there is deferred processing on the remote side,
     116             :  * or if outgoing messages must be queued and wait on an
     117             :  * event/semaphore, a high-level driver can implement that.
     118             :  *
     119             :  * There are constraints on how much data can be sent or the maximum value
     120             :  * of id. Use the @a ipm_max_data_size_get and @a ipm_max_id_val_get routines
     121             :  * to determine them.
     122             :  *
     123             :  * The @a size parameter is used only on the sending side to determine
     124             :  * the amount of data to put in the message registers. It is not passed along
     125             :  * to the receiving side. The upper-level protocol dictates the amount of
     126             :  * data read back.
     127             :  *
     128             :  * @param ipmdev Driver instance
     129             :  * @param wait If nonzero, busy-wait for remote to consume the message. The
     130             :  *             message is considered consumed once the remote interrupt handler
     131             :  *             finishes. If there is deferred processing on the remote side,
     132             :  *             or you would like to queue outgoing messages and wait on an
     133             :  *             event/semaphore, you can implement that in a high-level driver
     134             :  * @param id Message identifier. Values are constrained by
     135             :  *        @a ipm_max_data_size_get since many boards only allow for a
     136             :  *        subset of bits in a 32-bit register to store the ID.
     137             :  * @param data Pointer to the data sent in the message.
     138             :  * @param size Size of the data.
     139             :  *
     140             :  * @retval -EBUSY    If the remote hasn't yet read the last data sent.
     141             :  * @retval -EMSGSIZE If the supplied data size is unsupported by the driver.
     142             :  * @retval -EINVAL   If there was a bad parameter, such as: too-large id value.
     143             :  *                   or the device isn't an outbound IPM channel.
     144             :  * @retval 0         On success.
     145             :  */
     146           1 : __syscall int ipm_send(const struct device *ipmdev, int wait, uint32_t id,
     147             :                        const void *data, int size);
     148             : 
     149             : static inline int z_impl_ipm_send(const struct device *ipmdev, int wait,
     150             :                                   uint32_t id,
     151             :                                   const void *data, int size)
     152             : {
     153             :         const struct ipm_driver_api *api =
     154             :                 (const struct ipm_driver_api *)ipmdev->api;
     155             : 
     156             :         return api->send(ipmdev, wait, id, data, size);
     157             : }
     158             : 
     159             : /**
     160             :  * @brief Register a callback function for incoming messages.
     161             :  *
     162             :  * @param ipmdev Driver instance pointer.
     163             :  * @param cb Callback function to execute on incoming message interrupts.
     164             :  * @param user_data Application-specific data pointer which will be passed
     165             :  *        to the callback function when executed.
     166             :  */
     167           1 : static inline void ipm_register_callback(const struct device *ipmdev,
     168             :                                          ipm_callback_t cb, void *user_data)
     169             : {
     170             :         const struct ipm_driver_api *api =
     171             :                 (const struct ipm_driver_api *)ipmdev->api;
     172             : 
     173             :         api->register_callback(ipmdev, cb, user_data);
     174             : }
     175             : 
     176             : /**
     177             :  * @brief Return the maximum number of bytes possible in an outbound message.
     178             :  *
     179             :  * IPM implementations vary on the amount of data that can be sent in a
     180             :  * single message since the data payload is typically stored in registers.
     181             :  *
     182             :  * @param ipmdev Driver instance pointer.
     183             :  *
     184             :  * @return Maximum possible size of a message in bytes.
     185             :  */
     186           1 : __syscall int ipm_max_data_size_get(const struct device *ipmdev);
     187             : 
     188             : static inline int z_impl_ipm_max_data_size_get(const struct device *ipmdev)
     189             : {
     190             :         const struct ipm_driver_api *api =
     191             :                 (const struct ipm_driver_api *)ipmdev->api;
     192             : 
     193             :         return api->max_data_size_get(ipmdev);
     194             : }
     195             : 
     196             : 
     197             : /**
     198             :  * @brief Return the maximum id value possible in an outbound message.
     199             :  *
     200             :  * Many IPM implementations store the message's ID in a register with
     201             :  * some bits reserved for other uses.
     202             :  *
     203             :  * @param ipmdev Driver instance pointer.
     204             :  *
     205             :  * @return Maximum possible value of a message ID.
     206             :  */
     207           1 : __syscall uint32_t ipm_max_id_val_get(const struct device *ipmdev);
     208             : 
     209             : static inline uint32_t z_impl_ipm_max_id_val_get(const struct device *ipmdev)
     210             : {
     211             :         const struct ipm_driver_api *api =
     212             :                 (const struct ipm_driver_api *)ipmdev->api;
     213             : 
     214             :         return api->max_id_val_get(ipmdev);
     215             : }
     216             : 
     217             : /**
     218             :  * @brief Enable interrupts and callbacks for inbound channels.
     219             :  *
     220             :  * @param ipmdev Driver instance pointer.
     221             :  * @param enable Set to 0 to disable and to nonzero to enable.
     222             :  *
     223             :  * @retval 0       On success.
     224             :  * @retval -EINVAL If it isn't an inbound channel.
     225             :  */
     226           1 : __syscall int ipm_set_enabled(const struct device *ipmdev, int enable);
     227             : 
     228             : static inline int z_impl_ipm_set_enabled(const struct device *ipmdev,
     229             :                                          int enable)
     230             : {
     231             :         const struct ipm_driver_api *api =
     232             :                 (const struct ipm_driver_api *)ipmdev->api;
     233             : 
     234             :         return api->set_enabled(ipmdev, enable);
     235             : }
     236             : 
     237             : /**
     238             :  * @brief Signal asynchronous command completion
     239             :  *
     240             :  * Some IPM backends have an ability to deliver a command
     241             :  * asynchronously.  The callback will be invoked in interrupt context,
     242             :  * but the message (including the provided data pointer) will stay
     243             :  * "active" and unacknowledged until later code (presumably in thread
     244             :  * mode) calls ipm_complete().
     245             :  *
     246             :  * This function is, obviously, a noop on drivers without async
     247             :  * support.
     248             :  *
     249             :  * @param ipmdev Driver instance pointer.
     250             :  */
     251           1 : __syscall void ipm_complete(const struct device *ipmdev);
     252             : 
     253             : static inline void z_impl_ipm_complete(const struct device *ipmdev)
     254             : {
     255             : #ifdef CONFIG_IPM_CALLBACK_ASYNC
     256             :         const struct ipm_driver_api *api =
     257             :                 (const struct ipm_driver_api *)ipmdev->api;
     258             : 
     259             :         if (api->complete != NULL) {
     260             :                 api->complete(ipmdev);
     261             :         }
     262             : #endif
     263             : }
     264             : 
     265             : #ifdef __cplusplus
     266             : }
     267             : #endif
     268             : 
     269             : /**
     270             :  * @}
     271             :  */
     272             : 
     273             : #include <zephyr/syscalls/ipm.h>
     274             : 
     275             : #endif /* ZEPHYR_INCLUDE_DRIVERS_IPM_H_ */

Generated by: LCOV version 1.14