xref: /openbmc/linux/drivers/base/property.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1989d42e8SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2b31384faSRafael J. Wysocki /*
3b31384faSRafael J. Wysocki  * property.c - Unified device property interface.
4b31384faSRafael J. Wysocki  *
5b31384faSRafael J. Wysocki  * Copyright (C) 2014, Intel Corporation
6b31384faSRafael J. Wysocki  * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
7b31384faSRafael J. Wysocki  *          Mika Westerberg <mika.westerberg@linux.intel.com>
8b31384faSRafael J. Wysocki  */
9b31384faSRafael J. Wysocki 
10b31384faSRafael J. Wysocki #include <linux/acpi.h>
1116ba08d5SRafael J. Wysocki #include <linux/export.h>
1216ba08d5SRafael J. Wysocki #include <linux/kernel.h>
13b31384faSRafael J. Wysocki #include <linux/of.h>
1405ca5560SSuthikulpanit, Suravee #include <linux/of_address.h>
1507bb80d4SMika Westerberg #include <linux/of_graph.h>
167c6c57f2SMarcin Wojtas #include <linux/of_irq.h>
1716ba08d5SRafael J. Wysocki #include <linux/property.h>
184c96b7dcSJeremy Linton #include <linux/phy.h>
1916ba08d5SRafael J. Wysocki 
__dev_fwnode(struct device * dev)20b295d484SAndy Shevchenko struct fwnode_handle *__dev_fwnode(struct device *dev)
219017f252SRafael J. Wysocki {
229017f252SRafael J. Wysocki 	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
233cd80150SAndy Shevchenko 		of_fwnode_handle(dev->of_node) : dev->fwnode;
249017f252SRafael J. Wysocki }
25b295d484SAndy Shevchenko EXPORT_SYMBOL_GPL(__dev_fwnode);
26b295d484SAndy Shevchenko 
__dev_fwnode_const(const struct device * dev)27b295d484SAndy Shevchenko const struct fwnode_handle *__dev_fwnode_const(const struct device *dev)
28b295d484SAndy Shevchenko {
29b295d484SAndy Shevchenko 	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
30b295d484SAndy Shevchenko 		of_fwnode_handle(dev->of_node) : dev->fwnode;
31b295d484SAndy Shevchenko }
32b295d484SAndy Shevchenko EXPORT_SYMBOL_GPL(__dev_fwnode_const);
33b31384faSRafael J. Wysocki 
34b31384faSRafael J. Wysocki /**
35b31384faSRafael J. Wysocki  * device_property_present - check if a property of a device is present
36b31384faSRafael J. Wysocki  * @dev: Device whose property is being checked
37b31384faSRafael J. Wysocki  * @propname: Name of the property
38b31384faSRafael J. Wysocki  *
39b31384faSRafael J. Wysocki  * Check if property @propname is present in the device firmware description.
40295209caSAndy Shevchenko  *
41295209caSAndy Shevchenko  * Return: true if property @propname is present. Otherwise, returns false.
42b31384faSRafael J. Wysocki  */
device_property_present(const struct device * dev,const char * propname)43*046b6a17SGuenter Roeck bool device_property_present(const struct device *dev, const char *propname)
44b31384faSRafael J. Wysocki {
459017f252SRafael J. Wysocki 	return fwnode_property_present(dev_fwnode(dev), propname);
46b31384faSRafael J. Wysocki }
47b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_present);
48b31384faSRafael J. Wysocki 
49362c0b30SAndy Shevchenko /**
50362c0b30SAndy Shevchenko  * fwnode_property_present - check if a property of a firmware node is present
51362c0b30SAndy Shevchenko  * @fwnode: Firmware node whose property to check
52362c0b30SAndy Shevchenko  * @propname: Name of the property
53295209caSAndy Shevchenko  *
54295209caSAndy Shevchenko  * Return: true if property @propname is present. Otherwise, returns false.
55362c0b30SAndy Shevchenko  */
fwnode_property_present(const struct fwnode_handle * fwnode,const char * propname)5637ba983cSSakari Ailus bool fwnode_property_present(const struct fwnode_handle *fwnode,
5737ba983cSSakari Ailus 			     const char *propname)
58362c0b30SAndy Shevchenko {
59362c0b30SAndy Shevchenko 	bool ret;
60362c0b30SAndy Shevchenko 
61002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
62002752afSAndy Shevchenko 		return false;
63002752afSAndy Shevchenko 
64e8158b48SSakari Ailus 	ret = fwnode_call_bool_op(fwnode, property_present, propname);
65002752afSAndy Shevchenko 	if (ret)
66362c0b30SAndy Shevchenko 		return ret;
67002752afSAndy Shevchenko 
68002752afSAndy Shevchenko 	return fwnode_call_bool_op(fwnode->secondary, property_present, propname);
69362c0b30SAndy Shevchenko }
708a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_present);
718a0662d9SRafael J. Wysocki 
72b31384faSRafael J. Wysocki /**
73b31384faSRafael J. Wysocki  * device_property_read_u8_array - return a u8 array property of a device
74b31384faSRafael J. Wysocki  * @dev: Device to get the property of
75b31384faSRafael J. Wysocki  * @propname: Name of the property
765c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
77b31384faSRafael J. Wysocki  * @nval: Size of the @val array
78b31384faSRafael J. Wysocki  *
79b31384faSRafael J. Wysocki  * Function reads an array of u8 properties with @propname from the device
80b31384faSRafael J. Wysocki  * firmware description and stores them to @val if found.
81b31384faSRafael J. Wysocki  *
82f6e109a0SAndy Shevchenko  * It's recommended to call device_property_count_u8() instead of calling
83f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
84f6e109a0SAndy Shevchenko  *
855c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
865c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
87b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
88b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
89b31384faSRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
90b31384faSRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected.
914fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
92b31384faSRafael J. Wysocki  */
device_property_read_u8_array(const struct device * dev,const char * propname,u8 * val,size_t nval)93*046b6a17SGuenter Roeck int device_property_read_u8_array(const struct device *dev, const char *propname,
94b31384faSRafael J. Wysocki 				  u8 *val, size_t nval)
95b31384faSRafael J. Wysocki {
969017f252SRafael J. Wysocki 	return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
97b31384faSRafael J. Wysocki }
98b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_u8_array);
99b31384faSRafael J. Wysocki 
100b31384faSRafael J. Wysocki /**
101b31384faSRafael J. Wysocki  * device_property_read_u16_array - return a u16 array property of a device
102b31384faSRafael J. Wysocki  * @dev: Device to get the property of
103b31384faSRafael J. Wysocki  * @propname: Name of the property
1045c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
105b31384faSRafael J. Wysocki  * @nval: Size of the @val array
106b31384faSRafael J. Wysocki  *
107b31384faSRafael J. Wysocki  * Function reads an array of u16 properties with @propname from the device
108b31384faSRafael J. Wysocki  * firmware description and stores them to @val if found.
109b31384faSRafael J. Wysocki  *
110f6e109a0SAndy Shevchenko  * It's recommended to call device_property_count_u16() instead of calling
111f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
112f6e109a0SAndy Shevchenko  *
1135c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
1145c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
115b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
116b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
117b31384faSRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
118b31384faSRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected.
1194fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
120b31384faSRafael J. Wysocki  */
device_property_read_u16_array(const struct device * dev,const char * propname,u16 * val,size_t nval)121*046b6a17SGuenter Roeck int device_property_read_u16_array(const struct device *dev, const char *propname,
122b31384faSRafael J. Wysocki 				   u16 *val, size_t nval)
123b31384faSRafael J. Wysocki {
1249017f252SRafael J. Wysocki 	return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
125b31384faSRafael J. Wysocki }
126b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_u16_array);
127b31384faSRafael J. Wysocki 
128b31384faSRafael J. Wysocki /**
129b31384faSRafael J. Wysocki  * device_property_read_u32_array - return a u32 array property of a device
130b31384faSRafael J. Wysocki  * @dev: Device to get the property of
131b31384faSRafael J. Wysocki  * @propname: Name of the property
1325c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
133b31384faSRafael J. Wysocki  * @nval: Size of the @val array
134b31384faSRafael J. Wysocki  *
135b31384faSRafael J. Wysocki  * Function reads an array of u32 properties with @propname from the device
136b31384faSRafael J. Wysocki  * firmware description and stores them to @val if found.
137b31384faSRafael J. Wysocki  *
138f6e109a0SAndy Shevchenko  * It's recommended to call device_property_count_u32() instead of calling
139f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
140f6e109a0SAndy Shevchenko  *
1415c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
1425c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
143b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
144b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
145b31384faSRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
146b31384faSRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected.
1474fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
148b31384faSRafael J. Wysocki  */
device_property_read_u32_array(const struct device * dev,const char * propname,u32 * val,size_t nval)149*046b6a17SGuenter Roeck int device_property_read_u32_array(const struct device *dev, const char *propname,
150b31384faSRafael J. Wysocki 				   u32 *val, size_t nval)
151b31384faSRafael J. Wysocki {
1529017f252SRafael J. Wysocki 	return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
153b31384faSRafael J. Wysocki }
154b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_u32_array);
155b31384faSRafael J. Wysocki 
156b31384faSRafael J. Wysocki /**
157b31384faSRafael J. Wysocki  * device_property_read_u64_array - return a u64 array property of a device
158b31384faSRafael J. Wysocki  * @dev: Device to get the property of
159b31384faSRafael J. Wysocki  * @propname: Name of the property
1605c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
161b31384faSRafael J. Wysocki  * @nval: Size of the @val array
162b31384faSRafael J. Wysocki  *
163b31384faSRafael J. Wysocki  * Function reads an array of u64 properties with @propname from the device
164b31384faSRafael J. Wysocki  * firmware description and stores them to @val if found.
165b31384faSRafael J. Wysocki  *
166f6e109a0SAndy Shevchenko  * It's recommended to call device_property_count_u64() instead of calling
167f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
168f6e109a0SAndy Shevchenko  *
1695c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
1705c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
171b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
172b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
173b31384faSRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
174b31384faSRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected.
1754fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
176b31384faSRafael J. Wysocki  */
device_property_read_u64_array(const struct device * dev,const char * propname,u64 * val,size_t nval)177*046b6a17SGuenter Roeck int device_property_read_u64_array(const struct device *dev, const char *propname,
178b31384faSRafael J. Wysocki 				   u64 *val, size_t nval)
179b31384faSRafael J. Wysocki {
1809017f252SRafael J. Wysocki 	return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
181b31384faSRafael J. Wysocki }
182b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_u64_array);
183b31384faSRafael J. Wysocki 
184b31384faSRafael J. Wysocki /**
185b31384faSRafael J. Wysocki  * device_property_read_string_array - return a string array property of device
186b31384faSRafael J. Wysocki  * @dev: Device to get the property of
187b31384faSRafael J. Wysocki  * @propname: Name of the property
1885c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
189b31384faSRafael J. Wysocki  * @nval: Size of the @val array
190b31384faSRafael J. Wysocki  *
191b31384faSRafael J. Wysocki  * Function reads an array of string properties with @propname from the device
192b31384faSRafael J. Wysocki  * firmware description and stores them to @val if found.
193b31384faSRafael J. Wysocki  *
194f6e109a0SAndy Shevchenko  * It's recommended to call device_property_string_array_count() instead of calling
195f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
196f6e109a0SAndy Shevchenko  *
197b0b027ceSSakari Ailus  * Return: number of values read on success if @val is non-NULL,
198b0b027ceSSakari Ailus  *	   number of values available on success if @val is NULL,
199b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
200b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
201b31384faSRafael J. Wysocki  *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
202b31384faSRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected.
2034fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
204b31384faSRafael J. Wysocki  */
device_property_read_string_array(const struct device * dev,const char * propname,const char ** val,size_t nval)205*046b6a17SGuenter Roeck int device_property_read_string_array(const struct device *dev, const char *propname,
206b31384faSRafael J. Wysocki 				      const char **val, size_t nval)
207b31384faSRafael J. Wysocki {
2089017f252SRafael J. Wysocki 	return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
209b31384faSRafael J. Wysocki }
210b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_string_array);
211b31384faSRafael J. Wysocki 
212b31384faSRafael J. Wysocki /**
213b31384faSRafael J. Wysocki  * device_property_read_string - return a string property of a device
214b31384faSRafael J. Wysocki  * @dev: Device to get the property of
215b31384faSRafael J. Wysocki  * @propname: Name of the property
216b31384faSRafael J. Wysocki  * @val: The value is stored here
217b31384faSRafael J. Wysocki  *
218b31384faSRafael J. Wysocki  * Function reads property @propname from the device firmware description and
219b31384faSRafael J. Wysocki  * stores the value into @val if found. The value is checked to be a string.
220b31384faSRafael J. Wysocki  *
221b31384faSRafael J. Wysocki  * Return: %0 if the property was found (success),
222b31384faSRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
223b31384faSRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
224b31384faSRafael J. Wysocki  *	   %-EPROTO or %-EILSEQ if the property type is not a string.
2254fa7508eSGuenter Roeck  *	   %-ENXIO if no suitable firmware interface is present.
226b31384faSRafael J. Wysocki  */
device_property_read_string(const struct device * dev,const char * propname,const char ** val)227*046b6a17SGuenter Roeck int device_property_read_string(const struct device *dev, const char *propname,
228b31384faSRafael J. Wysocki 				const char **val)
229b31384faSRafael J. Wysocki {
2309017f252SRafael J. Wysocki 	return fwnode_property_read_string(dev_fwnode(dev), propname, val);
231b31384faSRafael J. Wysocki }
232b31384faSRafael J. Wysocki EXPORT_SYMBOL_GPL(device_property_read_string);
2338a0662d9SRafael J. Wysocki 
2343f5c8d31SMika Westerberg /**
2353f5c8d31SMika Westerberg  * device_property_match_string - find a string in an array and return index
2363f5c8d31SMika Westerberg  * @dev: Device to get the property of
2373f5c8d31SMika Westerberg  * @propname: Name of the property holding the array
2383f5c8d31SMika Westerberg  * @string: String to look for
2393f5c8d31SMika Westerberg  *
2403f5c8d31SMika Westerberg  * Find a given string in a string array and if it is found return the
2413f5c8d31SMika Westerberg  * index back.
2423f5c8d31SMika Westerberg  *
24392e10465SAndy Shevchenko  * Return: index, starting from %0, if the property was found (success),
2443f5c8d31SMika Westerberg  *	   %-EINVAL if given arguments are not valid,
2453f5c8d31SMika Westerberg  *	   %-ENODATA if the property does not have a value,
2463f5c8d31SMika Westerberg  *	   %-EPROTO if the property is not an array of strings,
2473f5c8d31SMika Westerberg  *	   %-ENXIO if no suitable firmware interface is present.
2483f5c8d31SMika Westerberg  */
device_property_match_string(const struct device * dev,const char * propname,const char * string)249*046b6a17SGuenter Roeck int device_property_match_string(const struct device *dev, const char *propname,
2503f5c8d31SMika Westerberg 				 const char *string)
2513f5c8d31SMika Westerberg {
2523f5c8d31SMika Westerberg 	return fwnode_property_match_string(dev_fwnode(dev), propname, string);
2533f5c8d31SMika Westerberg }
2543f5c8d31SMika Westerberg EXPORT_SYMBOL_GPL(device_property_match_string);
2553f5c8d31SMika Westerberg 
fwnode_property_read_int_array(const struct fwnode_handle * fwnode,const char * propname,unsigned int elem_size,void * val,size_t nval)25637ba983cSSakari Ailus static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
2573708184aSSakari Ailus 					  const char *propname,
2583708184aSSakari Ailus 					  unsigned int elem_size, void *val,
2593708184aSSakari Ailus 					  size_t nval)
2603708184aSSakari Ailus {
2613708184aSSakari Ailus 	int ret;
2629017f252SRafael J. Wysocki 
263002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
264002752afSAndy Shevchenko 		return -EINVAL;
265002752afSAndy Shevchenko 
2663708184aSSakari Ailus 	ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
2673708184aSSakari Ailus 				 elem_size, val, nval);
268002752afSAndy Shevchenko 	if (ret != -EINVAL)
2693708184aSSakari Ailus 		return ret;
270002752afSAndy Shevchenko 
271002752afSAndy Shevchenko 	return fwnode_call_int_op(fwnode->secondary, property_read_int_array, propname,
272002752afSAndy Shevchenko 				  elem_size, val, nval);
2733708184aSSakari Ailus }
274362c0b30SAndy Shevchenko 
2758a0662d9SRafael J. Wysocki /**
2768a0662d9SRafael J. Wysocki  * fwnode_property_read_u8_array - return a u8 array property of firmware node
2778a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
2788a0662d9SRafael J. Wysocki  * @propname: Name of the property
2795c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
2808a0662d9SRafael J. Wysocki  * @nval: Size of the @val array
2818a0662d9SRafael J. Wysocki  *
2828a0662d9SRafael J. Wysocki  * Read an array of u8 properties with @propname from @fwnode and stores them to
2838a0662d9SRafael J. Wysocki  * @val if found.
2848a0662d9SRafael J. Wysocki  *
285f6e109a0SAndy Shevchenko  * It's recommended to call fwnode_property_count_u8() instead of calling
286f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
287f6e109a0SAndy Shevchenko  *
2885c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
2895c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
2908a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
2918a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
2928a0662d9SRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
2938a0662d9SRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected,
2948a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
2958a0662d9SRafael J. Wysocki  */
fwnode_property_read_u8_array(const struct fwnode_handle * fwnode,const char * propname,u8 * val,size_t nval)29637ba983cSSakari Ailus int fwnode_property_read_u8_array(const struct fwnode_handle *fwnode,
2978a0662d9SRafael J. Wysocki 				  const char *propname, u8 *val, size_t nval)
2988a0662d9SRafael J. Wysocki {
2993708184aSSakari Ailus 	return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
3008a0662d9SRafael J. Wysocki 					      val, nval);
3018a0662d9SRafael J. Wysocki }
3028a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
3038a0662d9SRafael J. Wysocki 
3048a0662d9SRafael J. Wysocki /**
3058a0662d9SRafael J. Wysocki  * fwnode_property_read_u16_array - return a u16 array property of firmware node
3068a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
3078a0662d9SRafael J. Wysocki  * @propname: Name of the property
3085c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
3098a0662d9SRafael J. Wysocki  * @nval: Size of the @val array
3108a0662d9SRafael J. Wysocki  *
3118a0662d9SRafael J. Wysocki  * Read an array of u16 properties with @propname from @fwnode and store them to
3128a0662d9SRafael J. Wysocki  * @val if found.
3138a0662d9SRafael J. Wysocki  *
314f6e109a0SAndy Shevchenko  * It's recommended to call fwnode_property_count_u16() instead of calling
315f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
316f6e109a0SAndy Shevchenko  *
3175c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
3185c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
3198a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
3208a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
3218a0662d9SRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
3228a0662d9SRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected,
3238a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
3248a0662d9SRafael J. Wysocki  */
fwnode_property_read_u16_array(const struct fwnode_handle * fwnode,const char * propname,u16 * val,size_t nval)32537ba983cSSakari Ailus int fwnode_property_read_u16_array(const struct fwnode_handle *fwnode,
3268a0662d9SRafael J. Wysocki 				   const char *propname, u16 *val, size_t nval)
3278a0662d9SRafael J. Wysocki {
3283708184aSSakari Ailus 	return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
3298a0662d9SRafael J. Wysocki 					      val, nval);
3308a0662d9SRafael J. Wysocki }
3318a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
3328a0662d9SRafael J. Wysocki 
3338a0662d9SRafael J. Wysocki /**
3348a0662d9SRafael J. Wysocki  * fwnode_property_read_u32_array - return a u32 array property of firmware node
3358a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
3368a0662d9SRafael J. Wysocki  * @propname: Name of the property
3375c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
3388a0662d9SRafael J. Wysocki  * @nval: Size of the @val array
3398a0662d9SRafael J. Wysocki  *
3408a0662d9SRafael J. Wysocki  * Read an array of u32 properties with @propname from @fwnode store them to
3418a0662d9SRafael J. Wysocki  * @val if found.
3428a0662d9SRafael J. Wysocki  *
343f6e109a0SAndy Shevchenko  * It's recommended to call fwnode_property_count_u32() instead of calling
344f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
345f6e109a0SAndy Shevchenko  *
3465c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
3475c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
3488a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
3498a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
3508a0662d9SRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
3518a0662d9SRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected,
3528a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
3538a0662d9SRafael J. Wysocki  */
fwnode_property_read_u32_array(const struct fwnode_handle * fwnode,const char * propname,u32 * val,size_t nval)35437ba983cSSakari Ailus int fwnode_property_read_u32_array(const struct fwnode_handle *fwnode,
3558a0662d9SRafael J. Wysocki 				   const char *propname, u32 *val, size_t nval)
3568a0662d9SRafael J. Wysocki {
3573708184aSSakari Ailus 	return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
3588a0662d9SRafael J. Wysocki 					      val, nval);
3598a0662d9SRafael J. Wysocki }
3608a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
3618a0662d9SRafael J. Wysocki 
3628a0662d9SRafael J. Wysocki /**
3638a0662d9SRafael J. Wysocki  * fwnode_property_read_u64_array - return a u64 array property firmware node
3648a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
3658a0662d9SRafael J. Wysocki  * @propname: Name of the property
3665c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
3678a0662d9SRafael J. Wysocki  * @nval: Size of the @val array
3688a0662d9SRafael J. Wysocki  *
3698a0662d9SRafael J. Wysocki  * Read an array of u64 properties with @propname from @fwnode and store them to
3708a0662d9SRafael J. Wysocki  * @val if found.
3718a0662d9SRafael J. Wysocki  *
372f6e109a0SAndy Shevchenko  * It's recommended to call fwnode_property_count_u64() instead of calling
373f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
374f6e109a0SAndy Shevchenko  *
3755c0acf3bSAdrian Hunter  * Return: number of values if @val was %NULL,
3765c0acf3bSAdrian Hunter  *         %0 if the property was found (success),
3778a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
3788a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
3798a0662d9SRafael J. Wysocki  *	   %-EPROTO if the property is not an array of numbers,
3808a0662d9SRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected,
3818a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
3828a0662d9SRafael J. Wysocki  */
fwnode_property_read_u64_array(const struct fwnode_handle * fwnode,const char * propname,u64 * val,size_t nval)38337ba983cSSakari Ailus int fwnode_property_read_u64_array(const struct fwnode_handle *fwnode,
3848a0662d9SRafael J. Wysocki 				   const char *propname, u64 *val, size_t nval)
3858a0662d9SRafael J. Wysocki {
3863708184aSSakari Ailus 	return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
3878a0662d9SRafael J. Wysocki 					      val, nval);
3888a0662d9SRafael J. Wysocki }
3898a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
3908a0662d9SRafael J. Wysocki 
3918a0662d9SRafael J. Wysocki /**
3928a0662d9SRafael J. Wysocki  * fwnode_property_read_string_array - return string array property of a node
3938a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
3948a0662d9SRafael J. Wysocki  * @propname: Name of the property
3955c0acf3bSAdrian Hunter  * @val: The values are stored here or %NULL to return the number of values
3968a0662d9SRafael J. Wysocki  * @nval: Size of the @val array
3978a0662d9SRafael J. Wysocki  *
3988a0662d9SRafael J. Wysocki  * Read an string list property @propname from the given firmware node and store
3998a0662d9SRafael J. Wysocki  * them to @val if found.
4008a0662d9SRafael J. Wysocki  *
401f6e109a0SAndy Shevchenko  * It's recommended to call fwnode_property_string_array_count() instead of calling
402f6e109a0SAndy Shevchenko  * this function with @val equals %NULL and @nval equals 0.
403f6e109a0SAndy Shevchenko  *
404b0b027ceSSakari Ailus  * Return: number of values read on success if @val is non-NULL,
405b0b027ceSSakari Ailus  *	   number of values available on success if @val is NULL,
4068a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
4078a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
408026b8217SSakari Ailus  *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
4098a0662d9SRafael J. Wysocki  *	   %-EOVERFLOW if the size of the property is not as expected,
4108a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
4118a0662d9SRafael J. Wysocki  */
fwnode_property_read_string_array(const struct fwnode_handle * fwnode,const char * propname,const char ** val,size_t nval)41237ba983cSSakari Ailus int fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
4138a0662d9SRafael J. Wysocki 				      const char *propname, const char **val,
4148a0662d9SRafael J. Wysocki 				      size_t nval)
4158a0662d9SRafael J. Wysocki {
416362c0b30SAndy Shevchenko 	int ret;
417362c0b30SAndy Shevchenko 
418002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
419002752afSAndy Shevchenko 		return -EINVAL;
420002752afSAndy Shevchenko 
4213708184aSSakari Ailus 	ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
4223708184aSSakari Ailus 				 val, nval);
423002752afSAndy Shevchenko 	if (ret != -EINVAL)
424362c0b30SAndy Shevchenko 		return ret;
425002752afSAndy Shevchenko 
426002752afSAndy Shevchenko 	return fwnode_call_int_op(fwnode->secondary, property_read_string_array, propname,
427002752afSAndy Shevchenko 				  val, nval);
4288a0662d9SRafael J. Wysocki }
4298a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
4308a0662d9SRafael J. Wysocki 
4318a0662d9SRafael J. Wysocki /**
4328a0662d9SRafael J. Wysocki  * fwnode_property_read_string - return a string property of a firmware node
4338a0662d9SRafael J. Wysocki  * @fwnode: Firmware node to get the property of
4348a0662d9SRafael J. Wysocki  * @propname: Name of the property
4358a0662d9SRafael J. Wysocki  * @val: The value is stored here
4368a0662d9SRafael J. Wysocki  *
4378a0662d9SRafael J. Wysocki  * Read property @propname from the given firmware node and store the value into
4388a0662d9SRafael J. Wysocki  * @val if found.  The value is checked to be a string.
4398a0662d9SRafael J. Wysocki  *
4408a0662d9SRafael J. Wysocki  * Return: %0 if the property was found (success),
4418a0662d9SRafael J. Wysocki  *	   %-EINVAL if given arguments are not valid,
4428a0662d9SRafael J. Wysocki  *	   %-ENODATA if the property does not have a value,
4438a0662d9SRafael J. Wysocki  *	   %-EPROTO or %-EILSEQ if the property is not a string,
4448a0662d9SRafael J. Wysocki  *	   %-ENXIO if no suitable firmware interface is present.
4458a0662d9SRafael J. Wysocki  */
fwnode_property_read_string(const struct fwnode_handle * fwnode,const char * propname,const char ** val)44637ba983cSSakari Ailus int fwnode_property_read_string(const struct fwnode_handle *fwnode,
4478a0662d9SRafael J. Wysocki 				const char *propname, const char **val)
4488a0662d9SRafael J. Wysocki {
449e4817477SSakari Ailus 	int ret = fwnode_property_read_string_array(fwnode, propname, val, 1);
450362c0b30SAndy Shevchenko 
451b0b027ceSSakari Ailus 	return ret < 0 ? ret : 0;
4528a0662d9SRafael J. Wysocki }
4538a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_property_read_string);
4548a0662d9SRafael J. Wysocki 
4558a0662d9SRafael J. Wysocki /**
4563f5c8d31SMika Westerberg  * fwnode_property_match_string - find a string in an array and return index
4573f5c8d31SMika Westerberg  * @fwnode: Firmware node to get the property of
4583f5c8d31SMika Westerberg  * @propname: Name of the property holding the array
4593f5c8d31SMika Westerberg  * @string: String to look for
4603f5c8d31SMika Westerberg  *
4613f5c8d31SMika Westerberg  * Find a given string in a string array and if it is found return the
4623f5c8d31SMika Westerberg  * index back.
4633f5c8d31SMika Westerberg  *
46492e10465SAndy Shevchenko  * Return: index, starting from %0, if the property was found (success),
4653f5c8d31SMika Westerberg  *	   %-EINVAL if given arguments are not valid,
4663f5c8d31SMika Westerberg  *	   %-ENODATA if the property does not have a value,
4673f5c8d31SMika Westerberg  *	   %-EPROTO if the property is not an array of strings,
4683f5c8d31SMika Westerberg  *	   %-ENXIO if no suitable firmware interface is present.
4693f5c8d31SMika Westerberg  */
fwnode_property_match_string(const struct fwnode_handle * fwnode,const char * propname,const char * string)47037ba983cSSakari Ailus int fwnode_property_match_string(const struct fwnode_handle *fwnode,
4713f5c8d31SMika Westerberg 	const char *propname, const char *string)
4723f5c8d31SMika Westerberg {
4733f5c8d31SMika Westerberg 	const char **values;
474a7c1d0a9SAndy Shevchenko 	int nval, ret;
4753f5c8d31SMika Westerberg 
4763f5c8d31SMika Westerberg 	nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
4773f5c8d31SMika Westerberg 	if (nval < 0)
4783f5c8d31SMika Westerberg 		return nval;
4793f5c8d31SMika Westerberg 
480f6740c18SAndy Shevchenko 	if (nval == 0)
481f6740c18SAndy Shevchenko 		return -ENODATA;
482f6740c18SAndy Shevchenko 
4833f5c8d31SMika Westerberg 	values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
4843f5c8d31SMika Westerberg 	if (!values)
4853f5c8d31SMika Westerberg 		return -ENOMEM;
4863f5c8d31SMika Westerberg 
4873f5c8d31SMika Westerberg 	ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
4883f5c8d31SMika Westerberg 	if (ret < 0)
4894d57b4f2SAndy Shevchenko 		goto out_free;
4903f5c8d31SMika Westerberg 
491a7c1d0a9SAndy Shevchenko 	ret = match_string(values, nval, string);
492a7c1d0a9SAndy Shevchenko 	if (ret < 0)
4933f5c8d31SMika Westerberg 		ret = -ENODATA;
4944d57b4f2SAndy Shevchenko 
4954d57b4f2SAndy Shevchenko out_free:
4963f5c8d31SMika Westerberg 	kfree(values);
4973f5c8d31SMika Westerberg 	return ret;
4983f5c8d31SMika Westerberg }
4993f5c8d31SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_property_match_string);
5003f5c8d31SMika Westerberg 
5013e3119d3SSakari Ailus /**
5023e3119d3SSakari Ailus  * fwnode_property_get_reference_args() - Find a reference with arguments
5033e3119d3SSakari Ailus  * @fwnode:	Firmware node where to look for the reference
5043e3119d3SSakari Ailus  * @prop:	The name of the property
5053e3119d3SSakari Ailus  * @nargs_prop:	The name of the property telling the number of
5063e3119d3SSakari Ailus  *		arguments in the referred node. NULL if @nargs is known,
5073e3119d3SSakari Ailus  *		otherwise @nargs is ignored. Only relevant on OF.
5083e3119d3SSakari Ailus  * @nargs:	Number of arguments. Ignored if @nargs_prop is non-NULL.
5093e3119d3SSakari Ailus  * @index:	Index of the reference, from zero onwards.
5103e3119d3SSakari Ailus  * @args:	Result structure with reference and integer arguments.
5113e3119d3SSakari Ailus  *
5123e3119d3SSakari Ailus  * Obtain a reference based on a named property in an fwnode, with
5133e3119d3SSakari Ailus  * integer arguments.
5143e3119d3SSakari Ailus  *
515295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
516295209caSAndy Shevchenko  * @args->fwnode pointer.
5173e3119d3SSakari Ailus  *
518295209caSAndy Shevchenko  * Return: %0 on success
519c343bc2cSSakari Ailus  *	    %-ENOENT when the index is out of bounds, the index has an empty
520c343bc2cSSakari Ailus  *		     reference or the property was not found
521c343bc2cSSakari Ailus  *	    %-EINVAL on parse error
5223e3119d3SSakari Ailus  */
fwnode_property_get_reference_args(const struct fwnode_handle * fwnode,const char * prop,const char * nargs_prop,unsigned int nargs,unsigned int index,struct fwnode_reference_args * args)5233e3119d3SSakari Ailus int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
5243e3119d3SSakari Ailus 				       const char *prop, const char *nargs_prop,
5253e3119d3SSakari Ailus 				       unsigned int nargs, unsigned int index,
5263e3119d3SSakari Ailus 				       struct fwnode_reference_args *args)
5273e3119d3SSakari Ailus {
528c097af1dSDaniel Scally 	int ret;
529c097af1dSDaniel Scally 
530002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
531002752afSAndy Shevchenko 		return -ENOENT;
532002752afSAndy Shevchenko 
533c097af1dSDaniel Scally 	ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
5343e3119d3SSakari Ailus 				 nargs, index, args);
535002752afSAndy Shevchenko 	if (ret == 0)
536c097af1dSDaniel Scally 		return ret;
537002752afSAndy Shevchenko 
538002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode->secondary))
539002752afSAndy Shevchenko 		return ret;
540002752afSAndy Shevchenko 
541002752afSAndy Shevchenko 	return fwnode_call_int_op(fwnode->secondary, get_reference_args, prop, nargs_prop,
542002752afSAndy Shevchenko 				  nargs, index, args);
5433e3119d3SSakari Ailus }
5443e3119d3SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
5453e3119d3SSakari Ailus 
5462d479e1fSDmitry Torokhov /**
54783b34afbSHeikki Krogerus  * fwnode_find_reference - Find named reference to a fwnode_handle
54883b34afbSHeikki Krogerus  * @fwnode: Firmware node where to look for the reference
54983b34afbSHeikki Krogerus  * @name: The name of the reference
55083b34afbSHeikki Krogerus  * @index: Index of the reference
55183b34afbSHeikki Krogerus  *
55283b34afbSHeikki Krogerus  * @index can be used when the named reference holds a table of references.
55383b34afbSHeikki Krogerus  *
554295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
555295209caSAndy Shevchenko  * fwnode pointer.
556295209caSAndy Shevchenko  *
557295209caSAndy Shevchenko  * Return: a pointer to the reference fwnode, when found. Otherwise,
558295209caSAndy Shevchenko  * returns an error pointer.
55983b34afbSHeikki Krogerus  */
fwnode_find_reference(const struct fwnode_handle * fwnode,const char * name,unsigned int index)56083b34afbSHeikki Krogerus struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
56183b34afbSHeikki Krogerus 					    const char *name,
56283b34afbSHeikki Krogerus 					    unsigned int index)
56383b34afbSHeikki Krogerus {
56483b34afbSHeikki Krogerus 	struct fwnode_reference_args args;
56583b34afbSHeikki Krogerus 	int ret;
56683b34afbSHeikki Krogerus 
56783b34afbSHeikki Krogerus 	ret = fwnode_property_get_reference_args(fwnode, name, NULL, 0, index,
56883b34afbSHeikki Krogerus 						 &args);
56983b34afbSHeikki Krogerus 	return ret ? ERR_PTR(ret) : args.fwnode;
57083b34afbSHeikki Krogerus }
57183b34afbSHeikki Krogerus EXPORT_SYMBOL_GPL(fwnode_find_reference);
57283b34afbSHeikki Krogerus 
57383b34afbSHeikki Krogerus /**
574bc0500c1SSakari Ailus  * fwnode_get_name - Return the name of a node
575bc0500c1SSakari Ailus  * @fwnode: The firmware node
576bc0500c1SSakari Ailus  *
577295209caSAndy Shevchenko  * Return: a pointer to the node name, or %NULL.
578bc0500c1SSakari Ailus  */
fwnode_get_name(const struct fwnode_handle * fwnode)579bc0500c1SSakari Ailus const char *fwnode_get_name(const struct fwnode_handle *fwnode)
580bc0500c1SSakari Ailus {
581bc0500c1SSakari Ailus 	return fwnode_call_ptr_op(fwnode, get_name);
582bc0500c1SSakari Ailus }
5836fafbbe8SHeikki Krogerus EXPORT_SYMBOL_GPL(fwnode_get_name);
584bc0500c1SSakari Ailus 
585bc0500c1SSakari Ailus /**
586e7e242bcSSakari Ailus  * fwnode_get_name_prefix - Return the prefix of node for printing purposes
587e7e242bcSSakari Ailus  * @fwnode: The firmware node
588e7e242bcSSakari Ailus  *
589295209caSAndy Shevchenko  * Return: the prefix of a node, intended to be printed right before the node.
590e7e242bcSSakari Ailus  * The prefix works also as a separator between the nodes.
591e7e242bcSSakari Ailus  */
fwnode_get_name_prefix(const struct fwnode_handle * fwnode)592e7e242bcSSakari Ailus const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
593e7e242bcSSakari Ailus {
594e7e242bcSSakari Ailus 	return fwnode_call_ptr_op(fwnode, get_name_prefix);
595e7e242bcSSakari Ailus }
596e7e242bcSSakari Ailus 
597e7e242bcSSakari Ailus /**
598a57b7fb7SSakari Ailus  * fwnode_get_parent - Return parent firwmare node
599a57b7fb7SSakari Ailus  * @fwnode: Firmware whose parent is retrieved
600a57b7fb7SSakari Ailus  *
601295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
602295209caSAndy Shevchenko  * fwnode pointer.
603295209caSAndy Shevchenko  *
604295209caSAndy Shevchenko  * Return: parent firmware node of the given node if possible or %NULL if no
605a57b7fb7SSakari Ailus  * parent was available.
606a57b7fb7SSakari Ailus  */
fwnode_get_parent(const struct fwnode_handle * fwnode)607a57b7fb7SSakari Ailus struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode)
608a57b7fb7SSakari Ailus {
609a57b7fb7SSakari Ailus 	return fwnode_call_ptr_op(fwnode, get_parent);
610a57b7fb7SSakari Ailus }
611a57b7fb7SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_get_parent);
612a57b7fb7SSakari Ailus 
613a57b7fb7SSakari Ailus /**
61423387258SSakari Ailus  * fwnode_get_next_parent - Iterate to the node's parent
61523387258SSakari Ailus  * @fwnode: Firmware whose parent is retrieved
61623387258SSakari Ailus  *
61723387258SSakari Ailus  * This is like fwnode_get_parent() except that it drops the refcount
61823387258SSakari Ailus  * on the passed node, making it suitable for iterating through a
61923387258SSakari Ailus  * node's parents.
62023387258SSakari Ailus  *
621295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
622295209caSAndy Shevchenko  * fwnode pointer. Note that this function also puts a reference to @fwnode
623295209caSAndy Shevchenko  * unconditionally.
624295209caSAndy Shevchenko  *
625295209caSAndy Shevchenko  * Return: parent firmware node of the given node if possible or %NULL if no
626295209caSAndy Shevchenko  * parent was available.
62723387258SSakari Ailus  */
fwnode_get_next_parent(struct fwnode_handle * fwnode)62823387258SSakari Ailus struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode)
62923387258SSakari Ailus {
63023387258SSakari Ailus 	struct fwnode_handle *parent = fwnode_get_parent(fwnode);
63123387258SSakari Ailus 
63223387258SSakari Ailus 	fwnode_handle_put(fwnode);
63323387258SSakari Ailus 
63423387258SSakari Ailus 	return parent;
63523387258SSakari Ailus }
63623387258SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
63723387258SSakari Ailus 
63823387258SSakari Ailus /**
639b5d3e2fbSSaravana Kannan  * fwnode_get_next_parent_dev - Find device of closest ancestor fwnode
640b5d3e2fbSSaravana Kannan  * @fwnode: firmware node
641b5d3e2fbSSaravana Kannan  *
642b5d3e2fbSSaravana Kannan  * Given a firmware node (@fwnode), this function finds its closest ancestor
643b5d3e2fbSSaravana Kannan  * firmware node that has a corresponding struct device and returns that struct
644b5d3e2fbSSaravana Kannan  * device.
645b5d3e2fbSSaravana Kannan  *
646295209caSAndy Shevchenko  * The caller is responsible for calling put_device() on the returned device
647295209caSAndy Shevchenko  * pointer.
648295209caSAndy Shevchenko  *
649295209caSAndy Shevchenko  * Return: a pointer to the device of the @fwnode's closest ancestor.
650b5d3e2fbSSaravana Kannan  */
fwnode_get_next_parent_dev(const struct fwnode_handle * fwnode)6515b9ff0baSAndy Shevchenko struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwnode)
652b5d3e2fbSSaravana Kannan {
65387ffea09SAndy Shevchenko 	struct fwnode_handle *parent;
6547e7ba9b3SAndy Shevchenko 	struct device *dev;
655b5d3e2fbSSaravana Kannan 
65687ffea09SAndy Shevchenko 	fwnode_for_each_parent_node(fwnode, parent) {
657117ef574SDouglas Anderson 		dev = get_dev_from_fwnode(parent);
65887ffea09SAndy Shevchenko 		if (dev) {
65987ffea09SAndy Shevchenko 			fwnode_handle_put(parent);
660b5d3e2fbSSaravana Kannan 			return dev;
661b5d3e2fbSSaravana Kannan 		}
66287ffea09SAndy Shevchenko 	}
66387ffea09SAndy Shevchenko 	return NULL;
66487ffea09SAndy Shevchenko }
665b5d3e2fbSSaravana Kannan 
666b5d3e2fbSSaravana Kannan /**
66787e5e95dSSakari Ailus  * fwnode_count_parents - Return the number of parents a node has
66887e5e95dSSakari Ailus  * @fwnode: The node the parents of which are to be counted
66987e5e95dSSakari Ailus  *
670295209caSAndy Shevchenko  * Return: the number of parents a node has.
67187e5e95dSSakari Ailus  */
fwnode_count_parents(const struct fwnode_handle * fwnode)67287e5e95dSSakari Ailus unsigned int fwnode_count_parents(const struct fwnode_handle *fwnode)
67387e5e95dSSakari Ailus {
67487ffea09SAndy Shevchenko 	struct fwnode_handle *parent;
67587ffea09SAndy Shevchenko 	unsigned int count = 0;
67687e5e95dSSakari Ailus 
67787ffea09SAndy Shevchenko 	fwnode_for_each_parent_node(fwnode, parent)
67887ffea09SAndy Shevchenko 		count++;
67987e5e95dSSakari Ailus 
68087e5e95dSSakari Ailus 	return count;
68187e5e95dSSakari Ailus }
68287e5e95dSSakari Ailus EXPORT_SYMBOL_GPL(fwnode_count_parents);
68387e5e95dSSakari Ailus 
68487e5e95dSSakari Ailus /**
68587e5e95dSSakari Ailus  * fwnode_get_nth_parent - Return an nth parent of a node
68687e5e95dSSakari Ailus  * @fwnode: The node the parent of which is requested
68787e5e95dSSakari Ailus  * @depth: Distance of the parent from the node
68887e5e95dSSakari Ailus  *
689295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
690295209caSAndy Shevchenko  * fwnode pointer.
691295209caSAndy Shevchenko  *
692295209caSAndy Shevchenko  * Return: the nth parent of a node. If there is no parent at the requested
69387e5e95dSSakari Ailus  * @depth, %NULL is returned. If @depth is 0, the functionality is equivalent to
69487e5e95dSSakari Ailus  * fwnode_handle_get(). For @depth == 1, it is fwnode_get_parent() and so on.
69587e5e95dSSakari Ailus  */
fwnode_get_nth_parent(struct fwnode_handle * fwnode,unsigned int depth)69687e5e95dSSakari Ailus struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
69787e5e95dSSakari Ailus 					    unsigned int depth)
69887e5e95dSSakari Ailus {
69987ffea09SAndy Shevchenko 	struct fwnode_handle *parent;
70087e5e95dSSakari Ailus 
70187ffea09SAndy Shevchenko 	if (depth == 0)
70287ffea09SAndy Shevchenko 		return fwnode_handle_get(fwnode);
70387e5e95dSSakari Ailus 
70487ffea09SAndy Shevchenko 	fwnode_for_each_parent_node(fwnode, parent) {
70587ffea09SAndy Shevchenko 		if (--depth == 0)
70687ffea09SAndy Shevchenko 			return parent;
70787ffea09SAndy Shevchenko 	}
70887ffea09SAndy Shevchenko 	return NULL;
70987e5e95dSSakari Ailus }
71087e5e95dSSakari Ailus EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
71187e5e95dSSakari Ailus 
71287e5e95dSSakari Ailus /**
713022fe6bcSAndy Shevchenko  * fwnode_is_ancestor_of - Test if @ancestor is ancestor of @child
714022fe6bcSAndy Shevchenko  * @ancestor: Firmware which is tested for being an ancestor
715022fe6bcSAndy Shevchenko  * @child: Firmware which is tested for being the child
716b5d3e2fbSSaravana Kannan  *
717b5d3e2fbSSaravana Kannan  * A node is considered an ancestor of itself too.
718b5d3e2fbSSaravana Kannan  *
719295209caSAndy Shevchenko  * Return: true if @ancestor is an ancestor of @child. Otherwise, returns false.
720b5d3e2fbSSaravana Kannan  */
fwnode_is_ancestor_of(const struct fwnode_handle * ancestor,const struct fwnode_handle * child)7215b9ff0baSAndy Shevchenko bool fwnode_is_ancestor_of(const struct fwnode_handle *ancestor, const struct fwnode_handle *child)
722b5d3e2fbSSaravana Kannan {
72387ffea09SAndy Shevchenko 	struct fwnode_handle *parent;
72487ffea09SAndy Shevchenko 
725022fe6bcSAndy Shevchenko 	if (IS_ERR_OR_NULL(ancestor))
726b5d3e2fbSSaravana Kannan 		return false;
727b5d3e2fbSSaravana Kannan 
728022fe6bcSAndy Shevchenko 	if (child == ancestor)
72987ffea09SAndy Shevchenko 		return true;
73087ffea09SAndy Shevchenko 
731022fe6bcSAndy Shevchenko 	fwnode_for_each_parent_node(child, parent) {
732022fe6bcSAndy Shevchenko 		if (parent == ancestor) {
73387ffea09SAndy Shevchenko 			fwnode_handle_put(parent);
734b5d3e2fbSSaravana Kannan 			return true;
735b5d3e2fbSSaravana Kannan 		}
73687ffea09SAndy Shevchenko 	}
737b5d3e2fbSSaravana Kannan 	return false;
738b5d3e2fbSSaravana Kannan }
739b5d3e2fbSSaravana Kannan 
740b5d3e2fbSSaravana Kannan /**
74134055190SMika Westerberg  * fwnode_get_next_child_node - Return the next child node handle for a node
74234055190SMika Westerberg  * @fwnode: Firmware node to find the next child node for.
74334055190SMika Westerberg  * @child: Handle to one of the node's child nodes or a %NULL handle.
744295209caSAndy Shevchenko  *
745295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
746295209caSAndy Shevchenko  * fwnode pointer. Note that this function also puts a reference to @child
747295209caSAndy Shevchenko  * unconditionally.
74834055190SMika Westerberg  */
74937ba983cSSakari Ailus struct fwnode_handle *
fwnode_get_next_child_node(const struct fwnode_handle * fwnode,struct fwnode_handle * child)75037ba983cSSakari Ailus fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
75134055190SMika Westerberg 			   struct fwnode_handle *child)
75234055190SMika Westerberg {
7533708184aSSakari Ailus 	return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
75434055190SMika Westerberg }
75534055190SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
75634055190SMika Westerberg 
75734055190SMika Westerberg /**
758295209caSAndy Shevchenko  * fwnode_get_next_available_child_node - Return the next available child node handle for a node
7593395de96SMarcin Wojtas  * @fwnode: Firmware node to find the next child node for.
7603395de96SMarcin Wojtas  * @child: Handle to one of the node's child nodes or a %NULL handle.
761295209caSAndy Shevchenko  *
762295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
763295209caSAndy Shevchenko  * fwnode pointer. Note that this function also puts a reference to @child
764295209caSAndy Shevchenko  * unconditionally.
7653395de96SMarcin Wojtas  */
7663395de96SMarcin Wojtas struct fwnode_handle *
fwnode_get_next_available_child_node(const struct fwnode_handle * fwnode,struct fwnode_handle * child)7673395de96SMarcin Wojtas fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
7683395de96SMarcin Wojtas 				     struct fwnode_handle *child)
7693395de96SMarcin Wojtas {
7703395de96SMarcin Wojtas 	struct fwnode_handle *next_child = child;
7713395de96SMarcin Wojtas 
772002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
7733395de96SMarcin Wojtas 		return NULL;
7743395de96SMarcin Wojtas 
7753395de96SMarcin Wojtas 	do {
7763395de96SMarcin Wojtas 		next_child = fwnode_get_next_child_node(fwnode, next_child);
7777e7ba9b3SAndy Shevchenko 		if (!next_child)
7787e7ba9b3SAndy Shevchenko 			return NULL;
7797e7ba9b3SAndy Shevchenko 	} while (!fwnode_device_is_available(next_child));
7803395de96SMarcin Wojtas 
7813395de96SMarcin Wojtas 	return next_child;
7823395de96SMarcin Wojtas }
7833395de96SMarcin Wojtas EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
7843395de96SMarcin Wojtas 
7853395de96SMarcin Wojtas /**
7868a0662d9SRafael J. Wysocki  * device_get_next_child_node - Return the next child node handle for a device
7878a0662d9SRafael J. Wysocki  * @dev: Device to find the next child node for.
788295209caSAndy Shevchenko  * @child: Handle to one of the device's child nodes or a %NULL handle.
789295209caSAndy Shevchenko  *
790295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
791295209caSAndy Shevchenko  * fwnode pointer. Note that this function also puts a reference to @child
792295209caSAndy Shevchenko  * unconditionally.
7938a0662d9SRafael J. Wysocki  */
device_get_next_child_node(const struct device * dev,struct fwnode_handle * child)7947952cd2bSAndy Shevchenko struct fwnode_handle *device_get_next_child_node(const struct device *dev,
7958a0662d9SRafael J. Wysocki 						 struct fwnode_handle *child)
7968a0662d9SRafael J. Wysocki {
797fb38f314SAndy Shevchenko 	const struct fwnode_handle *fwnode = dev_fwnode(dev);
798fb38f314SAndy Shevchenko 	struct fwnode_handle *next;
79934055190SMika Westerberg 
800002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
801002752afSAndy Shevchenko 		return NULL;
802002752afSAndy Shevchenko 
803114dbb4fSAndy Shevchenko 	/* Try to find a child in primary fwnode */
804114dbb4fSAndy Shevchenko 	next = fwnode_get_next_child_node(fwnode, child);
805114dbb4fSAndy Shevchenko 	if (next)
806114dbb4fSAndy Shevchenko 		return next;
807114dbb4fSAndy Shevchenko 
808114dbb4fSAndy Shevchenko 	/* When no more children in primary, continue with secondary */
809002752afSAndy Shevchenko 	return fwnode_get_next_child_node(fwnode->secondary, child);
8108a0662d9SRafael J. Wysocki }
8118a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(device_get_next_child_node);
8128a0662d9SRafael J. Wysocki 
8138a0662d9SRafael J. Wysocki /**
81421ea73f5SMika Westerberg  * fwnode_get_named_child_node - Return first matching named child node handle
81521ea73f5SMika Westerberg  * @fwnode: Firmware node to find the named child node for.
816613e9721SAdam Thomson  * @childname: String to match child node name against.
817295209caSAndy Shevchenko  *
818295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
819295209caSAndy Shevchenko  * fwnode pointer.
820613e9721SAdam Thomson  */
82137ba983cSSakari Ailus struct fwnode_handle *
fwnode_get_named_child_node(const struct fwnode_handle * fwnode,const char * childname)82237ba983cSSakari Ailus fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
823613e9721SAdam Thomson 			    const char *childname)
824613e9721SAdam Thomson {
8253708184aSSakari Ailus 	return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);
826613e9721SAdam Thomson }
82721ea73f5SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
82821ea73f5SMika Westerberg 
82921ea73f5SMika Westerberg /**
83021ea73f5SMika Westerberg  * device_get_named_child_node - Return first matching named child node handle
83121ea73f5SMika Westerberg  * @dev: Device to find the named child node for.
83221ea73f5SMika Westerberg  * @childname: String to match child node name against.
833295209caSAndy Shevchenko  *
834295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
835295209caSAndy Shevchenko  * fwnode pointer.
83621ea73f5SMika Westerberg  */
device_get_named_child_node(const struct device * dev,const char * childname)8377952cd2bSAndy Shevchenko struct fwnode_handle *device_get_named_child_node(const struct device *dev,
83821ea73f5SMika Westerberg 						  const char *childname)
83921ea73f5SMika Westerberg {
84021ea73f5SMika Westerberg 	return fwnode_get_named_child_node(dev_fwnode(dev), childname);
84121ea73f5SMika Westerberg }
842613e9721SAdam Thomson EXPORT_SYMBOL_GPL(device_get_named_child_node);
843613e9721SAdam Thomson 
844613e9721SAdam Thomson /**
845e7887c28SSakari Ailus  * fwnode_handle_get - Obtain a reference to a device node
846e7887c28SSakari Ailus  * @fwnode: Pointer to the device node to obtain the reference to.
847cf89a31cSSakari Ailus  *
848295209caSAndy Shevchenko  * The caller is responsible for calling fwnode_handle_put() on the returned
849295209caSAndy Shevchenko  * fwnode pointer.
850295209caSAndy Shevchenko  *
851295209caSAndy Shevchenko  * Return: the fwnode handle.
852e7887c28SSakari Ailus  */
fwnode_handle_get(struct fwnode_handle * fwnode)853cf89a31cSSakari Ailus struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode)
854e7887c28SSakari Ailus {
855cf89a31cSSakari Ailus 	if (!fwnode_has_op(fwnode, get))
856cf89a31cSSakari Ailus 		return fwnode;
857cf89a31cSSakari Ailus 
858cf89a31cSSakari Ailus 	return fwnode_call_ptr_op(fwnode, get);
859e7887c28SSakari Ailus }
860e7887c28SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_handle_get);
861e7887c28SSakari Ailus 
862e7887c28SSakari Ailus /**
8638a0662d9SRafael J. Wysocki  * fwnode_handle_put - Drop reference to a device node
8648a0662d9SRafael J. Wysocki  * @fwnode: Pointer to the device node to drop the reference to.
8658a0662d9SRafael J. Wysocki  *
8668a0662d9SRafael J. Wysocki  * This has to be used when terminating device_for_each_child_node() iteration
8678a0662d9SRafael J. Wysocki  * with break or return to prevent stale device node references from being left
8688a0662d9SRafael J. Wysocki  * behind.
8698a0662d9SRafael J. Wysocki  */
fwnode_handle_put(struct fwnode_handle * fwnode)8708a0662d9SRafael J. Wysocki void fwnode_handle_put(struct fwnode_handle *fwnode)
8718a0662d9SRafael J. Wysocki {
8723708184aSSakari Ailus 	fwnode_call_void_op(fwnode, put);
8738a0662d9SRafael J. Wysocki }
8748a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(fwnode_handle_put);
8758a0662d9SRafael J. Wysocki 
8768a0662d9SRafael J. Wysocki /**
8772294b3afSSakari Ailus  * fwnode_device_is_available - check if a device is available for use
8782294b3afSSakari Ailus  * @fwnode: Pointer to the fwnode of the device.
8795273382dSDaniel Scally  *
880295209caSAndy Shevchenko  * Return: true if device is available for use. Otherwise, returns false.
881295209caSAndy Shevchenko  *
8825273382dSDaniel Scally  * For fwnode node types that don't implement the .device_is_available()
8835273382dSDaniel Scally  * operation, this function returns true.
8842294b3afSSakari Ailus  */
fwnode_device_is_available(const struct fwnode_handle * fwnode)88537ba983cSSakari Ailus bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
8862294b3afSSakari Ailus {
887002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(fwnode))
888002752afSAndy Shevchenko 		return false;
889002752afSAndy Shevchenko 
8905273382dSDaniel Scally 	if (!fwnode_has_op(fwnode, device_is_available))
8915273382dSDaniel Scally 		return true;
8925273382dSDaniel Scally 
893e8158b48SSakari Ailus 	return fwnode_call_bool_op(fwnode, device_is_available);
8942294b3afSSakari Ailus }
8952294b3afSSakari Ailus EXPORT_SYMBOL_GPL(fwnode_device_is_available);
8962294b3afSSakari Ailus 
8972294b3afSSakari Ailus /**
8988a0662d9SRafael J. Wysocki  * device_get_child_node_count - return the number of child nodes for device
8998a0662d9SRafael J. Wysocki  * @dev: Device to cound the child nodes for
900295209caSAndy Shevchenko  *
901295209caSAndy Shevchenko  * Return: the number of child nodes for a given device.
9028a0662d9SRafael J. Wysocki  */
device_get_child_node_count(const struct device * dev)9037952cd2bSAndy Shevchenko unsigned int device_get_child_node_count(const struct device *dev)
9048a0662d9SRafael J. Wysocki {
9058a0662d9SRafael J. Wysocki 	struct fwnode_handle *child;
9068a0662d9SRafael J. Wysocki 	unsigned int count = 0;
9078a0662d9SRafael J. Wysocki 
9088a0662d9SRafael J. Wysocki 	device_for_each_child_node(dev, child)
9098a0662d9SRafael J. Wysocki 		count++;
9108a0662d9SRafael J. Wysocki 
9118a0662d9SRafael J. Wysocki 	return count;
9128a0662d9SRafael J. Wysocki }
9138a0662d9SRafael J. Wysocki EXPORT_SYMBOL_GPL(device_get_child_node_count);
91405ca5560SSuthikulpanit, Suravee 
device_dma_supported(const struct device * dev)91559789f34SAndy Shevchenko bool device_dma_supported(const struct device *dev)
916e5e55864SSuthikulpanit, Suravee {
9178c756a0aSSakari Ailus 	return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
918e5e55864SSuthikulpanit, Suravee }
919e5e55864SSuthikulpanit, Suravee EXPORT_SYMBOL_GPL(device_dma_supported);
920e5e55864SSuthikulpanit, Suravee 
device_get_dma_attr(const struct device * dev)92159789f34SAndy Shevchenko enum dev_dma_attr device_get_dma_attr(const struct device *dev)
922e5e55864SSuthikulpanit, Suravee {
9238c756a0aSSakari Ailus 	if (!fwnode_has_op(dev_fwnode(dev), device_get_dma_attr))
9248c756a0aSSakari Ailus 		return DEV_DMA_NOT_SUPPORTED;
925e5e55864SSuthikulpanit, Suravee 
9268c756a0aSSakari Ailus 	return fwnode_call_int_op(dev_fwnode(dev), device_get_dma_attr);
927e5e55864SSuthikulpanit, Suravee }
928e5e55864SSuthikulpanit, Suravee EXPORT_SYMBOL_GPL(device_get_dma_attr);
929e5e55864SSuthikulpanit, Suravee 
9304c96b7dcSJeremy Linton /**
931b28f263bSMarcin Wojtas  * fwnode_get_phy_mode - Get phy mode for given firmware node
932b28f263bSMarcin Wojtas  * @fwnode:	Pointer to the given node
9334c96b7dcSJeremy Linton  *
9344c96b7dcSJeremy Linton  * The function gets phy interface string from property 'phy-mode' or
9354c96b7dcSJeremy Linton  * 'phy-connection-type', and return its index in phy_modes table, or errno in
9364c96b7dcSJeremy Linton  * error case.
9374c96b7dcSJeremy Linton  */
fwnode_get_phy_mode(const struct fwnode_handle * fwnode)9380a392354SRussell King int fwnode_get_phy_mode(const struct fwnode_handle *fwnode)
9394c96b7dcSJeremy Linton {
9404c96b7dcSJeremy Linton 	const char *pm;
9414c96b7dcSJeremy Linton 	int err, i;
9424c96b7dcSJeremy Linton 
943b28f263bSMarcin Wojtas 	err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
9444c96b7dcSJeremy Linton 	if (err < 0)
945b28f263bSMarcin Wojtas 		err = fwnode_property_read_string(fwnode,
9464c96b7dcSJeremy Linton 						  "phy-connection-type", &pm);
9474c96b7dcSJeremy Linton 	if (err < 0)
9484c96b7dcSJeremy Linton 		return err;
9494c96b7dcSJeremy Linton 
9504c96b7dcSJeremy Linton 	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
9514c96b7dcSJeremy Linton 		if (!strcasecmp(pm, phy_modes(i)))
9524c96b7dcSJeremy Linton 			return i;
9534c96b7dcSJeremy Linton 
9544c96b7dcSJeremy Linton 	return -ENODEV;
9554c96b7dcSJeremy Linton }
956b28f263bSMarcin Wojtas EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
957b28f263bSMarcin Wojtas 
958b28f263bSMarcin Wojtas /**
959b28f263bSMarcin Wojtas  * device_get_phy_mode - Get phy mode for given device
960b28f263bSMarcin Wojtas  * @dev:	Pointer to the given device
961b28f263bSMarcin Wojtas  *
962b28f263bSMarcin Wojtas  * The function gets phy interface string from property 'phy-mode' or
963b28f263bSMarcin Wojtas  * 'phy-connection-type', and return its index in phy_modes table, or errno in
964b28f263bSMarcin Wojtas  * error case.
965b28f263bSMarcin Wojtas  */
device_get_phy_mode(struct device * dev)966b28f263bSMarcin Wojtas int device_get_phy_mode(struct device *dev)
967b28f263bSMarcin Wojtas {
968b28f263bSMarcin Wojtas 	return fwnode_get_phy_mode(dev_fwnode(dev));
969b28f263bSMarcin Wojtas }
9704c96b7dcSJeremy Linton EXPORT_SYMBOL_GPL(device_get_phy_mode);
9714c96b7dcSJeremy Linton 
97207bb80d4SMika Westerberg /**
973b2638e56SAndy Shevchenko  * fwnode_iomap - Maps the memory mapped IO for a given fwnode
974b2638e56SAndy Shevchenko  * @fwnode:	Pointer to the firmware node
975b2638e56SAndy Shevchenko  * @index:	Index of the IO range
976b2638e56SAndy Shevchenko  *
977295209caSAndy Shevchenko  * Return: a pointer to the mapped memory.
978b2638e56SAndy Shevchenko  */
fwnode_iomap(struct fwnode_handle * fwnode,int index)979b2638e56SAndy Shevchenko void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index)
980b2638e56SAndy Shevchenko {
98168b979d0SSakari Ailus 	return fwnode_call_ptr_op(fwnode, iomap, index);
982b2638e56SAndy Shevchenko }
983b2638e56SAndy Shevchenko EXPORT_SYMBOL(fwnode_iomap);
984b2638e56SAndy Shevchenko 
985b2638e56SAndy Shevchenko /**
9867c6c57f2SMarcin Wojtas  * fwnode_irq_get - Get IRQ directly from a fwnode
9877c6c57f2SMarcin Wojtas  * @fwnode:	Pointer to the firmware node
9887c6c57f2SMarcin Wojtas  * @index:	Zero-based index of the IRQ
9897c6c57f2SMarcin Wojtas  *
990295209caSAndy Shevchenko  * Return: Linux IRQ number on success. Negative errno on failure.
991295209caSAndy Shevchenko  */
fwnode_irq_get(const struct fwnode_handle * fwnode,unsigned int index)9927c6c57f2SMarcin Wojtas int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
993fb38f314SAndy Shevchenko {
9947c6c57f2SMarcin Wojtas 	int ret;
99599c63707SSakari Ailus 
9967c6c57f2SMarcin Wojtas 	ret = fwnode_call_int_op(fwnode, irq_get, index);
9977c6c57f2SMarcin Wojtas 	/* We treat mapping errors as invalid case */
9987c6c57f2SMarcin Wojtas 	if (ret == 0)
9997c6c57f2SMarcin Wojtas 		return -EINVAL;
1000ca0acb51SAkhil R 
1001ca0acb51SAkhil R 	return ret;
1002ca0acb51SAkhil R }
1003ca0acb51SAkhil R EXPORT_SYMBOL(fwnode_irq_get);
1004ca0acb51SAkhil R 
1005ca0acb51SAkhil R /**
1006ca0acb51SAkhil R  * fwnode_irq_get_byname - Get IRQ from a fwnode using its name
1007ca0acb51SAkhil R  * @fwnode:	Pointer to the firmware node
1008ca0acb51SAkhil R  * @name:	IRQ name
1009ca0acb51SAkhil R  *
1010295209caSAndy Shevchenko  * Description:
1011ca0acb51SAkhil R  * Find a match to the string @name in the 'interrupt-names' string array
1012ca0acb51SAkhil R  * in _DSD for ACPI, or of_node for Device Tree. Then get the Linux IRQ
1013ca0acb51SAkhil R  * number of the IRQ resource corresponding to the index of the matched
1014ca0acb51SAkhil R  * string.
1015ca0acb51SAkhil R  *
1016ca0acb51SAkhil R  * Return: Linux IRQ number on success, or negative errno otherwise.
1017ca0acb51SAkhil R  */
fwnode_irq_get_byname(const struct fwnode_handle * fwnode,const char * name)1018ca0acb51SAkhil R int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
1019ca0acb51SAkhil R {
1020ca0acb51SAkhil R 	int index;
1021ca0acb51SAkhil R 
1022ca0acb51SAkhil R 	if (!name)
1023ca0acb51SAkhil R 		return -EINVAL;
1024ca0acb51SAkhil R 
1025ca0acb51SAkhil R 	index = fwnode_property_match_string(fwnode, "interrupt-names",  name);
1026ca0acb51SAkhil R 	if (index < 0)
1027ca0acb51SAkhil R 		return index;
1028f569da8cSMarco Felsch 
102907bb80d4SMika Westerberg 	return fwnode_irq_get(fwnode, index);
103007bb80d4SMika Westerberg }
103107bb80d4SMika Westerberg EXPORT_SYMBOL(fwnode_irq_get_byname);
1032295209caSAndy Shevchenko 
1033295209caSAndy Shevchenko /**
1034295209caSAndy Shevchenko  * fwnode_graph_get_next_endpoint - Get next endpoint firmware node
1035295209caSAndy Shevchenko  * @fwnode: Pointer to the parent firmware node
1036295209caSAndy Shevchenko  * @prev: Previous endpoint node or %NULL to get the first
103707bb80d4SMika Westerberg  *
103807bb80d4SMika Westerberg  * The caller is responsible for calling fwnode_handle_put() on the returned
103907bb80d4SMika Westerberg  * fwnode pointer. Note that this function also puts a reference to @prev
104037ba983cSSakari Ailus  * unconditionally.
104107bb80d4SMika Westerberg  *
104207bb80d4SMika Westerberg  * Return: an endpoint firmware node pointer or %NULL if no more endpoints
104339af7286SYang Yingliang  * are available.
1044b5b41ab6SDaniel Scally  */
1045b5b41ab6SDaniel Scally struct fwnode_handle *
fwnode_graph_get_next_endpoint(const struct fwnode_handle * fwnode,struct fwnode_handle * prev)1046b5b41ab6SDaniel Scally fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
1047b5b41ab6SDaniel Scally 			       struct fwnode_handle *prev)
1048b5b41ab6SDaniel Scally {
1049b5b41ab6SDaniel Scally 	struct fwnode_handle *ep, *port_parent = NULL;
1050b5b41ab6SDaniel Scally 	const struct fwnode_handle *parent;
105139af7286SYang Yingliang 
105239af7286SYang Yingliang 	/*
105339af7286SYang Yingliang 	 * If this function is in a loop and the previous iteration returned
105439af7286SYang Yingliang 	 * an endpoint from fwnode->secondary, then we need to use the secondary
1055b5b41ab6SDaniel Scally 	 * as parent rather than @fwnode.
105639af7286SYang Yingliang 	 */
1057002752afSAndy Shevchenko 	if (prev) {
1058002752afSAndy Shevchenko 		port_parent = fwnode_graph_get_port_parent(prev);
1059b5b41ab6SDaniel Scally 		parent = port_parent;
1060b5b41ab6SDaniel Scally 	} else {
1061002752afSAndy Shevchenko 		parent = fwnode;
106239af7286SYang Yingliang 	}
1063002752afSAndy Shevchenko 	if (IS_ERR_OR_NULL(parent))
106439af7286SYang Yingliang 		return NULL;
106539af7286SYang Yingliang 
106639af7286SYang Yingliang 	ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
106739af7286SYang Yingliang 	if (ep)
106839af7286SYang Yingliang 		goto out_put_port_parent;
106907bb80d4SMika Westerberg 
107007bb80d4SMika Westerberg 	ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
107107bb80d4SMika Westerberg 
107207bb80d4SMika Westerberg out_put_port_parent:
10736a71d8d7SKieran Bingham 	fwnode_handle_put(port_parent);
10746a71d8d7SKieran Bingham 	return ep;
10756a71d8d7SKieran Bingham }
1076295209caSAndy Shevchenko EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
1077295209caSAndy Shevchenko 
1078295209caSAndy Shevchenko /**
10796a71d8d7SKieran Bingham  * fwnode_graph_get_port_parent - Return the device fwnode of a port endpoint
10806a71d8d7SKieran Bingham  * @endpoint: Endpoint firmware node of the port
10816a71d8d7SKieran Bingham  *
108237ba983cSSakari Ailus  * The caller is responsible for calling fwnode_handle_put() on the returned
10836a71d8d7SKieran Bingham  * fwnode pointer.
10846a71d8d7SKieran Bingham  *
10856a71d8d7SKieran Bingham  * Return: the firmware node of the device the @endpoint belongs to.
10866a71d8d7SKieran Bingham  */
10876a71d8d7SKieran Bingham struct fwnode_handle *
fwnode_graph_get_port_parent(const struct fwnode_handle * endpoint)10886a71d8d7SKieran Bingham fwnode_graph_get_port_parent(const struct fwnode_handle *endpoint)
10896a71d8d7SKieran Bingham {
10906a71d8d7SKieran Bingham 	struct fwnode_handle *port, *parent;
10916a71d8d7SKieran Bingham 
10926a71d8d7SKieran Bingham 	port = fwnode_get_parent(endpoint);
10936a71d8d7SKieran Bingham 	parent = fwnode_call_ptr_op(port, graph_get_port_parent);
10946a71d8d7SKieran Bingham 
10956a71d8d7SKieran Bingham 	fwnode_handle_put(port);
109607bb80d4SMika Westerberg 
109707bb80d4SMika Westerberg 	return parent;
109807bb80d4SMika Westerberg }
109907bb80d4SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent);
1100295209caSAndy Shevchenko 
1101295209caSAndy Shevchenko /**
1102295209caSAndy Shevchenko  * fwnode_graph_get_remote_port_parent - Return fwnode of a remote device
110307bb80d4SMika Westerberg  * @fwnode: Endpoint firmware node pointing to the remote endpoint
110407bb80d4SMika Westerberg  *
110537ba983cSSakari Ailus  * Extracts firmware node of a remote device the @fwnode points to.
110607bb80d4SMika Westerberg  *
11076a71d8d7SKieran Bingham  * The caller is responsible for calling fwnode_handle_put() on the returned
110807bb80d4SMika Westerberg  * fwnode pointer.
11096a71d8d7SKieran Bingham  */
11106a71d8d7SKieran Bingham struct fwnode_handle *
fwnode_graph_get_remote_port_parent(const struct fwnode_handle * fwnode)111107bb80d4SMika Westerberg fwnode_graph_get_remote_port_parent(const struct fwnode_handle *fwnode)
11126a71d8d7SKieran Bingham {
111307bb80d4SMika Westerberg 	struct fwnode_handle *endpoint, *parent;
111407bb80d4SMika Westerberg 
111507bb80d4SMika Westerberg 	endpoint = fwnode_graph_get_remote_endpoint(fwnode);
111607bb80d4SMika Westerberg 	parent = fwnode_graph_get_port_parent(endpoint);
111707bb80d4SMika Westerberg 
111807bb80d4SMika Westerberg 	fwnode_handle_put(endpoint);
111907bb80d4SMika Westerberg 
112007bb80d4SMika Westerberg 	return parent;
112107bb80d4SMika Westerberg }
112207bb80d4SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
1123295209caSAndy Shevchenko 
1124295209caSAndy Shevchenko /**
1125295209caSAndy Shevchenko  * fwnode_graph_get_remote_port - Return fwnode of a remote port
112607bb80d4SMika Westerberg  * @fwnode: Endpoint firmware node pointing to the remote endpoint
112737ba983cSSakari Ailus  *
112837ba983cSSakari Ailus  * Extracts firmware node of a remote port the @fwnode points to.
112907bb80d4SMika Westerberg  *
11303b27d00eSSakari Ailus  * The caller is responsible for calling fwnode_handle_put() on the returned
113107bb80d4SMika Westerberg  * fwnode pointer.
113207bb80d4SMika Westerberg  */
113307bb80d4SMika Westerberg struct fwnode_handle *
fwnode_graph_get_remote_port(const struct fwnode_handle * fwnode)113407bb80d4SMika Westerberg fwnode_graph_get_remote_port(const struct fwnode_handle *fwnode)
113507bb80d4SMika Westerberg {
113607bb80d4SMika Westerberg 	return fwnode_get_next_parent(fwnode_graph_get_remote_endpoint(fwnode));
113707bb80d4SMika Westerberg }
113807bb80d4SMika Westerberg EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
1139295209caSAndy Shevchenko 
1140295209caSAndy Shevchenko /**
1141295209caSAndy Shevchenko  * fwnode_graph_get_remote_endpoint - Return fwnode of a remote endpoint
114207bb80d4SMika Westerberg  * @fwnode: Endpoint firmware node pointing to the remote endpoint
114307bb80d4SMika Westerberg  *
114437ba983cSSakari Ailus  * Extracts firmware node of a remote endpoint the @fwnode points to.
114507bb80d4SMika Westerberg  *
11463b27d00eSSakari Ailus  * The caller is responsible for calling fwnode_handle_put() on the returned
114707bb80d4SMika Westerberg  * fwnode pointer.
114807bb80d4SMika Westerberg  */
11492bd5452dSSakari Ailus struct fwnode_handle *
fwnode_graph_get_remote_endpoint(const struct fwnode_handle * fwnode)1150c87b8fc5SSakari Ailus fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
1151c87b8fc5SSakari Ailus {
1152c87b8fc5SSakari Ailus 	return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
1153c87b8fc5SSakari Ailus }
1154c87b8fc5SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
1155c87b8fc5SSakari Ailus 
fwnode_graph_remote_available(struct fwnode_handle * ep)1156c87b8fc5SSakari Ailus static bool fwnode_graph_remote_available(struct fwnode_handle *ep)
1157c87b8fc5SSakari Ailus {
1158c87b8fc5SSakari Ailus 	struct fwnode_handle *dev_node;
1159c87b8fc5SSakari Ailus 	bool available;
1160c87b8fc5SSakari Ailus 
1161c87b8fc5SSakari Ailus 	dev_node = fwnode_graph_get_remote_port_parent(ep);
1162125ee6b3SSakari Ailus 	available = fwnode_device_is_available(dev_node);
11630fcc2bdcSSakari Ailus 	fwnode_handle_put(dev_node);
11640fcc2bdcSSakari Ailus 
11650fcc2bdcSSakari Ailus 	return available;
11660fcc2bdcSSakari Ailus }
11670fcc2bdcSSakari Ailus 
11680fcc2bdcSSakari Ailus /**
1169295209caSAndy Shevchenko  * fwnode_graph_get_endpoint_by_id - get endpoint by port and endpoint numbers
1170295209caSAndy Shevchenko  * @fwnode: parent fwnode_handle containing the graph
1171295209caSAndy Shevchenko  * @port: identifier of the port node
1172295209caSAndy Shevchenko  * @endpoint: identifier of the endpoint node under the port node
1173295209caSAndy Shevchenko  * @flags: fwnode lookup flags
11740fcc2bdcSSakari Ailus  *
11750fcc2bdcSSakari Ailus  * The caller is responsible for calling fwnode_handle_put() on the returned
11760fcc2bdcSSakari Ailus  * fwnode pointer.
11770fcc2bdcSSakari Ailus  *
11780fcc2bdcSSakari Ailus  * Return: the fwnode handle of the local endpoint corresponding the port and
117949f39cb0SSakari Ailus  * endpoint IDs or %NULL if not found.
118049f39cb0SSakari Ailus  *
11810fcc2bdcSSakari Ailus  * If FWNODE_GRAPH_ENDPOINT_NEXT is passed in @flags and the specified endpoint
11820fcc2bdcSSakari Ailus  * has not been found, look for the closest endpoint ID greater than the
11830fcc2bdcSSakari Ailus  * specified one and return the endpoint that corresponds to it, if present.
11840fcc2bdcSSakari Ailus  *
11850fcc2bdcSSakari Ailus  * Does not return endpoints that belong to disabled devices or endpoints that
11860d82017bSSakari Ailus  * are unconnected, unless FWNODE_GRAPH_DEVICE_DISABLED is passed in @flags.
11870fcc2bdcSSakari Ailus  */
11880fcc2bdcSSakari Ailus struct fwnode_handle *
fwnode_graph_get_endpoint_by_id(const struct fwnode_handle * fwnode,u32 port,u32 endpoint,unsigned long flags)11890fcc2bdcSSakari Ailus fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
11900fcc2bdcSSakari Ailus 				u32 port, u32 endpoint, unsigned long flags)
11910d82017bSSakari Ailus {
11920fcc2bdcSSakari Ailus 	struct fwnode_handle *ep, *best_ep = NULL;
11930fcc2bdcSSakari Ailus 	unsigned int best_ep_id = 0;
11940fcc2bdcSSakari Ailus 	bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
1195c87b8fc5SSakari Ailus 	bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);
11960fcc2bdcSSakari Ailus 
11970fcc2bdcSSakari Ailus 	fwnode_graph_for_each_endpoint(fwnode, ep) {
11980fcc2bdcSSakari Ailus 		struct fwnode_endpoint fwnode_ep = { 0 };
11990fcc2bdcSSakari Ailus 		int ret;
12000fcc2bdcSSakari Ailus 
12010fcc2bdcSSakari Ailus 		if (enabled_only && !fwnode_graph_remote_available(ep))
12020fcc2bdcSSakari Ailus 			continue;
12030fcc2bdcSSakari Ailus 
12040fcc2bdcSSakari Ailus 		ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
12050fcc2bdcSSakari Ailus 		if (ret < 0)
12060fcc2bdcSSakari Ailus 			continue;
12070fcc2bdcSSakari Ailus 
12080fcc2bdcSSakari Ailus 		if (fwnode_ep.port != port)
12090fcc2bdcSSakari Ailus 			continue;
12100fcc2bdcSSakari Ailus 
12110fcc2bdcSSakari Ailus 		if (fwnode_ep.id == endpoint)
12120fcc2bdcSSakari Ailus 			return ep;
12130fcc2bdcSSakari Ailus 
12140fcc2bdcSSakari Ailus 		if (!endpoint_next)
12150fcc2bdcSSakari Ailus 			continue;
12160fcc2bdcSSakari Ailus 
12170fcc2bdcSSakari Ailus 		/*
12180fcc2bdcSSakari Ailus 		 * If the endpoint that has just been found is not the first
12190fcc2bdcSSakari Ailus 		 * matching one and the ID of the one found previously is closer
12200fcc2bdcSSakari Ailus 		 * to the requested endpoint ID, skip it.
12210fcc2bdcSSakari Ailus 		 */
12220fcc2bdcSSakari Ailus 		if (fwnode_ep.id < endpoint ||
12230fcc2bdcSSakari Ailus 		    (best_ep && best_ep_id < fwnode_ep.id))
12240fcc2bdcSSakari Ailus 			continue;
12250fcc2bdcSSakari Ailus 
12260fcc2bdcSSakari Ailus 		fwnode_handle_put(best_ep);
12270fcc2bdcSSakari Ailus 		best_ep = fwnode_handle_get(ep);
12280fcc2bdcSSakari Ailus 		best_ep_id = fwnode_ep.id;
12290fcc2bdcSSakari Ailus 	}
1230c87b8fc5SSakari Ailus 
1231c87b8fc5SSakari Ailus 	return best_ep;
1232c87b8fc5SSakari Ailus }
1233c87b8fc5SSakari Ailus EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
1234c87b8fc5SSakari Ailus 
1235c87b8fc5SSakari Ailus /**
1236c87b8fc5SSakari Ailus  * fwnode_graph_get_endpoint_count - Count endpoints on a device node
1237c87b8fc5SSakari Ailus  * @fwnode: The node related to a device
12385b9ff0baSAndy Shevchenko  * @flags: fwnode lookup flags
1239c87b8fc5SSakari Ailus  * Count endpoints in a device node.
1240c87b8fc5SSakari Ailus  *
1241c87b8fc5SSakari Ailus  * If FWNODE_GRAPH_DEVICE_DISABLED flag is specified, also unconnected endpoints
1242c87b8fc5SSakari Ailus  * and endpoints connected to disabled devices are counted.
1243c87b8fc5SSakari Ailus  */
fwnode_graph_get_endpoint_count(const struct fwnode_handle * fwnode,unsigned long flags)1244c87b8fc5SSakari Ailus unsigned int fwnode_graph_get_endpoint_count(const struct fwnode_handle *fwnode,
1245c87b8fc5SSakari Ailus 					     unsigned long flags)
1246c87b8fc5SSakari Ailus {
1247c87b8fc5SSakari Ailus 	struct fwnode_handle *ep;
1248c87b8fc5SSakari Ailus 	unsigned int count = 0;
1249c87b8fc5SSakari Ailus 
1250c87b8fc5SSakari Ailus 	fwnode_graph_for_each_endpoint(fwnode, ep) {
1251c87b8fc5SSakari Ailus 		if (flags & FWNODE_GRAPH_DEVICE_DISABLED ||
1252c87b8fc5SSakari Ailus 		    fwnode_graph_remote_available(ep))
1253c87b8fc5SSakari Ailus 			count++;
1254c87b8fc5SSakari Ailus 	}
12552bd5452dSSakari Ailus 
12562bd5452dSSakari Ailus 	return count;
12572bd5452dSSakari Ailus }
12582bd5452dSSakari Ailus EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_count);
12592bd5452dSSakari Ailus 
12602bd5452dSSakari Ailus /**
12612bd5452dSSakari Ailus  * fwnode_graph_parse_endpoint - parse common endpoint node properties
12622bd5452dSSakari Ailus  * @fwnode: pointer to endpoint fwnode_handle
126337ba983cSSakari Ailus  * @endpoint: pointer to the fwnode endpoint data structure
12642bd5452dSSakari Ailus  *
12652bd5452dSSakari Ailus  * Parse @fwnode representing a graph endpoint node and store the
12662bd5452dSSakari Ailus  * information in @endpoint. The caller must hold a reference to
12672bd5452dSSakari Ailus  * @fwnode.
12683b27d00eSSakari Ailus  */
fwnode_graph_parse_endpoint(const struct fwnode_handle * fwnode,struct fwnode_endpoint * endpoint)12692bd5452dSSakari Ailus int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
12702bd5452dSSakari Ailus 				struct fwnode_endpoint *endpoint)
1271b283f157SSinan Kaya {
1272aade55c8SAndy Shevchenko 	memset(endpoint, 0, sizeof(*endpoint));
1273b283f157SSinan Kaya 
127467dcc26dSAndy Shevchenko 	return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
1275b283f157SSinan Kaya }
1276b283f157SSinan Kaya EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
1277d7cf5590SHeikki Krogerus 
device_get_match_data(const struct device * dev)127823ead33bSAndy Shevchenko const void *device_get_match_data(const struct device *dev)
12797a20917dSBjorn Andersson {
12807a20917dSBjorn Andersson 	return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev);
12817a20917dSBjorn Andersson }
12827a20917dSBjorn Andersson EXPORT_SYMBOL_GPL(device_get_match_data);
1283d7cf5590SHeikki Krogerus 
fwnode_graph_devcon_matches(const struct fwnode_handle * fwnode,const char * con_id,void * data,devcon_match_fn_t match,void ** matches,unsigned int matches_len)1284d7cf5590SHeikki Krogerus static unsigned int fwnode_graph_devcon_matches(const struct fwnode_handle *fwnode,
1285d7cf5590SHeikki Krogerus 						const char *con_id, void *data,
12867a20917dSBjorn Andersson 						devcon_match_fn_t match,
1287d7cf5590SHeikki Krogerus 						void **matches,
1288d7cf5590SHeikki Krogerus 						unsigned int matches_len)
1289d7cf5590SHeikki Krogerus {
12907a20917dSBjorn Andersson 	struct fwnode_handle *node;
12917a20917dSBjorn Andersson 	struct fwnode_handle *ep;
12927a20917dSBjorn Andersson 	unsigned int count = 0;
12937a20917dSBjorn Andersson 	void *ret;
12947a20917dSBjorn Andersson 
1295d7cf5590SHeikki Krogerus 	fwnode_graph_for_each_endpoint(fwnode, ep) {
12964a7f4110SSakari Ailus 		if (matches && count >= matches_len) {
12974a7f4110SSakari Ailus 			fwnode_handle_put(ep);
1298d7cf5590SHeikki Krogerus 			break;
12994a7f4110SSakari Ailus 		}
1300d7cf5590SHeikki Krogerus 
1301d7cf5590SHeikki Krogerus 		node = fwnode_graph_get_remote_port_parent(ep);
1302d7cf5590SHeikki Krogerus 		if (!fwnode_device_is_available(node)) {
1303d7cf5590SHeikki Krogerus 			fwnode_handle_put(node);
13047a20917dSBjorn Andersson 			continue;
13057a20917dSBjorn Andersson 		}
13067a20917dSBjorn Andersson 
1307d7cf5590SHeikki Krogerus 		ret = match(node, con_id, data);
1308d7cf5590SHeikki Krogerus 		fwnode_handle_put(node);
13097a20917dSBjorn Andersson 		if (ret) {
1310d7cf5590SHeikki Krogerus 			if (matches)
1311d7cf5590SHeikki Krogerus 				matches[count] = ret;
131223ead33bSAndy Shevchenko 			count++;
13137a20917dSBjorn Andersson 		}
13147a20917dSBjorn Andersson 	}
13157a20917dSBjorn Andersson 	return count;
13167a20917dSBjorn Andersson }
1317d7cf5590SHeikki Krogerus 
fwnode_devcon_matches(const struct fwnode_handle * fwnode,const char * con_id,void * data,devcon_match_fn_t match,void ** matches,unsigned int matches_len)1318d7cf5590SHeikki Krogerus static unsigned int fwnode_devcon_matches(const struct fwnode_handle *fwnode,
13197a20917dSBjorn Andersson 					  const char *con_id, void *data,
13207a20917dSBjorn Andersson 					  devcon_match_fn_t match,
1321d7cf5590SHeikki Krogerus 					  void **matches,
1322d7cf5590SHeikki Krogerus 					  unsigned int matches_len)
1323d7cf5590SHeikki Krogerus {
13247a20917dSBjorn Andersson 	struct fwnode_handle *node;
13257a20917dSBjorn Andersson 	unsigned int count = 0;
13267a20917dSBjorn Andersson 	unsigned int i;
1327d7cf5590SHeikki Krogerus 	void *ret;
1328d7cf5590SHeikki Krogerus 
1329d7cf5590SHeikki Krogerus 	for (i = 0; ; i++) {
1330d7cf5590SHeikki Krogerus 		if (matches && count >= matches_len)
1331d7cf5590SHeikki Krogerus 			break;
1332d7cf5590SHeikki Krogerus 
13337a20917dSBjorn Andersson 		node = fwnode_find_reference(fwnode, con_id, i);
13347a20917dSBjorn Andersson 		if (IS_ERR(node))
13357a20917dSBjorn Andersson 			break;
13367a20917dSBjorn Andersson 
13377a20917dSBjorn Andersson 		ret = match(node, NULL, data);
1338d7cf5590SHeikki Krogerus 		fwnode_handle_put(node);
1339d7cf5590SHeikki Krogerus 		if (ret) {
13407a20917dSBjorn Andersson 			if (matches)
1341d7cf5590SHeikki Krogerus 				matches[count] = ret;
1342d7cf5590SHeikki Krogerus 			count++;
1343d7cf5590SHeikki Krogerus 		}
1344d7cf5590SHeikki Krogerus 	}
1345d7cf5590SHeikki Krogerus 
1346d7cf5590SHeikki Krogerus 	return count;
1347d7cf5590SHeikki Krogerus }
1348d7cf5590SHeikki Krogerus 
1349d7cf5590SHeikki Krogerus /**
1350d7cf5590SHeikki Krogerus  * fwnode_connection_find_match - Find connection from a device node
1351d7cf5590SHeikki Krogerus  * @fwnode: Device node with the connection
1352d7cf5590SHeikki Krogerus  * @con_id: Identifier for the connection
1353d7cf5590SHeikki Krogerus  * @data: Data for the match function
135423ead33bSAndy Shevchenko  * @match: Function to check and convert the connection description
1355d7cf5590SHeikki Krogerus  *
1356d7cf5590SHeikki Krogerus  * Find a connection with unique identifier @con_id between @fwnode and another
1357d7cf5590SHeikki Krogerus  * device node. @match will be used to convert the connection description to
1358bcd6a517SBjorn Andersson  * data the caller is expecting to be returned.
1359d7cf5590SHeikki Krogerus  */
fwnode_connection_find_match(const struct fwnode_handle * fwnode,const char * con_id,void * data,devcon_match_fn_t match)1360d7cf5590SHeikki Krogerus void *fwnode_connection_find_match(const struct fwnode_handle *fwnode,
1361d7cf5590SHeikki Krogerus 				   const char *con_id, void *data,
1362d7cf5590SHeikki Krogerus 				   devcon_match_fn_t match)
1363d7cf5590SHeikki Krogerus {
1364bcd6a517SBjorn Andersson 	unsigned int count;
1365bcd6a517SBjorn Andersson 	void *ret;
1366d7cf5590SHeikki Krogerus 
1367d7cf5590SHeikki Krogerus 	if (!fwnode || !match)
1368bcd6a517SBjorn Andersson 		return NULL;
1369bcd6a517SBjorn Andersson 
1370d7cf5590SHeikki Krogerus 	count = fwnode_graph_devcon_matches(fwnode, con_id, data, match, &ret, 1);
1371d7cf5590SHeikki Krogerus 	if (count)
13727a20917dSBjorn Andersson 		return ret;
13737a20917dSBjorn Andersson 
13747a20917dSBjorn Andersson 	count = fwnode_devcon_matches(fwnode, con_id, data, match, &ret, 1);
13757a20917dSBjorn Andersson 	return count ? ret : NULL;
13767a20917dSBjorn Andersson }
13777a20917dSBjorn Andersson EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
13787a20917dSBjorn Andersson 
13797a20917dSBjorn Andersson /**
13807a20917dSBjorn Andersson  * fwnode_connection_find_matches - Find connections from a device node
13817a20917dSBjorn Andersson  * @fwnode: Device node with the connection
13827a20917dSBjorn Andersson  * @con_id: Identifier for the connection
13837a20917dSBjorn Andersson  * @data: Data for the match function
13847a20917dSBjorn Andersson  * @match: Function to check and convert the connection description
13857a20917dSBjorn Andersson  * @matches: (Optional) array of pointers to fill with matches
1386295209caSAndy Shevchenko  * @matches_len: Length of @matches
1387295209caSAndy Shevchenko  *
13887a20917dSBjorn Andersson  * Find up to @matches_len connections with unique identifier @con_id between
13897a20917dSBjorn Andersson  * @fwnode and other device nodes. @match will be used to convert the
13907a20917dSBjorn Andersson  * connection description to data the caller is expecting to be returned
13917a20917dSBjorn Andersson  * through the @matches array.
139223ead33bSAndy Shevchenko  *
13937a20917dSBjorn Andersson  * If @matches is %NULL @matches_len is ignored and the total number of resolved
13947a20917dSBjorn Andersson  * matches is returned.
13957a20917dSBjorn Andersson  *
13967a20917dSBjorn Andersson  * Return: Number of matches resolved, or negative errno.
13977a20917dSBjorn Andersson  */
fwnode_connection_find_matches(const struct fwnode_handle * fwnode,const char * con_id,void * data,devcon_match_fn_t match,void ** matches,unsigned int matches_len)13987a20917dSBjorn Andersson int fwnode_connection_find_matches(const struct fwnode_handle *fwnode,
13997a20917dSBjorn Andersson 				   const char *con_id, void *data,
14007a20917dSBjorn Andersson 				   devcon_match_fn_t match,
14017a20917dSBjorn Andersson 				   void **matches, unsigned int matches_len)
14027a20917dSBjorn Andersson {
14037a20917dSBjorn Andersson 	unsigned int count_graph;
14047a20917dSBjorn Andersson 	unsigned int count_ref;
14057a20917dSBjorn Andersson 
14067a20917dSBjorn Andersson 	if (!fwnode || !match)
14077a20917dSBjorn Andersson 		return -EINVAL;
14087a20917dSBjorn Andersson 
14097a20917dSBjorn Andersson 	count_graph = fwnode_graph_devcon_matches(fwnode, con_id, data, match,
14107a20917dSBjorn Andersson 						  matches, matches_len);
14117a20917dSBjorn Andersson 
14127a20917dSBjorn Andersson 	if (matches) {
14137a20917dSBjorn Andersson 		matches += count_graph;
14147a20917dSBjorn Andersson 		matches_len -= count_graph;
14157a20917dSBjorn Andersson 	}
14167a20917dSBjorn Andersson 
1417 	count_ref = fwnode_devcon_matches(fwnode, con_id, data, match,
1418 					  matches, matches_len);
1419 
1420 	return count_graph + count_ref;
1421 }
1422 EXPORT_SYMBOL_GPL(fwnode_connection_find_matches);
1423