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