1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2017 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #define LOG_CATEGORY	LOGC_DT
8 
9 #include <common.h>
10 #include <dm.h>
11 #include <fdtdec.h>
12 #include <fdt_support.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <linux/libfdt.h>
16 #include <dm/of_access.h>
17 #include <dm/of_addr.h>
18 #include <dm/ofnode.h>
19 #include <linux/err.h>
20 #include <linux/ioport.h>
21 #include <asm/global_data.h>
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
25 #if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
26 static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
27 static int oftree_count;
28 
oftree_reset(void)29 void oftree_reset(void)
30 {
31 	if (gd->flags & GD_FLG_RELOC) {
32 		oftree_count = 0;
33 		oftree_list[oftree_count++] = (void *)gd->fdt_blob;
34 	}
35 }
36 
oftree_find(const void * fdt)37 static int oftree_find(const void *fdt)
38 {
39 	int i;
40 
41 	for (i = 0; i < oftree_count; i++) {
42 		if (fdt == oftree_list[i])
43 			return i;
44 	}
45 
46 	return -1;
47 }
48 
oftree_ensure(void * fdt)49 static oftree oftree_ensure(void *fdt)
50 {
51 	oftree tree;
52 	int i;
53 
54 	if (gd->flags & GD_FLG_RELOC) {
55 		i = oftree_find(fdt);
56 		if (i == -1) {
57 			if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
58 				log_warning("Too many registered device trees (max %d)\n",
59 					    CONFIG_OFNODE_MULTI_TREE_MAX);
60 				return oftree_null();
61 			}
62 
63 			/* register the new tree */
64 			i = oftree_count++;
65 			oftree_list[i] = fdt;
66 			log_debug("oftree: registered tree %d: %p\n", i, fdt);
67 		}
68 	} else {
69 		if (fdt != gd->fdt_blob) {
70 			log_debug("Cannot only access control FDT before relocation\n");
71 			return oftree_null();
72 		}
73 	}
74 
75 	tree.fdt = fdt;
76 
77 	return tree;
78 }
79 
ofnode_lookup_fdt(ofnode node)80 void *ofnode_lookup_fdt(ofnode node)
81 {
82 	if (gd->flags & GD_FLG_RELOC) {
83 		uint i = OFTREE_TREE_ID(node.of_offset);
84 
85 		if (i > oftree_count) {
86 			log_debug("Invalid tree ID %x\n", i);
87 			return NULL;
88 		}
89 
90 		return oftree_list[i];
91 	} else {
92 		return (void *)gd->fdt_blob;
93 	}
94 }
95 
ofnode_to_fdt(ofnode node)96 void *ofnode_to_fdt(ofnode node)
97 {
98 #ifdef OF_CHECKS
99 	if (of_live_active())
100 		return NULL;
101 #endif
102 	if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node))
103 		return ofnode_lookup_fdt(node);
104 
105 	/* Use the control FDT by default */
106 	return (void *)gd->fdt_blob;
107 }
108 
109 /**
110  * ofnode_to_offset() - convert an ofnode to a flat DT offset
111  *
112  * This cannot be called if the reference contains a node pointer.
113  *
114  * @node: Reference containing offset (possibly invalid)
115  * Return: DT offset (can be -1)
116  */
ofnode_to_offset(ofnode node)117 int ofnode_to_offset(ofnode node)
118 {
119 #ifdef OF_CHECKS
120 	if (of_live_active())
121 		return -1;
122 #endif
123 	if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0)
124 		return OFTREE_OFFSET(node.of_offset);
125 
126 	return node.of_offset;
127 }
128 
oftree_from_fdt(void * fdt)129 oftree oftree_from_fdt(void *fdt)
130 {
131 	oftree tree;
132 
133 	if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE))
134 		return oftree_ensure(fdt);
135 
136 	tree.fdt = fdt;
137 
138 	return tree;
139 }
140 
141 /**
142  * noffset_to_ofnode() - convert a DT offset to an ofnode
143  *
144  * @other_node: Node in the same tree to use as a reference
145  * @of_offset: DT offset (either valid, or -1)
146  * Return: reference to the associated DT offset
147  */
noffset_to_ofnode(ofnode other_node,int of_offset)148 ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
149 {
150 	ofnode node;
151 
152 	if (of_live_active())
153 		node.np = NULL;
154 	else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 ||
155 		 !ofnode_valid(other_node))
156 		node.of_offset = of_offset;
157 	else
158 		node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset,
159 						  of_offset);
160 
161 	return node;
162 }
163 
164 #else /* !OFNODE_MULTI_TREE */
165 
oftree_find(const void * fdt)166 static inline int oftree_find(const void *fdt)
167 {
168 	return 0;
169 }
170 
171 #endif /* OFNODE_MULTI_TREE */
172 
173 /**
174  * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree)
175  *
176  * Looks up the tree and returns an ofnode with the correct of_offset (i.e.
177  * containing the tree ID).
178  *
179  * If @offset is < 0 then this returns an ofnode with that offset and no tree
180  * ID.
181  *
182  * @tree: tree to check
183  * @offset: offset within that tree (can be < 0)
184  * @return node for that offset, with the correct ID
185  */
ofnode_from_tree_offset(oftree tree,int offset)186 static ofnode ofnode_from_tree_offset(oftree tree, int offset)
187 {
188 	ofnode node;
189 
190 	if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) {
191 		int tree_id = oftree_find(tree.fdt);
192 
193 		if (tree_id == -1)
194 			return ofnode_null();
195 		node.of_offset = OFTREE_NODE(tree_id, offset);
196 	} else {
197 		node.of_offset = offset;
198 	}
199 
200 	return node;
201 }
202 
ofnode_name_eq(ofnode node,const char * name)203 bool ofnode_name_eq(ofnode node, const char *name)
204 {
205 	const char *node_name;
206 	size_t len;
207 
208 	assert(ofnode_valid(node));
209 
210 	node_name = ofnode_get_name(node);
211 	len = strchrnul(node_name, '@') - node_name;
212 
213 	return (strlen(name) == len) && !strncmp(node_name, name, len);
214 }
215 
ofnode_read_u8(ofnode node,const char * propname,u8 * outp)216 int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
217 {
218 	const u8 *cell;
219 	int len;
220 
221 	assert(ofnode_valid(node));
222 	debug("%s: %s: ", __func__, propname);
223 
224 	if (ofnode_is_np(node))
225 		return of_read_u8(ofnode_to_np(node), propname, outp);
226 
227 	cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
228 			   &len);
229 	if (!cell || len < sizeof(*cell)) {
230 		debug("(not found)\n");
231 		return -EINVAL;
232 	}
233 	*outp = *cell;
234 	debug("%#x (%d)\n", *outp, *outp);
235 
236 	return 0;
237 }
238 
ofnode_read_u8_default(ofnode node,const char * propname,u8 def)239 u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def)
240 {
241 	assert(ofnode_valid(node));
242 	ofnode_read_u8(node, propname, &def);
243 
244 	return def;
245 }
246 
ofnode_read_u16(ofnode node,const char * propname,u16 * outp)247 int ofnode_read_u16(ofnode node, const char *propname, u16 *outp)
248 {
249 	const fdt16_t *cell;
250 	int len;
251 
252 	assert(ofnode_valid(node));
253 	debug("%s: %s: ", __func__, propname);
254 
255 	if (ofnode_is_np(node))
256 		return of_read_u16(ofnode_to_np(node), propname, outp);
257 
258 	cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
259 			   &len);
260 	if (!cell || len < sizeof(*cell)) {
261 		debug("(not found)\n");
262 		return -EINVAL;
263 	}
264 	*outp = be16_to_cpup(cell);
265 	debug("%#x (%d)\n", *outp, *outp);
266 
267 	return 0;
268 }
269 
ofnode_read_u16_default(ofnode node,const char * propname,u16 def)270 u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def)
271 {
272 	assert(ofnode_valid(node));
273 	ofnode_read_u16(node, propname, &def);
274 
275 	return def;
276 }
277 
ofnode_read_u32(ofnode node,const char * propname,u32 * outp)278 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
279 {
280 	return ofnode_read_u32_index(node, propname, 0, outp);
281 }
282 
ofnode_read_u32_default(ofnode node,const char * propname,u32 def)283 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
284 {
285 	assert(ofnode_valid(node));
286 	ofnode_read_u32_index(node, propname, 0, &def);
287 
288 	return def;
289 }
290 
ofnode_read_u32_index(ofnode node,const char * propname,int index,u32 * outp)291 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
292 			  u32 *outp)
293 {
294 	const fdt32_t *cell;
295 	int len;
296 
297 	assert(ofnode_valid(node));
298 	debug("%s: %s: ", __func__, propname);
299 
300 	if (ofnode_is_np(node))
301 		return of_read_u32_index(ofnode_to_np(node), propname, index,
302 					 outp);
303 
304 	cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
305 			   propname, &len);
306 	if (!cell) {
307 		debug("(not found)\n");
308 		return -EINVAL;
309 	}
310 
311 	if (len < (sizeof(int) * (index + 1))) {
312 		debug("(not large enough)\n");
313 		return -EOVERFLOW;
314 	}
315 
316 	*outp = fdt32_to_cpu(cell[index]);
317 	debug("%#x (%d)\n", *outp, *outp);
318 
319 	return 0;
320 }
321 
ofnode_read_u32_index_default(ofnode node,const char * propname,int index,u32 def)322 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
323 				  u32 def)
324 {
325 	assert(ofnode_valid(node));
326 	ofnode_read_u32_index(node, propname, index, &def);
327 
328 	return def;
329 }
330 
ofnode_read_s32_default(ofnode node,const char * propname,s32 def)331 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
332 {
333 	assert(ofnode_valid(node));
334 	ofnode_read_u32(node, propname, (u32 *)&def);
335 
336 	return def;
337 }
338 
ofnode_read_u64(ofnode node,const char * propname,u64 * outp)339 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
340 {
341 	const unaligned_fdt64_t *cell;
342 	int len;
343 
344 	assert(ofnode_valid(node));
345 	debug("%s: %s: ", __func__, propname);
346 
347 	if (ofnode_is_np(node))
348 		return of_read_u64(ofnode_to_np(node), propname, outp);
349 
350 	cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
351 			   propname, &len);
352 	if (!cell || len < sizeof(*cell)) {
353 		debug("(not found)\n");
354 		return -EINVAL;
355 	}
356 	*outp = fdt64_to_cpu(cell[0]);
357 	debug("%#llx (%lld)\n", (unsigned long long)*outp,
358 	      (unsigned long long)*outp);
359 
360 	return 0;
361 }
362 
ofnode_read_u64_default(ofnode node,const char * propname,u64 def)363 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
364 {
365 	assert(ofnode_valid(node));
366 	ofnode_read_u64(node, propname, &def);
367 
368 	return def;
369 }
370 
ofnode_read_bool(ofnode node,const char * propname)371 bool ofnode_read_bool(ofnode node, const char *propname)
372 {
373 	const void *prop;
374 
375 	assert(ofnode_valid(node));
376 	debug("%s: %s: ", __func__, propname);
377 
378 	prop = ofnode_get_property(node, propname, NULL);
379 
380 	debug("%s\n", prop ? "true" : "false");
381 
382 	return prop ? true : false;
383 }
384 
ofnode_read_prop(ofnode node,const char * propname,int * sizep)385 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
386 {
387 	const char *val = NULL;
388 	int len;
389 
390 	assert(ofnode_valid(node));
391 	debug("%s: %s: ", __func__, propname);
392 
393 	if (ofnode_is_np(node)) {
394 		struct property *prop = of_find_property(
395 				ofnode_to_np(node), propname, &len);
396 
397 		if (prop) {
398 			val = prop->value;
399 			len = prop->length;
400 		}
401 	} else {
402 		val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
403 				  propname, &len);
404 	}
405 	if (!val) {
406 		debug("<not found>\n");
407 		if (sizep)
408 			*sizep = -FDT_ERR_NOTFOUND;
409 		return NULL;
410 	}
411 	if (sizep)
412 		*sizep = len;
413 
414 	return val;
415 }
416 
ofnode_read_string(ofnode node,const char * propname)417 const char *ofnode_read_string(ofnode node, const char *propname)
418 {
419 	const char *str;
420 	int len;
421 
422 	str = ofnode_read_prop(node, propname, &len);
423 	if (!str)
424 		return NULL;
425 
426 	if (strnlen(str, len) >= len) {
427 		debug("<invalid>\n");
428 		return NULL;
429 	}
430 	debug("%s\n", str);
431 
432 	return str;
433 }
434 
ofnode_read_size(ofnode node,const char * propname)435 int ofnode_read_size(ofnode node, const char *propname)
436 {
437 	int len;
438 
439 	if (!ofnode_read_prop(node, propname, &len))
440 		return -EINVAL;
441 
442 	return len;
443 }
444 
ofnode_find_subnode(ofnode node,const char * subnode_name)445 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
446 {
447 	ofnode subnode;
448 
449 	assert(ofnode_valid(node));
450 	debug("%s: %s: ", __func__, subnode_name);
451 
452 	if (ofnode_is_np(node)) {
453 		struct device_node *np = ofnode_to_np(node);
454 
455 		for (np = np->child; np; np = np->sibling) {
456 			if (!strcmp(subnode_name, np->name))
457 				break;
458 		}
459 		subnode = np_to_ofnode(np);
460 	} else {
461 		int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
462 				ofnode_to_offset(node), subnode_name);
463 		subnode = noffset_to_ofnode(node, ooffset);
464 	}
465 	debug("%s\n", ofnode_valid(subnode) ?
466 	      ofnode_get_name(subnode) : "<none>");
467 
468 	return subnode;
469 }
470 
ofnode_read_u32_array(ofnode node,const char * propname,u32 * out_values,size_t sz)471 int ofnode_read_u32_array(ofnode node, const char *propname,
472 			  u32 *out_values, size_t sz)
473 {
474 	assert(ofnode_valid(node));
475 	debug("%s: %s: ", __func__, propname);
476 
477 	if (ofnode_is_np(node)) {
478 		return of_read_u32_array(ofnode_to_np(node), propname,
479 					 out_values, sz);
480 	} else {
481 		int ret;
482 
483 		ret = fdtdec_get_int_array(ofnode_to_fdt(node),
484 					   ofnode_to_offset(node), propname,
485 					   out_values, sz);
486 
487 		/* get the error right, but space is more important in SPL */
488 		if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
489 			if (ret == -FDT_ERR_NOTFOUND)
490 				return -EINVAL;
491 			else if (ret == -FDT_ERR_BADLAYOUT)
492 				return -EOVERFLOW;
493 		}
494 		return ret;
495 	}
496 }
497 
498 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
ofnode_is_enabled(ofnode node)499 bool ofnode_is_enabled(ofnode node)
500 {
501 	if (ofnode_is_np(node)) {
502 		return of_device_is_available(ofnode_to_np(node));
503 	} else {
504 		return fdtdec_get_is_enabled(ofnode_to_fdt(node),
505 					     ofnode_to_offset(node));
506 	}
507 }
508 
ofnode_first_subnode(ofnode node)509 ofnode ofnode_first_subnode(ofnode node)
510 {
511 	assert(ofnode_valid(node));
512 	if (ofnode_is_np(node))
513 		return np_to_ofnode(node.np->child);
514 
515 	return noffset_to_ofnode(node,
516 		fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
517 }
518 
ofnode_next_subnode(ofnode node)519 ofnode ofnode_next_subnode(ofnode node)
520 {
521 	assert(ofnode_valid(node));
522 	if (ofnode_is_np(node))
523 		return np_to_ofnode(node.np->sibling);
524 
525 	return noffset_to_ofnode(node,
526 		fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
527 }
528 #endif /* !DM_INLINE_OFNODE */
529 
ofnode_get_parent(ofnode node)530 ofnode ofnode_get_parent(ofnode node)
531 {
532 	ofnode parent;
533 
534 	assert(ofnode_valid(node));
535 	if (ofnode_is_np(node))
536 		parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
537 	else
538 		parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
539 						     ofnode_to_offset(node));
540 
541 	return parent;
542 }
543 
ofnode_get_name(ofnode node)544 const char *ofnode_get_name(ofnode node)
545 {
546 	if (!ofnode_valid(node)) {
547 		debug("%s node not valid\n", __func__);
548 		return NULL;
549 	}
550 
551 	if (ofnode_is_np(node))
552 		return node.np->name;
553 
554 	return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
555 }
556 
ofnode_get_path(ofnode node,char * buf,int buflen)557 int ofnode_get_path(ofnode node, char *buf, int buflen)
558 {
559 	assert(ofnode_valid(node));
560 
561 	if (ofnode_is_np(node)) {
562 		if (strlen(node.np->full_name) >= buflen)
563 			return -ENOSPC;
564 
565 		strcpy(buf, node.np->full_name);
566 
567 		return 0;
568 	} else {
569 		int res;
570 
571 		res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
572 				   buflen);
573 		if (!res)
574 			return res;
575 		else if (res == -FDT_ERR_NOSPACE)
576 			return -ENOSPC;
577 		else
578 			return -EINVAL;
579 	}
580 }
581 
ofnode_get_by_phandle(uint phandle)582 ofnode ofnode_get_by_phandle(uint phandle)
583 {
584 	ofnode node;
585 
586 	if (of_live_active())
587 		node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
588 	else
589 		node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
590 							    phandle);
591 
592 	return node;
593 }
594 
oftree_get_by_phandle(oftree tree,uint phandle)595 ofnode oftree_get_by_phandle(oftree tree, uint phandle)
596 {
597 	ofnode node;
598 
599 	if (of_live_active())
600 		node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
601 	else
602 		node = ofnode_from_tree_offset(tree,
603 			fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
604 						   phandle));
605 
606 	return node;
607 }
608 
__ofnode_get_addr_size_index(ofnode node,int index,fdt_size_t * size,bool translate)609 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
610 					       fdt_size_t *size, bool translate)
611 {
612 	int na, ns;
613 
614 	if (size)
615 		*size = FDT_SIZE_T_NONE;
616 
617 	if (ofnode_is_np(node)) {
618 		const __be32 *prop_val;
619 		u64 size64;
620 		uint flags;
621 
622 		prop_val = of_get_address(ofnode_to_np(node), index, &size64,
623 					  &flags);
624 		if (!prop_val)
625 			return FDT_ADDR_T_NONE;
626 
627 		if (size)
628 			*size = size64;
629 
630 		ns = of_n_size_cells(ofnode_to_np(node));
631 
632 		if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
633 			return of_translate_address(ofnode_to_np(node), prop_val);
634 		} else {
635 			na = of_n_addr_cells(ofnode_to_np(node));
636 			return of_read_number(prop_val, na);
637 		}
638 	} else {
639 		na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
640 		ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
641 		return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
642 						  ofnode_to_offset(node), "reg",
643 						  index, na, ns, size,
644 						  translate);
645 	}
646 }
647 
ofnode_get_addr_size_index(ofnode node,int index,fdt_size_t * size)648 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
649 {
650 	return __ofnode_get_addr_size_index(node, index, size, true);
651 }
652 
ofnode_get_addr_size_index_notrans(ofnode node,int index,fdt_size_t * size)653 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
654 					      fdt_size_t *size)
655 {
656 	return __ofnode_get_addr_size_index(node, index, size, false);
657 }
658 
ofnode_get_addr_index(ofnode node,int index)659 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
660 {
661 	fdt_size_t size;
662 
663 	return ofnode_get_addr_size_index(node, index, &size);
664 }
665 
ofnode_get_addr(ofnode node)666 fdt_addr_t ofnode_get_addr(ofnode node)
667 {
668 	return ofnode_get_addr_index(node, 0);
669 }
670 
ofnode_get_size(ofnode node)671 fdt_size_t ofnode_get_size(ofnode node)
672 {
673 	fdt_size_t size;
674 
675 	ofnode_get_addr_size_index(node, 0, &size);
676 
677 	return size;
678 }
679 
ofnode_stringlist_search(ofnode node,const char * property,const char * string)680 int ofnode_stringlist_search(ofnode node, const char *property,
681 			     const char *string)
682 {
683 	if (ofnode_is_np(node)) {
684 		return of_property_match_string(ofnode_to_np(node),
685 						property, string);
686 	} else {
687 		int ret;
688 
689 		ret = fdt_stringlist_search(ofnode_to_fdt(node),
690 					    ofnode_to_offset(node), property,
691 					    string);
692 		if (ret == -FDT_ERR_NOTFOUND)
693 			return -ENODATA;
694 		else if (ret < 0)
695 			return -EINVAL;
696 
697 		return ret;
698 	}
699 }
700 
ofnode_read_string_index(ofnode node,const char * property,int index,const char ** outp)701 int ofnode_read_string_index(ofnode node, const char *property, int index,
702 			     const char **outp)
703 {
704 	if (ofnode_is_np(node)) {
705 		return of_property_read_string_index(ofnode_to_np(node),
706 						     property, index, outp);
707 	} else {
708 		int len;
709 
710 		*outp = fdt_stringlist_get(ofnode_to_fdt(node),
711 					   ofnode_to_offset(node),
712 					   property, index, &len);
713 		if (len < 0)
714 			return -EINVAL;
715 		return 0;
716 	}
717 }
718 
ofnode_read_string_count(ofnode node,const char * property)719 int ofnode_read_string_count(ofnode node, const char *property)
720 {
721 	if (ofnode_is_np(node)) {
722 		return of_property_count_strings(ofnode_to_np(node), property);
723 	} else {
724 		return fdt_stringlist_count(ofnode_to_fdt(node),
725 					    ofnode_to_offset(node), property);
726 	}
727 }
728 
ofnode_read_string_list(ofnode node,const char * property,const char *** listp)729 int ofnode_read_string_list(ofnode node, const char *property,
730 			    const char ***listp)
731 {
732 	const char **prop;
733 	int count;
734 	int i;
735 
736 	*listp = NULL;
737 	count = ofnode_read_string_count(node, property);
738 	if (count < 0)
739 		return count;
740 	if (!count)
741 		return 0;
742 
743 	prop = calloc(count + 1, sizeof(char *));
744 	if (!prop)
745 		return -ENOMEM;
746 
747 	for (i = 0; i < count; i++)
748 		ofnode_read_string_index(node, property, i, &prop[i]);
749 	prop[count] = NULL;
750 	*listp = prop;
751 
752 	return count;
753 }
754 
ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args * in,struct ofnode_phandle_args * out)755 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
756 					    struct ofnode_phandle_args *out)
757 {
758 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
759 	out->node = offset_to_ofnode(in->node);
760 	out->args_count = in->args_count;
761 	memcpy(out->args, in->args, sizeof(out->args));
762 }
763 
ofnode_from_of_phandle_args(struct of_phandle_args * in,struct ofnode_phandle_args * out)764 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
765 					struct ofnode_phandle_args *out)
766 {
767 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
768 	out->node = np_to_ofnode(in->np);
769 	out->args_count = in->args_count;
770 	memcpy(out->args, in->args, sizeof(out->args));
771 }
772 
ofnode_parse_phandle_with_args(ofnode node,const char * list_name,const char * cells_name,int cell_count,int index,struct ofnode_phandle_args * out_args)773 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
774 				   const char *cells_name, int cell_count,
775 				   int index,
776 				   struct ofnode_phandle_args *out_args)
777 {
778 	if (ofnode_is_np(node)) {
779 		struct of_phandle_args args;
780 		int ret;
781 
782 		ret = of_parse_phandle_with_args(ofnode_to_np(node),
783 						 list_name, cells_name,
784 						 cell_count, index,
785 						 &args);
786 		if (ret)
787 			return ret;
788 		ofnode_from_of_phandle_args(&args, out_args);
789 	} else {
790 		struct fdtdec_phandle_args args;
791 		int ret;
792 
793 		ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
794 						     ofnode_to_offset(node),
795 						     list_name, cells_name,
796 						     cell_count, index, &args);
797 		if (ret)
798 			return ret;
799 		ofnode_from_fdtdec_phandle_args(&args, out_args);
800 	}
801 
802 	return 0;
803 }
804 
ofnode_count_phandle_with_args(ofnode node,const char * list_name,const char * cells_name,int cell_count)805 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
806 				   const char *cells_name, int cell_count)
807 {
808 	if (ofnode_is_np(node))
809 		return of_count_phandle_with_args(ofnode_to_np(node),
810 				list_name, cells_name, cell_count);
811 	else
812 		return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
813 				ofnode_to_offset(node), list_name, cells_name,
814 				cell_count, -1, NULL);
815 }
816 
ofnode_path(const char * path)817 ofnode ofnode_path(const char *path)
818 {
819 	if (of_live_active())
820 		return np_to_ofnode(of_find_node_by_path(path));
821 	else
822 		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
823 }
824 
oftree_root(oftree tree)825 ofnode oftree_root(oftree tree)
826 {
827 	if (of_live_active()) {
828 		return np_to_ofnode(tree.np);
829 	} else {
830 		return ofnode_from_tree_offset(tree, 0);
831 	}
832 }
833 
oftree_path(oftree tree,const char * path)834 ofnode oftree_path(oftree tree, const char *path)
835 {
836 	if (of_live_active()) {
837 		return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
838 							      NULL));
839 	} else if (*path != '/' && tree.fdt != gd->fdt_blob) {
840 		return ofnode_null();  /* Aliases only on control FDT */
841 	} else {
842 		int offset = fdt_path_offset(tree.fdt, path);
843 
844 		return ofnode_from_tree_offset(tree, offset);
845 	}
846 }
847 
ofnode_read_chosen_prop(const char * propname,int * sizep)848 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
849 {
850 	ofnode chosen_node;
851 
852 	chosen_node = ofnode_path("/chosen");
853 
854 	return ofnode_read_prop(chosen_node, propname, sizep);
855 }
856 
ofnode_read_chosen_string(const char * propname)857 const char *ofnode_read_chosen_string(const char *propname)
858 {
859 	return ofnode_read_chosen_prop(propname, NULL);
860 }
861 
ofnode_get_chosen_node(const char * name)862 ofnode ofnode_get_chosen_node(const char *name)
863 {
864 	const char *prop;
865 
866 	prop = ofnode_read_chosen_prop(name, NULL);
867 	if (!prop)
868 		return ofnode_null();
869 
870 	return ofnode_path(prop);
871 }
872 
ofnode_read_aliases_prop(const char * propname,int * sizep)873 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
874 {
875 	ofnode node;
876 
877 	node = ofnode_path("/aliases");
878 
879 	return ofnode_read_prop(node, propname, sizep);
880 }
881 
ofnode_get_aliases_node(const char * name)882 ofnode ofnode_get_aliases_node(const char *name)
883 {
884 	const char *prop;
885 
886 	prop = ofnode_read_aliases_prop(name, NULL);
887 	if (!prop)
888 		return ofnode_null();
889 
890 	debug("%s: node_path: %s\n", __func__, prop);
891 
892 	return ofnode_path(prop);
893 }
894 
ofnode_get_child_count(ofnode parent)895 int ofnode_get_child_count(ofnode parent)
896 {
897 	ofnode child;
898 	int num = 0;
899 
900 	ofnode_for_each_subnode(child, parent)
901 		num++;
902 
903 	return num;
904 }
905 
decode_timing_property(ofnode node,const char * name,struct timing_entry * result)906 static int decode_timing_property(ofnode node, const char *name,
907 				  struct timing_entry *result)
908 {
909 	int length, ret = 0;
910 
911 	length = ofnode_read_size(node, name);
912 	if (length < 0) {
913 		debug("%s: could not find property %s\n",
914 		      ofnode_get_name(node), name);
915 		return length;
916 	}
917 
918 	if (length == sizeof(u32)) {
919 		result->typ = ofnode_read_u32_default(node, name, 0);
920 		result->min = result->typ;
921 		result->max = result->typ;
922 	} else {
923 		ret = ofnode_read_u32_array(node, name, &result->min, 3);
924 	}
925 
926 	return ret;
927 }
928 
ofnode_decode_display_timing(ofnode parent,int index,struct display_timing * dt)929 int ofnode_decode_display_timing(ofnode parent, int index,
930 				 struct display_timing *dt)
931 {
932 	int i;
933 	ofnode timings, node;
934 	u32 val = 0;
935 	int ret = 0;
936 
937 	timings = ofnode_find_subnode(parent, "display-timings");
938 	if (!ofnode_valid(timings))
939 		return -EINVAL;
940 
941 	i = 0;
942 	ofnode_for_each_subnode(node, timings) {
943 		if (i++ == index)
944 			break;
945 	}
946 
947 	if (!ofnode_valid(node))
948 		return -EINVAL;
949 
950 	memset(dt, 0, sizeof(*dt));
951 
952 	ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
953 	ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
954 	ret |= decode_timing_property(node, "hactive", &dt->hactive);
955 	ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
956 	ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
957 	ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
958 	ret |= decode_timing_property(node, "vactive", &dt->vactive);
959 	ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
960 	ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
961 
962 	dt->flags = 0;
963 	val = ofnode_read_u32_default(node, "vsync-active", -1);
964 	if (val != -1) {
965 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
966 				DISPLAY_FLAGS_VSYNC_LOW;
967 	}
968 	val = ofnode_read_u32_default(node, "hsync-active", -1);
969 	if (val != -1) {
970 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
971 				DISPLAY_FLAGS_HSYNC_LOW;
972 	}
973 	val = ofnode_read_u32_default(node, "de-active", -1);
974 	if (val != -1) {
975 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
976 				DISPLAY_FLAGS_DE_LOW;
977 	}
978 	val = ofnode_read_u32_default(node, "pixelclk-active", -1);
979 	if (val != -1) {
980 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
981 				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
982 	}
983 
984 	if (ofnode_read_bool(node, "interlaced"))
985 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
986 	if (ofnode_read_bool(node, "doublescan"))
987 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
988 	if (ofnode_read_bool(node, "doubleclk"))
989 		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
990 
991 	return ret;
992 }
993 
ofnode_decode_panel_timing(ofnode parent,struct display_timing * dt)994 int ofnode_decode_panel_timing(ofnode parent,
995 			       struct display_timing *dt)
996 {
997 	ofnode timings;
998 	u32 val = 0;
999 	int ret = 0;
1000 
1001 	timings = ofnode_find_subnode(parent, "panel-timing");
1002 	if (!ofnode_valid(timings))
1003 		return -EINVAL;
1004 	memset(dt, 0, sizeof(*dt));
1005 	ret |= decode_timing_property(timings, "hback-porch", &dt->hback_porch);
1006 	ret |= decode_timing_property(timings, "hfront-porch", &dt->hfront_porch);
1007 	ret |= decode_timing_property(timings, "hactive", &dt->hactive);
1008 	ret |= decode_timing_property(timings, "hsync-len", &dt->hsync_len);
1009 	ret |= decode_timing_property(timings, "vback-porch", &dt->vback_porch);
1010 	ret |= decode_timing_property(timings, "vfront-porch", &dt->vfront_porch);
1011 	ret |= decode_timing_property(timings, "vactive", &dt->vactive);
1012 	ret |= decode_timing_property(timings, "vsync-len", &dt->vsync_len);
1013 	ret |= decode_timing_property(timings, "clock-frequency", &dt->pixelclock);
1014 	dt->flags = 0;
1015 	if (!ofnode_read_u32(timings, "vsync-active", &val)) {
1016 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1017 		    DISPLAY_FLAGS_VSYNC_LOW;
1018 	}
1019 	if (!ofnode_read_u32(timings, "hsync-active", &val)) {
1020 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1021 		    DISPLAY_FLAGS_HSYNC_LOW;
1022 	}
1023 	if (!ofnode_read_u32(timings, "de-active", &val)) {
1024 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1025 		    DISPLAY_FLAGS_DE_LOW;
1026 	}
1027 	if (!ofnode_read_u32(timings, "pixelclk-active", &val)) {
1028 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1029 		DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1030 	}
1031 	if (ofnode_read_bool(timings, "interlaced"))
1032 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
1033 	if (ofnode_read_bool(timings, "doublescan"))
1034 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1035 	if (ofnode_read_bool(timings, "doubleclk"))
1036 		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1037 
1038 	return ret;
1039 }
1040 
ofnode_get_property(ofnode node,const char * propname,int * lenp)1041 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
1042 {
1043 	if (ofnode_is_np(node))
1044 		return of_get_property(ofnode_to_np(node), propname, lenp);
1045 	else
1046 		return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1047 				   propname, lenp);
1048 }
1049 
ofnode_first_property(ofnode node,struct ofprop * prop)1050 int ofnode_first_property(ofnode node, struct ofprop *prop)
1051 {
1052 	prop->node = node;
1053 
1054 	if (ofnode_is_np(node)) {
1055 		prop->prop = of_get_first_property(ofnode_to_np(prop->node));
1056 		if (!prop->prop)
1057 			return -FDT_ERR_NOTFOUND;
1058 	} else {
1059 		prop->offset =
1060 			fdt_first_property_offset(ofnode_to_fdt(node),
1061 						  ofnode_to_offset(prop->node));
1062 		if (prop->offset < 0)
1063 			return prop->offset;
1064 	}
1065 
1066 	return 0;
1067 }
1068 
ofnode_next_property(struct ofprop * prop)1069 int ofnode_next_property(struct ofprop *prop)
1070 {
1071 	if (ofnode_is_np(prop->node)) {
1072 		prop->prop = of_get_next_property(ofnode_to_np(prop->node),
1073 						  prop->prop);
1074 		if (!prop->prop)
1075 			return -FDT_ERR_NOTFOUND;
1076 	} else {
1077 		prop->offset =
1078 			fdt_next_property_offset(ofnode_to_fdt(prop->node),
1079 						 prop->offset);
1080 		if (prop->offset  < 0)
1081 			return prop->offset;
1082 	}
1083 
1084 	return 0;
1085 }
1086 
ofprop_get_property(const struct ofprop * prop,const char ** propname,int * lenp)1087 const void *ofprop_get_property(const struct ofprop *prop,
1088 				const char **propname, int *lenp)
1089 {
1090 	if (ofnode_is_np(prop->node))
1091 		return of_get_property_by_prop(ofnode_to_np(prop->node),
1092 					       prop->prop, propname, lenp);
1093 	else
1094 		return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
1095 					     prop->offset,
1096 					     propname, lenp);
1097 }
1098 
ofnode_get_addr_size(ofnode node,const char * property,fdt_size_t * sizep)1099 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
1100 				fdt_size_t *sizep)
1101 {
1102 	if (ofnode_is_np(node)) {
1103 		int na, ns;
1104 		int psize;
1105 		const struct device_node *np = ofnode_to_np(node);
1106 		const __be32 *prop = of_get_property(np, property, &psize);
1107 
1108 		if (!prop)
1109 			return FDT_ADDR_T_NONE;
1110 		na = of_n_addr_cells(np);
1111 		ns = of_n_size_cells(np);
1112 		*sizep = of_read_number(prop + na, ns);
1113 
1114 		if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
1115 			return of_translate_address(np, prop);
1116 		else
1117 			return of_read_number(prop, na);
1118 	} else {
1119 		return fdtdec_get_addr_size(ofnode_to_fdt(node),
1120 					    ofnode_to_offset(node), property,
1121 					    sizep);
1122 	}
1123 }
1124 
ofnode_read_u8_array_ptr(ofnode node,const char * propname,size_t sz)1125 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
1126 					size_t sz)
1127 {
1128 	if (ofnode_is_np(node)) {
1129 		const struct device_node *np = ofnode_to_np(node);
1130 		int psize;
1131 		const __be32 *prop = of_get_property(np, propname, &psize);
1132 
1133 		if (!prop || sz != psize)
1134 			return NULL;
1135 		return (uint8_t *)prop;
1136 
1137 	} else {
1138 		return fdtdec_locate_byte_array(ofnode_to_fdt(node),
1139 				ofnode_to_offset(node), propname, sz);
1140 	}
1141 }
1142 
ofnode_read_pci_addr(ofnode node,enum fdt_pci_space type,const char * propname,struct fdt_pci_addr * addr)1143 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
1144 			 const char *propname, struct fdt_pci_addr *addr)
1145 {
1146 	const fdt32_t *cell;
1147 	int len;
1148 	int ret = -ENOENT;
1149 
1150 	debug("%s: %s: ", __func__, propname);
1151 
1152 	/*
1153 	 * If we follow the pci bus bindings strictly, we should check
1154 	 * the value of the node's parent node's #address-cells and
1155 	 * #size-cells. They need to be 3 and 2 accordingly. However,
1156 	 * for simplicity we skip the check here.
1157 	 */
1158 	cell = ofnode_get_property(node, propname, &len);
1159 	if (!cell)
1160 		goto fail;
1161 
1162 	if ((len % FDT_PCI_REG_SIZE) == 0) {
1163 		int num = len / FDT_PCI_REG_SIZE;
1164 		int i;
1165 
1166 		for (i = 0; i < num; i++) {
1167 			debug("pci address #%d: %08lx %08lx %08lx\n", i,
1168 			      (ulong)fdt32_to_cpu(cell[0]),
1169 			      (ulong)fdt32_to_cpu(cell[1]),
1170 			      (ulong)fdt32_to_cpu(cell[2]));
1171 			if ((fdt32_to_cpu(*cell) & type) == type) {
1172 				addr->phys_hi = fdt32_to_cpu(cell[0]);
1173 				addr->phys_mid = fdt32_to_cpu(cell[1]);
1174 				addr->phys_lo = fdt32_to_cpu(cell[2]);
1175 				break;
1176 			}
1177 
1178 			cell += (FDT_PCI_ADDR_CELLS +
1179 				 FDT_PCI_SIZE_CELLS);
1180 		}
1181 
1182 		if (i == num) {
1183 			ret = -ENXIO;
1184 			goto fail;
1185 		}
1186 
1187 		return 0;
1188 	}
1189 
1190 	ret = -EINVAL;
1191 
1192 fail:
1193 	debug("(not found)\n");
1194 	return ret;
1195 }
1196 
ofnode_read_pci_vendev(ofnode node,u16 * vendor,u16 * device)1197 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
1198 {
1199 	const char *list, *end;
1200 	int len;
1201 
1202 	list = ofnode_get_property(node, "compatible", &len);
1203 	if (!list)
1204 		return -ENOENT;
1205 
1206 	end = list + len;
1207 	while (list < end) {
1208 		len = strlen(list);
1209 		if (len >= strlen("pciVVVV,DDDD")) {
1210 			char *s = strstr(list, "pci");
1211 
1212 			/*
1213 			 * check if the string is something like pciVVVV,DDDD.RR
1214 			 * or just pciVVVV,DDDD
1215 			 */
1216 			if (s && s[7] == ',' &&
1217 			    (s[12] == '.' || s[12] == 0)) {
1218 				s += 3;
1219 				*vendor = simple_strtol(s, NULL, 16);
1220 
1221 				s += 5;
1222 				*device = simple_strtol(s, NULL, 16);
1223 
1224 				return 0;
1225 			}
1226 		}
1227 		list += (len + 1);
1228 	}
1229 
1230 	return -ENOENT;
1231 }
1232 
ofnode_read_eth_phy_id(ofnode node,u16 * vendor,u16 * device)1233 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
1234 {
1235 	const char *list, *end;
1236 	int len;
1237 
1238 	list = ofnode_get_property(node, "compatible", &len);
1239 
1240 	if (!list)
1241 		return -ENOENT;
1242 
1243 	end = list + len;
1244 	while (list < end) {
1245 		len = strlen(list);
1246 
1247 		if (len >= strlen("ethernet-phy-idVVVV.DDDD")) {
1248 			char *s = strstr(list, "ethernet-phy-id");
1249 
1250 			/*
1251 			 * check if the string is something like
1252 			 * ethernet-phy-idVVVV.DDDD
1253 			 */
1254 			if (s && s[19] == '.') {
1255 				s += strlen("ethernet-phy-id");
1256 				*vendor = simple_strtol(s, NULL, 16);
1257 				s += 5;
1258 				*device = simple_strtol(s, NULL, 16);
1259 
1260 				return 0;
1261 			}
1262 		}
1263 		list += (len + 1);
1264 	}
1265 
1266 	return -ENOENT;
1267 }
1268 
ofnode_read_addr_cells(ofnode node)1269 int ofnode_read_addr_cells(ofnode node)
1270 {
1271 	if (ofnode_is_np(node)) {
1272 		return of_n_addr_cells(ofnode_to_np(node));
1273 	} else {
1274 		int parent = fdt_parent_offset(ofnode_to_fdt(node),
1275 					       ofnode_to_offset(node));
1276 
1277 		return fdt_address_cells(ofnode_to_fdt(node), parent);
1278 	}
1279 }
1280 
ofnode_read_size_cells(ofnode node)1281 int ofnode_read_size_cells(ofnode node)
1282 {
1283 	if (ofnode_is_np(node)) {
1284 		return of_n_size_cells(ofnode_to_np(node));
1285 	} else {
1286 		int parent = fdt_parent_offset(ofnode_to_fdt(node),
1287 					       ofnode_to_offset(node));
1288 
1289 		return fdt_size_cells(ofnode_to_fdt(node), parent);
1290 	}
1291 }
1292 
ofnode_read_simple_addr_cells(ofnode node)1293 int ofnode_read_simple_addr_cells(ofnode node)
1294 {
1295 	if (ofnode_is_np(node))
1296 		return of_simple_addr_cells(ofnode_to_np(node));
1297 	else
1298 		return fdt_address_cells(ofnode_to_fdt(node),
1299 					 ofnode_to_offset(node));
1300 }
1301 
ofnode_read_simple_size_cells(ofnode node)1302 int ofnode_read_simple_size_cells(ofnode node)
1303 {
1304 	if (ofnode_is_np(node))
1305 		return of_simple_size_cells(ofnode_to_np(node));
1306 	else
1307 		return fdt_size_cells(ofnode_to_fdt(node),
1308 				      ofnode_to_offset(node));
1309 }
1310 
ofnode_pre_reloc(ofnode node)1311 bool ofnode_pre_reloc(ofnode node)
1312 {
1313 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
1314 	/* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1315 	 * had property bootph-all or bootph-pre-sram/bootph-pre-ram.
1316 	 * They are removed in final dtb (fdtgrep 2nd pass)
1317 	 */
1318 	return true;
1319 #else
1320 	if (ofnode_read_bool(node, "bootph-all"))
1321 		return true;
1322 	if (ofnode_read_bool(node, "bootph-some-ram"))
1323 		return true;
1324 
1325 	/*
1326 	 * In regular builds individual spl and tpl handling both
1327 	 * count as handled pre-relocation for later second init.
1328 	 */
1329 	if (ofnode_read_bool(node, "bootph-pre-ram") ||
1330 	    ofnode_read_bool(node, "bootph-pre-sram"))
1331 		return true;
1332 
1333 	if (IS_ENABLED(CONFIG_OF_TAG_MIGRATE)) {
1334 		/* detect and handle old tags */
1335 		if (ofnode_read_bool(node, "u-boot,dm-pre-reloc") ||
1336 		    ofnode_read_bool(node, "u-boot,dm-pre-proper") ||
1337 		    ofnode_read_bool(node, "u-boot,dm-spl") ||
1338 		    ofnode_read_bool(node, "u-boot,dm-tpl") ||
1339 		    ofnode_read_bool(node, "u-boot,dm-vpl")) {
1340 			gd->flags |= GD_FLG_OF_TAG_MIGRATE;
1341 			return true;
1342 		}
1343 	}
1344 
1345 	return false;
1346 #endif
1347 }
1348 
ofnode_read_resource(ofnode node,uint index,struct resource * res)1349 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1350 {
1351 	if (ofnode_is_np(node)) {
1352 		return of_address_to_resource(ofnode_to_np(node), index, res);
1353 	} else {
1354 		struct fdt_resource fres;
1355 		int ret;
1356 
1357 		ret = fdt_get_resource(ofnode_to_fdt(node),
1358 				       ofnode_to_offset(node),
1359 				       "reg", index, &fres);
1360 		if (ret < 0)
1361 			return -EINVAL;
1362 		memset(res, '\0', sizeof(*res));
1363 		res->start = fres.start;
1364 		res->end = fres.end;
1365 
1366 		return 0;
1367 	}
1368 }
1369 
ofnode_read_resource_byname(ofnode node,const char * name,struct resource * res)1370 int ofnode_read_resource_byname(ofnode node, const char *name,
1371 				struct resource *res)
1372 {
1373 	int index;
1374 
1375 	index = ofnode_stringlist_search(node, "reg-names", name);
1376 	if (index < 0)
1377 		return index;
1378 
1379 	return ofnode_read_resource(node, index, res);
1380 }
1381 
ofnode_translate_address(ofnode node,const fdt32_t * in_addr)1382 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1383 {
1384 	if (ofnode_is_np(node))
1385 		return of_translate_address(ofnode_to_np(node), in_addr);
1386 	else
1387 		return fdt_translate_address(ofnode_to_fdt(node),
1388 					     ofnode_to_offset(node), in_addr);
1389 }
1390 
ofnode_translate_dma_address(ofnode node,const fdt32_t * in_addr)1391 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1392 {
1393 	if (ofnode_is_np(node))
1394 		return of_translate_dma_address(ofnode_to_np(node), in_addr);
1395 	else
1396 		return fdt_translate_dma_address(ofnode_to_fdt(node),
1397 						 ofnode_to_offset(node), in_addr);
1398 }
1399 
ofnode_get_dma_range(ofnode node,phys_addr_t * cpu,dma_addr_t * bus,u64 * size)1400 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1401 {
1402 	if (ofnode_is_np(node))
1403 		return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1404 	else
1405 		return fdt_get_dma_range(ofnode_to_fdt(node),
1406 					 ofnode_to_offset(node),
1407 					 cpu, bus, size);
1408 }
1409 
ofnode_device_is_compatible(ofnode node,const char * compat)1410 int ofnode_device_is_compatible(ofnode node, const char *compat)
1411 {
1412 	if (ofnode_is_np(node))
1413 		return of_device_is_compatible(ofnode_to_np(node), compat,
1414 					       NULL, NULL);
1415 	else
1416 		return !fdt_node_check_compatible(ofnode_to_fdt(node),
1417 						  ofnode_to_offset(node),
1418 						  compat);
1419 }
1420 
ofnode_by_compatible(ofnode from,const char * compat)1421 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1422 {
1423 	if (of_live_active()) {
1424 		return np_to_ofnode(of_find_compatible_node(
1425 			(struct device_node *)ofnode_to_np(from), NULL,
1426 			compat));
1427 	} else {
1428 		return noffset_to_ofnode(from,
1429 			fdt_node_offset_by_compatible(ofnode_to_fdt(from),
1430 					ofnode_to_offset(from), compat));
1431 	}
1432 }
1433 
ofnode_by_prop_value(ofnode from,const char * propname,const void * propval,int proplen)1434 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1435 			    const void *propval, int proplen)
1436 {
1437 	if (of_live_active()) {
1438 		return np_to_ofnode(of_find_node_by_prop_value(
1439 			(struct device_node *)ofnode_to_np(from), propname,
1440 			propval, proplen));
1441 	} else {
1442 		return noffset_to_ofnode(from,
1443 			 fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
1444 				ofnode_to_offset(from), propname, propval,
1445 				proplen));
1446 	}
1447 }
1448 
ofnode_write_prop(ofnode node,const char * propname,const void * value,int len,bool copy)1449 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1450 		      int len, bool copy)
1451 {
1452 	if (of_live_active()) {
1453 		void *newval;
1454 		int ret;
1455 
1456 		if (copy) {
1457 			newval = malloc(len);
1458 			if (!newval)
1459 				return log_ret(-ENOMEM);
1460 			memcpy(newval, value, len);
1461 			value = newval;
1462 		}
1463 		ret = of_write_prop(ofnode_to_np(node), propname, len, value);
1464 		if (ret && copy)
1465 			free(newval);
1466 		return ret;
1467 	} else {
1468 		return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1469 				   propname, value, len);
1470 	}
1471 }
1472 
ofnode_write_string(ofnode node,const char * propname,const char * value)1473 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1474 {
1475 	assert(ofnode_valid(node));
1476 
1477 	debug("%s: %s = %s", __func__, propname, value);
1478 
1479 	return ofnode_write_prop(node, propname, value, strlen(value) + 1,
1480 				 false);
1481 }
1482 
ofnode_write_u32(ofnode node,const char * propname,u32 value)1483 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1484 {
1485 	fdt32_t *val;
1486 
1487 	assert(ofnode_valid(node));
1488 
1489 	log_debug("%s = %x", propname, value);
1490 	val = malloc(sizeof(*val));
1491 	if (!val)
1492 		return -ENOMEM;
1493 	*val = cpu_to_fdt32(value);
1494 
1495 	return ofnode_write_prop(node, propname, val, sizeof(value), false);
1496 }
1497 
ofnode_set_enabled(ofnode node,bool value)1498 int ofnode_set_enabled(ofnode node, bool value)
1499 {
1500 	assert(ofnode_valid(node));
1501 
1502 	if (value)
1503 		return ofnode_write_string(node, "status", "okay");
1504 	else
1505 		return ofnode_write_string(node, "status", "disabled");
1506 }
1507 
ofnode_conf_read_bool(const char * prop_name)1508 bool ofnode_conf_read_bool(const char *prop_name)
1509 {
1510 	ofnode node;
1511 
1512 	node = ofnode_path("/config");
1513 	if (!ofnode_valid(node))
1514 		return false;
1515 
1516 	return ofnode_read_bool(node, prop_name);
1517 }
1518 
ofnode_conf_read_int(const char * prop_name,int default_val)1519 int ofnode_conf_read_int(const char *prop_name, int default_val)
1520 {
1521 	ofnode node;
1522 
1523 	node = ofnode_path("/config");
1524 	if (!ofnode_valid(node))
1525 		return default_val;
1526 
1527 	return ofnode_read_u32_default(node, prop_name, default_val);
1528 }
1529 
ofnode_conf_read_str(const char * prop_name)1530 const char *ofnode_conf_read_str(const char *prop_name)
1531 {
1532 	ofnode node;
1533 
1534 	node = ofnode_path("/config");
1535 	if (!ofnode_valid(node))
1536 		return NULL;
1537 
1538 	return ofnode_read_string(node, prop_name);
1539 }
1540 
ofnode_get_phy_node(ofnode node)1541 ofnode ofnode_get_phy_node(ofnode node)
1542 {
1543 	/* DT node properties that reference a PHY node */
1544 	static const char * const phy_handle_str[] = {
1545 		"phy-handle", "phy", "phy-device",
1546 	};
1547 	struct ofnode_phandle_args args = {
1548 		.node = ofnode_null()
1549 	};
1550 	int i;
1551 
1552 	assert(ofnode_valid(node));
1553 
1554 	for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
1555 		if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
1556 						    NULL, 0, 0, &args))
1557 			break;
1558 
1559 	return args.node;
1560 }
1561 
ofnode_read_phy_mode(ofnode node)1562 phy_interface_t ofnode_read_phy_mode(ofnode node)
1563 {
1564 	const char *mode;
1565 	int i;
1566 
1567 	assert(ofnode_valid(node));
1568 
1569 	mode = ofnode_read_string(node, "phy-mode");
1570 	if (!mode)
1571 		mode = ofnode_read_string(node, "phy-connection-type");
1572 
1573 	if (!mode)
1574 		return PHY_INTERFACE_MODE_NA;
1575 
1576 	for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1577 		if (!strcmp(mode, phy_interface_strings[i]))
1578 			return i;
1579 
1580 	debug("%s: Invalid PHY interface '%s'\n", __func__, mode);
1581 
1582 	return PHY_INTERFACE_MODE_NA;
1583 }
1584 
ofnode_add_subnode(ofnode node,const char * name,ofnode * subnodep)1585 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
1586 {
1587 	ofnode subnode;
1588 	int ret = 0;
1589 
1590 	assert(ofnode_valid(node));
1591 
1592 	if (ofnode_is_np(node)) {
1593 		struct device_node *np, *child;
1594 
1595 		np = (struct device_node *)ofnode_to_np(node);
1596 		ret = of_add_subnode(np, name, -1, &child);
1597 		if (ret && ret != -EEXIST)
1598 			return ret;
1599 		subnode = np_to_ofnode(child);
1600 	} else {
1601 		void *fdt = ofnode_to_fdt(node);
1602 		int poffset = ofnode_to_offset(node);
1603 		int offset;
1604 
1605 		offset = fdt_add_subnode(fdt, poffset, name);
1606 		if (offset == -FDT_ERR_EXISTS) {
1607 			offset = fdt_subnode_offset(fdt, poffset, name);
1608 			ret = -EEXIST;
1609 		}
1610 		if (offset < 0)
1611 			return -EINVAL;
1612 		subnode = noffset_to_ofnode(node, offset);
1613 	}
1614 
1615 	*subnodep = subnode;
1616 
1617 	return ret;	/* 0 or -EEXIST */
1618 }
1619 
ofnode_copy_props(ofnode src,ofnode dst)1620 int ofnode_copy_props(ofnode src, ofnode dst)
1621 {
1622 	struct ofprop prop;
1623 
1624 	ofnode_for_each_prop(prop, src) {
1625 		const char *name;
1626 		const char *val;
1627 		int len, ret;
1628 
1629 		val = ofprop_get_property(&prop, &name, &len);
1630 		if (!val) {
1631 			log_debug("Cannot read prop (err=%d)\n", len);
1632 			return log_msg_ret("get", -EINVAL);
1633 		}
1634 		ret = ofnode_write_prop(dst, name, val, len, true);
1635 		if (ret) {
1636 			log_debug("Cannot write prop (err=%d)\n", ret);
1637 			return log_msg_ret("wr", -EINVAL);
1638 		}
1639 	}
1640 
1641 	return 0;
1642 }
1643