Line data Source code
1 0 : /*
2 : * Copyright (c) 2024, Ambiq Micro Inc. <www.ambiq.com>
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : #ifndef ZEPHYR_INCLUDE_DRIVERS_MSPI_DEVICETREE_H_
8 : #define ZEPHYR_INCLUDE_DRIVERS_MSPI_DEVICETREE_H_
9 :
10 : /**
11 : * @brief MSPI Devicetree related macros
12 : * @defgroup mspi_devicetree MSPI Devicetree related macros
13 : * @ingroup io_interfaces
14 : * @{
15 : */
16 :
17 : #include <zephyr/drivers/gpio.h>
18 :
19 : #ifdef __cplusplus
20 : extern "C" {
21 : #endif
22 :
23 : /**
24 : * @brief Structure initializer for <tt>struct mspi_dev_cfg</tt> from devicetree
25 : *
26 : * This helper macro expands to a static initializer for a <tt>struct
27 : * mspi_dev_cfg</tt> by reading the relevant data from the devicetree.
28 : *
29 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
30 : * struct mspi_dev_cfg to create an initializer for
31 : */
32 1 : #define MSPI_DEVICE_CONFIG_DT(mspi_dev) \
33 : { \
34 : .ce_num = DT_PROP_OR(mspi_dev, mspi_hardware_ce_num, 0), \
35 : .freq = DT_PROP(mspi_dev, mspi_max_frequency), \
36 : .io_mode = DT_ENUM_IDX_OR(mspi_dev, mspi_io_mode, \
37 : MSPI_IO_MODE_SINGLE), \
38 : .data_rate = DT_ENUM_IDX_OR(mspi_dev, mspi_data_rate, \
39 : MSPI_DATA_RATE_SINGLE), \
40 : .cpp = DT_ENUM_IDX_OR(mspi_dev, mspi_cpp_mode, MSPI_CPP_MODE_0), \
41 : .endian = DT_ENUM_IDX_OR(mspi_dev, mspi_endian, \
42 : MSPI_XFER_LITTLE_ENDIAN), \
43 : .ce_polarity = DT_ENUM_IDX_OR(mspi_dev, mspi_ce_polarity, \
44 : MSPI_CE_ACTIVE_LOW), \
45 : .dqs_enable = DT_PROP(mspi_dev, mspi_dqs_enable), \
46 : .rx_dummy = DT_PROP_OR(mspi_dev, rx_dummy, 0), \
47 : .tx_dummy = DT_PROP_OR(mspi_dev, tx_dummy, 0), \
48 : .read_cmd = DT_PROP_OR(mspi_dev, read_command, 0), \
49 : .write_cmd = DT_PROP_OR(mspi_dev, write_command, 0), \
50 : .cmd_length = DT_ENUM_IDX_OR(mspi_dev, command_length, 0), \
51 : .addr_length = DT_ENUM_IDX_OR(mspi_dev, address_length, 0), \
52 : .mem_boundary = COND_CODE_1(DT_NODE_HAS_PROP(mspi_dev, ce_break_config), \
53 : (DT_PROP_BY_IDX(mspi_dev, ce_break_config, 0)), \
54 : (0)), \
55 : .time_to_break = COND_CODE_1(DT_NODE_HAS_PROP(mspi_dev, ce_break_config), \
56 : (DT_PROP_BY_IDX(mspi_dev, ce_break_config, 1)), \
57 : (0)), \
58 : }
59 :
60 : /**
61 : * @brief Structure initializer for <tt>struct mspi_dev_cfg</tt> from devicetree instance
62 : *
63 : * This is equivalent to
64 : * <tt>MSPI_DEVICE_CONFIG_DT(DT_DRV_INST(inst))</tt>.
65 : *
66 : * @param inst Devicetree instance number
67 : */
68 1 : #define MSPI_DEVICE_CONFIG_DT_INST(inst) MSPI_DEVICE_CONFIG_DT(DT_DRV_INST(inst))
69 :
70 : /**
71 : * @brief Structure initializer for <tt>struct mspi_xip_cfg</tt> from devicetree
72 : *
73 : * This helper macro expands to a static initializer for a <tt>struct
74 : * mspi_xip_cfg</tt> by reading the relevant data from the devicetree.
75 : *
76 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
77 : * struct mspi_xip_cfg to create an initializer for
78 : */
79 1 : #define MSPI_XIP_CONFIG_DT_NO_CHECK(mspi_dev) \
80 : { \
81 : .enable = DT_PROP_BY_IDX(mspi_dev, xip_config, 0), \
82 : .address_offset = DT_PROP_BY_IDX(mspi_dev, xip_config, 1), \
83 : .size = DT_PROP_BY_IDX(mspi_dev, xip_config, 2), \
84 : .permission = DT_PROP_BY_IDX(mspi_dev, xip_config, 3), \
85 : }
86 :
87 : /**
88 : * @brief Structure initializer for <tt>struct mspi_xip_cfg</tt> from devicetree
89 : *
90 : * This helper macro check whether <tt>xip_config</tt> binding exist first
91 : * before calling <tt>MSPI_XIP_CONFIG_DT_NO_CHECK</tt>.
92 : *
93 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
94 : * struct mspi_xip_cfg to create an initializer for
95 : */
96 1 : #define MSPI_XIP_CONFIG_DT(mspi_dev) \
97 : COND_CODE_1(DT_NODE_HAS_PROP(mspi_dev, xip_config), \
98 : (MSPI_XIP_CONFIG_DT_NO_CHECK(mspi_dev)), \
99 : ({}))
100 :
101 : /**
102 : * @brief Structure initializer for <tt>struct mspi_xip_cfg</tt> from devicetree instance
103 : *
104 : * This is equivalent to
105 : * <tt>MSPI_XIP_CONFIG_DT(DT_DRV_INST(inst))</tt>.
106 : *
107 : * @param inst Devicetree instance number
108 : */
109 1 : #define MSPI_XIP_CONFIG_DT_INST(inst) MSPI_XIP_CONFIG_DT(DT_DRV_INST(inst))
110 :
111 : /**
112 : * @brief Structure initializer for <tt>struct mspi_scramble_cfg</tt> from devicetree
113 : *
114 : * This helper macro expands to a static initializer for a <tt>struct
115 : * mspi_scramble_cfg</tt> by reading the relevant data from the devicetree.
116 : *
117 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
118 : * struct mspi_scramble_cfg to create an initializer for
119 : */
120 1 : #define MSPI_SCRAMBLE_CONFIG_DT_NO_CHECK(mspi_dev) \
121 : { \
122 : .enable = DT_PROP_BY_IDX(mspi_dev, scramble_config, 0), \
123 : .address_offset = DT_PROP_BY_IDX(mspi_dev, scramble_config, 1), \
124 : .size = DT_PROP_BY_IDX(mspi_dev, scramble_config, 2), \
125 : }
126 :
127 : /**
128 : * @brief Structure initializer for <tt>struct mspi_scramble_cfg</tt> from devicetree
129 : *
130 : * This helper macro check whether <tt>scramble_config</tt> binding exist first
131 : * before calling <tt>MSPI_SCRAMBLE_CONFIG_DT_NO_CHECK</tt>.
132 : *
133 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
134 : * struct mspi_scramble_cfg to create an initializer for
135 : */
136 1 : #define MSPI_SCRAMBLE_CONFIG_DT(mspi_dev) \
137 : COND_CODE_1(DT_NODE_HAS_PROP(mspi_dev, scramble_config), \
138 : (MSPI_SCRAMBLE_CONFIG_DT_NO_CHECK(mspi_dev)), \
139 : ({}))
140 :
141 : /**
142 : * @brief Structure initializer for <tt>struct mspi_scramble_cfg</tt> from devicetree instance
143 : *
144 : * This is equivalent to
145 : * <tt>MSPI_SCRAMBLE_CONFIG_DT(DT_DRV_INST(inst))</tt>.
146 : *
147 : * @param inst Devicetree instance number
148 : */
149 1 : #define MSPI_SCRAMBLE_CONFIG_DT_INST(inst) MSPI_SCRAMBLE_CONFIG_DT(DT_DRV_INST(inst))
150 :
151 : /**
152 : * @brief Structure initializer for <tt>struct mspi_dev_id</tt> from devicetree
153 : *
154 : * This helper macro expands to a static initializer for a <tt>struct
155 : * mspi_dev_id</tt> by reading the relevant data from the devicetree.
156 : *
157 : * @param mspi_dev Devicetree node identifier for the MSPI device whose
158 : * struct mspi_dev_id to create an initializer for
159 : */
160 1 : #define MSPI_DEVICE_ID_DT(mspi_dev) \
161 : { \
162 : .ce = MSPI_DEV_CE_GPIOS_DT_SPEC_GET(mspi_dev), \
163 : .dev_idx = DT_REG_ADDR(mspi_dev), \
164 : }
165 :
166 : /**
167 : * @brief Structure initializer for <tt>struct mspi_dev_id</tt> from devicetree instance
168 : *
169 : * This is equivalent to
170 : * <tt>MSPI_DEVICE_ID_DT(DT_DRV_INST(inst))</tt>.
171 : *
172 : * @param inst Devicetree instance number
173 : */
174 1 : #define MSPI_DEVICE_ID_DT_INST(inst) MSPI_DEVICE_ID_DT(DT_DRV_INST(inst))
175 :
176 :
177 : /**
178 : * @brief Get a <tt>struct gpio_dt_spec</tt> for a MSPI device's chip enable pin
179 : *
180 : * Example devicetree fragment:
181 : *
182 : * @code{.devicetree}
183 : * gpio1: gpio@abcd0001 { ... };
184 : *
185 : * gpio2: gpio@abcd0002 { ... };
186 : *
187 : * mspi@abcd0003 {
188 : * compatible = "ambiq,mspi";
189 : * ce-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>,
190 : * <&gpio2 20 GPIO_ACTIVE_LOW>;
191 : *
192 : * a: mspi-dev-a@0 {
193 : * reg = <0>;
194 : * };
195 : *
196 : * b: mspi-dev-b@1 {
197 : * reg = <1>;
198 : * };
199 : * };
200 : * @endcode
201 : *
202 : * Example usage:
203 : *
204 : * @code{.c}
205 : * MSPI_DEV_CE_GPIOS_DT_SPEC_GET(DT_NODELABEL(a)) \
206 : * // { DEVICE_DT_GET(DT_NODELABEL(gpio1)), 10, GPIO_ACTIVE_LOW }
207 : * MSPI_DEV_CE_GPIOS_DT_SPEC_GET(DT_NODELABEL(b)) \
208 : * // { DEVICE_DT_GET(DT_NODELABEL(gpio2)), 20, GPIO_ACTIVE_LOW }
209 : * @endcode
210 : *
211 : * @param mspi_dev a MSPI device node identifier
212 : * @return #gpio_dt_spec struct corresponding with mspi_dev's chip enable
213 : */
214 1 : #define MSPI_DEV_CE_GPIOS_DT_SPEC_GET(mspi_dev) \
215 : GPIO_DT_SPEC_GET_BY_IDX_OR(DT_BUS(mspi_dev), ce_gpios, \
216 : DT_REG_ADDR_RAW(mspi_dev), {})
217 :
218 : /**
219 : * @brief Get a <tt>struct gpio_dt_spec</tt> for a MSPI device's chip enable pin
220 : *
221 : * This is equivalent to
222 : * <tt>MSPI_DEV_CE_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))</tt>.
223 : *
224 : * @param inst Devicetree instance number
225 : * @return #gpio_dt_spec struct corresponding with mspi_dev's chip enable
226 : */
227 1 : #define MSPI_DEV_CE_GPIOS_DT_SPEC_INST_GET(inst) \
228 : MSPI_DEV_CE_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))
229 :
230 :
231 : /**
232 : * @brief Get an array of <tt>struct gpio_dt_spec</tt> from devicetree for a MSPI controller
233 : *
234 : * This helper macro check whether <tt>ce_gpios</tt> binding exist first
235 : * before calling <tt>GPIO_DT_SPEC_GET_BY_IDX</tt> and expand to an array of
236 : * gpio_dt_spec.
237 : *
238 : * @param node_id Devicetree node identifier for the MSPI controller
239 : * @return an array of gpio_dt_spec struct corresponding with mspi_dev's chip enables
240 : */
241 1 : #define MSPI_CE_GPIOS_DT_SPEC_GET(node_id) \
242 : { \
243 : COND_CODE_1(DT_NODE_HAS_PROP(node_id, ce_gpios), \
244 : (DT_FOREACH_PROP_ELEM_SEP(node_id, ce_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))), \
245 : ()) \
246 : }
247 :
248 : /**
249 : * @brief Get an array of <tt>struct gpio_dt_spec</tt> for a MSPI controller
250 : *
251 : * This is equivalent to
252 : * <tt>MSPI_CE_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))</tt>.
253 : *
254 : * @param inst Devicetree instance number
255 : * @return an array of gpio_dt_spec struct corresponding with mspi_dev's chip enables
256 : */
257 1 : #define MSPI_CE_GPIOS_DT_SPEC_INST_GET(inst) \
258 : MSPI_CE_GPIOS_DT_SPEC_GET(DT_DRV_INST(inst))
259 :
260 : /**
261 : * @brief Initialize and get a pointer to a @p mspi_ce_control from a
262 : * devicetree node identifier
263 : *
264 : * This helper is useful for initializing a device on a MSPI bus. It
265 : * initializes a struct mspi_ce_control and returns a pointer to it.
266 : * Here, @p node_id is a node identifier for a MSPI device, not a MSPI
267 : * controller.
268 : *
269 : * Example devicetree fragment:
270 : *
271 : * @code{.devicetree}
272 : * mspi@abcd0001 {
273 : * ce-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
274 : * mspidev: mspi-device@0 { ... };
275 : * };
276 : * @endcode
277 : *
278 : * Example usage:
279 : *
280 : * @code{.c}
281 : * struct mspi_ce_control ctrl =
282 : * MSPI_CE_CONTROL_INIT(DT_NODELABEL(mspidev), 2);
283 : * @endcode
284 : *
285 : * This example is equivalent to:
286 : *
287 : * @code{.c}
288 : * struct mspi_ce_control ctrl = {
289 : * .gpio = MSPI_DEV_CE_GPIOS_DT_SPEC_GET(DT_NODELABEL(mspidev)),
290 : * .delay = 2,
291 : * };
292 : * @endcode
293 : *
294 : * @param node_id Devicetree node identifier for a device on a MSPI bus
295 : * @param delay_ The @p delay field to set in the @p mspi_ce_control
296 : * @return a pointer to the @p mspi_ce_control structure
297 : */
298 1 : #define MSPI_CE_CONTROL_INIT(node_id, delay_) \
299 : { \
300 : .gpio = MSPI_DEV_CE_GPIOS_DT_SPEC_GET(node_id), .delay = (delay_), \
301 : }
302 :
303 : /**
304 : * @brief Get a pointer to a @p mspi_ce_control from a devicetree node
305 : *
306 : * This is equivalent to
307 : * <tt>MSPI_CE_CONTROL_INIT(DT_DRV_INST(inst), delay)</tt>.
308 : *
309 : * Therefore, @p DT_DRV_COMPAT must already be defined before using
310 : * this macro.
311 : *
312 : * @param inst Devicetree node instance number
313 : * @param delay_ The @p delay field to set in the @p mspi_ce_control
314 : * @return a pointer to the @p mspi_ce_control structure
315 : */
316 1 : #define MSPI_CE_CONTROL_INIT_INST(inst, delay_) MSPI_CE_CONTROL_INIT(DT_DRV_INST(inst), delay_)
317 :
318 : #ifdef __cplusplus
319 : }
320 : #endif
321 :
322 : /**
323 : * @}
324 : */
325 :
326 : #endif /* ZEPHYR_INCLUDE_DRIVERS_MSPI_DEVICETREE_H_ */
|