1 /*
2  * Copyright (c) 2020 Nuvoton Technology Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef _NUVOTON_NPCX_SOC_DT_H_
8 #define _NUVOTON_NPCX_SOC_DT_H_
9 
10 #include <zephyr/devicetree.h>
11 #include <zephyr/irq.h>
12 #include <zephyr/sys/util_macro.h>
13 
14 /**
15  * @brief Like DT_PROP(), but expand parameters with
16  *        DT_ENUM_UPPER_TOKEN not DT_PROP
17  *
18  * If the prop exists, this expands to DT_ENUM_UPPER_TOKEN(node_id, prop).
19  * The default_value parameter is not expanded in this case.
20  *
21  * Otherwise, this expands to default_value.
22  *
23  * @param node_id node identifier
24  * @param prop lowercase-and-underscores property name
25  * @param default_value a fallback value to expand to
26  * @return the property's enum upper token value or default_value
27  */
28 #define NPCX_DT_PROP_ENUM_OR(node_id, prop, default_value) \
29 	COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \
30 		    (DT_STRING_UPPER_TOKEN(node_id, prop)), (default_value))
31 
32 /**
33  * @brief Like DT_INST_PROP_OR(), but expand parameters with
34  *        NPCX_DT_PROP_ENUM_OR not DT_PROP_OR
35  * @param inst instance number
36  * @param prop lowercase-and-underscores property name
37  * @param default_value a fallback value to expand to
38  * @return the property's enum upper token value or default_value
39  */
40 #define NPCX_DT_INST_PROP_ENUM_OR(inst, prop, default_value) \
41 	NPCX_DT_PROP_ENUM_OR(DT_DRV_INST(inst), prop, default_value)
42 
43 /**
44  * @brief Construct a npcx_clk_cfg item from first item in 'clocks' prop which
45  * type is 'phandle-array' to handle "clock-cells" in current driver.
46  *
47  * Example devicetree fragment:
48  *    / {
49  *		uart1: serial@400c4000 {
50  *			clocks = <&pcc NPCX_CLOCK_BUS_APB2 NPCX_PWDWN_CTL1 4>;
51  *			...
52  *		};
53  *	};
54  *
55  * Example usage:
56  *      const struct npcx_clk_cfg clk_cfg = NPCX_DT_CLK_CFG_ITEM(inst);
57  *
58  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
59  * @return npcx_clk_cfg item.
60  */
61 #define NPCX_DT_CLK_CFG_ITEM(inst)                                             \
62 	{                                                                      \
63 	  .bus  = NPCX_DT_INST_PROP_ENUM_OR(inst, clock_bus,                   \
64 				DT_PHA(DT_DRV_INST(inst), clocks, bus)),       \
65 	  .ctrl = DT_PHA(DT_DRV_INST(inst), clocks, ctl),                      \
66 	  .bit  = DT_PHA(DT_DRV_INST(inst), clocks, bit),                      \
67 	}
68 
69 /**
70  * @brief Construct a npcx_clk_cfg structure from 'clocks' property at index 'i'
71  *
72  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
73  * @param i index of clocks prop which type is 'phandle-array'
74  * @return npcx_clk_cfg item from 'clocks' property at index 'i'
75  */
76 #define NPCX_DT_CLK_CFG_ITEM_BY_IDX(inst, i)                                   \
77 	{                                                                      \
78 	  .bus  = DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), i, bus),            \
79 	  .ctrl = DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), i, ctl),            \
80 	  .bit  = DT_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), i, bit),            \
81 	}
82 
83 /**
84  * @brief Construct a npcx_clk_cfg structure from 'clocks' with the same clock 'name'.
85  *
86  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
87  * @param name name of the clock
88  * @return npcx_clk_cfg item from 'clocks' property with the same clock 'name'
89  */
90 #define NPCX_DT_CLK_CFG_ITEM_BY_NAME(inst, name)                               \
91 	{                                                                      \
92 	  .bus  = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, bus),        \
93 	  .ctrl = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, ctl),        \
94 	  .bit  = DT_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, bit),        \
95 	}
96 
97 /**
98  * @brief Length of 'clocks' property which type is 'phandle-array'
99  *
100  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
101  * @return length of 'clocks' property which type is 'phandle-array'
102  */
103 #define NPCX_DT_CLK_CFG_ITEMS_LEN(inst) DT_INST_PROP_LEN(inst, clocks)
104 
105 /**
106  * @brief Macro function to construct npcx_clk_cfg item in UTIL_LISTIFY
107  * extension.
108  *
109  * @param child child index in UTIL_LISTIFY extension.
110  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
111  * @return macro function to construct a npcx_clk_cfg structure.
112  */
113 #define NPCX_DT_CLK_CFG_ITEMS_FUNC(child, inst) \
114 					NPCX_DT_CLK_CFG_ITEM_BY_IDX(inst, child)
115 
116 /**
117  * @brief Macro function to construct a list of npcx_clk_cfg items by
118  * UTIL_LISTIFY func
119  *
120  * Example devicetree fragment:
121  *    / {
122  *		host_sub: lpc@400c1000 {
123  *			clocks = <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 3>,
124  *				 <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 4>,
125  *				 <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 5>,
126  *				 <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 6>,
127  *				 <&pcc NPCX_CLOCK_BUS_APB3 NPCX_PWDWN_CTL5 7>;
128  *			...
129  *		};
130  * Example usage:
131  *	const struct npcx_clk_cfg clk_cfg[] = NPCX_DT_CLK_CFG_ITEMS_LIST(0);
132  *
133  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
134  * @return an array of npcx_clk_cfg items.
135  */
136 #define NPCX_DT_CLK_CFG_ITEMS_LIST(inst) {        \
137 	LISTIFY(NPCX_DT_CLK_CFG_ITEMS_LEN(inst),  \
138 		NPCX_DT_CLK_CFG_ITEMS_FUNC, (,),  \
139 		inst)                             \
140 	}
141 
142 /**
143  * @brief Get phandle from "name" property which contains wui information.
144  *
145  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
146  * @param name property 'name' which type is 'phandle' and contains wui info.
147  * @return phandle from 'name' property.
148  */
149 #define NPCX_DT_PHANDLE_FROM_WUI_NAME(inst, name) \
150 	DT_INST_PHANDLE(inst, name)
151 
152 /**
153  * @brief Construct a npcx_wui structure from 'name' property
154  *
155  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
156  * @param name property 'name'which type is 'phandle' and contains wui info.
157  * @return npcx_wui item from 'name' property.
158  */
159 #define NPCX_DT_WUI_ITEM_BY_NAME(inst, name)				       \
160 	{                                                                      \
161 	  .table = DT_PROP(DT_PHANDLE(NPCX_DT_PHANDLE_FROM_WUI_NAME(inst,      \
162 					name), miwus), index),                 \
163 	  .group = DT_PHA(NPCX_DT_PHANDLE_FROM_WUI_NAME(inst, name), miwus,    \
164 					group),                                \
165 	  .bit   = DT_PHA(NPCX_DT_PHANDLE_FROM_WUI_NAME(inst, name), miwus,    \
166 					bit),                                  \
167 	}
168 
169 /**
170  * @brief Get phandle from 'wui-maps' prop which type is 'phandles' at index 'i'
171  *
172  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
173  * @param i index of 'wui-maps' prop which type is 'phandles'
174  * @return phandle from 'wui-maps' prop at index 'i'
175  */
176 #define NPCX_DT_PHANDLE_FROM_WUI_MAPS(inst, i) \
177 	DT_INST_PHANDLE_BY_IDX(inst, wui_maps, i)
178 
179 /**
180  * @brief Construct a npcx_wui structure from wui-maps property at index 'i'
181  *
182  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
183  * @param i index of 'wui-maps' prop which type is 'phandles'
184  * @return npcx_wui item at index 'i'
185  */
186 #define NPCX_DT_WUI_ITEM_BY_IDX(inst, i) \
187 	{                                                                      \
188 	  .table = DT_PROP(DT_PHANDLE(NPCX_DT_PHANDLE_FROM_WUI_MAPS(inst, i),  \
189 					miwus), index),                        \
190 	  .group = DT_PHA(NPCX_DT_PHANDLE_FROM_WUI_MAPS(inst, i), miwus,       \
191 							group),                \
192 	  .bit = DT_PHA(NPCX_DT_PHANDLE_FROM_WUI_MAPS(inst, i), miwus, bit),   \
193 	}
194 
195 /**
196  * @brief Length of npcx_wui structures in 'wui-maps' property
197  *
198  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
199  * @return length of 'wui-maps' prop which type is 'phandles'
200  */
201 #define NPCX_DT_WUI_ITEMS_LEN(inst) DT_INST_PROP_LEN(inst, wui_maps)
202 
203 /**
204  * @brief Macro function to construct a list of npcx_wui items by UTIL_LISTIFY
205  *
206  * @param child child index in UTIL_LISTIFY extension.
207  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
208  * @return macro function to construct a npcx_wui structure.
209  */
210 #define NPCX_DT_WUI_ITEMS_FUNC(child, inst) NPCX_DT_WUI_ITEM_BY_IDX(inst, child)
211 
212 /**
213  * @brief Macro function to construct a list of npcx_wui items by UTIL_LISTIFY
214  * func.
215  *
216  * Example devicetree fragment:
217  *    / {
218  *		uart1: serial@400c4000 {
219  *			uart-rx = <&wui_cr_sin1>;
220  *			...
221  *		};
222  *
223  *		gpio0: gpio@40081000 {
224  *			wui-maps = <&wui_io00 &wui_io01 &wui_io02 &wui_io03
225  *				    &wui_io04 &wui_io05 &wui_io06 &wui_io07>;
226  *			...
227  *		};
228  *	};
229  *
230  * Example usage:
231  * const struct npcx_wui wui_map = NPCX_DT_PHANDLE_FROM_WUI_NAME(inst, uart_rx);
232  * const struct npcx_wui wui_maps[] = NPCX_DT_WUI_ITEMS_LIST(inst);
233  *
234  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
235  * @return an array of npcx_wui items.
236  */
237 #define NPCX_DT_WUI_ITEMS_LIST(inst) {        \
238 	LISTIFY(NPCX_DT_WUI_ITEMS_LEN(inst),  \
239 		NPCX_DT_WUI_ITEMS_FUNC, (,),  \
240 		inst)                         \
241 	}
242 
243 /**
244  * @brief Get a node from path '/npcx_miwus_map/map_miwu(0/1/2)_groups'
245  *
246  * @param i index of npcx miwu devices
247  * @return node identifier with that path.
248  */
249 #define NPCX_DT_NODE_FROM_MIWU_MAP(i)  DT_PATH(npcx_miwus_int_map, \
250 						map_miwu##i##_groups)
251 /**
252  * @brief Get the index prop from parent MIWU device node.
253  *
254  * @param child index in UTIL_LISTIFY extension.
255  * @return 'index' prop value of the node which compatible type is
256  * "nuvoton,npcx-miwu".
257  */
258 #define NPCX_DT_MIWU_IRQ_TABLE_IDX(child) \
259 	DT_PROP(DT_PHANDLE(DT_PARENT(child), parent), index)
260 
261 /**
262  * @brief Macro function for DT_FOREACH_CHILD to generate a IRQ_CONNECT
263  * implementation.
264  *
265  * @param child index in UTIL_LISTIFY extension.
266  * @return implementation to initialize interrupts of MIWU groups and enable
267  * them.
268  */
269 #define NPCX_DT_MIWU_IRQ_CONNECT_IMPL_CHILD_FUNC(child) \
270 	NPCX_DT_MIWU_IRQ_CONNECT_IMPL_CHILD_FUNC_OBJ(child);
271 
272 #define NPCX_DT_MIWU_IRQ_CONNECT_IMPL_CHILD_FUNC_OBJ(child) \
273 	do {                                                                   \
274 		IRQ_CONNECT(DT_PROP(child, irq),		               \
275 			DT_PROP(child, irq_prio),		               \
276 			NPCX_MIWU_ISR_FUNC(NPCX_DT_MIWU_IRQ_TABLE_IDX(child)), \
277 			DT_PROP(child, group_mask),                            \
278 			0);						       \
279 		irq_enable(DT_PROP(child, irq));                               \
280 	} while (false)
281 
282 /**
283  * @brief Get a child node from path '/npcx-espi-vws-map/name'.
284  *
285  * @param name a path which name is /npcx-espi-vws-map/'name'.
286  * @return child node identifier with that path.
287  */
288 #define NPCX_DT_NODE_FROM_VWTABLE(name) DT_CHILD(DT_PATH(npcx_espi_vws_map),  \
289 									name)
290 
291 /**
292  * @brief Get phandle from vw-wui property of child node with that path.
293  *
294  * @param name path which name is /npcx-espi-vws-map/'name'.
295  * @return phandle from "vw-wui" prop of child node with that path.
296  */
297 #define NPCX_DT_PHANDLE_VW_WUI(name) DT_PHANDLE(NPCX_DT_NODE_FROM_VWTABLE(     \
298 								name), vw_wui)
299 
300 /**
301  * @brief Construct a npcx_wui structure from vw-wui property of a child node
302  * with that path.
303  *
304  * @param name a path which name is /npcx-espi-vws-map/'name'.
305  * @return npcx_wui item with that path.
306  */
307 #define NPCX_DT_VW_WUI_ITEM(name)			                       \
308 	{                                                                      \
309 	  .table = DT_PROP(DT_PHANDLE(NPCX_DT_PHANDLE_VW_WUI(name), miwus),    \
310 									index),\
311 	  .group = DT_PHA(NPCX_DT_PHANDLE_VW_WUI(name), miwus, group),         \
312 	  .bit = DT_PHA(NPCX_DT_PHANDLE_VW_WUI(name), miwus, bit),             \
313 	}
314 
315 /**
316  * @brief Construct a npcx espi device configuration of vw input signal from
317  * a child node with that path.
318  *
319  * @signal vw input signal name.
320  * @param name a path which name is /npcx-espi-vws-map/'name'.
321  * @return npcx_vw_in_config item with that path.
322  */
323 #define NPCX_DT_VW_IN_CONF(signal, name)                                       \
324 	{                                                                      \
325 	  .sig = signal,                                                       \
326 	  .reg_idx = DT_PROP_BY_IDX(NPCX_DT_NODE_FROM_VWTABLE(name), vw_reg,   \
327 									0),    \
328 	  .bitmask = DT_PROP_BY_IDX(NPCX_DT_NODE_FROM_VWTABLE(name), vw_reg,   \
329 									1),    \
330 	  .vw_wui  = NPCX_DT_VW_WUI_ITEM(name),                                \
331 	}
332 
333 /**
334  * @brief Construct a npcx espi device configuration of vw output signal from
335  * a child node with that path.
336  *
337  * @signal vw output signal name.
338  * @param name a path which name is /npcx-espi-vws-map/'name'.
339  * @return npcx_vw_in_config item with that path.
340  */
341 #define NPCX_DT_VW_OUT_CONF(signal, name)                                      \
342 	{                                                                      \
343 	  .sig = signal,                                                       \
344 	  .reg_idx = DT_PROP_BY_IDX(NPCX_DT_NODE_FROM_VWTABLE(name), vw_reg,   \
345 									0),    \
346 	  .bitmask = DT_PROP_BY_IDX(NPCX_DT_NODE_FROM_VWTABLE(name), vw_reg,   \
347 									1),    \
348 	}
349 
350 /**
351  * @brief Construct a npcx_lvol structure from 'lvol-maps' property at index 'i'.
352  *
353  * @param node_id Node identifier.
354  * @param prop Low voltage configurations property name. (i.e. 'lvol-maps')
355  * @param idx Property entry index.
356  */
357 #define NPCX_DT_LVOL_CTRL_NONE \
358 	DT_PHA(DT_NODELABEL(lvol_none), lvols, ctrl)
359 
360 /**
361  * @brief Length of npcx_lvol structures in 'lvol-maps' property
362  *
363  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
364  * @return length of 'lvol-maps' prop which type is 'phandles'
365  */
366 #define NPCX_DT_LVOL_ITEMS_LEN(inst) DT_INST_PROP_LEN(inst, lvol_maps)
367 
368 /**
369  * @brief Construct a npcx_lvol structure from 'lvol-maps' property at index 'i'.
370  *
371  * @param node_id Node identifier.
372  * @param prop Low voltage configurations property name. (i.e. 'lvol-maps')
373  * @param idx Property entry index.
374  */
375 #define NPCX_DT_LVOL_ITEMS_INIT(node_id, prop, idx)				\
376 	{									\
377 	  .ctrl = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), lvols, ctrl),	\
378 	  .bit = DT_PHA(DT_PROP_BY_IDX(node_id, prop, idx), lvols, bit),	\
379 	},
380 
381 /**
382  * @brief Macro function to construct a list of npcx_lvol items  from 'lvol-maps'
383  * property.
384  *
385  * @param inst instance number for compatible defined in DT_DRV_COMPAT.
386  * @return an array of npcx_lvol items.
387  */
388 #define NPCX_DT_LVOL_ITEMS_LIST(inst) {						\
389 	DT_FOREACH_PROP_ELEM(DT_DRV_INST(inst), lvol_maps,			\
390 						NPCX_DT_LVOL_ITEMS_INIT)}
391 
392 /**
393  * @brief Check if the host interface type is automatically configured by
394  * booter.
395  *
396  * @return TRUE - if the host interface is configured by booter,
397  *         FALSE - otherwise.
398  */
399 #define NPCX_BOOTER_IS_HIF_TYPE_SET() \
400 	DT_PROP(DT_PATH(booter_variant), hif_type_auto)
401 
402 /**
403  * @brief Helper macro to get address of system configuration module which is
404  * used by serval peripheral device drivers in npcx series.
405  *
406  * @return base address of system configuration module.
407  */
408 #define NPCX_SCFG_REG_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), scfg)
409 
410 /**
411  * @brief Helper macro to get address of system glue module which is
412  * used by serval peripheral device drivers in npcx series.
413  *
414  * @return base address of system glue module.
415  */
416 #define NPCX_GLUE_REG_ADDR DT_REG_ADDR_BY_NAME(DT_NODELABEL(scfg), glue)
417 
418 #endif /* _NUVOTON_NPCX_SOC_DT_H_ */
419