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