LCOV - code coverage report
Current view: top level - zephyr/drivers/firmware/scmi - transport.h Hit Total Coverage
Test: new.info Lines: 15 21 71.4 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /*
       2             :  * Copyright 2024 NXP
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : 
       7             : /**
       8             :  * @file
       9             :  * @brief Public APIs for the SCMI transport layer drivers
      10             :  */
      11             : 
      12             : #ifndef _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_TRANSPORT_H_
      13             : #define _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_TRANSPORT_H_
      14             : 
      15             : #include <zephyr/device.h>
      16             : #include <zephyr/kernel.h>
      17             : 
      18             : struct scmi_message;
      19             : struct scmi_channel;
      20             : 
      21             : /**
      22             :  * @typedef scmi_channel_cb
      23             :  *
      24             :  * @brief Callback function for message replies
      25             :  *
      26             :  * This function should be called by the transport layer
      27             :  * driver whenever a reply to a previously sent message
      28             :  * has been received. Its purpose is to notifying the SCMI
      29             :  * core of the reply's arrival so that proper action can
      30             :  * be taken.
      31             :  *
      32             :  * @param chan pointer to SCMI channel on which the reply
      33             :  * arrived
      34             :  */
      35           1 : typedef void (*scmi_channel_cb)(struct scmi_channel *chan);
      36             : 
      37             : /**
      38             :  * @struct scmi_channel
      39             :  * @brief SCMI channel structure
      40             :  *
      41             :  * An SCMI channel is a medium through which a protocol
      42             :  * is able to transmit/receive messages. Each of the SCMI
      43             :  * channels is represented by a `struct scmi_channel`.
      44             :  */
      45           1 : struct scmi_channel {
      46             :         /**
      47             :          * channel lock. This is meant to be initialized
      48             :          * and used only by the SCMI core to assure that
      49             :          * only one protocol can send/receive messages
      50             :          * through a channel at a given moment.
      51             :          */
      52           1 :         struct k_mutex lock;
      53             :         /**
      54             :          * binary semaphore. This is meant to be initialized
      55             :          * and used only by the SCMI core. Its purpose is to
      56             :          * signal that a reply has been received.
      57             :          */
      58           1 :         struct k_sem sem;
      59             :         /** channel private data */
      60           1 :         void *data;
      61             :         /**
      62             :          * callback function. This is meant to be set by
      63             :          * the SCMI core and should be called by the SCMI
      64             :          * transport layer driver whenever a reply has
      65             :          * been received.
      66             :          */
      67           1 :         scmi_channel_cb cb;
      68             :         /** is the channel ready to be used by a protocol? */
      69           1 :         bool ready;
      70             : };
      71             : 
      72           0 : struct scmi_transport_api {
      73           0 :         int (*init)(const struct device *transport);
      74           0 :         int (*send_message)(const struct device *transport,
      75             :                             struct scmi_channel *chan,
      76             :                             struct scmi_message *msg);
      77           0 :         int (*setup_chan)(const struct device *transport,
      78             :                           struct scmi_channel *chan,
      79             :                           bool tx);
      80           0 :         int (*read_message)(const struct device *transport,
      81             :                             struct scmi_channel *chan,
      82             :                             struct scmi_message *msg);
      83           0 :         bool (*channel_is_free)(const struct device *transport,
      84             :                                 struct scmi_channel *chan);
      85             :         struct scmi_channel *(*request_channel)(const struct device *transport,
      86             :                                                 uint32_t proto, bool tx);
      87             : };
      88             : 
      89             : /**
      90             :  * @brief Request an SCMI channel dynamically
      91             :  *
      92             :  * Whenever the SCMI transport layer driver doesn't support
      93             :  * static channel allocation, the SCMI core will try to bind
      94             :  * a channel to a protocol dynamically using this function.
      95             :  * Note that no setup needs to be performed on the channel
      96             :  * in this function as the core will also call the channel
      97             :  * setup() function.
      98             :  *
      99             :  * @param transport pointer to the device structure for the
     100             :  * transport layer
     101             :  * @param proto ID of the protocol for which the core is
     102             :  * requesting the channel
     103             :  * @param tx true if the channel is TX, false if RX
     104             :  *
     105             :  * @retval pointer to SCMI channel that's to be bound
     106             :  * to the protocol
     107             :  * @retval NULL if operation was not successful
     108             :  */
     109             : static inline struct scmi_channel *
     110           1 : scmi_transport_request_channel(const struct device *transport,
     111             :                                uint32_t proto, bool tx)
     112             : {
     113             :         const struct scmi_transport_api *api =
     114             :                 (const struct scmi_transport_api *)transport->api;
     115             : 
     116             :         if (api->request_channel) {
     117             :                 return api->request_channel(transport, proto, tx);
     118             :         }
     119             : 
     120             :         return NULL;
     121             : }
     122             : 
     123             : /**
     124             :  * @brief Perform initialization for the transport layer driver
     125             :  *
     126             :  * The transport layer driver can't be initialized directly
     127             :  * (i.e via a call to its init() function) during system initialization.
     128             :  * This is because the macro used to define an SCMI transport places
     129             :  * `scmi_core_transport_init()` in the init section instead of the
     130             :  * driver's init() function. As such, `scmi_core_transport_init()`
     131             :  * needs to call this function to perfrom transport layer driver
     132             :  * initialization if required.
     133             :  *
     134             :  * This operation is optional.
     135             :  *
     136             :  * @param transport pointer to the device structure for the
     137             :  * transport layer
     138             :  *
     139             :  * @retval 0 if successful
     140             :  * @retval negative errno code if failure
     141             :  */
     142           1 : static inline int scmi_transport_init(const struct device *transport)
     143             : {
     144             :         const struct scmi_transport_api *api =
     145             :                 (const struct scmi_transport_api *)transport->api;
     146             : 
     147             :         if (api->init) {
     148             :                 return api->init(transport);
     149             :         }
     150             : 
     151             :         return 0;
     152             : }
     153             : 
     154             : /**
     155             :  * @brief Setup an SCMI channel
     156             :  *
     157             :  * Before being able to send/receive messages, an SCMI channel needs
     158             :  * to be prepared, which is what this function does. If it returns
     159             :  * successfully, an SCMI protocol will be able to use this channel
     160             :  * to send/receive messages.
     161             :  *
     162             :  * @param transport pointer to the device structure for the
     163             :  * transport layer
     164             :  * @param chan pointer to SCMI channel to be prepared
     165             :  * @param tx true if the channel is TX, false if RX
     166             :  *
     167             :  * @retval 0 if successful
     168             :  * @retval negative errno code if failure
     169             :  */
     170           1 : static inline int scmi_transport_setup_chan(const struct device *transport,
     171             :                                             struct scmi_channel *chan,
     172             :                                             bool tx)
     173             : {
     174             :         const struct scmi_transport_api *api =
     175             :                 (const struct scmi_transport_api *)transport->api;
     176             : 
     177             :         if (!api || !api->setup_chan) {
     178             :                 return -ENOSYS;
     179             :         }
     180             : 
     181             :         return api->setup_chan(transport, chan, tx);
     182             : }
     183             : 
     184             : /**
     185             :  * @brief Send an SCMI channel
     186             :  *
     187             :  * Send an SCMI message using given SCMI channel. This function is
     188             :  * not allowed to block.
     189             :  *
     190             :  * @param transport pointer to the device structure for the
     191             :  * transport layer
     192             :  * @param chan pointer to SCMI channel on which the message
     193             :  * is to be sent
     194             :  * @param msg pointer to message the caller wishes to send
     195             :  *
     196             :  * @retval 0 if successful
     197             :  * @retval negative errno code if failure
     198             :  */
     199           1 : static inline int scmi_transport_send_message(const struct device *transport,
     200             :                                               struct scmi_channel *chan,
     201             :                                               struct scmi_message *msg)
     202             : {
     203             :         const struct scmi_transport_api *api =
     204             :                 (const struct scmi_transport_api *)transport->api;
     205             : 
     206             :         if (!api || !api->send_message) {
     207             :                 return -ENOSYS;
     208             :         }
     209             : 
     210             :         return api->send_message(transport, chan, msg);
     211             : }
     212             : 
     213             : /**
     214             :  * @brief Read an SCMI message
     215             :  *
     216             :  * @param transport pointer to the device structure for the
     217             :  * transport layer
     218             :  * @param chan pointer to SCMI channel on which the message
     219             :  * is to be read
     220             :  * @param msg pointer to message the caller wishes to read
     221             :  *
     222             :  * @retval 0 if successful
     223             :  * @retval negative errno code if failure
     224             :  */
     225           1 : static inline int scmi_transport_read_message(const struct device *transport,
     226             :                                               struct scmi_channel *chan,
     227             :                                               struct scmi_message *msg)
     228             : {
     229             :         const struct scmi_transport_api *api =
     230             :                 (const struct scmi_transport_api *)transport->api;
     231             : 
     232             :         if (!api || !api->read_message) {
     233             :                 return -ENOSYS;
     234             :         }
     235             : 
     236             :         return api->read_message(transport, chan, msg);
     237             : }
     238             : 
     239             : /**
     240             :  * @brief Check if an SCMI channel is free
     241             :  *
     242             :  * @param transport pointer to the device structure for
     243             :  * the transport layer
     244             :  * @param chan pointer to SCMI channel the query is to be
     245             :  * performed on
     246             :  *
     247             :  * @retval 0 if successful
     248             :  * @retval negative errno code if failure
     249             :  */
     250           1 : static inline bool scmi_transport_channel_is_free(const struct device *transport,
     251             :                                                   struct scmi_channel *chan)
     252             : {
     253             :         const struct scmi_transport_api *api =
     254             :                 (const struct scmi_transport_api *)transport->api;
     255             : 
     256             :         if (!api || !api->channel_is_free) {
     257             :                 return -ENOSYS;
     258             :         }
     259             : 
     260             :         return api->channel_is_free(transport, chan);
     261             : }
     262             : 
     263             : /**
     264             :  * @brief Perfrom SCMI core initialization
     265             :  *
     266             :  * @param transport pointer to the device structure for
     267             :  * the transport layer
     268             :  *
     269             :  * @retval 0 if successful
     270             :  * @retval negative errno code if failure
     271             :  */
     272           1 : int scmi_core_transport_init(const struct device *transport);
     273             : 
     274             : #endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_TRANSPORT_H_ */

Generated by: LCOV version 1.14