LCOV - code coverage report
Current view: top level - zephyr/drivers/firmware/scmi - util.h Coverage Total Hit
Test: new.info Lines: 42.1 % 19 8
Test Date: 2025-09-05 20:47:19

            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 ARM SCMI utility header
      10              :  *
      11              :  * Contains various utility macros and macros used for protocol and
      12              :  * transport "registration".
      13              :  */
      14              : 
      15              : #ifndef _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_UTIL_H_
      16              : #define _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_UTIL_H_
      17              : 
      18              : /**
      19              :  * @brief Build protocol name from its ID
      20              :  *
      21              :  * Given a protocol ID, this macro builds the protocol
      22              :  * name. This is done by concatenating the scmi_protocol_
      23              :  * construct with the given protocol ID.
      24              :  *
      25              :  * @param proto protocol ID in decimal format
      26              :  *
      27              :  * @return protocol name
      28              :  */
      29            1 : #define SCMI_PROTOCOL_NAME(proto) CONCAT(scmi_protocol_, proto)
      30              : 
      31              : #ifdef CONFIG_ARM_SCMI_TRANSPORT_HAS_STATIC_CHANNELS
      32              : 
      33              : #ifdef CONFIG_ARM_SCMI_MAILBOX_TRANSPORT
      34              : /** @brief Check if a protocol node has an associated channel
      35              :  *
      36              :  * This macro, when applied to a protocol node, checks if
      37              :  * the node has a dedicated static channel allocated to it.
      38              :  * This definition is specific to the mailbox driver and
      39              :  * each new transport layer driver should define its own
      40              :  * version of this macro based on the devicetree properties
      41              :  * that indicate the presence of a dedicated channel.
      42              :  *
      43              :  * @param node_id protocol node identifier
      44              :  * @idx channel index. Should be 0 for TX channels and 1 for
      45              :  * RX channels
      46              :  */
      47              : #define DT_SCMI_TRANSPORT_PROTO_HAS_CHAN(node_id, idx)\
      48              :         DT_PROP_HAS_IDX(node_id, shmem, idx)
      49              : #else /* CONFIG_ARM_SCMI_MAILBOX_TRANSPORT */
      50              : #error "Transport with static channels needs to define HAS_CHAN macro"
      51              : #endif /* CONFIG_ARM_SCMI_MAILBOX_TRANSPORT */
      52              : 
      53              : #define SCMI_TRANSPORT_CHAN_NAME(proto, idx) CONCAT(scmi_channel_, proto, _, idx)
      54              : 
      55              : /**
      56              :  * @brief Declare a TX SCMI channel
      57              :  *
      58              :  * Given a node_id for a protocol, this macro declares the SCMI
      59              :  * TX channel statically bound to said protocol via the "extern"
      60              :  * qualifier. This is useful when the transport layer driver
      61              :  * supports static channels since all channel structures are
      62              :  * defined inside the transport layer driver.
      63              :  *
      64              :  * @param node_id protocol node identifier
      65              :  */
      66              : #define DT_SCMI_TRANSPORT_TX_CHAN_DECLARE(node_id)                              \
      67              :         COND_CODE_1(DT_SCMI_TRANSPORT_PROTO_HAS_CHAN(node_id, 0),               \
      68              :                     (extern struct scmi_channel                                 \
      69              :                      SCMI_TRANSPORT_CHAN_NAME(DT_REG_ADDR_RAW(node_id), 0);),   \
      70              :                     (extern struct scmi_channel                                 \
      71              :                      SCMI_TRANSPORT_CHAN_NAME(SCMI_PROTOCOL_BASE, 0);))         \
      72              : 
      73              : /**
      74              :  * @brief Declare SCMI TX/RX channels
      75              :  *
      76              :  * Given a node_id for a protocol, this macro declares the
      77              :  * SCMI TX and RX channels statically bound to said protocol via
      78              :  * the "extern" qualifier. Since RX channels are currently not
      79              :  * supported, this is equivalent to DT_SCMI_TRANSPORT_TX_CHAN_DECLARE().
      80              :  * Despite this, users should opt for this macro instead of the TX-specific
      81              :  * one.
      82              :  *
      83              :  * @param node_id protocol node identifier
      84              :  */
      85              : #define DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id)                             \
      86              :         DT_SCMI_TRANSPORT_TX_CHAN_DECLARE(node_id)                              \
      87              : 
      88              : /**
      89              :  * @brief Declare SCMI TX/RX channels using node instance number
      90              :  *
      91              :  * Same as DT_SCMI_TRANSPORT_CHANNELS_DECLARE() but uses the
      92              :  * protocol's node instance number and the DT_DRV_COMPAT macro.
      93              :  *
      94              :  * @param protocol node instance number
      95              :  */
      96              : #define DT_INST_SCMI_TRANSPORT_CHANNELS_DECLARE(inst)                           \
      97              :         DT_SCMI_TRANSPORT_CHANNELS_DECLARE(DT_INST(inst, DT_DRV_COMPAT))
      98              : 
      99              : /**
     100              :  * @brief Get a reference to a protocol's SCMI TX channel
     101              :  *
     102              :  * Given a node_id for a protocol, this macro returns a
     103              :  * reference to an SCMI TX channel statically bound to said
     104              :  * protocol.
     105              :  *
     106              :  * @param node_id protocol node identifier
     107              :  *
     108              :  * @return reference to the struct scmi_channel of the TX channel
     109              :  * bound to the protocol identifier by node_id
     110              :  */
     111              : #define DT_SCMI_TRANSPORT_TX_CHAN(node_id)                                      \
     112              :         COND_CODE_1(DT_SCMI_TRANSPORT_PROTO_HAS_CHAN(node_id, 0),               \
     113              :                     (&SCMI_TRANSPORT_CHAN_NAME(DT_REG_ADDR_RAW(node_id), 0)),       \
     114              :                     (&SCMI_TRANSPORT_CHAN_NAME(SCMI_PROTOCOL_BASE, 0)))
     115              : 
     116              : /**
     117              :  * @brief Define an SCMI channel for a protocol
     118              :  *
     119              :  * This macro defines a struct scmi_channel for a given protocol.
     120              :  * This should be used by the transport layer driver to statically
     121              :  * define SCMI channels for the protocols.
     122              :  *
     123              :  * @param node_id protocol node identifier
     124              :  * @param idx channel index. Should be 0 for TX channels and 1
     125              :  * for RX channels
     126              :  * @param proto protocol ID in decimal format
     127              :  */
     128              : #define DT_SCMI_TRANSPORT_CHAN_DEFINE(node_id, idx, proto, pdata)               \
     129              :         struct scmi_channel SCMI_TRANSPORT_CHAN_NAME(proto, idx) =              \
     130              :         {                                                                       \
     131              :                 .data = pdata,                                                  \
     132              :         }
     133              : 
     134              : /**
     135              :  * @brief Define an SCMI protocol's data
     136              :  *
     137              :  * Each SCMI protocol is identified by a struct scmi_protocol
     138              :  * placed in a linker section called scmi_protocol. Each protocol
     139              :  * driver is required to use this macro for "registration". Using
     140              :  * this macro directly is higly discouraged and users should opt
     141              :  * for macros such as DT_SCMI_PROTOCOL_DEFINE_NODEV() or
     142              :  * DT_SCMI_PROTOCOL_DEFINE(), which also takes care of the static
     143              :  * channel declaration (if applicable).
     144              :  *
     145              :  * @param node_id protocol node identifier
     146              :  * @param proto protocol ID in decimal format
     147              :  * @param pdata protocol private data
     148              :  */
     149              : #define DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, proto, pdata)                     \
     150              :         STRUCT_SECTION_ITERABLE(scmi_protocol, SCMI_PROTOCOL_NAME(proto)) =     \
     151              :         {                                                                       \
     152              :                 .id = proto,                                                    \
     153              :                 .tx = DT_SCMI_TRANSPORT_TX_CHAN(node_id),                       \
     154              :                 .data = pdata,                                                  \
     155              :         }
     156              : 
     157              : #else /* CONFIG_ARM_SCMI_TRANSPORT_HAS_STATIC_CHANNELS */
     158              : 
     159            0 : #define DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id)
     160              : 
     161            0 : #define DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, proto, pdata)                     \
     162              :         STRUCT_SECTION_ITERABLE(scmi_protocol, SCMI_PROTOCOL_NAME(proto)) =     \
     163              :         {                                                                       \
     164              :                 .id = proto,                                                    \
     165              :                 .data = pdata,                                                  \
     166              :         }
     167              : 
     168              : #endif /* CONFIG_ARM_SCMI_TRANSPORT_HAS_STATIC_CHANNELS */
     169              : 
     170              : /**
     171              :  * @brief Define an SCMI transport driver
     172              :  *
     173              :  * This is merely a wrapper over DEVICE_DT_INST_DEFINE(), but is
     174              :  * required since transport layer drivers are not allowed to place
     175              :  * their own init() function in the init section. Instead, transport
     176              :  * layer drivers place the scmi_core_transport_init() function in the
     177              :  * init section, which, in turn, will call the transport layer driver
     178              :  * init() function. This is required because the SCMI core needs to
     179              :  * perform channel binding and setup during the transport layer driver's
     180              :  * initialization.
     181              :  */
     182            1 : #define DT_INST_SCMI_TRANSPORT_DEFINE(inst, pm, data, config, level, prio, api) \
     183              :         DEVICE_DT_INST_DEFINE(inst, &scmi_core_transport_init,                      \
     184              :                               pm, data, config, level, prio, api)
     185              : 
     186              : /**
     187              :  * @brief Define an SCMI protocol
     188              :  *
     189              :  * This macro performs three important functions:
     190              :  *      1) It defines a `struct scmi_protocol`, which is
     191              :  *      needed by all protocol drivers to work with the SCMI API.
     192              :  *
     193              :  *      2) It declares the static channels bound to the protocol.
     194              :  *      This is only applicable if the transport layer driver
     195              :  *      supports static channels.
     196              :  *
     197              :  *      3) It creates a `struct device` a sets the `data` field
     198              :  *      to the newly defined `struct scmi_protocol`. This is
     199              :  *      needed because the protocol driver needs to work with the
     200              :  *      SCMI API **and** the subsystem API.
     201              :  *
     202              :  * @param node_id protocol node identifier
     203              :  * @param init_fn pointer to protocol's initialization function
     204              :  * @param api pointer to protocol's subsystem API
     205              :  * @param pm pointer to the protocol's power management resources
     206              :  * @param data pointer to protocol's private data
     207              :  * @param config pointer to protocol's private constant data
     208              :  * @param level protocol initialization level
     209              :  * @param prio protocol's priority within its initialization level
     210              :  */
     211              : #define DT_SCMI_PROTOCOL_DEFINE(node_id, init_fn, pm, data, config,             \
     212            1 :                                 level, prio, api)                               \
     213              :         DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id)                             \
     214              :         DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data);  \
     215              :         DEVICE_DT_DEFINE(node_id, init_fn, pm,                                  \
     216              :                          &SCMI_PROTOCOL_NAME(DT_REG_ADDR_RAW(node_id)),             \
     217              :                                              config, level, prio, api)
     218              : 
     219              : /**
     220              :  * @brief Just like DT_SCMI_PROTOCOL_DEFINE(), but uses an instance
     221              :  * of a `DT_DRV_COMPAT` compatible instead of a node identifier
     222              :  *
     223              :  * @param inst instance number
     224              :  * @param init_fn pointer to protocol's initialization function
     225              :  * @param api pointer to protocol's subsystem API
     226              :  * @param pm pointer to the protocol's power management resources
     227              :  * @param data pointer to protocol's private data
     228              :  * @param config pointer to protocol's private constant data
     229              :  * @param level protocol initialization level
     230              :  * @param prio protocol's priority within its initialization level
     231              :  */
     232              : #define DT_INST_SCMI_PROTOCOL_DEFINE(inst, init_fn, pm, data, config,           \
     233            1 :                                      level, prio, api)                          \
     234              :         DT_SCMI_PROTOCOL_DEFINE(DT_INST(inst, DT_DRV_COMPAT), init_fn, pm,      \
     235              :                                 data, config, level, prio, api)
     236              : 
     237              : /**
     238              :  * @brief Define an SCMI protocol with no device
     239              :  *
     240              :  * Variant of DT_SCMI_PROTOCOL_DEFINE(), but no `struct device` is
     241              :  * created and no initialization function is called during system
     242              :  * initialization. This is useful for protocols that are not really
     243              :  * part of a subsystem with an API (e.g: pinctrl).
     244              :  *
     245              :  * @param node_id protocol node identifier
     246              :  * @param data protocol private data
     247              :  */
     248            1 : #define DT_SCMI_PROTOCOL_DEFINE_NODEV(node_id, data)                            \
     249              :         DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id)                             \
     250              :         DT_SCMI_PROTOCOL_DATA_DEFINE(node_id, DT_REG_ADDR_RAW(node_id), data)
     251              : 
     252              : /**
     253              :  * @brief Create an SCMI message field
     254              :  *
     255              :  * Data might not necessarily be encoded in the first
     256              :  * x bits of an SCMI message parameter/return value.
     257              :  * This comes in handy when building said parameters/
     258              :  * return values.
     259              :  *
     260              :  * @param x value to encode
     261              :  * @param mask value to perform bitwise-and with `x`
     262              :  * @param shift value to left-shift masked `x`
     263              :  */
     264            1 : #define SCMI_FIELD_MAKE(x, mask, shift)\
     265              :         (((uint32_t)(x) & (mask)) << (shift))
     266              : 
     267              : /**
     268              :  * @brief SCMI protocol IDs
     269              :  *
     270              :  * Each SCMI protocol is identified by an ID. Each
     271              :  * of these IDs needs to be in decimal since they
     272              :  * might be used to build protocol and static channel
     273              :  * names.
     274              :  */
     275            1 : #define SCMI_PROTOCOL_BASE 16
     276            0 : #define SCMI_PROTOCOL_POWER_DOMAIN 17
     277            0 : #define SCMI_PROTOCOL_SYSTEM 18
     278            0 : #define SCMI_PROTOCOL_PERF 19
     279            0 : #define SCMI_PROTOCOL_CLOCK 20
     280            0 : #define SCMI_PROTOCOL_SENSOR 21
     281            0 : #define SCMI_PROTOCOL_RESET_DOMAIN 22
     282            0 : #define SCMI_PROTOCOL_VOLTAGE_DOMAIN 23
     283            0 : #define SCMI_PROTOCOL_PCAP_MONITOR 24
     284            0 : #define SCMI_PROTOCOL_PINCTRL 25
     285              : 
     286              : #endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_UTIL_H_ */
        

Generated by: LCOV version 2.0-1