xref: /linux-6.15/include/linux/property.h (revision bb391410)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2b31384faSRafael J. Wysocki /*
3b31384faSRafael J. Wysocki  * property.h - Unified device property interface.
4b31384faSRafael J. Wysocki  *
5b31384faSRafael J. Wysocki  * Copyright (C) 2014, Intel Corporation
6b31384faSRafael J. Wysocki  * Authors: Rafael J. Wysocki <[email protected]>
7b31384faSRafael J. Wysocki  *          Mika Westerberg <[email protected]>
8b31384faSRafael J. Wysocki  */
9b31384faSRafael J. Wysocki 
10b31384faSRafael J. Wysocki #ifndef _LINUX_PROPERTY_H_
11b31384faSRafael J. Wysocki #define _LINUX_PROPERTY_H_
12b31384faSRafael J. Wysocki 
131dc05a27SAndy Shevchenko #include <linux/args.h>
144dc3d612SAndy Shevchenko #include <linux/array_size.h>
150fcc2bdcSSakari Ailus #include <linux/bits.h>
1659ed5e2dSJonathan Cameron #include <linux/cleanup.h>
17ce793486SRafael J. Wysocki #include <linux/fwnode.h>
1840eb28dcSAndy Shevchenko #include <linux/stddef.h>
19b31384faSRafael J. Wysocki #include <linux/types.h>
20b31384faSRafael J. Wysocki 
21b31384faSRafael J. Wysocki struct device;
22b31384faSRafael J. Wysocki 
23b31384faSRafael J. Wysocki enum dev_prop_type {
24b31384faSRafael J. Wysocki 	DEV_PROP_U8,
25b31384faSRafael J. Wysocki 	DEV_PROP_U16,
26b31384faSRafael J. Wysocki 	DEV_PROP_U32,
27b31384faSRafael J. Wysocki 	DEV_PROP_U64,
28b31384faSRafael J. Wysocki 	DEV_PROP_STRING,
29e64b674bSDmitry Torokhov 	DEV_PROP_REF,
30b31384faSRafael J. Wysocki };
31b31384faSRafael J. Wysocki 
32b295d484SAndy Shevchenko const struct fwnode_handle *__dev_fwnode_const(const struct device *dev);
33b295d484SAndy Shevchenko struct fwnode_handle *__dev_fwnode(struct device *dev);
34b295d484SAndy Shevchenko #define dev_fwnode(dev)							\
35b295d484SAndy Shevchenko 	_Generic((dev),							\
36b295d484SAndy Shevchenko 		 const struct device *: __dev_fwnode_const,	\
37b295d484SAndy Shevchenko 		 struct device *: __dev_fwnode)(dev)
38e44bb0cbSSakari Ailus 
39046b6a17SGuenter Roeck bool device_property_present(const struct device *dev, const char *propname);
40*bb391410SRob Herring (Arm) bool device_property_read_bool(const struct device *dev, const char *propname);
41046b6a17SGuenter Roeck int device_property_read_u8_array(const struct device *dev, const char *propname,
42b31384faSRafael J. Wysocki 				  u8 *val, size_t nval);
43046b6a17SGuenter Roeck int device_property_read_u16_array(const struct device *dev, const char *propname,
44b31384faSRafael J. Wysocki 				   u16 *val, size_t nval);
45046b6a17SGuenter Roeck int device_property_read_u32_array(const struct device *dev, const char *propname,
46b31384faSRafael J. Wysocki 				   u32 *val, size_t nval);
47046b6a17SGuenter Roeck int device_property_read_u64_array(const struct device *dev, const char *propname,
48b31384faSRafael J. Wysocki 				   u64 *val, size_t nval);
49046b6a17SGuenter Roeck int device_property_read_string_array(const struct device *dev, const char *propname,
50b31384faSRafael J. Wysocki 				      const char **val, size_t nval);
51046b6a17SGuenter Roeck int device_property_read_string(const struct device *dev, const char *propname,
52b31384faSRafael J. Wysocki 				const char **val);
53046b6a17SGuenter Roeck int device_property_match_string(const struct device *dev,
543f5c8d31SMika Westerberg 				 const char *propname, const char *string);
55b31384faSRafael J. Wysocki 
5637ba983cSSakari Ailus bool fwnode_property_present(const struct fwnode_handle *fwnode,
5737ba983cSSakari Ailus 			     const char *propname);
58*bb391410SRob Herring (Arm) bool fwnode_property_read_bool(const struct fwnode_handle *fwnode,
59*bb391410SRob Herring (Arm) 			     const char *propname);
6037ba983cSSakari Ailus int fwnode_property_read_u8_array(const struct fwnode_handle *fwnode,
618a0662d9SRafael J. Wysocki 				  const char *propname, u8 *val,
628a0662d9SRafael J. Wysocki 				  size_t nval);
6337ba983cSSakari Ailus int fwnode_property_read_u16_array(const struct fwnode_handle *fwnode,
648a0662d9SRafael J. Wysocki 				   const char *propname, u16 *val,
658a0662d9SRafael J. Wysocki 				   size_t nval);
6637ba983cSSakari Ailus int fwnode_property_read_u32_array(const struct fwnode_handle *fwnode,
678a0662d9SRafael J. Wysocki 				   const char *propname, u32 *val,
688a0662d9SRafael J. Wysocki 				   size_t nval);
6937ba983cSSakari Ailus int fwnode_property_read_u64_array(const struct fwnode_handle *fwnode,
708a0662d9SRafael J. Wysocki 				   const char *propname, u64 *val,
718a0662d9SRafael J. Wysocki 				   size_t nval);
7237ba983cSSakari Ailus int fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
738a0662d9SRafael J. Wysocki 				      const char *propname, const char **val,
748a0662d9SRafael J. Wysocki 				      size_t nval);
7537ba983cSSakari Ailus int fwnode_property_read_string(const struct fwnode_handle *fwnode,
768a0662d9SRafael J. Wysocki 				const char *propname, const char **val);
7737ba983cSSakari Ailus int fwnode_property_match_string(const struct fwnode_handle *fwnode,
783f5c8d31SMika Westerberg 				 const char *propname, const char *string);
79a521075dSAndy Shevchenko 
80a521075dSAndy Shevchenko bool fwnode_device_is_available(const struct fwnode_handle *fwnode);
81a521075dSAndy Shevchenko 
fwnode_device_is_big_endian(const struct fwnode_handle * fwnode)82826a5d8cSAndy Shevchenko static inline bool fwnode_device_is_big_endian(const struct fwnode_handle *fwnode)
83826a5d8cSAndy Shevchenko {
84826a5d8cSAndy Shevchenko 	if (fwnode_property_present(fwnode, "big-endian"))
85826a5d8cSAndy Shevchenko 		return true;
86826a5d8cSAndy Shevchenko 	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
87826a5d8cSAndy Shevchenko 	    fwnode_property_present(fwnode, "native-endian"))
88826a5d8cSAndy Shevchenko 		return true;
89826a5d8cSAndy Shevchenko 	return false;
90826a5d8cSAndy Shevchenko }
91826a5d8cSAndy Shevchenko 
92a521075dSAndy Shevchenko static inline
fwnode_device_is_compatible(const struct fwnode_handle * fwnode,const char * compat)93a521075dSAndy Shevchenko bool fwnode_device_is_compatible(const struct fwnode_handle *fwnode, const char *compat)
94a521075dSAndy Shevchenko {
95a521075dSAndy Shevchenko 	return fwnode_property_match_string(fwnode, "compatible", compat) >= 0;
96a521075dSAndy Shevchenko }
97a521075dSAndy Shevchenko 
982de5897bSAndy Shevchenko /**
99826a5d8cSAndy Shevchenko  * device_is_big_endian - check if a device has BE registers
100826a5d8cSAndy Shevchenko  * @dev: Pointer to the struct device
101826a5d8cSAndy Shevchenko  *
102826a5d8cSAndy Shevchenko  * Returns: true if the device has a "big-endian" property, or if the kernel
103826a5d8cSAndy Shevchenko  * was compiled for BE *and* the device has a "native-endian" property.
104826a5d8cSAndy Shevchenko  * Returns false otherwise.
105826a5d8cSAndy Shevchenko  *
106826a5d8cSAndy Shevchenko  * Callers would nominally use ioread32be/iowrite32be if
107826a5d8cSAndy Shevchenko  * device_is_big_endian() == true, or readl/writel otherwise.
108826a5d8cSAndy Shevchenko  */
device_is_big_endian(const struct device * dev)109826a5d8cSAndy Shevchenko static inline bool device_is_big_endian(const struct device *dev)
110826a5d8cSAndy Shevchenko {
111826a5d8cSAndy Shevchenko 	return fwnode_device_is_big_endian(dev_fwnode(dev));
112826a5d8cSAndy Shevchenko }
113826a5d8cSAndy Shevchenko 
114826a5d8cSAndy Shevchenko /**
1152de5897bSAndy Shevchenko  * device_is_compatible - match 'compatible' property of the device with a given string
1162de5897bSAndy Shevchenko  * @dev: Pointer to the struct device
1172de5897bSAndy Shevchenko  * @compat: The string to match 'compatible' property with
1182de5897bSAndy Shevchenko  *
1192de5897bSAndy Shevchenko  * Returns: true if matches, otherwise false.
1202de5897bSAndy Shevchenko  */
device_is_compatible(const struct device * dev,const char * compat)1212de5897bSAndy Shevchenko static inline bool device_is_compatible(const struct device *dev, const char *compat)
1222de5897bSAndy Shevchenko {
1232de5897bSAndy Shevchenko 	return fwnode_device_is_compatible(dev_fwnode(dev), compat);
1242de5897bSAndy Shevchenko }
1252de5897bSAndy Shevchenko 
126fac4a535SAndy Shevchenko int fwnode_property_match_property_string(const struct fwnode_handle *fwnode,
127fac4a535SAndy Shevchenko 					  const char *propname,
128fac4a535SAndy Shevchenko 					  const char * const *array, size_t n);
129fac4a535SAndy Shevchenko 
130fac4a535SAndy Shevchenko static inline
device_property_match_property_string(const struct device * dev,const char * propname,const char * const * array,size_t n)131fac4a535SAndy Shevchenko int device_property_match_property_string(const struct device *dev,
132fac4a535SAndy Shevchenko 					  const char *propname,
133fac4a535SAndy Shevchenko 					  const char * const *array, size_t n)
134fac4a535SAndy Shevchenko {
135fac4a535SAndy Shevchenko 	return fwnode_property_match_property_string(dev_fwnode(dev), propname, array, n);
136fac4a535SAndy Shevchenko }
137fac4a535SAndy Shevchenko 
1383e3119d3SSakari Ailus int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
1393e3119d3SSakari Ailus 				       const char *prop, const char *nargs_prop,
1403e3119d3SSakari Ailus 				       unsigned int nargs, unsigned int index,
1413e3119d3SSakari Ailus 				       struct fwnode_reference_args *args);
1428a0662d9SRafael J. Wysocki 
14383b34afbSHeikki Krogerus struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
14483b34afbSHeikki Krogerus 					    const char *name,
14583b34afbSHeikki Krogerus 					    unsigned int index);
14683b34afbSHeikki Krogerus 
147bc0500c1SSakari Ailus const char *fwnode_get_name(const struct fwnode_handle *fwnode);
148e7e242bcSSakari Ailus const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode);
149a9c8c738SSakari Ailus bool fwnode_name_eq(const struct fwnode_handle *fwnode, const char *name);
15087ffea09SAndy Shevchenko 
15137ba983cSSakari Ailus struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode);
15287ffea09SAndy Shevchenko struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode);
15387ffea09SAndy Shevchenko 
15487ffea09SAndy Shevchenko #define fwnode_for_each_parent_node(fwnode, parent)		\
15587ffea09SAndy Shevchenko 	for (parent = fwnode_get_parent(fwnode); parent;	\
15687ffea09SAndy Shevchenko 	     parent = fwnode_get_next_parent(parent))
15787ffea09SAndy Shevchenko 
15887e5e95dSSakari Ailus unsigned int fwnode_count_parents(const struct fwnode_handle *fwn);
15987e5e95dSSakari Ailus struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwn,
16087e5e95dSSakari Ailus 					    unsigned int depth);
16137ba983cSSakari Ailus struct fwnode_handle *fwnode_get_next_child_node(
16237ba983cSSakari Ailus 	const struct fwnode_handle *fwnode, struct fwnode_handle *child);
1633395de96SMarcin Wojtas struct fwnode_handle *fwnode_get_next_available_child_node(
1643395de96SMarcin Wojtas 	const struct fwnode_handle *fwnode, struct fwnode_handle *child);
16534055190SMika Westerberg 
16634055190SMika Westerberg #define fwnode_for_each_child_node(fwnode, child)			\
16734055190SMika Westerberg 	for (child = fwnode_get_next_child_node(fwnode, NULL); child;	\
16834055190SMika Westerberg 	     child = fwnode_get_next_child_node(fwnode, child))
169afaf26fdSMika Westerberg 
1703395de96SMarcin Wojtas #define fwnode_for_each_available_child_node(fwnode, child)		       \
1713395de96SMarcin Wojtas 	for (child = fwnode_get_next_available_child_node(fwnode, NULL); child;\
1723395de96SMarcin Wojtas 	     child = fwnode_get_next_available_child_node(fwnode, child))
1733395de96SMarcin Wojtas 
1747952cd2bSAndy Shevchenko struct fwnode_handle *device_get_next_child_node(const struct device *dev,
1757952cd2bSAndy Shevchenko 						 struct fwnode_handle *child);
1768a0662d9SRafael J. Wysocki 
1778a0662d9SRafael J. Wysocki #define device_for_each_child_node(dev, child)				\
1788a0662d9SRafael J. Wysocki 	for (child = device_get_next_child_node(dev, NULL); child;	\
1798a0662d9SRafael J. Wysocki 	     child = device_get_next_child_node(dev, child))
1808a0662d9SRafael J. Wysocki 
181365130fdSJonathan Cameron #define device_for_each_child_node_scoped(dev, child)			\
182365130fdSJonathan Cameron 	for (struct fwnode_handle *child __free(fwnode_handle) =	\
183365130fdSJonathan Cameron 		device_get_next_child_node(dev, NULL);			\
184365130fdSJonathan Cameron 	     child; child = device_get_next_child_node(dev, child))
185365130fdSJonathan Cameron 
1867952cd2bSAndy Shevchenko struct fwnode_handle *fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
1877952cd2bSAndy Shevchenko 						  const char *childname);
1887952cd2bSAndy Shevchenko struct fwnode_handle *device_get_named_child_node(const struct device *dev,
189613e9721SAdam Thomson 						  const char *childname);
190613e9721SAdam Thomson 
191cf89a31cSSakari Ailus struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode);
19277fc5151SJonathan Cameron 
19377fc5151SJonathan Cameron /**
19477fc5151SJonathan Cameron  * fwnode_handle_put - Drop reference to a device node
19577fc5151SJonathan Cameron  * @fwnode: Pointer to the device node to drop the reference to.
19677fc5151SJonathan Cameron  *
19777fc5151SJonathan Cameron  * This has to be used when terminating device_for_each_child_node() iteration
19877fc5151SJonathan Cameron  * with break or return to prevent stale device node references from being left
19977fc5151SJonathan Cameron  * behind.
20077fc5151SJonathan Cameron  */
fwnode_handle_put(struct fwnode_handle * fwnode)20177fc5151SJonathan Cameron static inline void fwnode_handle_put(struct fwnode_handle *fwnode)
20277fc5151SJonathan Cameron {
20377fc5151SJonathan Cameron 	fwnode_call_void_op(fwnode, put);
20477fc5151SJonathan Cameron }
2058a0662d9SRafael J. Wysocki 
20659ed5e2dSJonathan Cameron DEFINE_FREE(fwnode_handle, struct fwnode_handle *, fwnode_handle_put(_T))
20759ed5e2dSJonathan Cameron 
208fb38f314SAndy Shevchenko int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
209ca0acb51SAkhil R int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
2107c6c57f2SMarcin Wojtas 
2117952cd2bSAndy Shevchenko unsigned int device_get_child_node_count(const struct device *dev);
2128a0662d9SRafael J. Wysocki 
device_property_read_u8(const struct device * dev,const char * propname,u8 * val)213046b6a17SGuenter Roeck static inline int device_property_read_u8(const struct device *dev,
214b31384faSRafael J. Wysocki 					  const char *propname, u8 *val)
215b31384faSRafael J. Wysocki {
216b31384faSRafael J. Wysocki 	return device_property_read_u8_array(dev, propname, val, 1);
217b31384faSRafael J. Wysocki }
218b31384faSRafael J. Wysocki 
device_property_read_u16(const struct device * dev,const char * propname,u16 * val)219046b6a17SGuenter Roeck static inline int device_property_read_u16(const struct device *dev,
220b31384faSRafael J. Wysocki 					   const char *propname, u16 *val)
221b31384faSRafael J. Wysocki {
222b31384faSRafael J. Wysocki 	return device_property_read_u16_array(dev, propname, val, 1);
223b31384faSRafael J. Wysocki }
224b31384faSRafael J. Wysocki 
device_property_read_u32(const struct device * dev,const char * propname,u32 * val)225046b6a17SGuenter Roeck static inline int device_property_read_u32(const struct device *dev,
226b31384faSRafael J. Wysocki 					   const char *propname, u32 *val)
227b31384faSRafael J. Wysocki {
228b31384faSRafael J. Wysocki 	return device_property_read_u32_array(dev, propname, val, 1);
229b31384faSRafael J. Wysocki }
230b31384faSRafael J. Wysocki 
device_property_read_u64(const struct device * dev,const char * propname,u64 * val)231046b6a17SGuenter Roeck static inline int device_property_read_u64(const struct device *dev,
232b31384faSRafael J. Wysocki 					   const char *propname, u64 *val)
233b31384faSRafael J. Wysocki {
234b31384faSRafael J. Wysocki 	return device_property_read_u64_array(dev, propname, val, 1);
235b31384faSRafael J. Wysocki }
236b31384faSRafael J. Wysocki 
device_property_count_u8(const struct device * dev,const char * propname)237046b6a17SGuenter Roeck static inline int device_property_count_u8(const struct device *dev, const char *propname)
23833ee09cdSAndy Shevchenko {
23933ee09cdSAndy Shevchenko 	return device_property_read_u8_array(dev, propname, NULL, 0);
24033ee09cdSAndy Shevchenko }
24133ee09cdSAndy Shevchenko 
device_property_count_u16(const struct device * dev,const char * propname)242046b6a17SGuenter Roeck static inline int device_property_count_u16(const struct device *dev, const char *propname)
24333ee09cdSAndy Shevchenko {
24433ee09cdSAndy Shevchenko 	return device_property_read_u16_array(dev, propname, NULL, 0);
24533ee09cdSAndy Shevchenko }
24633ee09cdSAndy Shevchenko 
device_property_count_u32(const struct device * dev,const char * propname)247046b6a17SGuenter Roeck static inline int device_property_count_u32(const struct device *dev, const char *propname)
24833ee09cdSAndy Shevchenko {
24933ee09cdSAndy Shevchenko 	return device_property_read_u32_array(dev, propname, NULL, 0);
25033ee09cdSAndy Shevchenko }
25133ee09cdSAndy Shevchenko 
device_property_count_u64(const struct device * dev,const char * propname)252046b6a17SGuenter Roeck static inline int device_property_count_u64(const struct device *dev, const char *propname)
25333ee09cdSAndy Shevchenko {
25433ee09cdSAndy Shevchenko 	return device_property_read_u64_array(dev, propname, NULL, 0);
25533ee09cdSAndy Shevchenko }
25633ee09cdSAndy Shevchenko 
device_property_string_array_count(const struct device * dev,const char * propname)257046b6a17SGuenter Roeck static inline int device_property_string_array_count(const struct device *dev,
2586b6ff4acSBartosz Golaszewski 						     const char *propname)
2596b6ff4acSBartosz Golaszewski {
2606b6ff4acSBartosz Golaszewski 	return device_property_read_string_array(dev, propname, NULL, 0);
2616b6ff4acSBartosz Golaszewski }
2626b6ff4acSBartosz Golaszewski 
fwnode_property_read_u8(const struct fwnode_handle * fwnode,const char * propname,u8 * val)26337ba983cSSakari Ailus static inline int fwnode_property_read_u8(const struct fwnode_handle *fwnode,
2648a0662d9SRafael J. Wysocki 					  const char *propname, u8 *val)
2658a0662d9SRafael J. Wysocki {
2668a0662d9SRafael J. Wysocki 	return fwnode_property_read_u8_array(fwnode, propname, val, 1);
2678a0662d9SRafael J. Wysocki }
2688a0662d9SRafael J. Wysocki 
fwnode_property_read_u16(const struct fwnode_handle * fwnode,const char * propname,u16 * val)26937ba983cSSakari Ailus static inline int fwnode_property_read_u16(const struct fwnode_handle *fwnode,
2708a0662d9SRafael J. Wysocki 					   const char *propname, u16 *val)
2718a0662d9SRafael J. Wysocki {
2728a0662d9SRafael J. Wysocki 	return fwnode_property_read_u16_array(fwnode, propname, val, 1);
2738a0662d9SRafael J. Wysocki }
2748a0662d9SRafael J. Wysocki 
fwnode_property_read_u32(const struct fwnode_handle * fwnode,const char * propname,u32 * val)27537ba983cSSakari Ailus static inline int fwnode_property_read_u32(const struct fwnode_handle *fwnode,
2768a0662d9SRafael J. Wysocki 					   const char *propname, u32 *val)
2778a0662d9SRafael J. Wysocki {
2788a0662d9SRafael J. Wysocki 	return fwnode_property_read_u32_array(fwnode, propname, val, 1);
2798a0662d9SRafael J. Wysocki }
2808a0662d9SRafael J. Wysocki 
fwnode_property_read_u64(const struct fwnode_handle * fwnode,const char * propname,u64 * val)28137ba983cSSakari Ailus static inline int fwnode_property_read_u64(const struct fwnode_handle *fwnode,
2828a0662d9SRafael J. Wysocki 					   const char *propname, u64 *val)
2838a0662d9SRafael J. Wysocki {
2848a0662d9SRafael J. Wysocki 	return fwnode_property_read_u64_array(fwnode, propname, val, 1);
2858a0662d9SRafael J. Wysocki }
2868a0662d9SRafael J. Wysocki 
fwnode_property_count_u8(const struct fwnode_handle * fwnode,const char * propname)28733ee09cdSAndy Shevchenko static inline int fwnode_property_count_u8(const struct fwnode_handle *fwnode,
28833ee09cdSAndy Shevchenko 					   const char *propname)
28933ee09cdSAndy Shevchenko {
29033ee09cdSAndy Shevchenko 	return fwnode_property_read_u8_array(fwnode, propname, NULL, 0);
29133ee09cdSAndy Shevchenko }
29233ee09cdSAndy Shevchenko 
fwnode_property_count_u16(const struct fwnode_handle * fwnode,const char * propname)29333ee09cdSAndy Shevchenko static inline int fwnode_property_count_u16(const struct fwnode_handle *fwnode,
29433ee09cdSAndy Shevchenko 					    const char *propname)
29533ee09cdSAndy Shevchenko {
29633ee09cdSAndy Shevchenko 	return fwnode_property_read_u16_array(fwnode, propname, NULL, 0);
29733ee09cdSAndy Shevchenko }
29833ee09cdSAndy Shevchenko 
fwnode_property_count_u32(const struct fwnode_handle * fwnode,const char * propname)29933ee09cdSAndy Shevchenko static inline int fwnode_property_count_u32(const struct fwnode_handle *fwnode,
30033ee09cdSAndy Shevchenko 					    const char *propname)
30133ee09cdSAndy Shevchenko {
30233ee09cdSAndy Shevchenko 	return fwnode_property_read_u32_array(fwnode, propname, NULL, 0);
30333ee09cdSAndy Shevchenko }
30433ee09cdSAndy Shevchenko 
fwnode_property_count_u64(const struct fwnode_handle * fwnode,const char * propname)30533ee09cdSAndy Shevchenko static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,
30633ee09cdSAndy Shevchenko 					    const char *propname)
30733ee09cdSAndy Shevchenko {
30833ee09cdSAndy Shevchenko 	return fwnode_property_read_u64_array(fwnode, propname, NULL, 0);
30933ee09cdSAndy Shevchenko }
31033ee09cdSAndy Shevchenko 
3116b6ff4acSBartosz Golaszewski static inline int
fwnode_property_string_array_count(const struct fwnode_handle * fwnode,const char * propname)3126b6ff4acSBartosz Golaszewski fwnode_property_string_array_count(const struct fwnode_handle *fwnode,
3136b6ff4acSBartosz Golaszewski 				   const char *propname)
3146b6ff4acSBartosz Golaszewski {
3156b6ff4acSBartosz Golaszewski 	return fwnode_property_read_string_array(fwnode, propname, NULL, 0);
3166b6ff4acSBartosz Golaszewski }
3176b6ff4acSBartosz Golaszewski 
318e64b674bSDmitry Torokhov struct software_node;
319e64b674bSDmitry Torokhov 
320e64b674bSDmitry Torokhov /**
321e64b674bSDmitry Torokhov  * struct software_node_ref_args - Reference property with additional arguments
322e64b674bSDmitry Torokhov  * @node: Reference to a software node
323e64b674bSDmitry Torokhov  * @nargs: Number of elements in @args array
324e64b674bSDmitry Torokhov  * @args: Integer arguments
325e64b674bSDmitry Torokhov  */
326e64b674bSDmitry Torokhov struct software_node_ref_args {
327e64b674bSDmitry Torokhov 	const struct software_node *node;
328e64b674bSDmitry Torokhov 	unsigned int nargs;
329e64b674bSDmitry Torokhov 	u64 args[NR_FWNODE_REFERENCE_ARGS];
330e64b674bSDmitry Torokhov };
331e64b674bSDmitry Torokhov 
332e588feadSAndy Shevchenko #define SOFTWARE_NODE_REFERENCE(_ref_, ...)			\
333e588feadSAndy Shevchenko (const struct software_node_ref_args) {				\
334e588feadSAndy Shevchenko 	.node = _ref_,						\
3351dc05a27SAndy Shevchenko 	.nargs = COUNT_ARGS(__VA_ARGS__),			\
336e588feadSAndy Shevchenko 	.args = { __VA_ARGS__ },				\
337e588feadSAndy Shevchenko }
338e588feadSAndy Shevchenko 
33916ba08d5SRafael J. Wysocki /**
34016ba08d5SRafael J. Wysocki  * struct property_entry - "Built-in" device property representation.
34116ba08d5SRafael J. Wysocki  * @name: Name of the property.
342318a1971SAndy Shevchenko  * @length: Length of data making up the value.
343e6bff466SDmitry Torokhov  * @is_inline: True when the property value is stored inline.
34463dcc709SAndy Shevchenko  * @type: Type of the data in unions.
345e6bff466SDmitry Torokhov  * @pointer: Pointer to the property when it is not stored inline.
346e6bff466SDmitry Torokhov  * @value: Value of the property when it is stored inline.
34716ba08d5SRafael J. Wysocki  */
34816ba08d5SRafael J. Wysocki struct property_entry {
34916ba08d5SRafael J. Wysocki 	const char *name;
350318a1971SAndy Shevchenko 	size_t length;
351e6bff466SDmitry Torokhov 	bool is_inline;
35263dcc709SAndy Shevchenko 	enum dev_prop_type type;
35366586babSAndy Shevchenko 	union {
3541f74d70fSDmitry Torokhov 		const void *pointer;
35566586babSAndy Shevchenko 		union {
356996b0830SDmitry Torokhov 			u8 u8_data[sizeof(u64) / sizeof(u8)];
357996b0830SDmitry Torokhov 			u16 u16_data[sizeof(u64) / sizeof(u16)];
358996b0830SDmitry Torokhov 			u32 u32_data[sizeof(u64) / sizeof(u32)];
359996b0830SDmitry Torokhov 			u64 u64_data[sizeof(u64) / sizeof(u64)];
360996b0830SDmitry Torokhov 			const char *str[sizeof(u64) / sizeof(char *)];
36116ba08d5SRafael J. Wysocki 		} value;
36216ba08d5SRafael J. Wysocki 	};
36366586babSAndy Shevchenko };
36416ba08d5SRafael J. Wysocki 
365d76eebfaSAndrew Morton /*
366daeba9bfSDmitry Torokhov  * Note: the below initializers for the anonymous union are carefully
367d76eebfaSAndrew Morton  * crafted to avoid gcc-4.4.4's problems with initialization of anon unions
368d76eebfaSAndrew Morton  * and structs.
369d76eebfaSAndrew Morton  */
37040eb28dcSAndy Shevchenko #define __PROPERTY_ENTRY_ARRAY_LEN(_name_, _elem_, _Type_, _val_, _len_)		\
371c505cbd4SAndy Shevchenko (struct property_entry) {								\
372a85f4204SHeikki Krogerus 	.name = _name_,									\
37340eb28dcSAndy Shevchenko 	.length = (_len_) * sizeof_field(struct property_entry, value._elem_[0]),	\
37463dcc709SAndy Shevchenko 	.type = DEV_PROP_##_Type_,							\
3751f74d70fSDmitry Torokhov 	{ .pointer = _val_ },								\
376a85f4204SHeikki Krogerus }
377a85f4204SHeikki Krogerus 
3781741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, _len_)		\
379daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u8_data, U8, _val_, _len_)
3801741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, _len_)		\
381daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u16_data, U16, _val_, _len_)
3821741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, _len_)		\
383daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u32_data, U32, _val_, _len_)
3841741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, _len_)		\
385daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ARRAY_LEN(_name_, u64_data, U64, _val_, _len_)
3861741cfacSDmitry Torokhov #define PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, _len_)		\
387daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ARRAY_LEN(_name_, str, STRING, _val_, _len_)
388c6c76563SAndy Shevchenko 
389e64b674bSDmitry Torokhov #define PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, _len_)		\
39040eb28dcSAndy Shevchenko (struct property_entry) {						\
39140eb28dcSAndy Shevchenko 	.name = _name_,							\
39240eb28dcSAndy Shevchenko 	.length = (_len_) * sizeof(struct software_node_ref_args),	\
39340eb28dcSAndy Shevchenko 	.type = DEV_PROP_REF,						\
39440eb28dcSAndy Shevchenko 	{ .pointer = _val_ },						\
39540eb28dcSAndy Shevchenko }
396a85f4204SHeikki Krogerus 
3971741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_)				\
3981741cfacSDmitry Torokhov 	PROPERTY_ENTRY_U8_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
3991741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_)				\
4001741cfacSDmitry Torokhov 	PROPERTY_ENTRY_U16_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
4011741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_)				\
4021741cfacSDmitry Torokhov 	PROPERTY_ENTRY_U32_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
4031741cfacSDmitry Torokhov #define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_)				\
4041741cfacSDmitry Torokhov 	PROPERTY_ENTRY_U64_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
4051741cfacSDmitry Torokhov #define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_)			\
4061741cfacSDmitry Torokhov 	PROPERTY_ENTRY_STRING_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
407e64b674bSDmitry Torokhov #define PROPERTY_ENTRY_REF_ARRAY(_name_, _val_)				\
408e64b674bSDmitry Torokhov 	PROPERTY_ENTRY_REF_ARRAY_LEN(_name_, _val_, ARRAY_SIZE(_val_))
4091741cfacSDmitry Torokhov 
410daeba9bfSDmitry Torokhov #define __PROPERTY_ENTRY_ELEMENT(_name_, _elem_, _Type_, _val_)		\
411c505cbd4SAndy Shevchenko (struct property_entry) {						\
412a85f4204SHeikki Krogerus 	.name = _name_,							\
41340eb28dcSAndy Shevchenko 	.length = sizeof_field(struct property_entry, value._elem_[0]),	\
414e6bff466SDmitry Torokhov 	.is_inline = true,						\
41563dcc709SAndy Shevchenko 	.type = DEV_PROP_##_Type_,					\
416996b0830SDmitry Torokhov 	{ .value = { ._elem_[0] = _val_ } },				\
417a85f4204SHeikki Krogerus }
418a85f4204SHeikki Krogerus 
419a85f4204SHeikki Krogerus #define PROPERTY_ENTRY_U8(_name_, _val_)				\
420daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ELEMENT(_name_, u8_data, U8, _val_)
421a85f4204SHeikki Krogerus #define PROPERTY_ENTRY_U16(_name_, _val_)				\
422daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ELEMENT(_name_, u16_data, U16, _val_)
423a85f4204SHeikki Krogerus #define PROPERTY_ENTRY_U32(_name_, _val_)				\
424daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ELEMENT(_name_, u32_data, U32, _val_)
425a85f4204SHeikki Krogerus #define PROPERTY_ENTRY_U64(_name_, _val_)				\
426daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ELEMENT(_name_, u64_data, U64, _val_)
427a85f4204SHeikki Krogerus #define PROPERTY_ENTRY_STRING(_name_, _val_)				\
428daeba9bfSDmitry Torokhov 	__PROPERTY_ENTRY_ELEMENT(_name_, str, STRING, _val_)
429a85f4204SHeikki Krogerus 
430e64b674bSDmitry Torokhov #define PROPERTY_ENTRY_REF(_name_, _ref_, ...)				\
431e64b674bSDmitry Torokhov (struct property_entry) {						\
432e64b674bSDmitry Torokhov 	.name = _name_,							\
433e64b674bSDmitry Torokhov 	.length = sizeof(struct software_node_ref_args),		\
434e64b674bSDmitry Torokhov 	.type = DEV_PROP_REF,						\
435e588feadSAndy Shevchenko 	{ .pointer = &SOFTWARE_NODE_REFERENCE(_ref_, ##__VA_ARGS__), },	\
436e64b674bSDmitry Torokhov }
437e64b674bSDmitry Torokhov 
438c6c76563SAndy Shevchenko #define PROPERTY_ENTRY_BOOL(_name_)		\
439c6c76563SAndy Shevchenko (struct property_entry) {			\
440c6c76563SAndy Shevchenko 	.name = _name_,				\
441c6c76563SAndy Shevchenko 	.is_inline = true,			\
442c6c76563SAndy Shevchenko }
443c6c76563SAndy Shevchenko 
4442d479e1fSDmitry Torokhov struct property_entry *
4452d479e1fSDmitry Torokhov property_entries_dup(const struct property_entry *properties);
4462d479e1fSDmitry Torokhov void property_entries_free(const struct property_entry *properties);
4472d479e1fSDmitry Torokhov 
44859789f34SAndy Shevchenko bool device_dma_supported(const struct device *dev);
44959789f34SAndy Shevchenko enum dev_dma_attr device_get_dma_attr(const struct device *dev);
450e5e55864SSuthikulpanit, Suravee 
451aade55c8SAndy Shevchenko const void *device_get_match_data(const struct device *dev);
452b283f157SSinan Kaya 
4534c96b7dcSJeremy Linton int device_get_phy_mode(struct device *dev);
4540a392354SRussell King int fwnode_get_phy_mode(const struct fwnode_handle *fwnode);
455b2638e56SAndy Shevchenko 
456b2638e56SAndy Shevchenko void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index);
457b2638e56SAndy Shevchenko 
45807bb80d4SMika Westerberg struct fwnode_handle *fwnode_graph_get_next_endpoint(
45937ba983cSSakari Ailus 	const struct fwnode_handle *fwnode, struct fwnode_handle *prev);
4606a71d8d7SKieran Bingham struct fwnode_handle *
46137ba983cSSakari Ailus fwnode_graph_get_port_parent(const struct fwnode_handle *fwnode);
46207bb80d4SMika Westerberg struct fwnode_handle *fwnode_graph_get_remote_port_parent(
46337ba983cSSakari Ailus 	const struct fwnode_handle *fwnode);
46407bb80d4SMika Westerberg struct fwnode_handle *fwnode_graph_get_remote_port(
46537ba983cSSakari Ailus 	const struct fwnode_handle *fwnode);
46607bb80d4SMika Westerberg struct fwnode_handle *fwnode_graph_get_remote_endpoint(
46737ba983cSSakari Ailus 	const struct fwnode_handle *fwnode);
46807bb80d4SMika Westerberg 
fwnode_graph_is_endpoint(const struct fwnode_handle * fwnode)469a1bfed60SAndy Shevchenko static inline bool fwnode_graph_is_endpoint(const struct fwnode_handle *fwnode)
47035694afcSLaurent Pinchart {
47135694afcSLaurent Pinchart 	return fwnode_property_present(fwnode, "remote-endpoint");
47235694afcSLaurent Pinchart }
47335694afcSLaurent Pinchart 
4740fcc2bdcSSakari Ailus /*
4750fcc2bdcSSakari Ailus  * Fwnode lookup flags
4760fcc2bdcSSakari Ailus  *
4770fcc2bdcSSakari Ailus  * @FWNODE_GRAPH_ENDPOINT_NEXT: In the case of no exact match, look for the
4780fcc2bdcSSakari Ailus  *				closest endpoint ID greater than the specified
4790fcc2bdcSSakari Ailus  *				one.
4800fcc2bdcSSakari Ailus  * @FWNODE_GRAPH_DEVICE_DISABLED: That the device to which the remote
4810fcc2bdcSSakari Ailus  *				  endpoint of the given endpoint belongs to,
48249f39cb0SSakari Ailus  *				  may be disabled, or that the endpoint is not
48349f39cb0SSakari Ailus  *				  connected.
4840fcc2bdcSSakari Ailus  */
4850fcc2bdcSSakari Ailus #define FWNODE_GRAPH_ENDPOINT_NEXT	BIT(0)
4860fcc2bdcSSakari Ailus #define FWNODE_GRAPH_DEVICE_DISABLED	BIT(1)
4870fcc2bdcSSakari Ailus 
4880fcc2bdcSSakari Ailus struct fwnode_handle *
4890fcc2bdcSSakari Ailus fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
4900fcc2bdcSSakari Ailus 				u32 port, u32 endpoint, unsigned long flags);
4915b9ff0baSAndy Shevchenko unsigned int fwnode_graph_get_endpoint_count(const struct fwnode_handle *fwnode,
492c87b8fc5SSakari Ailus 					     unsigned long flags);
4930fcc2bdcSSakari Ailus 
4945e4b1b70SSakari Ailus #define fwnode_graph_for_each_endpoint(fwnode, child)				\
49552af7863SAndy Shevchenko 	for (child = fwnode_graph_get_next_endpoint(fwnode, NULL); child;	\
49652af7863SAndy Shevchenko 	     child = fwnode_graph_get_next_endpoint(fwnode, child))
4975e4b1b70SSakari Ailus 
49837ba983cSSakari Ailus int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
4992bd5452dSSakari Ailus 				struct fwnode_endpoint *endpoint);
5002bd5452dSSakari Ailus 
50123ead33bSAndy Shevchenko typedef void *(*devcon_match_fn_t)(const struct fwnode_handle *fwnode, const char *id,
502d7cf5590SHeikki Krogerus 				   void *data);
503d7cf5590SHeikki Krogerus 
50423ead33bSAndy Shevchenko void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
505d7cf5590SHeikki Krogerus 				   const char *con_id, void *data,
506d7cf5590SHeikki Krogerus 				   devcon_match_fn_t match);
507d7cf5590SHeikki Krogerus 
device_connection_find_match(const struct device * dev,const char * con_id,void * data,devcon_match_fn_t match)50823ead33bSAndy Shevchenko static inline void *device_connection_find_match(const struct device *dev,
509d7cf5590SHeikki Krogerus 						 const char *con_id, void *data,
510d7cf5590SHeikki Krogerus 						 devcon_match_fn_t match)
511d7cf5590SHeikki Krogerus {
512d7cf5590SHeikki Krogerus 	return fwnode_connection_find_match(dev_fwnode(dev), con_id, data, match);
513d7cf5590SHeikki Krogerus }
514d7cf5590SHeikki Krogerus 
51523ead33bSAndy Shevchenko int fwnode_connection_find_matches(const struct fwnode_handle *fwnode,
5167a20917dSBjorn Andersson 				   const char *con_id, void *data,
5177a20917dSBjorn Andersson 				   devcon_match_fn_t match,
5187a20917dSBjorn Andersson 				   void **matches, unsigned int matches_len);
5197a20917dSBjorn Andersson 
52059abd836SHeikki Krogerus /* -------------------------------------------------------------------------- */
52159abd836SHeikki Krogerus /* Software fwnode support - when HW description is incomplete or missing */
52259abd836SHeikki Krogerus 
523b06184acSHeikki Krogerus /**
52480488a6bSHeikki Krogerus  * struct software_node - Software node description
52580488a6bSHeikki Krogerus  * @name: Name of the software node
52680488a6bSHeikki Krogerus  * @parent: Parent of the software node
52780488a6bSHeikki Krogerus  * @properties: Array of device properties
52880488a6bSHeikki Krogerus  */
52980488a6bSHeikki Krogerus struct software_node {
53080488a6bSHeikki Krogerus 	const char *name;
53180488a6bSHeikki Krogerus 	const struct software_node *parent;
53280488a6bSHeikki Krogerus 	const struct property_entry *properties;
53380488a6bSHeikki Krogerus };
53480488a6bSHeikki Krogerus 
53548c9996fSSakari Ailus #define SOFTWARE_NODE(_name_, _properties_, _parent_)	\
53648c9996fSSakari Ailus 	(struct software_node) {			\
53748c9996fSSakari Ailus 		.name = _name_,				\
53848c9996fSSakari Ailus 		.properties = _properties_,		\
53948c9996fSSakari Ailus 		.parent = _parent_,			\
54048c9996fSSakari Ailus 	}
54148c9996fSSakari Ailus 
54259abd836SHeikki Krogerus bool is_software_node(const struct fwnode_handle *fwnode);
54356c9aa07SSakari Ailus const struct software_node *
54456c9aa07SSakari Ailus to_software_node(const struct fwnode_handle *fwnode);
54580488a6bSHeikki Krogerus struct fwnode_handle *software_node_fwnode(const struct software_node *node);
54680488a6bSHeikki Krogerus 
5471666faedSHeikki Krogerus const struct software_node *
5481666faedSHeikki Krogerus software_node_find_by_name(const struct software_node *parent,
5491666faedSHeikki Krogerus 			   const char *name);
5501666faedSHeikki Krogerus 
55102094d54SAndy Shevchenko int software_node_register_node_group(const struct software_node **node_group);
55202094d54SAndy Shevchenko void software_node_unregister_node_group(const struct software_node **node_group);
55302094d54SAndy Shevchenko 
55480488a6bSHeikki Krogerus int software_node_register(const struct software_node *node);
55546d26819SGreg Kroah-Hartman void software_node_unregister(const struct software_node *node);
55659abd836SHeikki Krogerus 
55759abd836SHeikki Krogerus struct fwnode_handle *
55859abd836SHeikki Krogerus fwnode_create_software_node(const struct property_entry *properties,
55959abd836SHeikki Krogerus 			    const struct fwnode_handle *parent);
56059abd836SHeikki Krogerus void fwnode_remove_software_node(struct fwnode_handle *fwnode);
56159abd836SHeikki Krogerus 
5622a92c90fSHeikki Krogerus int device_add_software_node(struct device *dev, const struct software_node *node);
563e68d0119SHeikki Krogerus void device_remove_software_node(struct device *dev);
564e68d0119SHeikki Krogerus 
565151f6ff7SHeikki Krogerus int device_create_managed_software_node(struct device *dev,
566151f6ff7SHeikki Krogerus 					const struct property_entry *properties,
567151f6ff7SHeikki Krogerus 					const struct software_node *parent);
568151f6ff7SHeikki Krogerus 
569b31384faSRafael J. Wysocki #endif /* _LINUX_PROPERTY_H_ */
570