xref: /rk3399_rockchip-uboot/drivers/core/of_access.c (revision 644ec0a933ef5c4f8e82b9fd8df9439386d0444d)
1*644ec0a9SSimon Glass /*
2*644ec0a9SSimon Glass  * Originally from Linux v4.9
3*644ec0a9SSimon Glass  * Paul Mackerras	August 1996.
4*644ec0a9SSimon Glass  * Copyright (C) 1996-2005 Paul Mackerras.
5*644ec0a9SSimon Glass  *
6*644ec0a9SSimon Glass  * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
7*644ec0a9SSimon Glass  *   {engebret|bergner}@us.ibm.com
8*644ec0a9SSimon Glass  *
9*644ec0a9SSimon Glass  * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
10*644ec0a9SSimon Glass  *
11*644ec0a9SSimon Glass  * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
12*644ec0a9SSimon Glass  * Grant Likely.
13*644ec0a9SSimon Glass  *
14*644ec0a9SSimon Glass  * Modified for U-Boot
15*644ec0a9SSimon Glass  * Copyright (c) 2017 Google, Inc
16*644ec0a9SSimon Glass  *
17*644ec0a9SSimon Glass  * This file follows drivers/of/base.c with functions in the same order as the
18*644ec0a9SSimon Glass  * Linux version.
19*644ec0a9SSimon Glass  *
20*644ec0a9SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
21*644ec0a9SSimon Glass  */
22*644ec0a9SSimon Glass 
23*644ec0a9SSimon Glass #include <common.h>
24*644ec0a9SSimon Glass #include <libfdt.h>
25*644ec0a9SSimon Glass #include <dm/of_access.h>
26*644ec0a9SSimon Glass #include <linux/ctype.h>
27*644ec0a9SSimon Glass #include <linux/err.h>
28*644ec0a9SSimon Glass #include <linux/ioport.h>
29*644ec0a9SSimon Glass 
30*644ec0a9SSimon Glass DECLARE_GLOBAL_DATA_PTR;
31*644ec0a9SSimon Glass 
32*644ec0a9SSimon Glass /* list of struct alias_prop aliases */
33*644ec0a9SSimon Glass LIST_HEAD(aliases_lookup);
34*644ec0a9SSimon Glass 
35*644ec0a9SSimon Glass /* "/aliaes" node */
36*644ec0a9SSimon Glass static struct device_node *of_aliases;
37*644ec0a9SSimon Glass 
38*644ec0a9SSimon Glass /* "/chosen" node */
39*644ec0a9SSimon Glass static struct device_node *of_chosen;
40*644ec0a9SSimon Glass 
41*644ec0a9SSimon Glass /* node pointed to by the stdout-path alias */
42*644ec0a9SSimon Glass static struct device_node *of_stdout;
43*644ec0a9SSimon Glass 
44*644ec0a9SSimon Glass /* pointer to options given after the alias (separated by :) or NULL if none */
45*644ec0a9SSimon Glass static const char *of_stdout_options;
46*644ec0a9SSimon Glass 
47*644ec0a9SSimon Glass /**
48*644ec0a9SSimon Glass  * struct alias_prop - Alias property in 'aliases' node
49*644ec0a9SSimon Glass  *
50*644ec0a9SSimon Glass  * The structure represents one alias property of 'aliases' node as
51*644ec0a9SSimon Glass  * an entry in aliases_lookup list.
52*644ec0a9SSimon Glass  *
53*644ec0a9SSimon Glass  * @link:	List node to link the structure in aliases_lookup list
54*644ec0a9SSimon Glass  * @alias:	Alias property name
55*644ec0a9SSimon Glass  * @np:		Pointer to device_node that the alias stands for
56*644ec0a9SSimon Glass  * @id:		Index value from end of alias name
57*644ec0a9SSimon Glass  * @stem:	Alias string without the index
58*644ec0a9SSimon Glass  */
59*644ec0a9SSimon Glass struct alias_prop {
60*644ec0a9SSimon Glass 	struct list_head link;
61*644ec0a9SSimon Glass 	const char *alias;
62*644ec0a9SSimon Glass 	struct device_node *np;
63*644ec0a9SSimon Glass 	int id;
64*644ec0a9SSimon Glass 	char stem[0];
65*644ec0a9SSimon Glass };
66*644ec0a9SSimon Glass 
67*644ec0a9SSimon Glass int of_n_addr_cells(const struct device_node *np)
68*644ec0a9SSimon Glass {
69*644ec0a9SSimon Glass 	const __be32 *ip;
70*644ec0a9SSimon Glass 
71*644ec0a9SSimon Glass 	do {
72*644ec0a9SSimon Glass 		if (np->parent)
73*644ec0a9SSimon Glass 			np = np->parent;
74*644ec0a9SSimon Glass 		ip = of_get_property(np, "#address-cells", NULL);
75*644ec0a9SSimon Glass 		if (ip)
76*644ec0a9SSimon Glass 			return be32_to_cpup(ip);
77*644ec0a9SSimon Glass 	} while (np->parent);
78*644ec0a9SSimon Glass 
79*644ec0a9SSimon Glass 	/* No #address-cells property for the root node */
80*644ec0a9SSimon Glass 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
81*644ec0a9SSimon Glass }
82*644ec0a9SSimon Glass 
83*644ec0a9SSimon Glass int of_n_size_cells(const struct device_node *np)
84*644ec0a9SSimon Glass {
85*644ec0a9SSimon Glass 	const __be32 *ip;
86*644ec0a9SSimon Glass 
87*644ec0a9SSimon Glass 	do {
88*644ec0a9SSimon Glass 		if (np->parent)
89*644ec0a9SSimon Glass 			np = np->parent;
90*644ec0a9SSimon Glass 		ip = of_get_property(np, "#size-cells", NULL);
91*644ec0a9SSimon Glass 		if (ip)
92*644ec0a9SSimon Glass 			return be32_to_cpup(ip);
93*644ec0a9SSimon Glass 	} while (np->parent);
94*644ec0a9SSimon Glass 
95*644ec0a9SSimon Glass 	/* No #size-cells property for the root node */
96*644ec0a9SSimon Glass 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
97*644ec0a9SSimon Glass }
98*644ec0a9SSimon Glass 
99*644ec0a9SSimon Glass struct property *of_find_property(const struct device_node *np,
100*644ec0a9SSimon Glass 				  const char *name, int *lenp)
101*644ec0a9SSimon Glass {
102*644ec0a9SSimon Glass 	struct property *pp;
103*644ec0a9SSimon Glass 
104*644ec0a9SSimon Glass 	if (!np)
105*644ec0a9SSimon Glass 		return NULL;
106*644ec0a9SSimon Glass 
107*644ec0a9SSimon Glass 	for (pp = np->properties; pp; pp = pp->next) {
108*644ec0a9SSimon Glass 		if (strcmp(pp->name, name) == 0) {
109*644ec0a9SSimon Glass 			if (lenp)
110*644ec0a9SSimon Glass 				*lenp = pp->length;
111*644ec0a9SSimon Glass 			break;
112*644ec0a9SSimon Glass 		}
113*644ec0a9SSimon Glass 	}
114*644ec0a9SSimon Glass 	if (!pp && lenp)
115*644ec0a9SSimon Glass 		*lenp = -FDT_ERR_NOTFOUND;
116*644ec0a9SSimon Glass 
117*644ec0a9SSimon Glass 	return pp;
118*644ec0a9SSimon Glass }
119*644ec0a9SSimon Glass 
120*644ec0a9SSimon Glass struct device_node *of_find_all_nodes(struct device_node *prev)
121*644ec0a9SSimon Glass {
122*644ec0a9SSimon Glass 	struct device_node *np;
123*644ec0a9SSimon Glass 
124*644ec0a9SSimon Glass 	if (!prev) {
125*644ec0a9SSimon Glass 		np = gd->of_root;
126*644ec0a9SSimon Glass 	} else if (prev->child) {
127*644ec0a9SSimon Glass 		np = prev->child;
128*644ec0a9SSimon Glass 	} else {
129*644ec0a9SSimon Glass 		/*
130*644ec0a9SSimon Glass 		 * Walk back up looking for a sibling, or the end of the
131*644ec0a9SSimon Glass 		 * structure
132*644ec0a9SSimon Glass 		 */
133*644ec0a9SSimon Glass 		np = prev;
134*644ec0a9SSimon Glass 		while (np->parent && !np->sibling)
135*644ec0a9SSimon Glass 			np = np->parent;
136*644ec0a9SSimon Glass 		np = np->sibling; /* Might be null at the end of the tree */
137*644ec0a9SSimon Glass 	}
138*644ec0a9SSimon Glass 
139*644ec0a9SSimon Glass 	return np;
140*644ec0a9SSimon Glass }
141*644ec0a9SSimon Glass 
142*644ec0a9SSimon Glass const void *of_get_property(const struct device_node *np, const char *name,
143*644ec0a9SSimon Glass 			    int *lenp)
144*644ec0a9SSimon Glass {
145*644ec0a9SSimon Glass 	struct property *pp = of_find_property(np, name, lenp);
146*644ec0a9SSimon Glass 
147*644ec0a9SSimon Glass 	return pp ? pp->value : NULL;
148*644ec0a9SSimon Glass }
149*644ec0a9SSimon Glass 
150*644ec0a9SSimon Glass static const char *of_prop_next_string(struct property *prop, const char *cur)
151*644ec0a9SSimon Glass {
152*644ec0a9SSimon Glass 	const void *curv = cur;
153*644ec0a9SSimon Glass 
154*644ec0a9SSimon Glass 	if (!prop)
155*644ec0a9SSimon Glass 		return NULL;
156*644ec0a9SSimon Glass 
157*644ec0a9SSimon Glass 	if (!cur)
158*644ec0a9SSimon Glass 		return prop->value;
159*644ec0a9SSimon Glass 
160*644ec0a9SSimon Glass 	curv += strlen(cur) + 1;
161*644ec0a9SSimon Glass 	if (curv >= prop->value + prop->length)
162*644ec0a9SSimon Glass 		return NULL;
163*644ec0a9SSimon Glass 
164*644ec0a9SSimon Glass 	return curv;
165*644ec0a9SSimon Glass }
166*644ec0a9SSimon Glass 
167*644ec0a9SSimon Glass int of_device_is_compatible(const struct device_node *device,
168*644ec0a9SSimon Glass 			    const char *compat, const char *type,
169*644ec0a9SSimon Glass 			    const char *name)
170*644ec0a9SSimon Glass {
171*644ec0a9SSimon Glass 	struct property *prop;
172*644ec0a9SSimon Glass 	const char *cp;
173*644ec0a9SSimon Glass 	int index = 0, score = 0;
174*644ec0a9SSimon Glass 
175*644ec0a9SSimon Glass 	/* Compatible match has highest priority */
176*644ec0a9SSimon Glass 	if (compat && compat[0]) {
177*644ec0a9SSimon Glass 		prop = of_find_property(device, "compatible", NULL);
178*644ec0a9SSimon Glass 		for (cp = of_prop_next_string(prop, NULL); cp;
179*644ec0a9SSimon Glass 		     cp = of_prop_next_string(prop, cp), index++) {
180*644ec0a9SSimon Glass 			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
181*644ec0a9SSimon Glass 				score = INT_MAX/2 - (index << 2);
182*644ec0a9SSimon Glass 				break;
183*644ec0a9SSimon Glass 			}
184*644ec0a9SSimon Glass 		}
185*644ec0a9SSimon Glass 		if (!score)
186*644ec0a9SSimon Glass 			return 0;
187*644ec0a9SSimon Glass 	}
188*644ec0a9SSimon Glass 
189*644ec0a9SSimon Glass 	/* Matching type is better than matching name */
190*644ec0a9SSimon Glass 	if (type && type[0]) {
191*644ec0a9SSimon Glass 		if (!device->type || of_node_cmp(type, device->type))
192*644ec0a9SSimon Glass 			return 0;
193*644ec0a9SSimon Glass 		score += 2;
194*644ec0a9SSimon Glass 	}
195*644ec0a9SSimon Glass 
196*644ec0a9SSimon Glass 	/* Matching name is a bit better than not */
197*644ec0a9SSimon Glass 	if (name && name[0]) {
198*644ec0a9SSimon Glass 		if (!device->name || of_node_cmp(name, device->name))
199*644ec0a9SSimon Glass 			return 0;
200*644ec0a9SSimon Glass 		score++;
201*644ec0a9SSimon Glass 	}
202*644ec0a9SSimon Glass 
203*644ec0a9SSimon Glass 	return score;
204*644ec0a9SSimon Glass }
205*644ec0a9SSimon Glass 
206*644ec0a9SSimon Glass bool of_device_is_available(const struct device_node *device)
207*644ec0a9SSimon Glass {
208*644ec0a9SSimon Glass 	const char *status;
209*644ec0a9SSimon Glass 	int statlen;
210*644ec0a9SSimon Glass 
211*644ec0a9SSimon Glass 	if (!device)
212*644ec0a9SSimon Glass 		return false;
213*644ec0a9SSimon Glass 
214*644ec0a9SSimon Glass 	status = of_get_property(device, "status", &statlen);
215*644ec0a9SSimon Glass 	if (status == NULL)
216*644ec0a9SSimon Glass 		return true;
217*644ec0a9SSimon Glass 
218*644ec0a9SSimon Glass 	if (statlen > 0) {
219*644ec0a9SSimon Glass 		if (!strcmp(status, "okay"))
220*644ec0a9SSimon Glass 			return true;
221*644ec0a9SSimon Glass 	}
222*644ec0a9SSimon Glass 
223*644ec0a9SSimon Glass 	return false;
224*644ec0a9SSimon Glass }
225*644ec0a9SSimon Glass 
226*644ec0a9SSimon Glass struct device_node *of_get_parent(const struct device_node *node)
227*644ec0a9SSimon Glass {
228*644ec0a9SSimon Glass 	const struct device_node *np;
229*644ec0a9SSimon Glass 
230*644ec0a9SSimon Glass 	if (!node)
231*644ec0a9SSimon Glass 		return NULL;
232*644ec0a9SSimon Glass 
233*644ec0a9SSimon Glass 	np = of_node_get(node->parent);
234*644ec0a9SSimon Glass 
235*644ec0a9SSimon Glass 	return (struct device_node *)np;
236*644ec0a9SSimon Glass }
237*644ec0a9SSimon Glass 
238*644ec0a9SSimon Glass static struct device_node *__of_get_next_child(const struct device_node *node,
239*644ec0a9SSimon Glass 					       struct device_node *prev)
240*644ec0a9SSimon Glass {
241*644ec0a9SSimon Glass 	struct device_node *next;
242*644ec0a9SSimon Glass 
243*644ec0a9SSimon Glass 	if (!node)
244*644ec0a9SSimon Glass 		return NULL;
245*644ec0a9SSimon Glass 
246*644ec0a9SSimon Glass 	next = prev ? prev->sibling : node->child;
247*644ec0a9SSimon Glass 	for (; next; next = next->sibling)
248*644ec0a9SSimon Glass 		if (of_node_get(next))
249*644ec0a9SSimon Glass 			break;
250*644ec0a9SSimon Glass 	of_node_put(prev);
251*644ec0a9SSimon Glass 	return next;
252*644ec0a9SSimon Glass }
253*644ec0a9SSimon Glass 
254*644ec0a9SSimon Glass #define __for_each_child_of_node(parent, child) \
255*644ec0a9SSimon Glass 	for (child = __of_get_next_child(parent, NULL); child != NULL; \
256*644ec0a9SSimon Glass 	     child = __of_get_next_child(parent, child))
257*644ec0a9SSimon Glass 
258*644ec0a9SSimon Glass static struct device_node *__of_find_node_by_path(struct device_node *parent,
259*644ec0a9SSimon Glass 						  const char *path)
260*644ec0a9SSimon Glass {
261*644ec0a9SSimon Glass 	struct device_node *child;
262*644ec0a9SSimon Glass 	int len;
263*644ec0a9SSimon Glass 
264*644ec0a9SSimon Glass 	len = strcspn(path, "/:");
265*644ec0a9SSimon Glass 	if (!len)
266*644ec0a9SSimon Glass 		return NULL;
267*644ec0a9SSimon Glass 
268*644ec0a9SSimon Glass 	__for_each_child_of_node(parent, child) {
269*644ec0a9SSimon Glass 		const char *name = strrchr(child->full_name, '/');
270*644ec0a9SSimon Glass 
271*644ec0a9SSimon Glass 		name++;
272*644ec0a9SSimon Glass 		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
273*644ec0a9SSimon Glass 			return child;
274*644ec0a9SSimon Glass 	}
275*644ec0a9SSimon Glass 	return NULL;
276*644ec0a9SSimon Glass }
277*644ec0a9SSimon Glass 
278*644ec0a9SSimon Glass #define for_each_property_of_node(dn, pp) \
279*644ec0a9SSimon Glass 	for (pp = dn->properties; pp != NULL; pp = pp->next)
280*644ec0a9SSimon Glass 
281*644ec0a9SSimon Glass struct device_node *of_find_node_opts_by_path(const char *path,
282*644ec0a9SSimon Glass 					      const char **opts)
283*644ec0a9SSimon Glass {
284*644ec0a9SSimon Glass 	struct device_node *np = NULL;
285*644ec0a9SSimon Glass 	struct property *pp;
286*644ec0a9SSimon Glass 	const char *separator = strchr(path, ':');
287*644ec0a9SSimon Glass 
288*644ec0a9SSimon Glass 	if (opts)
289*644ec0a9SSimon Glass 		*opts = separator ? separator + 1 : NULL;
290*644ec0a9SSimon Glass 
291*644ec0a9SSimon Glass 	if (strcmp(path, "/") == 0)
292*644ec0a9SSimon Glass 		return of_node_get(gd->of_root);
293*644ec0a9SSimon Glass 
294*644ec0a9SSimon Glass 	/* The path could begin with an alias */
295*644ec0a9SSimon Glass 	if (*path != '/') {
296*644ec0a9SSimon Glass 		int len;
297*644ec0a9SSimon Glass 		const char *p = separator;
298*644ec0a9SSimon Glass 
299*644ec0a9SSimon Glass 		if (!p)
300*644ec0a9SSimon Glass 			p = strchrnul(path, '/');
301*644ec0a9SSimon Glass 		len = p - path;
302*644ec0a9SSimon Glass 
303*644ec0a9SSimon Glass 		/* of_aliases must not be NULL */
304*644ec0a9SSimon Glass 		if (!of_aliases)
305*644ec0a9SSimon Glass 			return NULL;
306*644ec0a9SSimon Glass 
307*644ec0a9SSimon Glass 		for_each_property_of_node(of_aliases, pp) {
308*644ec0a9SSimon Glass 			if (strlen(pp->name) == len && !strncmp(pp->name, path,
309*644ec0a9SSimon Glass 								len)) {
310*644ec0a9SSimon Glass 				np = of_find_node_by_path(pp->value);
311*644ec0a9SSimon Glass 				break;
312*644ec0a9SSimon Glass 			}
313*644ec0a9SSimon Glass 		}
314*644ec0a9SSimon Glass 		if (!np)
315*644ec0a9SSimon Glass 			return NULL;
316*644ec0a9SSimon Glass 		path = p;
317*644ec0a9SSimon Glass 	}
318*644ec0a9SSimon Glass 
319*644ec0a9SSimon Glass 	/* Step down the tree matching path components */
320*644ec0a9SSimon Glass 	if (!np)
321*644ec0a9SSimon Glass 		np = of_node_get(gd->of_root);
322*644ec0a9SSimon Glass 	while (np && *path == '/') {
323*644ec0a9SSimon Glass 		struct device_node *tmp = np;
324*644ec0a9SSimon Glass 
325*644ec0a9SSimon Glass 		path++; /* Increment past '/' delimiter */
326*644ec0a9SSimon Glass 		np = __of_find_node_by_path(np, path);
327*644ec0a9SSimon Glass 		of_node_put(tmp);
328*644ec0a9SSimon Glass 		path = strchrnul(path, '/');
329*644ec0a9SSimon Glass 		if (separator && separator < path)
330*644ec0a9SSimon Glass 			break;
331*644ec0a9SSimon Glass 	}
332*644ec0a9SSimon Glass 
333*644ec0a9SSimon Glass 	return np;
334*644ec0a9SSimon Glass }
335*644ec0a9SSimon Glass 
336*644ec0a9SSimon Glass struct device_node *of_find_compatible_node(struct device_node *from,
337*644ec0a9SSimon Glass 		const char *type, const char *compatible)
338*644ec0a9SSimon Glass {
339*644ec0a9SSimon Glass 	struct device_node *np;
340*644ec0a9SSimon Glass 
341*644ec0a9SSimon Glass 	for_each_of_allnodes_from(from, np)
342*644ec0a9SSimon Glass 		if (of_device_is_compatible(np, compatible, type, NULL) &&
343*644ec0a9SSimon Glass 		    of_node_get(np))
344*644ec0a9SSimon Glass 			break;
345*644ec0a9SSimon Glass 	of_node_put(from);
346*644ec0a9SSimon Glass 
347*644ec0a9SSimon Glass 	return np;
348*644ec0a9SSimon Glass }
349*644ec0a9SSimon Glass 
350*644ec0a9SSimon Glass struct device_node *of_find_node_by_phandle(phandle handle)
351*644ec0a9SSimon Glass {
352*644ec0a9SSimon Glass 	struct device_node *np;
353*644ec0a9SSimon Glass 
354*644ec0a9SSimon Glass 	if (!handle)
355*644ec0a9SSimon Glass 		return NULL;
356*644ec0a9SSimon Glass 
357*644ec0a9SSimon Glass 	for_each_of_allnodes(np)
358*644ec0a9SSimon Glass 		if (np->phandle == handle)
359*644ec0a9SSimon Glass 			break;
360*644ec0a9SSimon Glass 	(void)of_node_get(np);
361*644ec0a9SSimon Glass 
362*644ec0a9SSimon Glass 	return np;
363*644ec0a9SSimon Glass }
364*644ec0a9SSimon Glass 
365*644ec0a9SSimon Glass /**
366*644ec0a9SSimon Glass  * of_find_property_value_of_size() - find property of given size
367*644ec0a9SSimon Glass  *
368*644ec0a9SSimon Glass  * Search for a property in a device node and validate the requested size.
369*644ec0a9SSimon Glass  *
370*644ec0a9SSimon Glass  * @np:		device node from which the property value is to be read.
371*644ec0a9SSimon Glass  * @propname:	name of the property to be searched.
372*644ec0a9SSimon Glass  * @len:	requested length of property value
373*644ec0a9SSimon Glass  *
374*644ec0a9SSimon Glass  * @return the property value on success, -EINVAL if the property does not
375*644ec0a9SSimon Glass  * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
376*644ec0a9SSimon Glass  * property data isn't large enough.
377*644ec0a9SSimon Glass  */
378*644ec0a9SSimon Glass static void *of_find_property_value_of_size(const struct device_node *np,
379*644ec0a9SSimon Glass 					    const char *propname, u32 len)
380*644ec0a9SSimon Glass {
381*644ec0a9SSimon Glass 	struct property *prop = of_find_property(np, propname, NULL);
382*644ec0a9SSimon Glass 
383*644ec0a9SSimon Glass 	if (!prop)
384*644ec0a9SSimon Glass 		return ERR_PTR(-EINVAL);
385*644ec0a9SSimon Glass 	if (!prop->value)
386*644ec0a9SSimon Glass 		return ERR_PTR(-ENODATA);
387*644ec0a9SSimon Glass 	if (len > prop->length)
388*644ec0a9SSimon Glass 		return ERR_PTR(-EOVERFLOW);
389*644ec0a9SSimon Glass 
390*644ec0a9SSimon Glass 	return prop->value;
391*644ec0a9SSimon Glass }
392*644ec0a9SSimon Glass 
393*644ec0a9SSimon Glass int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
394*644ec0a9SSimon Glass {
395*644ec0a9SSimon Glass 	const __be32 *val;
396*644ec0a9SSimon Glass 
397*644ec0a9SSimon Glass 	debug("%s: %s: ", __func__, propname);
398*644ec0a9SSimon Glass 	if (!np)
399*644ec0a9SSimon Glass 		return -EINVAL;
400*644ec0a9SSimon Glass 	val = of_find_property_value_of_size(np, propname, sizeof(*outp));
401*644ec0a9SSimon Glass 	if (IS_ERR(val)) {
402*644ec0a9SSimon Glass 		debug("(not found)\n");
403*644ec0a9SSimon Glass 		return PTR_ERR(val);
404*644ec0a9SSimon Glass 	}
405*644ec0a9SSimon Glass 
406*644ec0a9SSimon Glass 	*outp = be32_to_cpup(val);
407*644ec0a9SSimon Glass 	debug("%#x (%d)\n", *outp, *outp);
408*644ec0a9SSimon Glass 
409*644ec0a9SSimon Glass 	return 0;
410*644ec0a9SSimon Glass }
411*644ec0a9SSimon Glass 
412*644ec0a9SSimon Glass int of_read_u32_array(const struct device_node *np, const char *propname,
413*644ec0a9SSimon Glass 		      u32 *out_values, size_t sz)
414*644ec0a9SSimon Glass {
415*644ec0a9SSimon Glass 	const __be32 *val;
416*644ec0a9SSimon Glass 
417*644ec0a9SSimon Glass 	debug("%s: %s: ", __func__, propname);
418*644ec0a9SSimon Glass 	val = of_find_property_value_of_size(np, propname,
419*644ec0a9SSimon Glass 					     sz * sizeof(*out_values));
420*644ec0a9SSimon Glass 
421*644ec0a9SSimon Glass 	if (IS_ERR(val))
422*644ec0a9SSimon Glass 		return PTR_ERR(val);
423*644ec0a9SSimon Glass 
424*644ec0a9SSimon Glass 	debug("size %zd\n", sz);
425*644ec0a9SSimon Glass 	while (sz--)
426*644ec0a9SSimon Glass 		*out_values++ = be32_to_cpup(val++);
427*644ec0a9SSimon Glass 
428*644ec0a9SSimon Glass 	return 0;
429*644ec0a9SSimon Glass }
430*644ec0a9SSimon Glass 
431*644ec0a9SSimon Glass int of_property_match_string(const struct device_node *np, const char *propname,
432*644ec0a9SSimon Glass 			     const char *string)
433*644ec0a9SSimon Glass {
434*644ec0a9SSimon Glass 	const struct property *prop = of_find_property(np, propname, NULL);
435*644ec0a9SSimon Glass 	size_t l;
436*644ec0a9SSimon Glass 	int i;
437*644ec0a9SSimon Glass 	const char *p, *end;
438*644ec0a9SSimon Glass 
439*644ec0a9SSimon Glass 	if (!prop)
440*644ec0a9SSimon Glass 		return -EINVAL;
441*644ec0a9SSimon Glass 	if (!prop->value)
442*644ec0a9SSimon Glass 		return -ENODATA;
443*644ec0a9SSimon Glass 
444*644ec0a9SSimon Glass 	p = prop->value;
445*644ec0a9SSimon Glass 	end = p + prop->length;
446*644ec0a9SSimon Glass 
447*644ec0a9SSimon Glass 	for (i = 0; p < end; i++, p += l) {
448*644ec0a9SSimon Glass 		l = strnlen(p, end - p) + 1;
449*644ec0a9SSimon Glass 		if (p + l > end)
450*644ec0a9SSimon Glass 			return -EILSEQ;
451*644ec0a9SSimon Glass 		debug("comparing %s with %s\n", string, p);
452*644ec0a9SSimon Glass 		if (strcmp(string, p) == 0)
453*644ec0a9SSimon Glass 			return i; /* Found it; return index */
454*644ec0a9SSimon Glass 	}
455*644ec0a9SSimon Glass 	return -ENODATA;
456*644ec0a9SSimon Glass }
457*644ec0a9SSimon Glass 
458*644ec0a9SSimon Glass /**
459*644ec0a9SSimon Glass  * of_property_read_string_helper() - Utility helper for parsing string properties
460*644ec0a9SSimon Glass  * @np:		device node from which the property value is to be read.
461*644ec0a9SSimon Glass  * @propname:	name of the property to be searched.
462*644ec0a9SSimon Glass  * @out_strs:	output array of string pointers.
463*644ec0a9SSimon Glass  * @sz:		number of array elements to read.
464*644ec0a9SSimon Glass  * @skip:	Number of strings to skip over at beginning of list.
465*644ec0a9SSimon Glass  *
466*644ec0a9SSimon Glass  * Don't call this function directly. It is a utility helper for the
467*644ec0a9SSimon Glass  * of_property_read_string*() family of functions.
468*644ec0a9SSimon Glass  */
469*644ec0a9SSimon Glass int of_property_read_string_helper(const struct device_node *np,
470*644ec0a9SSimon Glass 				   const char *propname, const char **out_strs,
471*644ec0a9SSimon Glass 				   size_t sz, int skip)
472*644ec0a9SSimon Glass {
473*644ec0a9SSimon Glass 	const struct property *prop = of_find_property(np, propname, NULL);
474*644ec0a9SSimon Glass 	int l = 0, i = 0;
475*644ec0a9SSimon Glass 	const char *p, *end;
476*644ec0a9SSimon Glass 
477*644ec0a9SSimon Glass 	if (!prop)
478*644ec0a9SSimon Glass 		return -EINVAL;
479*644ec0a9SSimon Glass 	if (!prop->value)
480*644ec0a9SSimon Glass 		return -ENODATA;
481*644ec0a9SSimon Glass 	p = prop->value;
482*644ec0a9SSimon Glass 	end = p + prop->length;
483*644ec0a9SSimon Glass 
484*644ec0a9SSimon Glass 	for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
485*644ec0a9SSimon Glass 		l = strnlen(p, end - p) + 1;
486*644ec0a9SSimon Glass 		if (p + l > end)
487*644ec0a9SSimon Glass 			return -EILSEQ;
488*644ec0a9SSimon Glass 		if (out_strs && i >= skip)
489*644ec0a9SSimon Glass 			*out_strs++ = p;
490*644ec0a9SSimon Glass 	}
491*644ec0a9SSimon Glass 	i -= skip;
492*644ec0a9SSimon Glass 	return i <= 0 ? -ENODATA : i;
493*644ec0a9SSimon Glass }
494*644ec0a9SSimon Glass 
495*644ec0a9SSimon Glass static int __of_parse_phandle_with_args(const struct device_node *np,
496*644ec0a9SSimon Glass 					const char *list_name,
497*644ec0a9SSimon Glass 					const char *cells_name,
498*644ec0a9SSimon Glass 					int cell_count, int index,
499*644ec0a9SSimon Glass 					struct of_phandle_args *out_args)
500*644ec0a9SSimon Glass {
501*644ec0a9SSimon Glass 	const __be32 *list, *list_end;
502*644ec0a9SSimon Glass 	int rc = 0, cur_index = 0;
503*644ec0a9SSimon Glass 	uint32_t count = 0;
504*644ec0a9SSimon Glass 	struct device_node *node = NULL;
505*644ec0a9SSimon Glass 	phandle phandle;
506*644ec0a9SSimon Glass 	int size;
507*644ec0a9SSimon Glass 
508*644ec0a9SSimon Glass 	/* Retrieve the phandle list property */
509*644ec0a9SSimon Glass 	list = of_get_property(np, list_name, &size);
510*644ec0a9SSimon Glass 	if (!list)
511*644ec0a9SSimon Glass 		return -ENOENT;
512*644ec0a9SSimon Glass 	list_end = list + size / sizeof(*list);
513*644ec0a9SSimon Glass 
514*644ec0a9SSimon Glass 	/* Loop over the phandles until all the requested entry is found */
515*644ec0a9SSimon Glass 	while (list < list_end) {
516*644ec0a9SSimon Glass 		rc = -EINVAL;
517*644ec0a9SSimon Glass 		count = 0;
518*644ec0a9SSimon Glass 
519*644ec0a9SSimon Glass 		/*
520*644ec0a9SSimon Glass 		 * If phandle is 0, then it is an empty entry with no
521*644ec0a9SSimon Glass 		 * arguments.  Skip forward to the next entry.
522*644ec0a9SSimon Glass 		 */
523*644ec0a9SSimon Glass 		phandle = be32_to_cpup(list++);
524*644ec0a9SSimon Glass 		if (phandle) {
525*644ec0a9SSimon Glass 			/*
526*644ec0a9SSimon Glass 			 * Find the provider node and parse the #*-cells
527*644ec0a9SSimon Glass 			 * property to determine the argument length.
528*644ec0a9SSimon Glass 			 *
529*644ec0a9SSimon Glass 			 * This is not needed if the cell count is hard-coded
530*644ec0a9SSimon Glass 			 * (i.e. cells_name not set, but cell_count is set),
531*644ec0a9SSimon Glass 			 * except when we're going to return the found node
532*644ec0a9SSimon Glass 			 * below.
533*644ec0a9SSimon Glass 			 */
534*644ec0a9SSimon Glass 			if (cells_name || cur_index == index) {
535*644ec0a9SSimon Glass 				node = of_find_node_by_phandle(phandle);
536*644ec0a9SSimon Glass 				if (!node) {
537*644ec0a9SSimon Glass 					debug("%s: could not find phandle\n",
538*644ec0a9SSimon Glass 					      np->full_name);
539*644ec0a9SSimon Glass 					goto err;
540*644ec0a9SSimon Glass 				}
541*644ec0a9SSimon Glass 			}
542*644ec0a9SSimon Glass 
543*644ec0a9SSimon Glass 			if (cells_name) {
544*644ec0a9SSimon Glass 				if (of_read_u32(node, cells_name, &count)) {
545*644ec0a9SSimon Glass 					debug("%s: could not get %s for %s\n",
546*644ec0a9SSimon Glass 					      np->full_name, cells_name,
547*644ec0a9SSimon Glass 					      node->full_name);
548*644ec0a9SSimon Glass 					goto err;
549*644ec0a9SSimon Glass 				}
550*644ec0a9SSimon Glass 			} else {
551*644ec0a9SSimon Glass 				count = cell_count;
552*644ec0a9SSimon Glass 			}
553*644ec0a9SSimon Glass 
554*644ec0a9SSimon Glass 			/*
555*644ec0a9SSimon Glass 			 * Make sure that the arguments actually fit in the
556*644ec0a9SSimon Glass 			 * remaining property data length
557*644ec0a9SSimon Glass 			 */
558*644ec0a9SSimon Glass 			if (list + count > list_end) {
559*644ec0a9SSimon Glass 				debug("%s: arguments longer than property\n",
560*644ec0a9SSimon Glass 				      np->full_name);
561*644ec0a9SSimon Glass 				goto err;
562*644ec0a9SSimon Glass 			}
563*644ec0a9SSimon Glass 		}
564*644ec0a9SSimon Glass 
565*644ec0a9SSimon Glass 		/*
566*644ec0a9SSimon Glass 		 * All of the error cases above bail out of the loop, so at
567*644ec0a9SSimon Glass 		 * this point, the parsing is successful. If the requested
568*644ec0a9SSimon Glass 		 * index matches, then fill the out_args structure and return,
569*644ec0a9SSimon Glass 		 * or return -ENOENT for an empty entry.
570*644ec0a9SSimon Glass 		 */
571*644ec0a9SSimon Glass 		rc = -ENOENT;
572*644ec0a9SSimon Glass 		if (cur_index == index) {
573*644ec0a9SSimon Glass 			if (!phandle)
574*644ec0a9SSimon Glass 				goto err;
575*644ec0a9SSimon Glass 
576*644ec0a9SSimon Glass 			if (out_args) {
577*644ec0a9SSimon Glass 				int i;
578*644ec0a9SSimon Glass 				if (WARN_ON(count > OF_MAX_PHANDLE_ARGS))
579*644ec0a9SSimon Glass 					count = OF_MAX_PHANDLE_ARGS;
580*644ec0a9SSimon Glass 				out_args->np = node;
581*644ec0a9SSimon Glass 				out_args->args_count = count;
582*644ec0a9SSimon Glass 				for (i = 0; i < count; i++)
583*644ec0a9SSimon Glass 					out_args->args[i] =
584*644ec0a9SSimon Glass 							be32_to_cpup(list++);
585*644ec0a9SSimon Glass 			} else {
586*644ec0a9SSimon Glass 				of_node_put(node);
587*644ec0a9SSimon Glass 			}
588*644ec0a9SSimon Glass 
589*644ec0a9SSimon Glass 			/* Found it! return success */
590*644ec0a9SSimon Glass 			return 0;
591*644ec0a9SSimon Glass 		}
592*644ec0a9SSimon Glass 
593*644ec0a9SSimon Glass 		of_node_put(node);
594*644ec0a9SSimon Glass 		node = NULL;
595*644ec0a9SSimon Glass 		list += count;
596*644ec0a9SSimon Glass 		cur_index++;
597*644ec0a9SSimon Glass 	}
598*644ec0a9SSimon Glass 
599*644ec0a9SSimon Glass 	/*
600*644ec0a9SSimon Glass 	 * Unlock node before returning result; will be one of:
601*644ec0a9SSimon Glass 	 * -ENOENT : index is for empty phandle
602*644ec0a9SSimon Glass 	 * -EINVAL : parsing error on data
603*644ec0a9SSimon Glass 	 * [1..n]  : Number of phandle (count mode; when index = -1)
604*644ec0a9SSimon Glass 	 */
605*644ec0a9SSimon Glass 	rc = index < 0 ? cur_index : -ENOENT;
606*644ec0a9SSimon Glass  err:
607*644ec0a9SSimon Glass 	if (node)
608*644ec0a9SSimon Glass 		of_node_put(node);
609*644ec0a9SSimon Glass 	return rc;
610*644ec0a9SSimon Glass }
611*644ec0a9SSimon Glass 
612*644ec0a9SSimon Glass struct device_node *of_parse_phandle(const struct device_node *np,
613*644ec0a9SSimon Glass 				     const char *phandle_name, int index)
614*644ec0a9SSimon Glass {
615*644ec0a9SSimon Glass 	struct of_phandle_args args;
616*644ec0a9SSimon Glass 
617*644ec0a9SSimon Glass 	if (index < 0)
618*644ec0a9SSimon Glass 		return NULL;
619*644ec0a9SSimon Glass 
620*644ec0a9SSimon Glass 	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index,
621*644ec0a9SSimon Glass 					 &args))
622*644ec0a9SSimon Glass 		return NULL;
623*644ec0a9SSimon Glass 
624*644ec0a9SSimon Glass 	return args.np;
625*644ec0a9SSimon Glass }
626*644ec0a9SSimon Glass 
627*644ec0a9SSimon Glass int of_parse_phandle_with_args(const struct device_node *np,
628*644ec0a9SSimon Glass 			       const char *list_name, const char *cells_name,
629*644ec0a9SSimon Glass 			       int index, struct of_phandle_args *out_args)
630*644ec0a9SSimon Glass {
631*644ec0a9SSimon Glass 	if (index < 0)
632*644ec0a9SSimon Glass 		return -EINVAL;
633*644ec0a9SSimon Glass 
634*644ec0a9SSimon Glass 	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
635*644ec0a9SSimon Glass 					    index, out_args);
636*644ec0a9SSimon Glass }
637*644ec0a9SSimon Glass 
638*644ec0a9SSimon Glass static void of_alias_add(struct alias_prop *ap, struct device_node *np,
639*644ec0a9SSimon Glass 			 int id, const char *stem, int stem_len)
640*644ec0a9SSimon Glass {
641*644ec0a9SSimon Glass 	ap->np = np;
642*644ec0a9SSimon Glass 	ap->id = id;
643*644ec0a9SSimon Glass 	strncpy(ap->stem, stem, stem_len);
644*644ec0a9SSimon Glass 	ap->stem[stem_len] = 0;
645*644ec0a9SSimon Glass 	list_add_tail(&ap->link, &aliases_lookup);
646*644ec0a9SSimon Glass 	debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
647*644ec0a9SSimon Glass 	      ap->alias, ap->stem, ap->id, of_node_full_name(np));
648*644ec0a9SSimon Glass }
649*644ec0a9SSimon Glass 
650*644ec0a9SSimon Glass int of_alias_scan(void)
651*644ec0a9SSimon Glass {
652*644ec0a9SSimon Glass 	struct property *pp;
653*644ec0a9SSimon Glass 
654*644ec0a9SSimon Glass 	of_aliases = of_find_node_by_path("/aliases");
655*644ec0a9SSimon Glass 	of_chosen = of_find_node_by_path("/chosen");
656*644ec0a9SSimon Glass 	if (of_chosen == NULL)
657*644ec0a9SSimon Glass 		of_chosen = of_find_node_by_path("/chosen@0");
658*644ec0a9SSimon Glass 
659*644ec0a9SSimon Glass 	if (of_chosen) {
660*644ec0a9SSimon Glass 		const char *name;
661*644ec0a9SSimon Glass 
662*644ec0a9SSimon Glass 		name = of_get_property(of_chosen, "stdout-path", NULL);
663*644ec0a9SSimon Glass 		if (name)
664*644ec0a9SSimon Glass 			of_stdout = of_find_node_opts_by_path(name,
665*644ec0a9SSimon Glass 							&of_stdout_options);
666*644ec0a9SSimon Glass 	}
667*644ec0a9SSimon Glass 
668*644ec0a9SSimon Glass 	if (!of_aliases)
669*644ec0a9SSimon Glass 		return 0;
670*644ec0a9SSimon Glass 
671*644ec0a9SSimon Glass 	for_each_property_of_node(of_aliases, pp) {
672*644ec0a9SSimon Glass 		const char *start = pp->name;
673*644ec0a9SSimon Glass 		const char *end = start + strlen(start);
674*644ec0a9SSimon Glass 		struct device_node *np;
675*644ec0a9SSimon Glass 		struct alias_prop *ap;
676*644ec0a9SSimon Glass 		ulong id;
677*644ec0a9SSimon Glass 		int len;
678*644ec0a9SSimon Glass 
679*644ec0a9SSimon Glass 		/* Skip those we do not want to proceed */
680*644ec0a9SSimon Glass 		if (!strcmp(pp->name, "name") ||
681*644ec0a9SSimon Glass 		    !strcmp(pp->name, "phandle") ||
682*644ec0a9SSimon Glass 		    !strcmp(pp->name, "linux,phandle"))
683*644ec0a9SSimon Glass 			continue;
684*644ec0a9SSimon Glass 
685*644ec0a9SSimon Glass 		np = of_find_node_by_path(pp->value);
686*644ec0a9SSimon Glass 		if (!np)
687*644ec0a9SSimon Glass 			continue;
688*644ec0a9SSimon Glass 
689*644ec0a9SSimon Glass 		/*
690*644ec0a9SSimon Glass 		 * walk the alias backwards to extract the id and work out
691*644ec0a9SSimon Glass 		 * the 'stem' string
692*644ec0a9SSimon Glass 		 */
693*644ec0a9SSimon Glass 		while (isdigit(*(end-1)) && end > start)
694*644ec0a9SSimon Glass 			end--;
695*644ec0a9SSimon Glass 		len = end - start;
696*644ec0a9SSimon Glass 
697*644ec0a9SSimon Glass 		if (strict_strtoul(end, 10, &id) < 0)
698*644ec0a9SSimon Glass 			continue;
699*644ec0a9SSimon Glass 
700*644ec0a9SSimon Glass 		/* Allocate an alias_prop with enough space for the stem */
701*644ec0a9SSimon Glass 		ap = malloc(sizeof(*ap) + len + 1);
702*644ec0a9SSimon Glass 		if (!ap)
703*644ec0a9SSimon Glass 			return -ENOMEM;
704*644ec0a9SSimon Glass 		memset(ap, 0, sizeof(*ap) + len + 1);
705*644ec0a9SSimon Glass 		ap->alias = start;
706*644ec0a9SSimon Glass 		of_alias_add(ap, np, id, start, len);
707*644ec0a9SSimon Glass 	}
708*644ec0a9SSimon Glass 
709*644ec0a9SSimon Glass 	return 0;
710*644ec0a9SSimon Glass }
711*644ec0a9SSimon Glass 
712*644ec0a9SSimon Glass int of_alias_get_id(const struct device_node *np, const char *stem)
713*644ec0a9SSimon Glass {
714*644ec0a9SSimon Glass 	struct alias_prop *app;
715*644ec0a9SSimon Glass 	int id = -ENODEV;
716*644ec0a9SSimon Glass 
717*644ec0a9SSimon Glass 	mutex_lock(&of_mutex);
718*644ec0a9SSimon Glass 	list_for_each_entry(app, &aliases_lookup, link) {
719*644ec0a9SSimon Glass 		if (strcmp(app->stem, stem) != 0)
720*644ec0a9SSimon Glass 			continue;
721*644ec0a9SSimon Glass 
722*644ec0a9SSimon Glass 		if (np == app->np) {
723*644ec0a9SSimon Glass 			id = app->id;
724*644ec0a9SSimon Glass 			break;
725*644ec0a9SSimon Glass 		}
726*644ec0a9SSimon Glass 	}
727*644ec0a9SSimon Glass 	mutex_unlock(&of_mutex);
728*644ec0a9SSimon Glass 
729*644ec0a9SSimon Glass 	return id;
730*644ec0a9SSimon Glass }
731*644ec0a9SSimon Glass 
732*644ec0a9SSimon Glass struct device_node *of_get_stdout(void)
733*644ec0a9SSimon Glass {
734*644ec0a9SSimon Glass 	return of_stdout;
735*644ec0a9SSimon Glass }
736