1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0+
297e873e5SStephen Rothwell /*
397e873e5SStephen Rothwell * Procedures for creating, accessing and interpreting the device tree.
497e873e5SStephen Rothwell *
597e873e5SStephen Rothwell * Paul Mackerras August 1996.
697e873e5SStephen Rothwell * Copyright (C) 1996-2005 Paul Mackerras.
797e873e5SStephen Rothwell *
897e873e5SStephen Rothwell * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
997e873e5SStephen Rothwell * {engebret|bergner}@us.ibm.com
1097e873e5SStephen Rothwell *
1197e873e5SStephen Rothwell * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
1297e873e5SStephen Rothwell *
13e91edcf5SGrant Likely * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
14e91edcf5SGrant Likely * Grant Likely.
1597e873e5SStephen Rothwell */
16606ad42aSRob Herring
17606ad42aSRob Herring #define pr_fmt(fmt) "OF: " fmt
18606ad42aSRob Herring
193482f2c5SGrant Likely #include <linux/console.h>
20611cad72SShawn Guo #include <linux/ctype.h>
21183912d3SSudeep KarkadaNagesha #include <linux/cpu.h>
2297e873e5SStephen Rothwell #include <linux/module.h>
2397e873e5SStephen Rothwell #include <linux/of.h>
245fa23530SSudeep Holla #include <linux/of_device.h>
25fd9fdb78SPhilipp Zabel #include <linux/of_graph.h>
26581b605aSStephen Rothwell #include <linux/spinlock.h>
275a0e3ad6STejun Heo #include <linux/slab.h>
2875b57ecfSGrant Likely #include <linux/string.h>
29a9f2f63aSJeremy Kerr #include <linux/proc_fs.h>
30581b605aSStephen Rothwell
31ced4eec9SStepan Moskovchenko #include "of_private.h"
32611cad72SShawn Guo
33ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup);
34611cad72SShawn Guo
355063e25aSGrant Likely struct device_node *of_root;
365063e25aSGrant Likely EXPORT_SYMBOL(of_root);
37fc0bdae4SGrant Likely struct device_node *of_chosen;
38ec7cc3f7SArnd Bergmann EXPORT_SYMBOL(of_chosen);
39611cad72SShawn Guo struct device_node *of_aliases;
40a752ee56SGrant Likely struct device_node *of_stdout;
417914a7c5SLeif Lindholm static const char *of_stdout_options;
42611cad72SShawn Guo
438a2b22a2SGrant Likely struct kset *of_kset;
4475b57ecfSGrant Likely
4575b57ecfSGrant Likely /*
468a2b22a2SGrant Likely * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
478a2b22a2SGrant Likely * This mutex must be held whenever modifications are being made to the
488a2b22a2SGrant Likely * device tree. The of_{attach,detach}_node() and
498a2b22a2SGrant Likely * of_{add,remove,update}_property() helpers make sure this happens.
5075b57ecfSGrant Likely */
51c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex);
521ef4d424SStephen Rothwell
535063e25aSGrant Likely /* use when traversing tree through the child, sibling,
54581b605aSStephen Rothwell * or parent members of struct device_node.
55581b605aSStephen Rothwell */
56d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock);
5797e873e5SStephen Rothwell
of_node_name_eq(const struct device_node * np,const char * name)58f42b0e18SRob Herring bool of_node_name_eq(const struct device_node *np, const char *name)
59f42b0e18SRob Herring {
60f42b0e18SRob Herring const char *node_name;
61f42b0e18SRob Herring size_t len;
62f42b0e18SRob Herring
63f42b0e18SRob Herring if (!np)
64f42b0e18SRob Herring return false;
65f42b0e18SRob Herring
66f42b0e18SRob Herring node_name = kbasename(np->full_name);
67f42b0e18SRob Herring len = strchrnul(node_name, '@') - node_name;
68f42b0e18SRob Herring
69f42b0e18SRob Herring return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
70f42b0e18SRob Herring }
71173ee396SRob Herring EXPORT_SYMBOL(of_node_name_eq);
72f42b0e18SRob Herring
of_node_name_prefix(const struct device_node * np,const char * prefix)73f42b0e18SRob Herring bool of_node_name_prefix(const struct device_node *np, const char *prefix)
74f42b0e18SRob Herring {
75f42b0e18SRob Herring if (!np)
76f42b0e18SRob Herring return false;
77f42b0e18SRob Herring
78f42b0e18SRob Herring return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;
79f42b0e18SRob Herring }
80173ee396SRob Herring EXPORT_SYMBOL(of_node_name_prefix);
81f42b0e18SRob Herring
__of_node_is_type(const struct device_node * np,const char * type)82e8b1dee2SRob Herring static bool __of_node_is_type(const struct device_node *np, const char *type)
83e8b1dee2SRob Herring {
84e8b1dee2SRob Herring const char *match = __of_get_property(np, "device_type", NULL);
85e8b1dee2SRob Herring
86e8b1dee2SRob Herring return np && match && type && !strcmp(match, type);
87e8b1dee2SRob Herring }
88e8b1dee2SRob Herring
of_bus_n_addr_cells(struct device_node * np)89b68ac8dcSRobin Murphy int of_bus_n_addr_cells(struct device_node *np)
9097e873e5SStephen Rothwell {
918832963dSSergei Shtylyov u32 cells;
9297e873e5SStephen Rothwell
93b68ac8dcSRobin Murphy for (; np; np = np->parent)
948832963dSSergei Shtylyov if (!of_property_read_u32(np, "#address-cells", &cells))
958832963dSSergei Shtylyov return cells;
96b68ac8dcSRobin Murphy
9797e873e5SStephen Rothwell /* No #address-cells property for the root node */
9897e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
9997e873e5SStephen Rothwell }
100b68ac8dcSRobin Murphy
of_n_addr_cells(struct device_node * np)101b68ac8dcSRobin Murphy int of_n_addr_cells(struct device_node *np)
102b68ac8dcSRobin Murphy {
103b68ac8dcSRobin Murphy if (np->parent)
104b68ac8dcSRobin Murphy np = np->parent;
105b68ac8dcSRobin Murphy
106b68ac8dcSRobin Murphy return of_bus_n_addr_cells(np);
107b68ac8dcSRobin Murphy }
10897e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
10997e873e5SStephen Rothwell
of_bus_n_size_cells(struct device_node * np)110b68ac8dcSRobin Murphy int of_bus_n_size_cells(struct device_node *np)
11197e873e5SStephen Rothwell {
1128832963dSSergei Shtylyov u32 cells;
11397e873e5SStephen Rothwell
114b68ac8dcSRobin Murphy for (; np; np = np->parent)
1158832963dSSergei Shtylyov if (!of_property_read_u32(np, "#size-cells", &cells))
1168832963dSSergei Shtylyov return cells;
117b68ac8dcSRobin Murphy
11897e873e5SStephen Rothwell /* No #size-cells property for the root node */
11997e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
12097e873e5SStephen Rothwell }
121b68ac8dcSRobin Murphy
of_n_size_cells(struct device_node * np)122b68ac8dcSRobin Murphy int of_n_size_cells(struct device_node *np)
123b68ac8dcSRobin Murphy {
124b68ac8dcSRobin Murphy if (np->parent)
125b68ac8dcSRobin Murphy np = np->parent;
126b68ac8dcSRobin Murphy
127b68ac8dcSRobin Murphy return of_bus_n_size_cells(np);
128b68ac8dcSRobin Murphy }
12997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
13097e873e5SStephen Rothwell
1310c3f061cSRob Herring #ifdef CONFIG_NUMA
of_node_to_nid(struct device_node * np)1320c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np)
1330c3f061cSRob Herring {
134c8fff7bcSKonstantin Khlebnikov return NUMA_NO_NODE;
1350c3f061cSRob Herring }
1360c3f061cSRob Herring #endif
1370c3f061cSRob Herring
13890dc0d1cSRob Herring #define OF_PHANDLE_CACHE_BITS 7
13990dc0d1cSRob Herring #define OF_PHANDLE_CACHE_SZ BIT(OF_PHANDLE_CACHE_BITS)
140b8a9ac1aSFrank Rowand
14190dc0d1cSRob Herring static struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
14290dc0d1cSRob Herring
of_phandle_cache_hash(phandle handle)14390dc0d1cSRob Herring static u32 of_phandle_cache_hash(phandle handle)
14490dc0d1cSRob Herring {
14590dc0d1cSRob Herring return hash_32(handle, OF_PHANDLE_CACHE_BITS);
14690dc0d1cSRob Herring }
147b8a9ac1aSFrank Rowand
148b8a9ac1aSFrank Rowand /*
149b8a9ac1aSFrank Rowand * Caller must hold devtree_lock.
150b8a9ac1aSFrank Rowand */
__of_phandle_cache_inv_entry(phandle handle)15190dc0d1cSRob Herring void __of_phandle_cache_inv_entry(phandle handle)
152b8a9ac1aSFrank Rowand {
15390dc0d1cSRob Herring u32 handle_hash;
1545801169aSFrank Rowand struct device_node *np;
1555801169aSFrank Rowand
1565801169aSFrank Rowand if (!handle)
1575801169aSFrank Rowand return;
1585801169aSFrank Rowand
15990dc0d1cSRob Herring handle_hash = of_phandle_cache_hash(handle);
1605801169aSFrank Rowand
16190dc0d1cSRob Herring np = phandle_cache[handle_hash];
16290dc0d1cSRob Herring if (np && handle == np->phandle)
16390dc0d1cSRob Herring phandle_cache[handle_hash] = NULL;
1640b3ce78eSFrank Rowand }
1650b3ce78eSFrank Rowand
of_core_init(void)166194ec936SSudeep Holla void __init of_core_init(void)
16775b57ecfSGrant Likely {
16875b57ecfSGrant Likely struct device_node *np;
16975b57ecfSGrant Likely
17073aca58bSRob Herring of_platform_register_reconfig_notifier();
1710b3ce78eSFrank Rowand
17275b57ecfSGrant Likely /* Create the kset, and register existing nodes */
173c05aba2bSPantelis Antoniou mutex_lock(&of_mutex);
17475b57ecfSGrant Likely of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
17575b57ecfSGrant Likely if (!of_kset) {
176c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex);
177606ad42aSRob Herring pr_err("failed to register existing nodes\n");
178194ec936SSudeep Holla return;
17975b57ecfSGrant Likely }
18090dc0d1cSRob Herring for_each_of_allnodes(np) {
1818a2b22a2SGrant Likely __of_attach_node_sysfs(np);
18290dc0d1cSRob Herring if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
18390dc0d1cSRob Herring phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
18490dc0d1cSRob Herring }
185c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex);
18675b57ecfSGrant Likely
1878357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */
1885063e25aSGrant Likely if (of_root)
18975b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
19075b57ecfSGrant Likely }
19175b57ecfSGrant Likely
__of_find_property(const struct device_node * np,const char * name,int * lenp)19228d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np,
19328d0e36bSThomas Gleixner const char *name, int *lenp)
194581b605aSStephen Rothwell {
195581b605aSStephen Rothwell struct property *pp;
196581b605aSStephen Rothwell
19764e4566fSTimur Tabi if (!np)
19864e4566fSTimur Tabi return NULL;
19964e4566fSTimur Tabi
200a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) {
201581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) {
202a3a7cab1SSachin Kamat if (lenp)
203581b605aSStephen Rothwell *lenp = pp->length;
204581b605aSStephen Rothwell break;
205581b605aSStephen Rothwell }
206581b605aSStephen Rothwell }
20728d0e36bSThomas Gleixner
20828d0e36bSThomas Gleixner return pp;
20928d0e36bSThomas Gleixner }
21028d0e36bSThomas Gleixner
of_find_property(const struct device_node * np,const char * name,int * lenp)21128d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np,
21228d0e36bSThomas Gleixner const char *name,
21328d0e36bSThomas Gleixner int *lenp)
21428d0e36bSThomas Gleixner {
21528d0e36bSThomas Gleixner struct property *pp;
216d6d3c4e6SThomas Gleixner unsigned long flags;
21728d0e36bSThomas Gleixner
218d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
21928d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp);
220d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
221581b605aSStephen Rothwell
222581b605aSStephen Rothwell return pp;
223581b605aSStephen Rothwell }
224581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
225581b605aSStephen Rothwell
__of_find_all_nodes(struct device_node * prev)2265063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev)
2275063e25aSGrant Likely {
2285063e25aSGrant Likely struct device_node *np;
2295063e25aSGrant Likely if (!prev) {
2305063e25aSGrant Likely np = of_root;
2315063e25aSGrant Likely } else if (prev->child) {
2325063e25aSGrant Likely np = prev->child;
2335063e25aSGrant Likely } else {
2345063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */
2355063e25aSGrant Likely np = prev;
2365063e25aSGrant Likely while (np->parent && !np->sibling)
2375063e25aSGrant Likely np = np->parent;
2385063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */
2395063e25aSGrant Likely }
2405063e25aSGrant Likely return np;
2415063e25aSGrant Likely }
2425063e25aSGrant Likely
243e91edcf5SGrant Likely /**
244e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list
245e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration
246e91edcf5SGrant Likely * of_node_put() will be called on it
247e91edcf5SGrant Likely *
2488c8239c2SRob Herring * Return: A node pointer with refcount incremented, use
249e91edcf5SGrant Likely * of_node_put() on it when done.
250e91edcf5SGrant Likely */
of_find_all_nodes(struct device_node * prev)251e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
252e91edcf5SGrant Likely {
253e91edcf5SGrant Likely struct device_node *np;
254d25d8694SBenjamin Herrenschmidt unsigned long flags;
255e91edcf5SGrant Likely
256d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags);
2575063e25aSGrant Likely np = __of_find_all_nodes(prev);
2585063e25aSGrant Likely of_node_get(np);
259e91edcf5SGrant Likely of_node_put(prev);
260d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags);
261e91edcf5SGrant Likely return np;
262e91edcf5SGrant Likely }
263e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
264e91edcf5SGrant Likely
26597e873e5SStephen Rothwell /*
26697e873e5SStephen Rothwell * Find a property with a given name for a given node
26797e873e5SStephen Rothwell * and return the value.
26897e873e5SStephen Rothwell */
__of_get_property(const struct device_node * np,const char * name,int * lenp)269a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np,
27028d0e36bSThomas Gleixner const char *name, int *lenp)
27128d0e36bSThomas Gleixner {
27228d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp);
27328d0e36bSThomas Gleixner
27428d0e36bSThomas Gleixner return pp ? pp->value : NULL;
27528d0e36bSThomas Gleixner }
27628d0e36bSThomas Gleixner
27728d0e36bSThomas Gleixner /*
27828d0e36bSThomas Gleixner * Find a property with a given name for a given node
27928d0e36bSThomas Gleixner * and return the value.
28028d0e36bSThomas Gleixner */
of_get_property(const struct device_node * np,const char * name,int * lenp)28197e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
28297e873e5SStephen Rothwell int *lenp)
28397e873e5SStephen Rothwell {
28497e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp);
28597e873e5SStephen Rothwell
28697e873e5SStephen Rothwell return pp ? pp->value : NULL;
28797e873e5SStephen Rothwell }
28897e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
2890081cbc3SStephen Rothwell
290795e92ecSRob Herring /**
291215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints
292215a14cfSKevin Hao * @device: pointer to node
293215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match
294215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match
295215a14cfSKevin Hao * @name: required node name, NULL or "" for any match
296215a14cfSKevin Hao *
297215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the
298215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by
299215a14cfSKevin Hao * passing NULL or an empty string as the constraint.
300215a14cfSKevin Hao *
301215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return
302215a14cfSKevin Hao * value is a relative score with larger values indicating better
303215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value
304215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching
305215a14cfSKevin Hao * name. Practically speaking, this results in the following priority
306215a14cfSKevin Hao * order for matches:
307215a14cfSKevin Hao *
308215a14cfSKevin Hao * 1. specific compatible && type && name
309215a14cfSKevin Hao * 2. specific compatible && type
310215a14cfSKevin Hao * 3. specific compatible && name
311215a14cfSKevin Hao * 4. specific compatible
312215a14cfSKevin Hao * 5. general compatible && type && name
313215a14cfSKevin Hao * 6. general compatible && type
314215a14cfSKevin Hao * 7. general compatible && name
315215a14cfSKevin Hao * 8. general compatible
316215a14cfSKevin Hao * 9. type && name
317215a14cfSKevin Hao * 10. type
318215a14cfSKevin Hao * 11. name
3190081cbc3SStephen Rothwell */
__of_device_is_compatible(const struct device_node * device,const char * compat,const char * type,const char * name)32028d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device,
321215a14cfSKevin Hao const char *compat, const char *type, const char *name)
3220081cbc3SStephen Rothwell {
323215a14cfSKevin Hao struct property *prop;
3240081cbc3SStephen Rothwell const char *cp;
325215a14cfSKevin Hao int index = 0, score = 0;
3260081cbc3SStephen Rothwell
327215a14cfSKevin Hao /* Compatible match has highest priority */
328215a14cfSKevin Hao if (compat && compat[0]) {
329215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL);
330215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp;
331215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) {
332215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
333215a14cfSKevin Hao score = INT_MAX/2 - (index << 2);
334215a14cfSKevin Hao break;
335215a14cfSKevin Hao }
336215a14cfSKevin Hao }
337215a14cfSKevin Hao if (!score)
3380081cbc3SStephen Rothwell return 0;
3390081cbc3SStephen Rothwell }
3400081cbc3SStephen Rothwell
341215a14cfSKevin Hao /* Matching type is better than matching name */
342215a14cfSKevin Hao if (type && type[0]) {
343e8b1dee2SRob Herring if (!__of_node_is_type(device, type))
3440081cbc3SStephen Rothwell return 0;
345215a14cfSKevin Hao score += 2;
346215a14cfSKevin Hao }
347215a14cfSKevin Hao
348215a14cfSKevin Hao /* Matching name is a bit better than not */
349215a14cfSKevin Hao if (name && name[0]) {
350b3e46d1aSRob Herring if (!of_node_name_eq(device, name))
351215a14cfSKevin Hao return 0;
352215a14cfSKevin Hao score++;
353215a14cfSKevin Hao }
354215a14cfSKevin Hao
355215a14cfSKevin Hao return score;
3560081cbc3SStephen Rothwell }
35728d0e36bSThomas Gleixner
35828d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in
35928d0e36bSThomas Gleixner * the device's "compatible" property
36028d0e36bSThomas Gleixner */
of_device_is_compatible(const struct device_node * device,const char * compat)36128d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device,
36228d0e36bSThomas Gleixner const char *compat)
36328d0e36bSThomas Gleixner {
364d6d3c4e6SThomas Gleixner unsigned long flags;
36528d0e36bSThomas Gleixner int res;
36628d0e36bSThomas Gleixner
367d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
368215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL);
369d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
37028d0e36bSThomas Gleixner return res;
37128d0e36bSThomas Gleixner }
3720081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
373e679c5f4SStephen Rothwell
374b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in
375b9c13fe3SBenjamin Herrenschmidt * a NULL terminated array of strings. Returns the best match
376b9c13fe3SBenjamin Herrenschmidt * score or 0.
377b9c13fe3SBenjamin Herrenschmidt */
of_device_compatible_match(const struct device_node * device,const char * const * compat)37888269151SDmitry Torokhov int of_device_compatible_match(const struct device_node *device,
379b9c13fe3SBenjamin Herrenschmidt const char *const *compat)
380b9c13fe3SBenjamin Herrenschmidt {
381b9c13fe3SBenjamin Herrenschmidt unsigned int tmp, score = 0;
382b9c13fe3SBenjamin Herrenschmidt
383b9c13fe3SBenjamin Herrenschmidt if (!compat)
384b9c13fe3SBenjamin Herrenschmidt return 0;
385b9c13fe3SBenjamin Herrenschmidt
386b9c13fe3SBenjamin Herrenschmidt while (*compat) {
387b9c13fe3SBenjamin Herrenschmidt tmp = of_device_is_compatible(device, *compat);
388b9c13fe3SBenjamin Herrenschmidt if (tmp > score)
389b9c13fe3SBenjamin Herrenschmidt score = tmp;
390b9c13fe3SBenjamin Herrenschmidt compat++;
391b9c13fe3SBenjamin Herrenschmidt }
392b9c13fe3SBenjamin Herrenschmidt
393b9c13fe3SBenjamin Herrenschmidt return score;
394b9c13fe3SBenjamin Herrenschmidt }
395df55e317SVladimir Oltean EXPORT_SYMBOL_GPL(of_device_compatible_match);
396b9c13fe3SBenjamin Herrenschmidt
397e679c5f4SStephen Rothwell /**
39871a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value
3991f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property.
4001f43cfb9SGrant Likely *
4018c8239c2SRob Herring * Return: A positive integer if the root node has the given value in its
4021f43cfb9SGrant Likely * compatible property.
4031f43cfb9SGrant Likely */
of_machine_is_compatible(const char * compat)40471a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
4051f43cfb9SGrant Likely {
4061f43cfb9SGrant Likely struct device_node *root;
4071f43cfb9SGrant Likely int rc = 0;
4081f43cfb9SGrant Likely
4091f43cfb9SGrant Likely root = of_find_node_by_path("/");
4101f43cfb9SGrant Likely if (root) {
4111f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat);
4121f43cfb9SGrant Likely of_node_put(root);
4131f43cfb9SGrant Likely }
4141f43cfb9SGrant Likely return rc;
4151f43cfb9SGrant Likely }
41671a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
4171f43cfb9SGrant Likely
4181f43cfb9SGrant Likely /**
419c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use
420834d97d4SJosh Boyer *
421c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held
422834d97d4SJosh Boyer *
4238c8239c2SRob Herring * Return: True if the status property is absent or set to "okay" or "ok",
42453a4ab96SKevin Cernekee * false otherwise
425834d97d4SJosh Boyer */
__of_device_is_available(const struct device_node * device)42653a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device)
427834d97d4SJosh Boyer {
428834d97d4SJosh Boyer const char *status;
429834d97d4SJosh Boyer int statlen;
430834d97d4SJosh Boyer
43142ccd781SXiubo Li if (!device)
43253a4ab96SKevin Cernekee return false;
43342ccd781SXiubo Li
434c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen);
435834d97d4SJosh Boyer if (status == NULL)
43653a4ab96SKevin Cernekee return true;
437834d97d4SJosh Boyer
438834d97d4SJosh Boyer if (statlen > 0) {
439834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok"))
44053a4ab96SKevin Cernekee return true;
441834d97d4SJosh Boyer }
442834d97d4SJosh Boyer
44353a4ab96SKevin Cernekee return false;
444834d97d4SJosh Boyer }
445c31a0c05SStephen Warren
446c31a0c05SStephen Warren /**
447c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use
448c31a0c05SStephen Warren *
449c31a0c05SStephen Warren * @device: Node to check for availability
450c31a0c05SStephen Warren *
4518c8239c2SRob Herring * Return: True if the status property is absent or set to "okay" or "ok",
45253a4ab96SKevin Cernekee * false otherwise
453c31a0c05SStephen Warren */
of_device_is_available(const struct device_node * device)45453a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device)
455c31a0c05SStephen Warren {
456c31a0c05SStephen Warren unsigned long flags;
45753a4ab96SKevin Cernekee bool res;
458c31a0c05SStephen Warren
459c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags);
460c31a0c05SStephen Warren res = __of_device_is_available(device);
461c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags);
462c31a0c05SStephen Warren return res;
463c31a0c05SStephen Warren
464c31a0c05SStephen Warren }
465834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
466834d97d4SJosh Boyer
467834d97d4SJosh Boyer /**
4684fdd0736SMatthias Schiffer * __of_device_is_fail - check if a device has status "fail" or "fail-..."
4694fdd0736SMatthias Schiffer *
4704fdd0736SMatthias Schiffer * @device: Node to check status for, with locks already held
4714fdd0736SMatthias Schiffer *
4724fdd0736SMatthias Schiffer * Return: True if the status property is set to "fail" or "fail-..." (for any
4734fdd0736SMatthias Schiffer * error code suffix), false otherwise
4744fdd0736SMatthias Schiffer */
__of_device_is_fail(const struct device_node * device)4754fdd0736SMatthias Schiffer static bool __of_device_is_fail(const struct device_node *device)
4764fdd0736SMatthias Schiffer {
4774fdd0736SMatthias Schiffer const char *status;
4784fdd0736SMatthias Schiffer
4794fdd0736SMatthias Schiffer if (!device)
4804fdd0736SMatthias Schiffer return false;
4814fdd0736SMatthias Schiffer
4824fdd0736SMatthias Schiffer status = __of_get_property(device, "status", NULL);
4834fdd0736SMatthias Schiffer if (status == NULL)
4844fdd0736SMatthias Schiffer return false;
4854fdd0736SMatthias Schiffer
4864fdd0736SMatthias Schiffer return !strcmp(status, "fail") || !strncmp(status, "fail-", 5);
4874fdd0736SMatthias Schiffer }
4884fdd0736SMatthias Schiffer
4894fdd0736SMatthias Schiffer /**
49037786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers
49137786c7fSKevin Cernekee *
49237786c7fSKevin Cernekee * @device: Node to check for endianness
49337786c7fSKevin Cernekee *
4948c8239c2SRob Herring * Return: True if the device has a "big-endian" property, or if the kernel
49537786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property.
49637786c7fSKevin Cernekee * Returns false otherwise.
49737786c7fSKevin Cernekee *
49837786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if
49937786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise.
50037786c7fSKevin Cernekee */
of_device_is_big_endian(const struct device_node * device)50137786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device)
50237786c7fSKevin Cernekee {
50337786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian"))
50437786c7fSKevin Cernekee return true;
50537786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
50637786c7fSKevin Cernekee of_property_read_bool(device, "native-endian"))
50737786c7fSKevin Cernekee return true;
50837786c7fSKevin Cernekee return false;
50937786c7fSKevin Cernekee }
51037786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian);
51137786c7fSKevin Cernekee
51237786c7fSKevin Cernekee /**
513e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any
514e679c5f4SStephen Rothwell * @node: Node to get parent
515e679c5f4SStephen Rothwell *
51662f026f0SRob Herring * Return: A node pointer with refcount incremented, use
517e679c5f4SStephen Rothwell * of_node_put() on it when done.
518e679c5f4SStephen Rothwell */
of_get_parent(const struct device_node * node)519e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
520e679c5f4SStephen Rothwell {
521e679c5f4SStephen Rothwell struct device_node *np;
522d6d3c4e6SThomas Gleixner unsigned long flags;
523e679c5f4SStephen Rothwell
524e679c5f4SStephen Rothwell if (!node)
525e679c5f4SStephen Rothwell return NULL;
526e679c5f4SStephen Rothwell
527d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
528e679c5f4SStephen Rothwell np = of_node_get(node->parent);
529d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
530e679c5f4SStephen Rothwell return np;
531e679c5f4SStephen Rothwell }
532e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
533d1cd355aSStephen Rothwell
534d1cd355aSStephen Rothwell /**
535f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent
536f4eb0107SMichael Ellerman * @node: Node to get parent of
537f4eb0107SMichael Ellerman *
538f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the
539f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating
540f4eb0107SMichael Ellerman * through a node's parents.
541f4eb0107SMichael Ellerman *
54262f026f0SRob Herring * Return: A node pointer with refcount incremented, use
543f4eb0107SMichael Ellerman * of_node_put() on it when done.
544f4eb0107SMichael Ellerman */
of_get_next_parent(struct device_node * node)545f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
546f4eb0107SMichael Ellerman {
547f4eb0107SMichael Ellerman struct device_node *parent;
548d6d3c4e6SThomas Gleixner unsigned long flags;
549f4eb0107SMichael Ellerman
550f4eb0107SMichael Ellerman if (!node)
551f4eb0107SMichael Ellerman return NULL;
552f4eb0107SMichael Ellerman
553d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
554f4eb0107SMichael Ellerman parent = of_node_get(node->parent);
555f4eb0107SMichael Ellerman of_node_put(node);
556d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
557f4eb0107SMichael Ellerman return parent;
558f4eb0107SMichael Ellerman }
5596695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent);
560f4eb0107SMichael Ellerman
__of_get_next_child(const struct device_node * node,struct device_node * prev)5610d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node,
5620d0e02d6SGrant Likely struct device_node *prev)
5630d0e02d6SGrant Likely {
5640d0e02d6SGrant Likely struct device_node *next;
5650d0e02d6SGrant Likely
56643cb4367SFlorian Fainelli if (!node)
56743cb4367SFlorian Fainelli return NULL;
56843cb4367SFlorian Fainelli
5690d0e02d6SGrant Likely next = prev ? prev->sibling : node->child;
570ace1c4b5S권오훈 of_node_get(next);
5710d0e02d6SGrant Likely of_node_put(prev);
5720d0e02d6SGrant Likely return next;
5730d0e02d6SGrant Likely }
5740d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \
5750d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \
5760d0e02d6SGrant Likely child = __of_get_next_child(parent, child))
5770d0e02d6SGrant Likely
578f4eb0107SMichael Ellerman /**
579d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs
580d1cd355aSStephen Rothwell * @node: parent node
581d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first
582d1cd355aSStephen Rothwell *
58362f026f0SRob Herring * Return: A node pointer with refcount incremented, use of_node_put() on
58464808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the
58564808273SBaruch Siach * refcount of prev.
586d1cd355aSStephen Rothwell */
of_get_next_child(const struct device_node * node,struct device_node * prev)587d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
588d1cd355aSStephen Rothwell struct device_node *prev)
589d1cd355aSStephen Rothwell {
590d1cd355aSStephen Rothwell struct device_node *next;
591d6d3c4e6SThomas Gleixner unsigned long flags;
592d1cd355aSStephen Rothwell
593d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
5940d0e02d6SGrant Likely next = __of_get_next_child(node, prev);
595d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
596d1cd355aSStephen Rothwell return next;
597d1cd355aSStephen Rothwell }
598d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
5991ef4d424SStephen Rothwell
6001ef4d424SStephen Rothwell /**
6013296193dSTimur Tabi * of_get_next_available_child - Find the next available child node
6023296193dSTimur Tabi * @node: parent node
6033296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first
6043296193dSTimur Tabi *
6053296193dSTimur Tabi * This function is like of_get_next_child(), except that it
6063296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled").
6073296193dSTimur Tabi */
of_get_next_available_child(const struct device_node * node,struct device_node * prev)6083296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node,
6093296193dSTimur Tabi struct device_node *prev)
6103296193dSTimur Tabi {
6113296193dSTimur Tabi struct device_node *next;
612d25d8694SBenjamin Herrenschmidt unsigned long flags;
6133296193dSTimur Tabi
61443cb4367SFlorian Fainelli if (!node)
61543cb4367SFlorian Fainelli return NULL;
61643cb4367SFlorian Fainelli
617d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags);
6183296193dSTimur Tabi next = prev ? prev->sibling : node->child;
6193296193dSTimur Tabi for (; next; next = next->sibling) {
620c31a0c05SStephen Warren if (!__of_device_is_available(next))
6213296193dSTimur Tabi continue;
6223296193dSTimur Tabi if (of_node_get(next))
6233296193dSTimur Tabi break;
6243296193dSTimur Tabi }
6253296193dSTimur Tabi of_node_put(prev);
626d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags);
6273296193dSTimur Tabi return next;
6283296193dSTimur Tabi }
6293296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child);
6303296193dSTimur Tabi
6313296193dSTimur Tabi /**
632f1f207e4SRob Herring * of_get_next_cpu_node - Iterate on cpu nodes
633f1f207e4SRob Herring * @prev: previous child of the /cpus node, or NULL to get first
634f1f207e4SRob Herring *
6354fdd0736SMatthias Schiffer * Unusable CPUs (those with the status property set to "fail" or "fail-...")
6364fdd0736SMatthias Schiffer * will be skipped.
6374fdd0736SMatthias Schiffer *
63862f026f0SRob Herring * Return: A cpu node pointer with refcount incremented, use of_node_put()
639f1f207e4SRob Herring * on it when done. Returns NULL when prev is the last child. Decrements
640f1f207e4SRob Herring * the refcount of prev.
641f1f207e4SRob Herring */
of_get_next_cpu_node(struct device_node * prev)642f1f207e4SRob Herring struct device_node *of_get_next_cpu_node(struct device_node *prev)
643f1f207e4SRob Herring {
644f1f207e4SRob Herring struct device_node *next = NULL;
645f1f207e4SRob Herring unsigned long flags;
646f1f207e4SRob Herring struct device_node *node;
647f1f207e4SRob Herring
648f1f207e4SRob Herring if (!prev)
649f1f207e4SRob Herring node = of_find_node_by_path("/cpus");
650f1f207e4SRob Herring
651f1f207e4SRob Herring raw_spin_lock_irqsave(&devtree_lock, flags);
652f1f207e4SRob Herring if (prev)
653f1f207e4SRob Herring next = prev->sibling;
654f1f207e4SRob Herring else if (node) {
655f1f207e4SRob Herring next = node->child;
656f1f207e4SRob Herring of_node_put(node);
657f1f207e4SRob Herring }
658f1f207e4SRob Herring for (; next; next = next->sibling) {
6594fdd0736SMatthias Schiffer if (__of_device_is_fail(next))
6604fdd0736SMatthias Schiffer continue;
661f1f207e4SRob Herring if (!(of_node_name_eq(next, "cpu") ||
662e8b1dee2SRob Herring __of_node_is_type(next, "cpu")))
663f1f207e4SRob Herring continue;
664f1f207e4SRob Herring if (of_node_get(next))
665f1f207e4SRob Herring break;
666f1f207e4SRob Herring }
667f1f207e4SRob Herring of_node_put(prev);
668f1f207e4SRob Herring raw_spin_unlock_irqrestore(&devtree_lock, flags);
669f1f207e4SRob Herring return next;
670f1f207e4SRob Herring }
671f1f207e4SRob Herring EXPORT_SYMBOL(of_get_next_cpu_node);
672f1f207e4SRob Herring
673f1f207e4SRob Herring /**
67436156f92SJohan Hovold * of_get_compatible_child - Find compatible child node
67536156f92SJohan Hovold * @parent: parent node
67636156f92SJohan Hovold * @compatible: compatible string
67736156f92SJohan Hovold *
67836156f92SJohan Hovold * Lookup child node whose compatible property contains the given compatible
67936156f92SJohan Hovold * string.
68036156f92SJohan Hovold *
6818c8239c2SRob Herring * Return: a node pointer with refcount incremented, use of_node_put() on it
68236156f92SJohan Hovold * when done; or NULL if not found.
68336156f92SJohan Hovold */
of_get_compatible_child(const struct device_node * parent,const char * compatible)68436156f92SJohan Hovold struct device_node *of_get_compatible_child(const struct device_node *parent,
68536156f92SJohan Hovold const char *compatible)
68636156f92SJohan Hovold {
68736156f92SJohan Hovold struct device_node *child;
68836156f92SJohan Hovold
68936156f92SJohan Hovold for_each_child_of_node(parent, child) {
69036156f92SJohan Hovold if (of_device_is_compatible(child, compatible))
69136156f92SJohan Hovold break;
69236156f92SJohan Hovold }
69336156f92SJohan Hovold
69436156f92SJohan Hovold return child;
69536156f92SJohan Hovold }
69636156f92SJohan Hovold EXPORT_SYMBOL(of_get_compatible_child);
69736156f92SJohan Hovold
69836156f92SJohan Hovold /**
6999c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent
7009c19761aSSrinivas Kandagatla * @node: parent node
7019c19761aSSrinivas Kandagatla * @name: child name to look for.
7029c19761aSSrinivas Kandagatla *
7039c19761aSSrinivas Kandagatla * This function looks for child node for given matching name
7049c19761aSSrinivas Kandagatla *
70562f026f0SRob Herring * Return: A node pointer if found, with refcount incremented, use
7069c19761aSSrinivas Kandagatla * of_node_put() on it when done.
7079c19761aSSrinivas Kandagatla * Returns NULL if node is not found.
7089c19761aSSrinivas Kandagatla */
of_get_child_by_name(const struct device_node * node,const char * name)7099c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node,
7109c19761aSSrinivas Kandagatla const char *name)
7119c19761aSSrinivas Kandagatla {
7129c19761aSSrinivas Kandagatla struct device_node *child;
7139c19761aSSrinivas Kandagatla
7149c19761aSSrinivas Kandagatla for_each_child_of_node(node, child)
715b3e46d1aSRob Herring if (of_node_name_eq(child, name))
7169c19761aSSrinivas Kandagatla break;
7179c19761aSSrinivas Kandagatla return child;
7189c19761aSSrinivas Kandagatla }
7199c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name);
7209c19761aSSrinivas Kandagatla
__of_find_node_by_path(struct device_node * parent,const char * path)721e0a58f3eSFrank Rowand struct device_node *__of_find_node_by_path(struct device_node *parent,
722c22e650eSGrant Likely const char *path)
723c22e650eSGrant Likely {
724c22e650eSGrant Likely struct device_node *child;
725106937e8SLeif Lindholm int len;
726c22e650eSGrant Likely
727721a09e9SBrian Norris len = strcspn(path, "/:");
728c22e650eSGrant Likely if (!len)
729c22e650eSGrant Likely return NULL;
730c22e650eSGrant Likely
731c22e650eSGrant Likely __for_each_child_of_node(parent, child) {
73295e6b1faSRob Herring const char *name = kbasename(child->full_name);
733c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len))
734c22e650eSGrant Likely return child;
735c22e650eSGrant Likely }
736c22e650eSGrant Likely return NULL;
737c22e650eSGrant Likely }
738c22e650eSGrant Likely
__of_find_node_by_full_path(struct device_node * node,const char * path)73927497e11SRob Herring struct device_node *__of_find_node_by_full_path(struct device_node *node,
74027497e11SRob Herring const char *path)
74127497e11SRob Herring {
74227497e11SRob Herring const char *separator = strchr(path, ':');
74327497e11SRob Herring
74427497e11SRob Herring while (node && *path == '/') {
74527497e11SRob Herring struct device_node *tmp = node;
74627497e11SRob Herring
74727497e11SRob Herring path++; /* Increment past '/' delimiter */
74827497e11SRob Herring node = __of_find_node_by_path(node, path);
74927497e11SRob Herring of_node_put(tmp);
75027497e11SRob Herring path = strchrnul(path, '/');
75127497e11SRob Herring if (separator && separator < path)
75227497e11SRob Herring break;
75327497e11SRob Herring }
75427497e11SRob Herring return node;
75527497e11SRob Herring }
75627497e11SRob Herring
7579c19761aSSrinivas Kandagatla /**
75875c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path
759c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not
760c22e650eSGrant Likely * start with '/', the name of a property of the /aliases
761c22e650eSGrant Likely * node (an alias). In the case of an alias, the node
762c22e650eSGrant Likely * matching the alias' value will be returned.
76375c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of
76475c28c09SLeif Lindholm * an options string appended to the end of the path with
76575c28c09SLeif Lindholm * a ':' separator.
766c22e650eSGrant Likely *
767c22e650eSGrant Likely * Valid paths:
76862f026f0SRob Herring * * /foo/bar Full path
76962f026f0SRob Herring * * foo Valid alias
77062f026f0SRob Herring * * foo/bar Valid alias + relative path
7711ef4d424SStephen Rothwell *
77262f026f0SRob Herring * Return: A node pointer with refcount incremented, use
7731ef4d424SStephen Rothwell * of_node_put() on it when done.
7741ef4d424SStephen Rothwell */
of_find_node_opts_by_path(const char * path,const char ** opts)77575c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
7761ef4d424SStephen Rothwell {
777c22e650eSGrant Likely struct device_node *np = NULL;
778c22e650eSGrant Likely struct property *pp;
779d6d3c4e6SThomas Gleixner unsigned long flags;
78075c28c09SLeif Lindholm const char *separator = strchr(path, ':');
78175c28c09SLeif Lindholm
78275c28c09SLeif Lindholm if (opts)
78375c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL;
7841ef4d424SStephen Rothwell
785c22e650eSGrant Likely if (strcmp(path, "/") == 0)
7865063e25aSGrant Likely return of_node_get(of_root);
787c22e650eSGrant Likely
788c22e650eSGrant Likely /* The path could begin with an alias */
789c22e650eSGrant Likely if (*path != '/') {
790106937e8SLeif Lindholm int len;
791*b9f177d5SZijun Hu const char *p = strchrnul(path, '/');
792106937e8SLeif Lindholm
793*b9f177d5SZijun Hu if (separator && separator < p)
794*b9f177d5SZijun Hu p = separator;
795106937e8SLeif Lindholm len = p - path;
796c22e650eSGrant Likely
797c22e650eSGrant Likely /* of_aliases must not be NULL */
798c22e650eSGrant Likely if (!of_aliases)
799c22e650eSGrant Likely return NULL;
800c22e650eSGrant Likely
801c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) {
802c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
803c22e650eSGrant Likely np = of_find_node_by_path(pp->value);
8041ef4d424SStephen Rothwell break;
8051ef4d424SStephen Rothwell }
806c22e650eSGrant Likely }
807c22e650eSGrant Likely if (!np)
808c22e650eSGrant Likely return NULL;
809c22e650eSGrant Likely path = p;
810c22e650eSGrant Likely }
811c22e650eSGrant Likely
812c22e650eSGrant Likely /* Step down the tree matching path components */
813c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags);
814c22e650eSGrant Likely if (!np)
8155063e25aSGrant Likely np = of_node_get(of_root);
81627497e11SRob Herring np = __of_find_node_by_full_path(np, path);
817d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
8181ef4d424SStephen Rothwell return np;
8191ef4d424SStephen Rothwell }
82075c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path);
8211ef4d424SStephen Rothwell
8221ef4d424SStephen Rothwell /**
8231ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property
82402a876b5SStephen Boyd * @from: The node to start searching from or NULL; the node
8251ef4d424SStephen Rothwell * you pass will not be searched, only the next one
82602a876b5SStephen Boyd * will. Typically, you pass what the previous call
82702a876b5SStephen Boyd * returned. of_node_put() will be called on @from.
8281ef4d424SStephen Rothwell * @name: The name string to match against
8291ef4d424SStephen Rothwell *
83062f026f0SRob Herring * Return: A node pointer with refcount incremented, use
8311ef4d424SStephen Rothwell * of_node_put() on it when done.
8321ef4d424SStephen Rothwell */
of_find_node_by_name(struct device_node * from,const char * name)8331ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
8341ef4d424SStephen Rothwell const char *name)
8351ef4d424SStephen Rothwell {
8361ef4d424SStephen Rothwell struct device_node *np;
837d6d3c4e6SThomas Gleixner unsigned long flags;
8381ef4d424SStephen Rothwell
839d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
8405063e25aSGrant Likely for_each_of_allnodes_from(from, np)
841b3e46d1aSRob Herring if (of_node_name_eq(np, name) && of_node_get(np))
8421ef4d424SStephen Rothwell break;
8431ef4d424SStephen Rothwell of_node_put(from);
844d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
8451ef4d424SStephen Rothwell return np;
8461ef4d424SStephen Rothwell }
8471ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
8481ef4d424SStephen Rothwell
8491ef4d424SStephen Rothwell /**
8501ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property
8511ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching
8521ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be
8531ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass
8541ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be
8551ef4d424SStephen Rothwell * called on from for you.
8561ef4d424SStephen Rothwell * @type: The type string to match against
8571ef4d424SStephen Rothwell *
85862f026f0SRob Herring * Return: A node pointer with refcount incremented, use
8591ef4d424SStephen Rothwell * of_node_put() on it when done.
8601ef4d424SStephen Rothwell */
of_find_node_by_type(struct device_node * from,const char * type)8611ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
8621ef4d424SStephen Rothwell const char *type)
8631ef4d424SStephen Rothwell {
8641ef4d424SStephen Rothwell struct device_node *np;
865d6d3c4e6SThomas Gleixner unsigned long flags;
8661ef4d424SStephen Rothwell
867d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
8685063e25aSGrant Likely for_each_of_allnodes_from(from, np)
869e8b1dee2SRob Herring if (__of_node_is_type(np, type) && of_node_get(np))
8701ef4d424SStephen Rothwell break;
8711ef4d424SStephen Rothwell of_node_put(from);
872d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
8731ef4d424SStephen Rothwell return np;
8741ef4d424SStephen Rothwell }
8751ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
8761ef4d424SStephen Rothwell
8771ef4d424SStephen Rothwell /**
8781ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the
8791ef4d424SStephen Rothwell * tokens in its "compatible" property
8801ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node
8811ef4d424SStephen Rothwell * you pass will not be searched, only the next one
8821ef4d424SStephen Rothwell * will; typically, you pass what the previous call
8831ef4d424SStephen Rothwell * returned. of_node_put() will be called on it
8841ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore
8851ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device
8861ef4d424SStephen Rothwell * "compatible" list.
8871ef4d424SStephen Rothwell *
88862f026f0SRob Herring * Return: A node pointer with refcount incremented, use
8891ef4d424SStephen Rothwell * of_node_put() on it when done.
8901ef4d424SStephen Rothwell */
of_find_compatible_node(struct device_node * from,const char * type,const char * compatible)8911ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
8921ef4d424SStephen Rothwell const char *type, const char *compatible)
8931ef4d424SStephen Rothwell {
8941ef4d424SStephen Rothwell struct device_node *np;
895d6d3c4e6SThomas Gleixner unsigned long flags;
8961ef4d424SStephen Rothwell
897d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
8985063e25aSGrant Likely for_each_of_allnodes_from(from, np)
899215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) &&
90028d0e36bSThomas Gleixner of_node_get(np))
9011ef4d424SStephen Rothwell break;
9021ef4d424SStephen Rothwell of_node_put(from);
903d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
9041ef4d424SStephen Rothwell return np;
9051ef4d424SStephen Rothwell }
9061ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
907283029d1SGrant Likely
908283029d1SGrant Likely /**
9091e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with
9101e291b14SMichael Ellerman * the given name.
9111e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node
9121e291b14SMichael Ellerman * you pass will not be searched, only the next one
9131e291b14SMichael Ellerman * will; typically, you pass what the previous call
9141e291b14SMichael Ellerman * returned. of_node_put() will be called on it
9151e291b14SMichael Ellerman * @prop_name: The name of the property to look for.
9161e291b14SMichael Ellerman *
91762f026f0SRob Herring * Return: A node pointer with refcount incremented, use
9181e291b14SMichael Ellerman * of_node_put() on it when done.
9191e291b14SMichael Ellerman */
of_find_node_with_property(struct device_node * from,const char * prop_name)9201e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
9211e291b14SMichael Ellerman const char *prop_name)
9221e291b14SMichael Ellerman {
9231e291b14SMichael Ellerman struct device_node *np;
9241e291b14SMichael Ellerman struct property *pp;
925d6d3c4e6SThomas Gleixner unsigned long flags;
9261e291b14SMichael Ellerman
927d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
9285063e25aSGrant Likely for_each_of_allnodes_from(from, np) {
929a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) {
9301e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) {
9311e291b14SMichael Ellerman of_node_get(np);
9321e291b14SMichael Ellerman goto out;
9331e291b14SMichael Ellerman }
9341e291b14SMichael Ellerman }
9351e291b14SMichael Ellerman }
9361e291b14SMichael Ellerman out:
9371e291b14SMichael Ellerman of_node_put(from);
938d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
9391e291b14SMichael Ellerman return np;
9401e291b14SMichael Ellerman }
9411e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
9421e291b14SMichael Ellerman
94328d0e36bSThomas Gleixner static
__of_match_node(const struct of_device_id * matches,const struct device_node * node)94428d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches,
945283029d1SGrant Likely const struct device_node *node)
946283029d1SGrant Likely {
947215a14cfSKevin Hao const struct of_device_id *best_match = NULL;
948215a14cfSKevin Hao int score, best_score = 0;
949215a14cfSKevin Hao
950a52f07ecSGrant Likely if (!matches)
951a52f07ecSGrant Likely return NULL;
952a52f07ecSGrant Likely
953215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
954215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible,
955215a14cfSKevin Hao matches->type, matches->name);
956215a14cfSKevin Hao if (score > best_score) {
957215a14cfSKevin Hao best_match = matches;
958215a14cfSKevin Hao best_score = score;
959283029d1SGrant Likely }
960215a14cfSKevin Hao }
961215a14cfSKevin Hao
962215a14cfSKevin Hao return best_match;
963283029d1SGrant Likely }
96428d0e36bSThomas Gleixner
96528d0e36bSThomas Gleixner /**
966c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure
96728d0e36bSThomas Gleixner * @matches: array of of device match structures to search in
96828d0e36bSThomas Gleixner * @node: the of device structure to match against
96928d0e36bSThomas Gleixner *
97071c5498eSKevin Hao * Low level utility function used by device matching.
97128d0e36bSThomas Gleixner */
of_match_node(const struct of_device_id * matches,const struct device_node * node)97228d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches,
97328d0e36bSThomas Gleixner const struct device_node *node)
97428d0e36bSThomas Gleixner {
97528d0e36bSThomas Gleixner const struct of_device_id *match;
976d6d3c4e6SThomas Gleixner unsigned long flags;
97728d0e36bSThomas Gleixner
978d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
97928d0e36bSThomas Gleixner match = __of_match_node(matches, node);
980d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
98128d0e36bSThomas Gleixner return match;
98228d0e36bSThomas Gleixner }
983283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
984283029d1SGrant Likely
985283029d1SGrant Likely /**
98650c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id
98750c8af4cSStephen Warren * match table.
988283029d1SGrant Likely * @from: The node to start searching from or NULL, the node
989283029d1SGrant Likely * you pass will not be searched, only the next one
990283029d1SGrant Likely * will; typically, you pass what the previous call
991283029d1SGrant Likely * returned. of_node_put() will be called on it
992283029d1SGrant Likely * @matches: array of of device match structures to search in
9933637d49eSLee Jones * @match: Updated to point at the matches entry which matched
994283029d1SGrant Likely *
99562f026f0SRob Herring * Return: A node pointer with refcount incremented, use
996283029d1SGrant Likely * of_node_put() on it when done.
997283029d1SGrant Likely */
of_find_matching_node_and_match(struct device_node * from,const struct of_device_id * matches,const struct of_device_id ** match)99850c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from,
99950c8af4cSStephen Warren const struct of_device_id *matches,
100050c8af4cSStephen Warren const struct of_device_id **match)
1001283029d1SGrant Likely {
1002283029d1SGrant Likely struct device_node *np;
1003dc71bcf1SThomas Abraham const struct of_device_id *m;
1004d6d3c4e6SThomas Gleixner unsigned long flags;
1005283029d1SGrant Likely
100650c8af4cSStephen Warren if (match)
100750c8af4cSStephen Warren *match = NULL;
100850c8af4cSStephen Warren
1009d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags);
10105063e25aSGrant Likely for_each_of_allnodes_from(from, np) {
101128d0e36bSThomas Gleixner m = __of_match_node(matches, np);
1012dc71bcf1SThomas Abraham if (m && of_node_get(np)) {
101350c8af4cSStephen Warren if (match)
1014dc71bcf1SThomas Abraham *match = m;
1015283029d1SGrant Likely break;
1016283029d1SGrant Likely }
101750c8af4cSStephen Warren }
1018283029d1SGrant Likely of_node_put(from);
1019d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags);
1020283029d1SGrant Likely return np;
1021283029d1SGrant Likely }
102280c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match);
10233f07af49SGrant Likely
10243f07af49SGrant Likely /**
1025673aa1edSMiquel Raynal * of_alias_from_compatible - Lookup appropriate alias for a device node
1026673aa1edSMiquel Raynal * depending on compatible
10273f07af49SGrant Likely * @node: pointer to a device tree node
1028673aa1edSMiquel Raynal * @alias: Pointer to buffer that alias value will be copied into
1029673aa1edSMiquel Raynal * @len: Length of alias value
10303f07af49SGrant Likely *
10312ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt
1032673aa1edSMiquel Raynal * to choose an appropriate alias value for a particular device tree node.
10332ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',')
10342ffe8c5fSGrant Likely * from the first entry in the compatible list property.
10353f07af49SGrant Likely *
1036673aa1edSMiquel Raynal * Note: The matching on just the "product" side of the compatible is a relic
1037673aa1edSMiquel Raynal * from I2C and SPI. Please do not add any new user.
1038673aa1edSMiquel Raynal *
10398c8239c2SRob Herring * Return: This routine returns 0 on success, <0 on failure.
10403f07af49SGrant Likely */
of_alias_from_compatible(const struct device_node * node,char * alias,int len)1041673aa1edSMiquel Raynal int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
10423f07af49SGrant Likely {
10432ffe8c5fSGrant Likely const char *compatible, *p;
10442ffe8c5fSGrant Likely int cplen;
10453f07af49SGrant Likely
10463f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen);
10472ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen)
10483f07af49SGrant Likely return -ENODEV;
10493f07af49SGrant Likely p = strchr(compatible, ',');
1050673aa1edSMiquel Raynal strscpy(alias, p ? p + 1 : compatible, len);
10513f07af49SGrant Likely return 0;
10523f07af49SGrant Likely }
1053673aa1edSMiquel Raynal EXPORT_SYMBOL_GPL(of_alias_from_compatible);
10543f07af49SGrant Likely
105564b60e09SAnton Vorontsov /**
105689751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle
105789751a7cSJeremy Kerr * @handle: phandle of the node to find
105889751a7cSJeremy Kerr *
10598c8239c2SRob Herring * Return: A node pointer with refcount incremented, use
106089751a7cSJeremy Kerr * of_node_put() on it when done.
106189751a7cSJeremy Kerr */
of_find_node_by_phandle(phandle handle)106289751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
106389751a7cSJeremy Kerr {
10640b3ce78eSFrank Rowand struct device_node *np = NULL;
1065d25d8694SBenjamin Herrenschmidt unsigned long flags;
106690dc0d1cSRob Herring u32 handle_hash;
106789751a7cSJeremy Kerr
1068fc59b447SGrant Likely if (!handle)
1069fc59b447SGrant Likely return NULL;
1070fc59b447SGrant Likely
107190dc0d1cSRob Herring handle_hash = of_phandle_cache_hash(handle);
107290dc0d1cSRob Herring
1073d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags);
10740b3ce78eSFrank Rowand
107590dc0d1cSRob Herring if (phandle_cache[handle_hash] &&
107690dc0d1cSRob Herring handle == phandle_cache[handle_hash]->phandle)
107790dc0d1cSRob Herring np = phandle_cache[handle_hash];
10780b3ce78eSFrank Rowand
10790b3ce78eSFrank Rowand if (!np) {
10805063e25aSGrant Likely for_each_of_allnodes(np)
10815801169aSFrank Rowand if (np->phandle == handle &&
10825801169aSFrank Rowand !of_node_check_flag(np, OF_DETACHED)) {
108390dc0d1cSRob Herring phandle_cache[handle_hash] = np;
108489751a7cSJeremy Kerr break;
10850b3ce78eSFrank Rowand }
10860b3ce78eSFrank Rowand }
10870b3ce78eSFrank Rowand
108889751a7cSJeremy Kerr of_node_get(np);
1089d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags);
109089751a7cSJeremy Kerr return np;
109189751a7cSJeremy Kerr }
109289751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
109389751a7cSJeremy Kerr
of_print_phandle_args(const char * msg,const struct of_phandle_args * args)1094624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
1095624cfca5SGrant Likely {
1096624cfca5SGrant Likely int i;
10970d638a07SRob Herring printk("%s %pOF", msg, args->np);
10984aa66344SMarcin Nowakowski for (i = 0; i < args->args_count; i++) {
10994aa66344SMarcin Nowakowski const char delim = i ? ',' : ':';
11004aa66344SMarcin Nowakowski
11014aa66344SMarcin Nowakowski pr_cont("%c%08x", delim, args->args[i]);
11024aa66344SMarcin Nowakowski }
11034aa66344SMarcin Nowakowski pr_cont("\n");
1104624cfca5SGrant Likely }
1105624cfca5SGrant Likely
of_phandle_iterator_init(struct of_phandle_iterator * it,const struct device_node * np,const char * list_name,const char * cells_name,int cell_count)110674e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it,
110774e1fbb1SJoerg Roedel const struct device_node *np,
110874e1fbb1SJoerg Roedel const char *list_name,
110974e1fbb1SJoerg Roedel const char *cells_name,
111074e1fbb1SJoerg Roedel int cell_count)
111174e1fbb1SJoerg Roedel {
111274e1fbb1SJoerg Roedel const __be32 *list;
111374e1fbb1SJoerg Roedel int size;
111474e1fbb1SJoerg Roedel
111574e1fbb1SJoerg Roedel memset(it, 0, sizeof(*it));
111674e1fbb1SJoerg Roedel
111759e9fcf8SUwe Kleine-König /*
111859e9fcf8SUwe Kleine-König * one of cell_count or cells_name must be provided to determine the
111959e9fcf8SUwe Kleine-König * argument length.
112059e9fcf8SUwe Kleine-König */
112159e9fcf8SUwe Kleine-König if (cell_count < 0 && !cells_name)
112259e9fcf8SUwe Kleine-König return -EINVAL;
112359e9fcf8SUwe Kleine-König
112474e1fbb1SJoerg Roedel list = of_get_property(np, list_name, &size);
112574e1fbb1SJoerg Roedel if (!list)
112674e1fbb1SJoerg Roedel return -ENOENT;
112774e1fbb1SJoerg Roedel
112874e1fbb1SJoerg Roedel it->cells_name = cells_name;
112974e1fbb1SJoerg Roedel it->cell_count = cell_count;
113074e1fbb1SJoerg Roedel it->parent = np;
113174e1fbb1SJoerg Roedel it->list_end = list + size / sizeof(*list);
113274e1fbb1SJoerg Roedel it->phandle_end = list;
113374e1fbb1SJoerg Roedel it->cur = list;
113474e1fbb1SJoerg Roedel
113574e1fbb1SJoerg Roedel return 0;
113674e1fbb1SJoerg Roedel }
113700bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
113874e1fbb1SJoerg Roedel
of_phandle_iterator_next(struct of_phandle_iterator * it)1139cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it)
1140cd209b41SJoerg Roedel {
1141cd209b41SJoerg Roedel uint32_t count = 0;
1142cd209b41SJoerg Roedel
1143cd209b41SJoerg Roedel if (it->node) {
1144cd209b41SJoerg Roedel of_node_put(it->node);
1145cd209b41SJoerg Roedel it->node = NULL;
1146cd209b41SJoerg Roedel }
1147cd209b41SJoerg Roedel
1148cd209b41SJoerg Roedel if (!it->cur || it->phandle_end >= it->list_end)
1149cd209b41SJoerg Roedel return -ENOENT;
1150cd209b41SJoerg Roedel
1151cd209b41SJoerg Roedel it->cur = it->phandle_end;
1152cd209b41SJoerg Roedel
1153cd209b41SJoerg Roedel /* If phandle is 0, then it is an empty entry with no arguments. */
1154cd209b41SJoerg Roedel it->phandle = be32_to_cpup(it->cur++);
1155cd209b41SJoerg Roedel
1156cd209b41SJoerg Roedel if (it->phandle) {
1157cd209b41SJoerg Roedel
1158cd209b41SJoerg Roedel /*
1159cd209b41SJoerg Roedel * Find the provider node and parse the #*-cells property to
1160cd209b41SJoerg Roedel * determine the argument length.
1161cd209b41SJoerg Roedel */
1162cd209b41SJoerg Roedel it->node = of_find_node_by_phandle(it->phandle);
1163cd209b41SJoerg Roedel
1164cd209b41SJoerg Roedel if (it->cells_name) {
1165cd209b41SJoerg Roedel if (!it->node) {
116612e17243SEnrico Weigelt, metux IT consult pr_err("%pOF: could not find phandle %d\n",
116712e17243SEnrico Weigelt, metux IT consult it->parent, it->phandle);
1168cd209b41SJoerg Roedel goto err;
1169cd209b41SJoerg Roedel }
1170cd209b41SJoerg Roedel
1171cd209b41SJoerg Roedel if (of_property_read_u32(it->node, it->cells_name,
1172cd209b41SJoerg Roedel &count)) {
1173e42ee610SUwe Kleine-König /*
1174e42ee610SUwe Kleine-König * If both cell_count and cells_name is given,
1175e42ee610SUwe Kleine-König * fall back to cell_count in absence
1176e42ee610SUwe Kleine-König * of the cells_name property
1177e42ee610SUwe Kleine-König */
1178e42ee610SUwe Kleine-König if (it->cell_count >= 0) {
1179e42ee610SUwe Kleine-König count = it->cell_count;
1180e42ee610SUwe Kleine-König } else {
11810d638a07SRob Herring pr_err("%pOF: could not get %s for %pOF\n",
11820d638a07SRob Herring it->parent,
1183cd209b41SJoerg Roedel it->cells_name,
11840d638a07SRob Herring it->node);
1185cd209b41SJoerg Roedel goto err;
1186cd209b41SJoerg Roedel }
1187e42ee610SUwe Kleine-König }
1188cd209b41SJoerg Roedel } else {
1189cd209b41SJoerg Roedel count = it->cell_count;
1190cd209b41SJoerg Roedel }
1191cd209b41SJoerg Roedel
1192cd209b41SJoerg Roedel /*
1193cd209b41SJoerg Roedel * Make sure that the arguments actually fit in the remaining
1194cd209b41SJoerg Roedel * property data length
1195cd209b41SJoerg Roedel */
1196cd209b41SJoerg Roedel if (it->cur + count > it->list_end) {
11975d05b811SBaruch Siach if (it->cells_name)
119894a4950aSBaruch Siach pr_err("%pOF: %s = %d found %td\n",
1199af3be70aSFlorian Fainelli it->parent, it->cells_name,
120094a4950aSBaruch Siach count, it->list_end - it->cur);
12015d05b811SBaruch Siach else
12025d05b811SBaruch Siach pr_err("%pOF: phandle %s needs %d, found %td\n",
12035d05b811SBaruch Siach it->parent, of_node_full_name(it->node),
12045d05b811SBaruch Siach count, it->list_end - it->cur);
1205cd209b41SJoerg Roedel goto err;
1206cd209b41SJoerg Roedel }
1207cd209b41SJoerg Roedel }
1208cd209b41SJoerg Roedel
1209cd209b41SJoerg Roedel it->phandle_end = it->cur + count;
1210cd209b41SJoerg Roedel it->cur_count = count;
1211cd209b41SJoerg Roedel
1212cd209b41SJoerg Roedel return 0;
1213cd209b41SJoerg Roedel
1214cd209b41SJoerg Roedel err:
1215cd209b41SJoerg Roedel if (it->node) {
1216cd209b41SJoerg Roedel of_node_put(it->node);
1217cd209b41SJoerg Roedel it->node = NULL;
1218cd209b41SJoerg Roedel }
1219cd209b41SJoerg Roedel
1220cd209b41SJoerg Roedel return -EINVAL;
1221cd209b41SJoerg Roedel }
122200bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
1223cd209b41SJoerg Roedel
of_phandle_iterator_args(struct of_phandle_iterator * it,uint32_t * args,int size)1224abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it,
1225abdaa77bSJoerg Roedel uint32_t *args,
1226abdaa77bSJoerg Roedel int size)
1227abdaa77bSJoerg Roedel {
1228abdaa77bSJoerg Roedel int i, count;
1229abdaa77bSJoerg Roedel
1230abdaa77bSJoerg Roedel count = it->cur_count;
1231abdaa77bSJoerg Roedel
1232abdaa77bSJoerg Roedel if (WARN_ON(size < count))
1233abdaa77bSJoerg Roedel count = size;
1234abdaa77bSJoerg Roedel
1235abdaa77bSJoerg Roedel for (i = 0; i < count; i++)
1236abdaa77bSJoerg Roedel args[i] = be32_to_cpup(it->cur++);
1237abdaa77bSJoerg Roedel
1238abdaa77bSJoerg Roedel return count;
1239abdaa77bSJoerg Roedel }
1240abdaa77bSJoerg Roedel
__of_parse_phandle_with_args(const struct device_node * np,const char * list_name,const char * cells_name,int cell_count,int index,struct of_phandle_args * out_args)124166a8f7f0SMichael Walle int __of_parse_phandle_with_args(const struct device_node *np,
1242bd69f73fSGrant Likely const char *list_name,
1243035fd948SStephen Warren const char *cells_name,
1244035fd948SStephen Warren int cell_count, int index,
124515c9a0acSGrant Likely struct of_phandle_args *out_args)
124664b60e09SAnton Vorontsov {
124774e1fbb1SJoerg Roedel struct of_phandle_iterator it;
124874e1fbb1SJoerg Roedel int rc, cur_index = 0;
124915c9a0acSGrant Likely
125066a8f7f0SMichael Walle if (index < 0)
125166a8f7f0SMichael Walle return -EINVAL;
125266a8f7f0SMichael Walle
125315c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */
1254f623ce95SJoerg Roedel of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
125515c9a0acSGrant Likely /*
1256cd209b41SJoerg Roedel * All of the error cases bail out of the loop, so at
125715c9a0acSGrant Likely * this point, the parsing is successful. If the requested
125815c9a0acSGrant Likely * index matches, then fill the out_args structure and return,
125915c9a0acSGrant Likely * or return -ENOENT for an empty entry.
126015c9a0acSGrant Likely */
126123ce04c0SGrant Likely rc = -ENOENT;
126215c9a0acSGrant Likely if (cur_index == index) {
126374e1fbb1SJoerg Roedel if (!it.phandle)
126423ce04c0SGrant Likely goto err;
126515c9a0acSGrant Likely
126615c9a0acSGrant Likely if (out_args) {
1267abdaa77bSJoerg Roedel int c;
1268abdaa77bSJoerg Roedel
1269abdaa77bSJoerg Roedel c = of_phandle_iterator_args(&it,
1270abdaa77bSJoerg Roedel out_args->args,
1271abdaa77bSJoerg Roedel MAX_PHANDLE_ARGS);
127274e1fbb1SJoerg Roedel out_args->np = it.node;
1273abdaa77bSJoerg Roedel out_args->args_count = c;
1274b855f16bSTang Yuantian } else {
127574e1fbb1SJoerg Roedel of_node_put(it.node);
127615c9a0acSGrant Likely }
127723ce04c0SGrant Likely
127823ce04c0SGrant Likely /* Found it! return success */
127915c9a0acSGrant Likely return 0;
128015c9a0acSGrant Likely }
128164b60e09SAnton Vorontsov
128264b60e09SAnton Vorontsov cur_index++;
128364b60e09SAnton Vorontsov }
128464b60e09SAnton Vorontsov
128523ce04c0SGrant Likely /*
128623ce04c0SGrant Likely * Unlock node before returning result; will be one of:
128723ce04c0SGrant Likely * -ENOENT : index is for empty phandle
128823ce04c0SGrant Likely * -EINVAL : parsing error on data
128923ce04c0SGrant Likely */
1290cd209b41SJoerg Roedel
129123ce04c0SGrant Likely err:
129274e1fbb1SJoerg Roedel of_node_put(it.node);
129323ce04c0SGrant Likely return rc;
129464b60e09SAnton Vorontsov }
129566a8f7f0SMichael Walle EXPORT_SYMBOL(__of_parse_phandle_with_args);
129602af11b0SGrant Likely
1297bd69f73fSGrant Likely /**
1298bd6f2fd5SStephen Boyd * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
1299bd6f2fd5SStephen Boyd * @np: pointer to a device tree node containing a list
1300bd6f2fd5SStephen Boyd * @list_name: property name that contains a list
1301bd6f2fd5SStephen Boyd * @stem_name: stem of property names that specify phandles' arguments count
1302bd6f2fd5SStephen Boyd * @index: index of a phandle to parse out
1303bd6f2fd5SStephen Boyd * @out_args: optional pointer to output arguments structure (will be filled)
1304bd6f2fd5SStephen Boyd *
1305bd6f2fd5SStephen Boyd * This function is useful to parse lists of phandles and their arguments.
1306bd6f2fd5SStephen Boyd * Returns 0 on success and fills out_args, on error returns appropriate errno
1307bd6f2fd5SStephen Boyd * value. The difference between this function and of_parse_phandle_with_args()
1308bd6f2fd5SStephen Boyd * is that this API remaps a phandle if the node the phandle points to has
1309bd6f2fd5SStephen Boyd * a <@stem_name>-map property.
1310bd6f2fd5SStephen Boyd *
1311bd6f2fd5SStephen Boyd * Caller is responsible to call of_node_put() on the returned out_args->np
1312bd6f2fd5SStephen Boyd * pointer.
1313bd6f2fd5SStephen Boyd *
131462f026f0SRob Herring * Example::
1315bd6f2fd5SStephen Boyd *
1316bd6f2fd5SStephen Boyd * phandle1: node1 {
1317bd6f2fd5SStephen Boyd * #list-cells = <2>;
131862f026f0SRob Herring * };
1319bd6f2fd5SStephen Boyd *
1320bd6f2fd5SStephen Boyd * phandle2: node2 {
1321bd6f2fd5SStephen Boyd * #list-cells = <1>;
132262f026f0SRob Herring * };
1323bd6f2fd5SStephen Boyd *
1324bd6f2fd5SStephen Boyd * phandle3: node3 {
1325bd6f2fd5SStephen Boyd * #list-cells = <1>;
1326bd6f2fd5SStephen Boyd * list-map = <0 &phandle2 3>,
1327bd6f2fd5SStephen Boyd * <1 &phandle2 2>,
1328bd6f2fd5SStephen Boyd * <2 &phandle1 5 1>;
1329bd6f2fd5SStephen Boyd * list-map-mask = <0x3>;
1330bd6f2fd5SStephen Boyd * };
1331bd6f2fd5SStephen Boyd *
1332bd6f2fd5SStephen Boyd * node4 {
1333bd6f2fd5SStephen Boyd * list = <&phandle1 1 2 &phandle3 0>;
133462f026f0SRob Herring * };
1335bd6f2fd5SStephen Boyd *
133662f026f0SRob Herring * To get a device_node of the ``node2`` node you may call this:
1337bd6f2fd5SStephen Boyd * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
1338bd6f2fd5SStephen Boyd */
of_parse_phandle_with_args_map(const struct device_node * np,const char * list_name,const char * stem_name,int index,struct of_phandle_args * out_args)1339bd6f2fd5SStephen Boyd int of_parse_phandle_with_args_map(const struct device_node *np,
1340bd6f2fd5SStephen Boyd const char *list_name,
1341bd6f2fd5SStephen Boyd const char *stem_name,
1342bd6f2fd5SStephen Boyd int index, struct of_phandle_args *out_args)
1343bd6f2fd5SStephen Boyd {
1344bd6f2fd5SStephen Boyd char *cells_name, *map_name = NULL, *mask_name = NULL;
1345bd6f2fd5SStephen Boyd char *pass_name = NULL;
1346bd6f2fd5SStephen Boyd struct device_node *cur, *new = NULL;
1347bd6f2fd5SStephen Boyd const __be32 *map, *mask, *pass;
1348bd6f2fd5SStephen Boyd static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
1349bd6f2fd5SStephen Boyd static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
1350bd6f2fd5SStephen Boyd __be32 initial_match_array[MAX_PHANDLE_ARGS];
1351bd6f2fd5SStephen Boyd const __be32 *match_array = initial_match_array;
1352bd6f2fd5SStephen Boyd int i, ret, map_len, match;
1353bd6f2fd5SStephen Boyd u32 list_size, new_size;
1354bd6f2fd5SStephen Boyd
1355bd6f2fd5SStephen Boyd if (index < 0)
1356bd6f2fd5SStephen Boyd return -EINVAL;
1357bd6f2fd5SStephen Boyd
1358bd6f2fd5SStephen Boyd cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
1359bd6f2fd5SStephen Boyd if (!cells_name)
1360bd6f2fd5SStephen Boyd return -ENOMEM;
1361bd6f2fd5SStephen Boyd
1362bd6f2fd5SStephen Boyd ret = -ENOMEM;
1363bd6f2fd5SStephen Boyd map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
1364bd6f2fd5SStephen Boyd if (!map_name)
1365bd6f2fd5SStephen Boyd goto free;
1366bd6f2fd5SStephen Boyd
1367bd6f2fd5SStephen Boyd mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
1368bd6f2fd5SStephen Boyd if (!mask_name)
1369bd6f2fd5SStephen Boyd goto free;
1370bd6f2fd5SStephen Boyd
1371bd6f2fd5SStephen Boyd pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
1372bd6f2fd5SStephen Boyd if (!pass_name)
1373bd6f2fd5SStephen Boyd goto free;
1374bd6f2fd5SStephen Boyd
1375e42ee610SUwe Kleine-König ret = __of_parse_phandle_with_args(np, list_name, cells_name, -1, index,
1376bd6f2fd5SStephen Boyd out_args);
1377bd6f2fd5SStephen Boyd if (ret)
1378bd6f2fd5SStephen Boyd goto free;
1379bd6f2fd5SStephen Boyd
1380bd6f2fd5SStephen Boyd /* Get the #<list>-cells property */
1381bd6f2fd5SStephen Boyd cur = out_args->np;
1382bd6f2fd5SStephen Boyd ret = of_property_read_u32(cur, cells_name, &list_size);
1383bd6f2fd5SStephen Boyd if (ret < 0)
1384bd6f2fd5SStephen Boyd goto put;
1385bd6f2fd5SStephen Boyd
1386bd6f2fd5SStephen Boyd /* Precalculate the match array - this simplifies match loop */
1387bd6f2fd5SStephen Boyd for (i = 0; i < list_size; i++)
1388bd6f2fd5SStephen Boyd initial_match_array[i] = cpu_to_be32(out_args->args[i]);
1389bd6f2fd5SStephen Boyd
1390bd6f2fd5SStephen Boyd ret = -EINVAL;
1391bd6f2fd5SStephen Boyd while (cur) {
1392bd6f2fd5SStephen Boyd /* Get the <list>-map property */
1393bd6f2fd5SStephen Boyd map = of_get_property(cur, map_name, &map_len);
1394bd6f2fd5SStephen Boyd if (!map) {
1395bd6f2fd5SStephen Boyd ret = 0;
1396bd6f2fd5SStephen Boyd goto free;
1397bd6f2fd5SStephen Boyd }
1398bd6f2fd5SStephen Boyd map_len /= sizeof(u32);
1399bd6f2fd5SStephen Boyd
1400bd6f2fd5SStephen Boyd /* Get the <list>-map-mask property (optional) */
1401bd6f2fd5SStephen Boyd mask = of_get_property(cur, mask_name, NULL);
1402bd6f2fd5SStephen Boyd if (!mask)
1403bd6f2fd5SStephen Boyd mask = dummy_mask;
1404bd6f2fd5SStephen Boyd /* Iterate through <list>-map property */
1405bd6f2fd5SStephen Boyd match = 0;
1406bd6f2fd5SStephen Boyd while (map_len > (list_size + 1) && !match) {
1407bd6f2fd5SStephen Boyd /* Compare specifiers */
1408bd6f2fd5SStephen Boyd match = 1;
1409bd6f2fd5SStephen Boyd for (i = 0; i < list_size; i++, map_len--)
1410bd6f2fd5SStephen Boyd match &= !((match_array[i] ^ *map++) & mask[i]);
1411bd6f2fd5SStephen Boyd
1412bd6f2fd5SStephen Boyd of_node_put(new);
1413bd6f2fd5SStephen Boyd new = of_find_node_by_phandle(be32_to_cpup(map));
1414bd6f2fd5SStephen Boyd map++;
1415bd6f2fd5SStephen Boyd map_len--;
1416bd6f2fd5SStephen Boyd
1417bd6f2fd5SStephen Boyd /* Check if not found */
1418a7e5dc8dSHerve Codina if (!new) {
1419a7e5dc8dSHerve Codina ret = -EINVAL;
1420bd6f2fd5SStephen Boyd goto put;
1421a7e5dc8dSHerve Codina }
1422bd6f2fd5SStephen Boyd
1423bd6f2fd5SStephen Boyd if (!of_device_is_available(new))
1424bd6f2fd5SStephen Boyd match = 0;
1425bd6f2fd5SStephen Boyd
1426bd6f2fd5SStephen Boyd ret = of_property_read_u32(new, cells_name, &new_size);
1427bd6f2fd5SStephen Boyd if (ret)
1428bd6f2fd5SStephen Boyd goto put;
1429bd6f2fd5SStephen Boyd
1430bd6f2fd5SStephen Boyd /* Check for malformed properties */
1431a7e5dc8dSHerve Codina if (WARN_ON(new_size > MAX_PHANDLE_ARGS) ||
1432a7e5dc8dSHerve Codina map_len < new_size) {
1433a7e5dc8dSHerve Codina ret = -EINVAL;
1434bd6f2fd5SStephen Boyd goto put;
1435a7e5dc8dSHerve Codina }
1436bd6f2fd5SStephen Boyd
1437bd6f2fd5SStephen Boyd /* Move forward by new node's #<list>-cells amount */
1438bd6f2fd5SStephen Boyd map += new_size;
1439bd6f2fd5SStephen Boyd map_len -= new_size;
1440bd6f2fd5SStephen Boyd }
1441a7e5dc8dSHerve Codina if (!match) {
1442a7e5dc8dSHerve Codina ret = -ENOENT;
1443bd6f2fd5SStephen Boyd goto put;
1444a7e5dc8dSHerve Codina }
1445bd6f2fd5SStephen Boyd
1446bd6f2fd5SStephen Boyd /* Get the <list>-map-pass-thru property (optional) */
1447bd6f2fd5SStephen Boyd pass = of_get_property(cur, pass_name, NULL);
1448bd6f2fd5SStephen Boyd if (!pass)
1449bd6f2fd5SStephen Boyd pass = dummy_pass;
1450bd6f2fd5SStephen Boyd
1451bd6f2fd5SStephen Boyd /*
1452bd6f2fd5SStephen Boyd * Successfully parsed a <list>-map translation; copy new
1453bd6f2fd5SStephen Boyd * specifier into the out_args structure, keeping the
1454bd6f2fd5SStephen Boyd * bits specified in <list>-map-pass-thru.
1455bd6f2fd5SStephen Boyd */
1456bd6f2fd5SStephen Boyd for (i = 0; i < new_size; i++) {
1457bd6f2fd5SStephen Boyd __be32 val = *(map - new_size + i);
1458bd6f2fd5SStephen Boyd
1459bd6f2fd5SStephen Boyd if (i < list_size) {
1460bd6f2fd5SStephen Boyd val &= ~pass[i];
1461bd6f2fd5SStephen Boyd val |= cpu_to_be32(out_args->args[i]) & pass[i];
1462bd6f2fd5SStephen Boyd }
1463bd6f2fd5SStephen Boyd
1464fe44f5f5SZijun Hu initial_match_array[i] = val;
1465bd6f2fd5SStephen Boyd out_args->args[i] = be32_to_cpu(val);
1466bd6f2fd5SStephen Boyd }
1467bd6f2fd5SStephen Boyd out_args->args_count = list_size = new_size;
1468bd6f2fd5SStephen Boyd /* Iterate again with new provider */
1469bd6f2fd5SStephen Boyd out_args->np = new;
1470bd6f2fd5SStephen Boyd of_node_put(cur);
1471bd6f2fd5SStephen Boyd cur = new;
1472b64d09a4SChristian A. Ehrhardt new = NULL;
1473bd6f2fd5SStephen Boyd }
1474bd6f2fd5SStephen Boyd put:
1475bd6f2fd5SStephen Boyd of_node_put(cur);
1476bd6f2fd5SStephen Boyd of_node_put(new);
1477bd6f2fd5SStephen Boyd free:
1478bd6f2fd5SStephen Boyd kfree(mask_name);
1479bd6f2fd5SStephen Boyd kfree(map_name);
1480bd6f2fd5SStephen Boyd kfree(cells_name);
1481bd6f2fd5SStephen Boyd kfree(pass_name);
1482bd6f2fd5SStephen Boyd
1483bd6f2fd5SStephen Boyd return ret;
1484bd6f2fd5SStephen Boyd }
1485bd6f2fd5SStephen Boyd EXPORT_SYMBOL(of_parse_phandle_with_args_map);
1486bd6f2fd5SStephen Boyd
1487bd6f2fd5SStephen Boyd /**
1488bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property
1489bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list
1490bd69f73fSGrant Likely * @list_name: property name that contains a list
1491bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count
1492bd69f73fSGrant Likely *
14938c8239c2SRob Herring * Return: The number of phandle + argument tuples within a property. It
1494bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable
1495bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded
1496bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios
1497bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a
1498bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are
1499bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the
1500bd69f73fSGrant Likely * phandle.
1501bd69f73fSGrant Likely */
of_count_phandle_with_args(const struct device_node * np,const char * list_name,const char * cells_name)1502bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
1503bd69f73fSGrant Likely const char *cells_name)
1504bd69f73fSGrant Likely {
15052021bd01SJoerg Roedel struct of_phandle_iterator it;
15062021bd01SJoerg Roedel int rc, cur_index = 0;
15072021bd01SJoerg Roedel
150859e9fcf8SUwe Kleine-König /*
150959e9fcf8SUwe Kleine-König * If cells_name is NULL we assume a cell count of 0. This makes
151059e9fcf8SUwe Kleine-König * counting the phandles trivial as each 32bit word in the list is a
151159e9fcf8SUwe Kleine-König * phandle and no arguments are to consider. So we don't iterate through
151259e9fcf8SUwe Kleine-König * the list but just use the length to determine the phandle count.
151359e9fcf8SUwe Kleine-König */
151459e9fcf8SUwe Kleine-König if (!cells_name) {
151559e9fcf8SUwe Kleine-König const __be32 *list;
151659e9fcf8SUwe Kleine-König int size;
151759e9fcf8SUwe Kleine-König
151859e9fcf8SUwe Kleine-König list = of_get_property(np, list_name, &size);
151959e9fcf8SUwe Kleine-König if (!list)
152059e9fcf8SUwe Kleine-König return -ENOENT;
152159e9fcf8SUwe Kleine-König
152259e9fcf8SUwe Kleine-König return size / sizeof(*list);
152359e9fcf8SUwe Kleine-König }
152459e9fcf8SUwe Kleine-König
1525e42ee610SUwe Kleine-König rc = of_phandle_iterator_init(&it, np, list_name, cells_name, -1);
15262021bd01SJoerg Roedel if (rc)
15272021bd01SJoerg Roedel return rc;
15282021bd01SJoerg Roedel
15292021bd01SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0)
15302021bd01SJoerg Roedel cur_index += 1;
15312021bd01SJoerg Roedel
15322021bd01SJoerg Roedel if (rc != -ENOENT)
15332021bd01SJoerg Roedel return rc;
15342021bd01SJoerg Roedel
15352021bd01SJoerg Roedel return cur_index;
1536bd69f73fSGrant Likely }
1537bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args);
1538bd69f73fSGrant Likely
__of_remove_property_from_list(struct property ** list,struct property * prop)15396701c2c7SRob Herring static struct property *__of_remove_property_from_list(struct property **list, struct property *prop)
15406701c2c7SRob Herring {
15416701c2c7SRob Herring struct property **next;
15426701c2c7SRob Herring
15436701c2c7SRob Herring for (next = list; *next; next = &(*next)->next) {
15446701c2c7SRob Herring if (*next == prop) {
15456701c2c7SRob Herring *next = prop->next;
15466701c2c7SRob Herring prop->next = NULL;
15476701c2c7SRob Herring return prop;
15486701c2c7SRob Herring }
15496701c2c7SRob Herring }
15506701c2c7SRob Herring return NULL;
15516701c2c7SRob Herring }
15526701c2c7SRob Herring
155302af11b0SGrant Likely /**
155462664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations
15553637d49eSLee Jones * @np: Caller's Device Node
155631e46db0SLee Jones * @prop: Property to add
155762664f67SXiubo Li */
__of_add_property(struct device_node * np,struct property * prop)1558d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop)
155962664f67SXiubo Li {
1560fab610beSRob Herring int rc = 0;
1561fab610beSRob Herring unsigned long flags;
156262664f67SXiubo Li struct property **next;
156362664f67SXiubo Li
1564fab610beSRob Herring raw_spin_lock_irqsave(&devtree_lock, flags);
1565fab610beSRob Herring
15666701c2c7SRob Herring __of_remove_property_from_list(&np->deadprops, prop);
15676701c2c7SRob Herring
156862664f67SXiubo Li prop->next = NULL;
156962664f67SXiubo Li next = &np->properties;
157062664f67SXiubo Li while (*next) {
1571fab610beSRob Herring if (strcmp(prop->name, (*next)->name) == 0) {
157262664f67SXiubo Li /* duplicate ! don't insert it */
1573fab610beSRob Herring rc = -EEXIST;
1574fab610beSRob Herring goto out_unlock;
1575fab610beSRob Herring }
157662664f67SXiubo Li next = &(*next)->next;
157762664f67SXiubo Li }
157862664f67SXiubo Li *next = prop;
157962664f67SXiubo Li
1580fab610beSRob Herring out_unlock:
1581fab610beSRob Herring raw_spin_unlock_irqrestore(&devtree_lock, flags);
1582fab610beSRob Herring if (rc)
1583fab610beSRob Herring return rc;
1584fab610beSRob Herring
1585fab610beSRob Herring __of_add_property_sysfs(np, prop);
158662664f67SXiubo Li return 0;
158762664f67SXiubo Li }
158862664f67SXiubo Li
158962664f67SXiubo Li /**
159079d1c712SNathan Fontenot * of_add_property - Add a property to a node
15913637d49eSLee Jones * @np: Caller's Device Node
159231e46db0SLee Jones * @prop: Property to add
159302af11b0SGrant Likely */
of_add_property(struct device_node * np,struct property * prop)159479d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop)
159502af11b0SGrant Likely {
15961cf3d8b3SNathan Fontenot int rc;
15971cf3d8b3SNathan Fontenot
15988a2b22a2SGrant Likely mutex_lock(&of_mutex);
159962664f67SXiubo Li rc = __of_add_property(np, prop);
16008a2b22a2SGrant Likely mutex_unlock(&of_mutex);
16018a2b22a2SGrant Likely
1602259092a3SGrant Likely if (!rc)
1603259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
1604259092a3SGrant Likely
160562664f67SXiubo Li return rc;
160602af11b0SGrant Likely }
1607fe794e39SWesley Cheng EXPORT_SYMBOL_GPL(of_add_property);
160802af11b0SGrant Likely
__of_remove_property(struct device_node * np,struct property * prop)1609d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop)
1610d8c50088SPantelis Antoniou {
1611fab610beSRob Herring unsigned long flags;
1612fab610beSRob Herring int rc = -ENODEV;
1613fab610beSRob Herring
1614fab610beSRob Herring raw_spin_lock_irqsave(&devtree_lock, flags);
1615fab610beSRob Herring
16166701c2c7SRob Herring if (__of_remove_property_from_list(&np->properties, prop)) {
16176701c2c7SRob Herring /* Found the property, add it to deadprops list */
1618d8c50088SPantelis Antoniou prop->next = np->deadprops;
1619d8c50088SPantelis Antoniou np->deadprops = prop;
1620fab610beSRob Herring rc = 0;
1621d8c50088SPantelis Antoniou }
1622d8c50088SPantelis Antoniou
1623fab610beSRob Herring raw_spin_unlock_irqrestore(&devtree_lock, flags);
1624fab610beSRob Herring if (rc)
1625fab610beSRob Herring return rc;
1626fab610beSRob Herring
1627fab610beSRob Herring __of_remove_property_sysfs(np, prop);
1628fab610beSRob Herring return 0;
16296701c2c7SRob Herring }
16306701c2c7SRob Herring
163102af11b0SGrant Likely /**
163279d1c712SNathan Fontenot * of_remove_property - Remove a property from a node.
16333637d49eSLee Jones * @np: Caller's Device Node
163431e46db0SLee Jones * @prop: Property to remove
163502af11b0SGrant Likely *
163602af11b0SGrant Likely * Note that we don't actually remove it, since we have given out
163702af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property.
163802af11b0SGrant Likely * Instead we just move the property to the "dead properties"
163902af11b0SGrant Likely * list, so it won't be found any more.
164002af11b0SGrant Likely */
of_remove_property(struct device_node * np,struct property * prop)164179d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop)
164202af11b0SGrant Likely {
16431cf3d8b3SNathan Fontenot int rc;
16441cf3d8b3SNathan Fontenot
1645201b3fe5SSuraj Jitindar Singh if (!prop)
1646201b3fe5SSuraj Jitindar Singh return -ENODEV;
1647201b3fe5SSuraj Jitindar Singh
16488a2b22a2SGrant Likely mutex_lock(&of_mutex);
1649d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop);
16508a2b22a2SGrant Likely mutex_unlock(&of_mutex);
16518a2b22a2SGrant Likely
1652259092a3SGrant Likely if (!rc)
1653259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
1654259092a3SGrant Likely
1655d8c50088SPantelis Antoniou return rc;
165602af11b0SGrant Likely }
16570f7c5317SFlorian Fainelli EXPORT_SYMBOL_GPL(of_remove_property);
165802af11b0SGrant Likely
__of_update_property(struct device_node * np,struct property * newprop,struct property ** oldpropp)1659d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop,
1660d8c50088SPantelis Antoniou struct property **oldpropp)
1661d8c50088SPantelis Antoniou {
1662d8c50088SPantelis Antoniou struct property **next, *oldprop;
1663fab610beSRob Herring unsigned long flags;
1664fab610beSRob Herring
1665fab610beSRob Herring raw_spin_lock_irqsave(&devtree_lock, flags);
1666d8c50088SPantelis Antoniou
16676701c2c7SRob Herring __of_remove_property_from_list(&np->deadprops, newprop);
16686701c2c7SRob Herring
1669d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) {
1670d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0)
1671d8c50088SPantelis Antoniou break;
1672d8c50088SPantelis Antoniou }
1673d8c50088SPantelis Antoniou *oldpropp = oldprop = *next;
1674d8c50088SPantelis Antoniou
1675d8c50088SPantelis Antoniou if (oldprop) {
1676d8c50088SPantelis Antoniou /* replace the node */
1677d8c50088SPantelis Antoniou newprop->next = oldprop->next;
1678d8c50088SPantelis Antoniou *next = newprop;
1679d8c50088SPantelis Antoniou oldprop->next = np->deadprops;
1680d8c50088SPantelis Antoniou np->deadprops = oldprop;
1681d8c50088SPantelis Antoniou } else {
1682d8c50088SPantelis Antoniou /* new node */
1683d8c50088SPantelis Antoniou newprop->next = NULL;
1684d8c50088SPantelis Antoniou *next = newprop;
1685d8c50088SPantelis Antoniou }
1686d8c50088SPantelis Antoniou
1687fab610beSRob Herring raw_spin_unlock_irqrestore(&devtree_lock, flags);
1688fab610beSRob Herring
1689fab610beSRob Herring __of_update_property_sysfs(np, newprop, oldprop);
1690fab610beSRob Herring
1691d8c50088SPantelis Antoniou return 0;
1692d8c50088SPantelis Antoniou }
1693d8c50088SPantelis Antoniou
169402af11b0SGrant Likely /*
169579d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does
1696475d0094SDong Aisheng * not exist, add it.
169702af11b0SGrant Likely *
169802af11b0SGrant Likely * Note that we don't actually remove it, since we have given out
169902af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property.
170002af11b0SGrant Likely * Instead we just move the property to the "dead properties" list,
170102af11b0SGrant Likely * and add the new property to the property list
170202af11b0SGrant Likely */
of_update_property(struct device_node * np,struct property * newprop)170379d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop)
170402af11b0SGrant Likely {
1705d8c50088SPantelis Antoniou struct property *oldprop;
1706947fdaadSXiubo Li int rc;
17071cf3d8b3SNathan Fontenot
1708475d0094SDong Aisheng if (!newprop->name)
1709475d0094SDong Aisheng return -EINVAL;
1710475d0094SDong Aisheng
17118a2b22a2SGrant Likely mutex_lock(&of_mutex);
1712d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop);
17138a2b22a2SGrant Likely mutex_unlock(&of_mutex);
17141cf3d8b3SNathan Fontenot
1715259092a3SGrant Likely if (!rc)
1716259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
1717fcdeb7feSGrant Likely
17181cf3d8b3SNathan Fontenot return rc;
1719e81b3295SNathan Fontenot }
1720e81b3295SNathan Fontenot
of_alias_add(struct alias_prop * ap,struct device_node * np,int id,const char * stem,int stem_len)1721611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1722611cad72SShawn Guo int id, const char *stem, int stem_len)
1723611cad72SShawn Guo {
1724611cad72SShawn Guo ap->np = np;
1725611cad72SShawn Guo ap->id = id;
1726a98bf9dfSXu Panda strscpy(ap->stem, stem, stem_len + 1);
1727611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup);
17280d638a07SRob Herring pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
17290d638a07SRob Herring ap->alias, ap->stem, ap->id, np);
1730611cad72SShawn Guo }
1731611cad72SShawn Guo
1732611cad72SShawn Guo /**
17331821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node
173462f026f0SRob Herring * @dt_alloc: An allocator that provides a virtual address to memory
173562f026f0SRob Herring * for storing the resulting tree
1736611cad72SShawn Guo *
17371821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates
17381821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the
17391821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure.
1740611cad72SShawn Guo */
of_alias_scan(void * (* dt_alloc)(u64 size,u64 align))1741611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1742611cad72SShawn Guo {
1743611cad72SShawn Guo struct property *pp;
1744611cad72SShawn Guo
17457dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases");
1746611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen");
1747611cad72SShawn Guo if (of_chosen == NULL)
1748611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0");
17495c19e952SSascha Hauer
17505c19e952SSascha Hauer if (of_chosen) {
1751a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */
1752b0d9d92fSSergei Shtylyov const char *name = NULL;
1753b0d9d92fSSergei Shtylyov
1754b0d9d92fSSergei Shtylyov if (of_property_read_string(of_chosen, "stdout-path", &name))
1755b0d9d92fSSergei Shtylyov of_property_read_string(of_chosen, "linux,stdout-path",
1756b0d9d92fSSergei Shtylyov &name);
1757a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name)
1758b0d9d92fSSergei Shtylyov of_property_read_string(of_aliases, "stdout", &name);
1759f64255b5SPeter Hurley if (name)
17607914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
1761a244ec36SSaravana Kannan if (of_stdout)
1762a244ec36SSaravana Kannan of_stdout->fwnode.flags |= FWNODE_FLAG_BEST_EFFORT;
17635c19e952SSascha Hauer }
17645c19e952SSascha Hauer
1765611cad72SShawn Guo if (!of_aliases)
1766611cad72SShawn Guo return;
1767611cad72SShawn Guo
17688af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) {
1769611cad72SShawn Guo const char *start = pp->name;
1770611cad72SShawn Guo const char *end = start + strlen(start);
1771611cad72SShawn Guo struct device_node *np;
1772611cad72SShawn Guo struct alias_prop *ap;
1773611cad72SShawn Guo int id, len;
1774611cad72SShawn Guo
1775611cad72SShawn Guo /* Skip those we do not want to proceed */
1776611cad72SShawn Guo if (!strcmp(pp->name, "name") ||
1777611cad72SShawn Guo !strcmp(pp->name, "phandle") ||
1778611cad72SShawn Guo !strcmp(pp->name, "linux,phandle"))
1779611cad72SShawn Guo continue;
1780611cad72SShawn Guo
1781611cad72SShawn Guo np = of_find_node_by_path(pp->value);
1782611cad72SShawn Guo if (!np)
1783611cad72SShawn Guo continue;
1784611cad72SShawn Guo
1785611cad72SShawn Guo /* walk the alias backwards to extract the id and work out
1786611cad72SShawn Guo * the 'stem' string */
1787611cad72SShawn Guo while (isdigit(*(end-1)) && end > start)
1788611cad72SShawn Guo end--;
1789611cad72SShawn Guo len = end - start;
1790611cad72SShawn Guo
1791611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0)
1792611cad72SShawn Guo continue;
1793611cad72SShawn Guo
1794611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */
1795de96ec2aSPaul Burton ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
1796611cad72SShawn Guo if (!ap)
1797611cad72SShawn Guo continue;
17980640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1);
1799611cad72SShawn Guo ap->alias = start;
1800611cad72SShawn Guo of_alias_add(ap, np, id, start, len);
1801611cad72SShawn Guo }
1802611cad72SShawn Guo }
1803611cad72SShawn Guo
1804611cad72SShawn Guo /**
1805611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node
1806611cad72SShawn Guo * @np: Pointer to the given device_node
1807611cad72SShawn Guo * @stem: Alias stem of the given device_node
1808611cad72SShawn Guo *
18095a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given
18108c8239c2SRob Herring * device_node and alias stem.
18118c8239c2SRob Herring *
18128c8239c2SRob Herring * Return: The alias id if found.
1813611cad72SShawn Guo */
of_alias_get_id(struct device_node * np,const char * stem)1814611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1815611cad72SShawn Guo {
1816611cad72SShawn Guo struct alias_prop *app;
1817611cad72SShawn Guo int id = -ENODEV;
1818611cad72SShawn Guo
1819c05aba2bSPantelis Antoniou mutex_lock(&of_mutex);
1820611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) {
1821611cad72SShawn Guo if (strcmp(app->stem, stem) != 0)
1822611cad72SShawn Guo continue;
1823611cad72SShawn Guo
1824611cad72SShawn Guo if (np == app->np) {
1825611cad72SShawn Guo id = app->id;
1826611cad72SShawn Guo break;
1827611cad72SShawn Guo }
1828611cad72SShawn Guo }
1829c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex);
1830611cad72SShawn Guo
1831611cad72SShawn Guo return id;
1832611cad72SShawn Guo }
1833611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1834c541adc6SStephen Warren
1835351d224fSWolfram Sang /**
1836351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem
1837351d224fSWolfram Sang * @stem: Alias stem to be examined
1838351d224fSWolfram Sang *
1839351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the
1840351d224fSWolfram Sang * given alias stem. It returns the alias id if found.
1841351d224fSWolfram Sang */
of_alias_get_highest_id(const char * stem)1842351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem)
1843351d224fSWolfram Sang {
1844351d224fSWolfram Sang struct alias_prop *app;
1845351d224fSWolfram Sang int id = -ENODEV;
1846351d224fSWolfram Sang
1847351d224fSWolfram Sang mutex_lock(&of_mutex);
1848351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) {
1849351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0)
1850351d224fSWolfram Sang continue;
1851351d224fSWolfram Sang
1852351d224fSWolfram Sang if (app->id > id)
1853351d224fSWolfram Sang id = app->id;
1854351d224fSWolfram Sang }
1855351d224fSWolfram Sang mutex_unlock(&of_mutex);
1856351d224fSWolfram Sang
1857351d224fSWolfram Sang return id;
1858351d224fSWolfram Sang }
1859351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
1860351d224fSWolfram Sang
18615c19e952SSascha Hauer /**
18623482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup
18633637d49eSLee Jones * @dn: Pointer to device node
18643637d49eSLee Jones * @name: Name to use for preferred console without index. ex. "ttyS"
18653637d49eSLee Jones * @index: Index to use for preferred console.
18665c19e952SSascha Hauer *
18673482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the
18688c8239c2SRob Herring * /chosen node. If it does then register it as the preferred console.
18698c8239c2SRob Herring *
18708c8239c2SRob Herring * Return: TRUE if console successfully setup. Otherwise return FALSE.
18715c19e952SSascha Hauer */
of_console_check(struct device_node * dn,char * name,int index)18723482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index)
18735c19e952SSascha Hauer {
18743482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline)
18755c19e952SSascha Hauer return false;
1876db179e0dSSergey Senozhatsky
1877db179e0dSSergey Senozhatsky /*
1878db179e0dSSergey Senozhatsky * XXX: cast `options' to char pointer to suppress complication
1879db179e0dSSergey Senozhatsky * warnings: printk, UART and console drivers expect char pointer.
1880db179e0dSSergey Senozhatsky */
1881db179e0dSSergey Senozhatsky return !add_preferred_console(name, index, (char *)of_stdout_options);
18825c19e952SSascha Hauer }
18833482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check);
1884a3e31b45SSudeep KarkadaNagesha
1885a3e31b45SSudeep KarkadaNagesha /**
1886a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache
1887a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache"
1888a3e31b45SSudeep KarkadaNagesha *
188962f026f0SRob Herring * Return: A node pointer with refcount incremented, use
1890a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference
1891a3e31b45SSudeep KarkadaNagesha * to np.
1892a3e31b45SSudeep KarkadaNagesha */
of_find_next_cache_node(const struct device_node * np)1893a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np)
1894a3e31b45SSudeep KarkadaNagesha {
189591d96749SRob Herring struct device_node *child, *cache_node;
1896a3e31b45SSudeep KarkadaNagesha
189791d96749SRob Herring cache_node = of_parse_phandle(np, "l2-cache", 0);
189891d96749SRob Herring if (!cache_node)
189991d96749SRob Herring cache_node = of_parse_phandle(np, "next-level-cache", 0);
1900a3e31b45SSudeep KarkadaNagesha
190191d96749SRob Herring if (cache_node)
190291d96749SRob Herring return cache_node;
1903a3e31b45SSudeep KarkadaNagesha
1904a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache"
1905a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes.
1906a3e31b45SSudeep KarkadaNagesha */
1907e8b1dee2SRob Herring if (IS_ENABLED(CONFIG_PPC_PMAC) && of_node_is_type(np, "cpu"))
1908a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child)
1909e8b1dee2SRob Herring if (of_node_is_type(child, "cache"))
1910a3e31b45SSudeep KarkadaNagesha return child;
1911a3e31b45SSudeep KarkadaNagesha
1912a3e31b45SSudeep KarkadaNagesha return NULL;
1913a3e31b45SSudeep KarkadaNagesha }
1914fd9fdb78SPhilipp Zabel
1915fd9fdb78SPhilipp Zabel /**
19165fa23530SSudeep Holla * of_find_last_cache_level - Find the level at which the last cache is
19175fa23530SSudeep Holla * present for the given logical cpu
19185fa23530SSudeep Holla *
19195fa23530SSudeep Holla * @cpu: cpu number(logical index) for which the last cache level is needed
19205fa23530SSudeep Holla *
19213a5230a8SDeming Wang * Return: The level at which the last cache is present. It is exactly
19225fa23530SSudeep Holla * same as the total number of cache levels for the given logical cpu.
19235fa23530SSudeep Holla */
of_find_last_cache_level(unsigned int cpu)19245fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu)
19255fa23530SSudeep Holla {
19265fa23530SSudeep Holla u32 cache_level = 0;
19275fa23530SSudeep Holla struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
19285fa23530SSudeep Holla
19295fa23530SSudeep Holla while (np) {
19307a7f5857SPierre Gondois of_node_put(prev);
19315fa23530SSudeep Holla prev = np;
19325fa23530SSudeep Holla np = of_find_next_cache_node(np);
19335fa23530SSudeep Holla }
19345fa23530SSudeep Holla
19355fa23530SSudeep Holla of_property_read_u32(prev, "cache-level", &cache_level);
19367a7f5857SPierre Gondois of_node_put(prev);
19375fa23530SSudeep Holla
19385fa23530SSudeep Holla return cache_level;
19395fa23530SSudeep Holla }
19402a6db719SNipun Gupta
19412a6db719SNipun Gupta /**
1942746a71d0SLorenzo Pieralisi * of_map_id - Translate an ID through a downstream mapping.
19432a6db719SNipun Gupta * @np: root complex device node.
1944746a71d0SLorenzo Pieralisi * @id: device ID to map.
19452a6db719SNipun Gupta * @map_name: property name of the map to use.
19462a6db719SNipun Gupta * @map_mask_name: optional property name of the mask to use.
19472a6db719SNipun Gupta * @target: optional pointer to a target device node.
19482a6db719SNipun Gupta * @id_out: optional pointer to receive the translated ID.
19492a6db719SNipun Gupta *
1950746a71d0SLorenzo Pieralisi * Given a device ID, look up the appropriate implementation-defined
19512a6db719SNipun Gupta * platform ID and/or the target device which receives transactions on that
19522a6db719SNipun Gupta * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
19532a6db719SNipun Gupta * @id_out may be NULL if only the other is required. If @target points to
19542a6db719SNipun Gupta * a non-NULL device node pointer, only entries targeting that node will be
19552a6db719SNipun Gupta * matched; if it points to a NULL value, it will receive the device node of
19562a6db719SNipun Gupta * the first matching target phandle, with a reference held.
19572a6db719SNipun Gupta *
19582a6db719SNipun Gupta * Return: 0 on success or a standard error code on failure.
19592a6db719SNipun Gupta */
of_map_id(struct device_node * np,u32 id,const char * map_name,const char * map_mask_name,struct device_node ** target,u32 * id_out)1960746a71d0SLorenzo Pieralisi int of_map_id(struct device_node *np, u32 id,
19612a6db719SNipun Gupta const char *map_name, const char *map_mask_name,
19622a6db719SNipun Gupta struct device_node **target, u32 *id_out)
19632a6db719SNipun Gupta {
1964746a71d0SLorenzo Pieralisi u32 map_mask, masked_id;
19652a6db719SNipun Gupta int map_len;
19662a6db719SNipun Gupta const __be32 *map = NULL;
19672a6db719SNipun Gupta
19682a6db719SNipun Gupta if (!np || !map_name || (!target && !id_out))
19692a6db719SNipun Gupta return -EINVAL;
19702a6db719SNipun Gupta
19712a6db719SNipun Gupta map = of_get_property(np, map_name, &map_len);
19722a6db719SNipun Gupta if (!map) {
19732a6db719SNipun Gupta if (target)
19742a6db719SNipun Gupta return -ENODEV;
19752a6db719SNipun Gupta /* Otherwise, no map implies no translation */
1976746a71d0SLorenzo Pieralisi *id_out = id;
19772a6db719SNipun Gupta return 0;
19782a6db719SNipun Gupta }
19792a6db719SNipun Gupta
19802a6db719SNipun Gupta if (!map_len || map_len % (4 * sizeof(*map))) {
19812a6db719SNipun Gupta pr_err("%pOF: Error: Bad %s length: %d\n", np,
19822a6db719SNipun Gupta map_name, map_len);
19832a6db719SNipun Gupta return -EINVAL;
19842a6db719SNipun Gupta }
19852a6db719SNipun Gupta
19862a6db719SNipun Gupta /* The default is to select all bits. */
19872a6db719SNipun Gupta map_mask = 0xffffffff;
19882a6db719SNipun Gupta
19892a6db719SNipun Gupta /*
19902a6db719SNipun Gupta * Can be overridden by "{iommu,msi}-map-mask" property.
19912a6db719SNipun Gupta * If of_property_read_u32() fails, the default is used.
19922a6db719SNipun Gupta */
19932a6db719SNipun Gupta if (map_mask_name)
19942a6db719SNipun Gupta of_property_read_u32(np, map_mask_name, &map_mask);
19952a6db719SNipun Gupta
1996746a71d0SLorenzo Pieralisi masked_id = map_mask & id;
19972a6db719SNipun Gupta for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
19982a6db719SNipun Gupta struct device_node *phandle_node;
1999746a71d0SLorenzo Pieralisi u32 id_base = be32_to_cpup(map + 0);
20002a6db719SNipun Gupta u32 phandle = be32_to_cpup(map + 1);
20012a6db719SNipun Gupta u32 out_base = be32_to_cpup(map + 2);
2002746a71d0SLorenzo Pieralisi u32 id_len = be32_to_cpup(map + 3);
20032a6db719SNipun Gupta
2004746a71d0SLorenzo Pieralisi if (id_base & ~map_mask) {
2005746a71d0SLorenzo Pieralisi pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
20062a6db719SNipun Gupta np, map_name, map_name,
2007746a71d0SLorenzo Pieralisi map_mask, id_base);
20082a6db719SNipun Gupta return -EFAULT;
20092a6db719SNipun Gupta }
20102a6db719SNipun Gupta
2011746a71d0SLorenzo Pieralisi if (masked_id < id_base || masked_id >= id_base + id_len)
20122a6db719SNipun Gupta continue;
20132a6db719SNipun Gupta
20142a6db719SNipun Gupta phandle_node = of_find_node_by_phandle(phandle);
20152a6db719SNipun Gupta if (!phandle_node)
20162a6db719SNipun Gupta return -ENODEV;
20172a6db719SNipun Gupta
20182a6db719SNipun Gupta if (target) {
20192a6db719SNipun Gupta if (*target)
20202a6db719SNipun Gupta of_node_put(phandle_node);
20212a6db719SNipun Gupta else
20222a6db719SNipun Gupta *target = phandle_node;
20232a6db719SNipun Gupta
20242a6db719SNipun Gupta if (*target != phandle_node)
20252a6db719SNipun Gupta continue;
20262a6db719SNipun Gupta }
20272a6db719SNipun Gupta
20282a6db719SNipun Gupta if (id_out)
2029746a71d0SLorenzo Pieralisi *id_out = masked_id - id_base + out_base;
20302a6db719SNipun Gupta
2031746a71d0SLorenzo Pieralisi pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
2032746a71d0SLorenzo Pieralisi np, map_name, map_mask, id_base, out_base,
2033746a71d0SLorenzo Pieralisi id_len, id, masked_id - id_base + out_base);
20342a6db719SNipun Gupta return 0;
20352a6db719SNipun Gupta }
20362a6db719SNipun Gupta
2037746a71d0SLorenzo Pieralisi pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
2038746a71d0SLorenzo Pieralisi id, target && *target ? *target : NULL);
2039fb709b5eSJean-Philippe Brucker
2040fb709b5eSJean-Philippe Brucker /* Bypasses translation */
2041fb709b5eSJean-Philippe Brucker if (id_out)
2042746a71d0SLorenzo Pieralisi *id_out = id;
2043fb709b5eSJean-Philippe Brucker return 0;
20442a6db719SNipun Gupta }
2045746a71d0SLorenzo Pieralisi EXPORT_SYMBOL_GPL(of_map_id);
2046