LCOV - code coverage report
Current view: top level - zephyr/drivers/firmware/scmi - util.h Hit Total Coverage
Test: new.info Lines: 8 19 42.1 %
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 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 1.14