1 /*
2  * Copyright 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_I3C_DEVICETREE_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_I3C_DEVICETREE_H_
9 
10 /**
11  * @brief I3C Devicetree related bits
12  * @defgroup i3c_devicetree I3C Devicetree related bits
13  * @ingroup i3c_interface
14  * @{
15  */
16 
17 #include <stdint.h>
18 
19 #include <zephyr/device.h>
20 #include <zephyr/devicetree.h>
21 #include <zephyr/sys/util.h>
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 /**
28  * @brief Structure initializer for i3c_device_id from devicetree
29  *
30  * This helper macro expands to a static initializer for a <tt>struct
31  * i3c_device_id</tt> by reading the relevant device data from devicetree.
32  *
33  * @param node_id Devicetree node identifier for the I3C device whose
34  *                struct i3c_device_id to create an initializer for
35  */
36 #define I3C_DEVICE_ID_DT(node_id)					\
37 	{								\
38 		.pid = ((uint64_t)DT_PROP_BY_IDX(node_id, reg, 1) << 32)\
39 		       | DT_PROP_BY_IDX(node_id, reg, 2),		\
40 	}
41 
42 /**
43  * @brief Structure initializer for i3c_device_id from devicetree instance
44  *
45  * This is equivalent to
46  * @code{.c}
47  * I3C_DEVICE_ID_DT(DT_DRV_INST(inst))
48  * @endcode
49  *
50  * @param inst Devicetree instance number
51  */
52 #define I3C_DEVICE_ID_DT_INST(inst)					\
53 	I3C_DEVICE_ID_DT(DT_DRV_INST(inst))
54 
55 /**
56  * @brief Structure initializer for i3c_device_desc from devicetree
57  *
58  * This helper macro expands to a static initializer for a <tt>struct
59  * i3c_device_desc</tt> by reading the relevant bus and device data
60  * from the devicetree.
61  *
62  * @param node_id Devicetree node identifier for the I3C device whose
63  *                struct i3c_device_desc to create an initializer for
64  */
65 #define I3C_DEVICE_DESC_DT(node_id)					\
66 	{								\
67 		.bus = DEVICE_DT_GET(DT_BUS(node_id)),			\
68 		.dev = DEVICE_DT_GET(node_id),				\
69 		.static_addr = DT_PROP_BY_IDX(node_id, reg, 0),		\
70 		.pid = ((uint64_t)DT_PROP_BY_IDX(node_id, reg, 1) << 32)\
71 		       | DT_PROP_BY_IDX(node_id, reg, 2),		\
72 		.init_dynamic_addr =					\
73 			DT_PROP_OR(node_id, assigned_address, 0),	\
74 		.supports_setaasa = DT_PROP(node_id, supports_setaasa), \
75 	},
76 
77 /**
78  * @brief Structure initializer for i3c_device_desc from devicetree instance
79  *
80  * This is equivalent to
81  *
82  * @code{.c}
83  * I3C_DEVICE_DESC_DT(DT_DRV_INST(inst))
84  * @endcode
85  *
86  * @param inst Devicetree instance number
87  */
88 #define I3C_DEVICE_DESC_DT_INST(inst)					\
89 	I3C_DEVICE_DESC_DT(DT_DRV_INST(inst))
90 
91 /**
92  * @brief Structure initializer for i3c_device_desc from devicetree
93  *
94  * This is mainly used by I3C_DEVICE_ARRAY_DT() to only
95  * create a struct if and only if it is an I3C device.
96  */
97 #define I3C_DEVICE_DESC_DT_FILTERED(node_id)				\
98 	COND_CODE_0(DT_PROP_BY_IDX(node_id, reg, 1),			\
99 		    (), (I3C_DEVICE_DESC_DT(node_id)))
100 
101 /**
102  * @brief Array initializer for a list of i3c_device_desc from devicetree
103  *
104  * This is a helper macro to generate an array for a list of i3c_device_desc
105  * from device tree.
106  *
107  * @param node_id Devicetree node identifier of the I3C controller
108  */
109 #define I3C_DEVICE_ARRAY_DT(node_id)					\
110 	{								\
111 		DT_FOREACH_CHILD_STATUS_OKAY(				\
112 			node_id,					\
113 			I3C_DEVICE_DESC_DT_FILTERED)			\
114 	}
115 
116 /**
117  * @brief Array initializer for a list of i3c_device_desc from devicetree instance
118  *
119  * This is equivalent to
120  * @code{.c}
121  * I3C_DEVICE_ARRAY_DT(DT_DRV_INST(inst))
122  * @endcode
123  *
124  * @param inst Devicetree instance number of the I3C controller
125  */
126 #define I3C_DEVICE_ARRAY_DT_INST(inst)					\
127 	I3C_DEVICE_ARRAY_DT(DT_DRV_INST(inst))
128 
129 /**
130  * @brief Like DEVICE_DT_DEFINE() with I3C target device specifics.
131  *
132  * Defines a I3C target device which implements the I3C target device API.
133  *
134  * @param node_id The devicetree node identifier.
135  *
136  * @param init_fn Name of the init function of the driver.
137  *
138  * @param pm PM device resources reference (`NULL` if device does not use PM).
139  *
140  * @param data Pointer to the device's private data.
141  *
142  * @param config The address to the structure containing the
143  *               configuration information for this instance of the driver.
144  *
145  * @param level The initialization level. See SYS_INIT() for
146  *              details.
147  *
148  * @param prio Priority within the selected initialization level. See
149  *             SYS_INIT() for details.
150  *
151  * @param api Provides an initial pointer to the API function struct
152  *            used by the driver. Can be NULL.
153  */
154 #define I3C_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level,	\
155 			     prio, api, ...)				\
156 	DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level,	\
157 			 prio, api, __VA_ARGS__)
158 
159 /**
160  * @brief Like I3C_TARGET_DT_DEFINE() for an instance of a DT_DRV_COMPAT compatible
161  *
162  * @param inst instance number. This is replaced by
163  * `DT_DRV_COMPAT(inst)` in the call to I3C_TARGET_DT_DEFINE().
164  *
165  * @param ... other parameters as expected by I3C_TARGET_DT_DEFINE().
166  */
167 #define I3C_DEVICE_DT_INST_DEFINE(inst, ...)				\
168 	I3C_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
169 
170 /**
171  * @brief Structure initializer for i3c_i2c_device_desc from devicetree
172  *
173  * This helper macro expands to a static initializer for a i3c_i2c_device_desc
174  * by reading the relevant bus and device data from the devicetree.
175  *
176  * @param node_id Devicetree node identifier for the I3C device whose
177  *                struct i3c_i2c_device_desc to create an initializer for
178  */
179 #define I3C_I2C_DEVICE_DESC_DT(node_id)					\
180 	{								\
181 		.bus = DEVICE_DT_GET(DT_BUS(node_id)),			\
182 		.addr = DT_PROP_BY_IDX(node_id, reg, 0),		\
183 		.lvr = DT_PROP_BY_IDX(node_id, reg, 2),			\
184 	},
185 
186 /**
187  * @brief Structure initializer for i3c_i2c_device_desc from devicetree instance
188  *
189  * This is equivalent to
190  * @code{.c}
191  * I3C_I2C_DEVICE_DESC_DT(DT_DRV_INST(inst))
192  * @endcode
193  *
194  * @param inst Devicetree instance number
195  */
196 #define I3C_I2C_DEVICE_DESC_DT_INST(inst) \
197 	I3C_I2C_DEVICE_DESC_DT(DT_DRV_INST(inst))
198 
199 
200 /**
201  * @brief Structure initializer for i3c_i2c_device_desc from devicetree
202  *
203  * This is mainly used by I3C_I2C_DEVICE_ARRAY_DT() to only
204  * create a struct if and only if it is an I2C device.
205  */
206 #define I3C_I2C_DEVICE_DESC_DT_FILTERED(node_id)			\
207 	COND_CODE_0(DT_PROP_BY_IDX(node_id, reg, 1),			\
208 		    (I3C_I2C_DEVICE_DESC_DT(node_id)), ())
209 
210 /**
211  * @brief Array initializer for a list of i3c_i2c_device_desc from devicetree
212  *
213  * This is a helper macro to generate an array for a list of
214  * i3c_i2c_device_desc from device tree.
215  *
216  * @param node_id Devicetree node identifier of the I3C controller
217  */
218 #define I3C_I2C_DEVICE_ARRAY_DT(node_id)				\
219 	{								\
220 		DT_FOREACH_CHILD_STATUS_OKAY(				\
221 			node_id,					\
222 			I3C_I2C_DEVICE_DESC_DT_FILTERED)		\
223 	}
224 
225 /**
226  * @brief Array initializer for a list of i3c_i2c_device_desc from devicetree instance
227  *
228  * This is equivalent to
229  * @code{.c}
230  * I3C_I2C_DEVICE_ARRAY_DT(DT_DRV_INST(inst))
231  * @endcode
232  *
233  * @param inst Devicetree instance number of the I3C controller
234  */
235 #define I3C_I2C_DEVICE_ARRAY_DT_INST(inst)				\
236 	I3C_I2C_DEVICE_ARRAY_DT(DT_DRV_INST(inst))
237 
238 #ifdef __cplusplus
239 }
240 #endif
241 
242 /**
243  * @}
244  */
245 
246 #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_DEVICETREE_H_ */
247