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 #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 #define DT_SCMI_TRANSPORT_CHANNELS_DECLARE(node_id) 160 161 #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 #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 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 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 #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 #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 #define SCMI_PROTOCOL_BASE 16 276 #define SCMI_PROTOCOL_POWER_DOMAIN 17 277 #define SCMI_PROTOCOL_SYSTEM 18 278 #define SCMI_PROTOCOL_PERF 19 279 #define SCMI_PROTOCOL_CLOCK 20 280 #define SCMI_PROTOCOL_SENSOR 21 281 #define SCMI_PROTOCOL_RESET_DOMAIN 22 282 #define SCMI_PROTOCOL_VOLTAGE_DOMAIN 23 283 #define SCMI_PROTOCOL_PCAP_MONITOR 24 284 #define SCMI_PROTOCOL_PINCTRL 25 285 286 #endif /* _INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_SCMI_UTIL_H_ */ 287