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 #include <common.h>
8 #include <dm.h>
9 #include <fdtdec.h>
10 #include <fdt_support.h>
11 #include <log.h>
12 #include <malloc.h>
13 #include <linux/libfdt.h>
14 #include <dm/of_access.h>
15 #include <dm/of_addr.h>
16 #include <dm/ofnode.h>
17 #include <linux/err.h>
18 #include <linux/ioport.h>
19 #include <asm/global_data.h>
20 
ofnode_name_eq(ofnode node,const char * name)21 bool ofnode_name_eq(ofnode node, const char *name)
22 {
23 	const char *node_name;
24 	size_t len;
25 
26 	assert(ofnode_valid(node));
27 
28 	node_name = ofnode_get_name(node);
29 	len = strchrnul(node_name, '@') - node_name;
30 
31 	return (strlen(name) == len) && !strncmp(node_name, name, len);
32 }
33 
ofnode_read_u32(ofnode node,const char * propname,u32 * outp)34 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
35 {
36 	return ofnode_read_u32_index(node, propname, 0, outp);
37 }
38 
ofnode_read_u32_default(ofnode node,const char * propname,u32 def)39 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
40 {
41 	assert(ofnode_valid(node));
42 	ofnode_read_u32_index(node, propname, 0, &def);
43 
44 	return def;
45 }
46 
ofnode_read_u32_index(ofnode node,const char * propname,int index,u32 * outp)47 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
48 			  u32 *outp)
49 {
50 	const fdt32_t *cell;
51 	int len;
52 
53 	assert(ofnode_valid(node));
54 	debug("%s: %s: ", __func__, propname);
55 
56 	if (ofnode_is_np(node))
57 		return of_read_u32_index(ofnode_to_np(node), propname, index,
58 					 outp);
59 
60 	cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
61 			   &len);
62 	if (!cell) {
63 		debug("(not found)\n");
64 		return -EINVAL;
65 	}
66 
67 	if (len < (sizeof(int) * (index + 1))) {
68 		debug("(not large enough)\n");
69 		return -EOVERFLOW;
70 	}
71 
72 	*outp = fdt32_to_cpu(cell[index]);
73 	debug("%#x (%d)\n", *outp, *outp);
74 
75 	return 0;
76 }
77 
ofnode_read_u32_index_default(ofnode node,const char * propname,int index,u32 def)78 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
79 				  u32 def)
80 {
81 	assert(ofnode_valid(node));
82 	ofnode_read_u32_index(node, propname, index, &def);
83 
84 	return def;
85 }
86 
ofnode_read_s32_default(ofnode node,const char * propname,s32 def)87 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
88 {
89 	assert(ofnode_valid(node));
90 	ofnode_read_u32(node, propname, (u32 *)&def);
91 
92 	return def;
93 }
94 
ofnode_read_u64(ofnode node,const char * propname,u64 * outp)95 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
96 {
97 	const unaligned_fdt64_t *cell;
98 	int len;
99 
100 	assert(ofnode_valid(node));
101 	debug("%s: %s: ", __func__, propname);
102 
103 	if (ofnode_is_np(node))
104 		return of_read_u64(ofnode_to_np(node), propname, outp);
105 
106 	cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
107 			   &len);
108 	if (!cell || len < sizeof(*cell)) {
109 		debug("(not found)\n");
110 		return -EINVAL;
111 	}
112 	*outp = fdt64_to_cpu(cell[0]);
113 	debug("%#llx (%lld)\n", (unsigned long long)*outp,
114 	      (unsigned long long)*outp);
115 
116 	return 0;
117 }
118 
ofnode_read_u64_default(ofnode node,const char * propname,u64 def)119 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
120 {
121 	assert(ofnode_valid(node));
122 	ofnode_read_u64(node, propname, &def);
123 
124 	return def;
125 }
126 
ofnode_read_bool(ofnode node,const char * propname)127 bool ofnode_read_bool(ofnode node, const char *propname)
128 {
129 	const void *prop;
130 
131 	assert(ofnode_valid(node));
132 	debug("%s: %s: ", __func__, propname);
133 
134 	prop = ofnode_get_property(node, propname, NULL);
135 
136 	debug("%s\n", prop ? "true" : "false");
137 
138 	return prop ? true : false;
139 }
140 
ofnode_read_prop(ofnode node,const char * propname,int * sizep)141 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
142 {
143 	const char *val = NULL;
144 	int len;
145 
146 	assert(ofnode_valid(node));
147 	debug("%s: %s: ", __func__, propname);
148 
149 	if (ofnode_is_np(node)) {
150 		struct property *prop = of_find_property(
151 				ofnode_to_np(node), propname, &len);
152 
153 		if (prop) {
154 			val = prop->value;
155 			len = prop->length;
156 		}
157 	} else {
158 		val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
159 				  propname, &len);
160 	}
161 	if (!val) {
162 		debug("<not found>\n");
163 		if (sizep)
164 			*sizep = -FDT_ERR_NOTFOUND;
165 		return NULL;
166 	}
167 	if (sizep)
168 		*sizep = len;
169 
170 	return val;
171 }
172 
ofnode_read_string(ofnode node,const char * propname)173 const char *ofnode_read_string(ofnode node, const char *propname)
174 {
175 	const char *str;
176 	int len;
177 
178 	str = ofnode_read_prop(node, propname, &len);
179 	if (!str)
180 		return NULL;
181 
182 	if (strnlen(str, len) >= len) {
183 		debug("<invalid>\n");
184 		return NULL;
185 	}
186 	debug("%s\n", str);
187 
188 	return str;
189 }
190 
ofnode_read_size(ofnode node,const char * propname)191 int ofnode_read_size(ofnode node, const char *propname)
192 {
193 	int len;
194 
195 	if (!ofnode_read_prop(node, propname, &len))
196 		return -EINVAL;
197 
198 	return len;
199 }
200 
ofnode_find_subnode(ofnode node,const char * subnode_name)201 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
202 {
203 	ofnode subnode;
204 
205 	assert(ofnode_valid(node));
206 	debug("%s: %s: ", __func__, subnode_name);
207 
208 	if (ofnode_is_np(node)) {
209 		const struct device_node *np = ofnode_to_np(node);
210 
211 		for (np = np->child; np; np = np->sibling) {
212 			if (!strcmp(subnode_name, np->name))
213 				break;
214 		}
215 		subnode = np_to_ofnode(np);
216 	} else {
217 		int ooffset = fdt_subnode_offset(gd->fdt_blob,
218 				ofnode_to_offset(node), subnode_name);
219 		subnode = offset_to_ofnode(ooffset);
220 	}
221 	debug("%s\n", ofnode_valid(subnode) ?
222 	      ofnode_get_name(subnode) : "<none>");
223 
224 	return subnode;
225 }
226 
ofnode_read_u32_array(ofnode node,const char * propname,u32 * out_values,size_t sz)227 int ofnode_read_u32_array(ofnode node, const char *propname,
228 			  u32 *out_values, size_t sz)
229 {
230 	assert(ofnode_valid(node));
231 	debug("%s: %s: ", __func__, propname);
232 
233 	if (ofnode_is_np(node)) {
234 		return of_read_u32_array(ofnode_to_np(node), propname,
235 					 out_values, sz);
236 	} else {
237 		return fdtdec_get_int_array(gd->fdt_blob,
238 					    ofnode_to_offset(node), propname,
239 					    out_values, sz);
240 	}
241 }
242 
243 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
ofnode_is_enabled(ofnode node)244 bool ofnode_is_enabled(ofnode node)
245 {
246 	if (ofnode_is_np(node)) {
247 		return of_device_is_available(ofnode_to_np(node));
248 	} else {
249 		return fdtdec_get_is_enabled(gd->fdt_blob,
250 					     ofnode_to_offset(node));
251 	}
252 }
253 
ofnode_first_subnode(ofnode node)254 ofnode ofnode_first_subnode(ofnode node)
255 {
256 	assert(ofnode_valid(node));
257 	if (ofnode_is_np(node))
258 		return np_to_ofnode(node.np->child);
259 
260 	return offset_to_ofnode(
261 		fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
262 }
263 
ofnode_next_subnode(ofnode node)264 ofnode ofnode_next_subnode(ofnode node)
265 {
266 	assert(ofnode_valid(node));
267 	if (ofnode_is_np(node))
268 		return np_to_ofnode(node.np->sibling);
269 
270 	return offset_to_ofnode(
271 		fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
272 }
273 #endif /* !DM_INLINE_OFNODE */
274 
ofnode_get_parent(ofnode node)275 ofnode ofnode_get_parent(ofnode node)
276 {
277 	ofnode parent;
278 
279 	assert(ofnode_valid(node));
280 	if (ofnode_is_np(node))
281 		parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
282 	else
283 		parent.of_offset = fdt_parent_offset(gd->fdt_blob,
284 						     ofnode_to_offset(node));
285 
286 	return parent;
287 }
288 
ofnode_get_name(ofnode node)289 const char *ofnode_get_name(ofnode node)
290 {
291 	if (!ofnode_valid(node)) {
292 		debug("%s node not valid\n", __func__);
293 		return NULL;
294 	}
295 
296 	if (ofnode_is_np(node))
297 		return strrchr(node.np->full_name, '/') + 1;
298 
299 	return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
300 }
301 
ofnode_get_path(ofnode node,char * buf,int buflen)302 int ofnode_get_path(ofnode node, char *buf, int buflen)
303 {
304 	assert(ofnode_valid(node));
305 
306 	if (ofnode_is_np(node)) {
307 		if (strlen(node.np->full_name) >= buflen)
308 			return -ENOSPC;
309 
310 		strcpy(buf, node.np->full_name);
311 
312 		return 0;
313 	} else {
314 		int res;
315 
316 		res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf,
317 				   buflen);
318 		if (!res)
319 			return res;
320 		else if (res == -FDT_ERR_NOSPACE)
321 			return -ENOSPC;
322 		else
323 			return -EINVAL;
324 	}
325 }
326 
ofnode_get_by_phandle(uint phandle)327 ofnode ofnode_get_by_phandle(uint phandle)
328 {
329 	ofnode node;
330 
331 	if (of_live_active())
332 		node = np_to_ofnode(of_find_node_by_phandle(phandle));
333 	else
334 		node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
335 							    phandle);
336 
337 	return node;
338 }
339 
__ofnode_get_addr_size_index(ofnode node,int index,fdt_size_t * size,bool translate)340 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
341 					       fdt_size_t *size, bool translate)
342 {
343 	int na, ns;
344 
345 	if (size)
346 		*size = FDT_SIZE_T_NONE;
347 
348 	if (ofnode_is_np(node)) {
349 		const __be32 *prop_val;
350 		u64 size64;
351 		uint flags;
352 
353 		prop_val = of_get_address(ofnode_to_np(node), index, &size64,
354 					  &flags);
355 		if (!prop_val)
356 			return FDT_ADDR_T_NONE;
357 
358 		if (size)
359 			*size = size64;
360 
361 		ns = of_n_size_cells(ofnode_to_np(node));
362 
363 		if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
364 			return of_translate_address(ofnode_to_np(node), prop_val);
365 		} else {
366 			na = of_n_addr_cells(ofnode_to_np(node));
367 			return of_read_number(prop_val, na);
368 		}
369 	} else {
370 		na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
371 		ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
372 		return fdtdec_get_addr_size_fixed(gd->fdt_blob,
373 						  ofnode_to_offset(node), "reg",
374 						  index, na, ns, size,
375 						  translate);
376 	}
377 }
378 
ofnode_get_addr_size_index(ofnode node,int index,fdt_size_t * size)379 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
380 {
381 	return __ofnode_get_addr_size_index(node, index, size, true);
382 }
383 
ofnode_get_addr_size_index_notrans(ofnode node,int index,fdt_size_t * size)384 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
385 					      fdt_size_t *size)
386 {
387 	return __ofnode_get_addr_size_index(node, index, size, false);
388 }
389 
ofnode_get_addr_index(ofnode node,int index)390 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
391 {
392 	fdt_size_t size;
393 
394 	return ofnode_get_addr_size_index(node, index, &size);
395 }
396 
ofnode_get_addr(ofnode node)397 fdt_addr_t ofnode_get_addr(ofnode node)
398 {
399 	return ofnode_get_addr_index(node, 0);
400 }
401 
ofnode_get_size(ofnode node)402 fdt_size_t ofnode_get_size(ofnode node)
403 {
404 	fdt_size_t size;
405 
406 	ofnode_get_addr_size_index(node, 0, &size);
407 
408 	return size;
409 }
410 
ofnode_stringlist_search(ofnode node,const char * property,const char * string)411 int ofnode_stringlist_search(ofnode node, const char *property,
412 			     const char *string)
413 {
414 	if (ofnode_is_np(node)) {
415 		return of_property_match_string(ofnode_to_np(node),
416 						property, string);
417 	} else {
418 		int ret;
419 
420 		ret = fdt_stringlist_search(gd->fdt_blob,
421 					    ofnode_to_offset(node), property,
422 					    string);
423 		if (ret == -FDT_ERR_NOTFOUND)
424 			return -ENODATA;
425 		else if (ret < 0)
426 			return -EINVAL;
427 
428 		return ret;
429 	}
430 }
431 
ofnode_read_string_index(ofnode node,const char * property,int index,const char ** outp)432 int ofnode_read_string_index(ofnode node, const char *property, int index,
433 			     const char **outp)
434 {
435 	if (ofnode_is_np(node)) {
436 		return of_property_read_string_index(ofnode_to_np(node),
437 						     property, index, outp);
438 	} else {
439 		int len;
440 
441 		*outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
442 					   property, index, &len);
443 		if (len < 0)
444 			return -EINVAL;
445 		return 0;
446 	}
447 }
448 
ofnode_read_string_count(ofnode node,const char * property)449 int ofnode_read_string_count(ofnode node, const char *property)
450 {
451 	if (ofnode_is_np(node)) {
452 		return of_property_count_strings(ofnode_to_np(node), property);
453 	} else {
454 		return fdt_stringlist_count(gd->fdt_blob,
455 					    ofnode_to_offset(node), property);
456 	}
457 }
458 
ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args * in,struct ofnode_phandle_args * out)459 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
460 					    struct ofnode_phandle_args *out)
461 {
462 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
463 	out->node = offset_to_ofnode(in->node);
464 	out->args_count = in->args_count;
465 	memcpy(out->args, in->args, sizeof(out->args));
466 }
467 
ofnode_from_of_phandle_args(struct of_phandle_args * in,struct ofnode_phandle_args * out)468 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
469 					struct ofnode_phandle_args *out)
470 {
471 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
472 	out->node = np_to_ofnode(in->np);
473 	out->args_count = in->args_count;
474 	memcpy(out->args, in->args, sizeof(out->args));
475 }
476 
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)477 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
478 				   const char *cells_name, int cell_count,
479 				   int index,
480 				   struct ofnode_phandle_args *out_args)
481 {
482 	if (ofnode_is_np(node)) {
483 		struct of_phandle_args args;
484 		int ret;
485 
486 		ret = of_parse_phandle_with_args(ofnode_to_np(node),
487 						 list_name, cells_name,
488 						 cell_count, index,
489 						 &args);
490 		if (ret)
491 			return ret;
492 		ofnode_from_of_phandle_args(&args, out_args);
493 	} else {
494 		struct fdtdec_phandle_args args;
495 		int ret;
496 
497 		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
498 						     ofnode_to_offset(node),
499 						     list_name, cells_name,
500 						     cell_count, index, &args);
501 		if (ret)
502 			return ret;
503 		ofnode_from_fdtdec_phandle_args(&args, out_args);
504 	}
505 
506 	return 0;
507 }
508 
ofnode_count_phandle_with_args(ofnode node,const char * list_name,const char * cells_name,int cell_count)509 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
510 				   const char *cells_name, int cell_count)
511 {
512 	if (ofnode_is_np(node))
513 		return of_count_phandle_with_args(ofnode_to_np(node),
514 				list_name, cells_name, cell_count);
515 	else
516 		return fdtdec_parse_phandle_with_args(gd->fdt_blob,
517 				ofnode_to_offset(node), list_name, cells_name,
518 				cell_count, -1, NULL);
519 }
520 
ofnode_path(const char * path)521 ofnode ofnode_path(const char *path)
522 {
523 	if (of_live_active())
524 		return np_to_ofnode(of_find_node_by_path(path));
525 	else
526 		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
527 }
528 
ofnode_read_chosen_prop(const char * propname,int * sizep)529 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
530 {
531 	ofnode chosen_node;
532 
533 	chosen_node = ofnode_path("/chosen");
534 
535 	return ofnode_read_prop(chosen_node, propname, sizep);
536 }
537 
ofnode_read_chosen_string(const char * propname)538 const char *ofnode_read_chosen_string(const char *propname)
539 {
540 	return ofnode_read_chosen_prop(propname, NULL);
541 }
542 
ofnode_get_chosen_node(const char * name)543 ofnode ofnode_get_chosen_node(const char *name)
544 {
545 	const char *prop;
546 
547 	prop = ofnode_read_chosen_prop(name, NULL);
548 	if (!prop)
549 		return ofnode_null();
550 
551 	return ofnode_path(prop);
552 }
553 
ofnode_read_aliases_prop(const char * propname,int * sizep)554 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
555 {
556 	ofnode node;
557 
558 	node = ofnode_path("/aliases");
559 
560 	return ofnode_read_prop(node, propname, sizep);
561 }
562 
ofnode_get_aliases_node(const char * name)563 ofnode ofnode_get_aliases_node(const char *name)
564 {
565 	const char *prop;
566 
567 	prop = ofnode_read_aliases_prop(name, NULL);
568 	if (!prop)
569 		return ofnode_null();
570 
571 	debug("%s: node_path: %s\n", __func__, prop);
572 
573 	return ofnode_path(prop);
574 }
575 
ofnode_get_child_count(ofnode parent)576 int ofnode_get_child_count(ofnode parent)
577 {
578 	ofnode child;
579 	int num = 0;
580 
581 	ofnode_for_each_subnode(child, parent)
582 		num++;
583 
584 	return num;
585 }
586 
decode_timing_property(ofnode node,const char * name,struct timing_entry * result)587 static int decode_timing_property(ofnode node, const char *name,
588 				  struct timing_entry *result)
589 {
590 	int length, ret = 0;
591 
592 	length = ofnode_read_size(node, name);
593 	if (length < 0) {
594 		debug("%s: could not find property %s\n",
595 		      ofnode_get_name(node), name);
596 		return length;
597 	}
598 
599 	if (length == sizeof(u32)) {
600 		result->typ = ofnode_read_u32_default(node, name, 0);
601 		result->min = result->typ;
602 		result->max = result->typ;
603 	} else {
604 		ret = ofnode_read_u32_array(node, name, &result->min, 3);
605 	}
606 
607 	return ret;
608 }
609 
ofnode_decode_display_timing(ofnode parent,int index,struct display_timing * dt)610 int ofnode_decode_display_timing(ofnode parent, int index,
611 				 struct display_timing *dt)
612 {
613 	int i;
614 	ofnode timings, node;
615 	u32 val = 0;
616 	int ret = 0;
617 
618 	timings = ofnode_find_subnode(parent, "display-timings");
619 	if (!ofnode_valid(timings))
620 		return -EINVAL;
621 
622 	i = 0;
623 	ofnode_for_each_subnode(node, timings) {
624 		if (i++ == index)
625 			break;
626 	}
627 
628 	if (!ofnode_valid(node))
629 		return -EINVAL;
630 
631 	memset(dt, 0, sizeof(*dt));
632 
633 	ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
634 	ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
635 	ret |= decode_timing_property(node, "hactive", &dt->hactive);
636 	ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
637 	ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
638 	ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
639 	ret |= decode_timing_property(node, "vactive", &dt->vactive);
640 	ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
641 	ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
642 
643 	dt->flags = 0;
644 	val = ofnode_read_u32_default(node, "vsync-active", -1);
645 	if (val != -1) {
646 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
647 				DISPLAY_FLAGS_VSYNC_LOW;
648 	}
649 	val = ofnode_read_u32_default(node, "hsync-active", -1);
650 	if (val != -1) {
651 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
652 				DISPLAY_FLAGS_HSYNC_LOW;
653 	}
654 	val = ofnode_read_u32_default(node, "de-active", -1);
655 	if (val != -1) {
656 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
657 				DISPLAY_FLAGS_DE_LOW;
658 	}
659 	val = ofnode_read_u32_default(node, "pixelclk-active", -1);
660 	if (val != -1) {
661 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
662 				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
663 	}
664 
665 	if (ofnode_read_bool(node, "interlaced"))
666 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
667 	if (ofnode_read_bool(node, "doublescan"))
668 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
669 	if (ofnode_read_bool(node, "doubleclk"))
670 		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
671 
672 	return ret;
673 }
674 
ofnode_get_property(ofnode node,const char * propname,int * lenp)675 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
676 {
677 	if (ofnode_is_np(node))
678 		return of_get_property(ofnode_to_np(node), propname, lenp);
679 	else
680 		return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
681 				   propname, lenp);
682 }
683 
ofnode_get_first_property(ofnode node,struct ofprop * prop)684 int ofnode_get_first_property(ofnode node, struct ofprop *prop)
685 {
686 	prop->node = node;
687 
688 	if (ofnode_is_np(node)) {
689 		prop->prop = of_get_first_property(ofnode_to_np(prop->node));
690 		if (!prop->prop)
691 			return -FDT_ERR_NOTFOUND;
692 	} else {
693 		prop->offset =
694 			fdt_first_property_offset(gd->fdt_blob,
695 						  ofnode_to_offset(prop->node));
696 		if (prop->offset < 0)
697 			return prop->offset;
698 	}
699 
700 	return 0;
701 }
702 
ofnode_get_next_property(struct ofprop * prop)703 int ofnode_get_next_property(struct ofprop *prop)
704 {
705 	if (ofnode_is_np(prop->node)) {
706 		prop->prop = of_get_next_property(ofnode_to_np(prop->node),
707 						  prop->prop);
708 		if (!prop->prop)
709 			return -FDT_ERR_NOTFOUND;
710 	} else {
711 		prop->offset = fdt_next_property_offset(gd->fdt_blob,
712 							prop->offset);
713 		if (prop->offset  < 0)
714 			return prop->offset;
715 	}
716 
717 	return 0;
718 }
719 
ofnode_get_property_by_prop(const struct ofprop * prop,const char ** propname,int * lenp)720 const void *ofnode_get_property_by_prop(const struct ofprop *prop,
721 					const char **propname, int *lenp)
722 {
723 	if (ofnode_is_np(prop->node))
724 		return of_get_property_by_prop(ofnode_to_np(prop->node),
725 					       prop->prop, propname, lenp);
726 	else
727 		return fdt_getprop_by_offset(gd->fdt_blob,
728 					     prop->offset,
729 					     propname, lenp);
730 }
731 
ofnode_is_available(ofnode node)732 bool ofnode_is_available(ofnode node)
733 {
734 	if (ofnode_is_np(node))
735 		return of_device_is_available(ofnode_to_np(node));
736 	else
737 		return fdtdec_get_is_enabled(gd->fdt_blob,
738 					     ofnode_to_offset(node));
739 }
740 
ofnode_get_addr_size(ofnode node,const char * property,fdt_size_t * sizep)741 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
742 				fdt_size_t *sizep)
743 {
744 	if (ofnode_is_np(node)) {
745 		int na, ns;
746 		int psize;
747 		const struct device_node *np = ofnode_to_np(node);
748 		const __be32 *prop = of_get_property(np, property, &psize);
749 
750 		if (!prop)
751 			return FDT_ADDR_T_NONE;
752 		na = of_n_addr_cells(np);
753 		ns = of_n_size_cells(np);
754 		*sizep = of_read_number(prop + na, ns);
755 
756 		if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
757 			return of_translate_address(np, prop);
758 		else
759 			return of_read_number(prop, na);
760 	} else {
761 		return fdtdec_get_addr_size(gd->fdt_blob,
762 					    ofnode_to_offset(node), property,
763 					    sizep);
764 	}
765 }
766 
ofnode_read_u8_array_ptr(ofnode node,const char * propname,size_t sz)767 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
768 					size_t sz)
769 {
770 	if (ofnode_is_np(node)) {
771 		const struct device_node *np = ofnode_to_np(node);
772 		int psize;
773 		const __be32 *prop = of_get_property(np, propname, &psize);
774 
775 		if (!prop || sz != psize)
776 			return NULL;
777 		return (uint8_t *)prop;
778 
779 	} else {
780 		return fdtdec_locate_byte_array(gd->fdt_blob,
781 				ofnode_to_offset(node), propname, sz);
782 	}
783 }
784 
ofnode_read_pci_addr(ofnode node,enum fdt_pci_space type,const char * propname,struct fdt_pci_addr * addr)785 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
786 			 const char *propname, struct fdt_pci_addr *addr)
787 {
788 	const fdt32_t *cell;
789 	int len;
790 	int ret = -ENOENT;
791 
792 	debug("%s: %s: ", __func__, propname);
793 
794 	/*
795 	 * If we follow the pci bus bindings strictly, we should check
796 	 * the value of the node's parent node's #address-cells and
797 	 * #size-cells. They need to be 3 and 2 accordingly. However,
798 	 * for simplicity we skip the check here.
799 	 */
800 	cell = ofnode_get_property(node, propname, &len);
801 	if (!cell)
802 		goto fail;
803 
804 	if ((len % FDT_PCI_REG_SIZE) == 0) {
805 		int num = len / FDT_PCI_REG_SIZE;
806 		int i;
807 
808 		for (i = 0; i < num; i++) {
809 			debug("pci address #%d: %08lx %08lx %08lx\n", i,
810 			      (ulong)fdt32_to_cpu(cell[0]),
811 			      (ulong)fdt32_to_cpu(cell[1]),
812 			      (ulong)fdt32_to_cpu(cell[2]));
813 			if ((fdt32_to_cpu(*cell) & type) == type) {
814 				addr->phys_hi = fdt32_to_cpu(cell[0]);
815 				addr->phys_mid = fdt32_to_cpu(cell[1]);
816 				addr->phys_lo = fdt32_to_cpu(cell[2]);
817 				break;
818 			}
819 
820 			cell += (FDT_PCI_ADDR_CELLS +
821 				 FDT_PCI_SIZE_CELLS);
822 		}
823 
824 		if (i == num) {
825 			ret = -ENXIO;
826 			goto fail;
827 		}
828 
829 		return 0;
830 	}
831 
832 	ret = -EINVAL;
833 
834 fail:
835 	debug("(not found)\n");
836 	return ret;
837 }
838 
ofnode_read_pci_vendev(ofnode node,u16 * vendor,u16 * device)839 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
840 {
841 	const char *list, *end;
842 	int len;
843 
844 	list = ofnode_get_property(node, "compatible", &len);
845 	if (!list)
846 		return -ENOENT;
847 
848 	end = list + len;
849 	while (list < end) {
850 		len = strlen(list);
851 		if (len >= strlen("pciVVVV,DDDD")) {
852 			char *s = strstr(list, "pci");
853 
854 			/*
855 			 * check if the string is something like pciVVVV,DDDD.RR
856 			 * or just pciVVVV,DDDD
857 			 */
858 			if (s && s[7] == ',' &&
859 			    (s[12] == '.' || s[12] == 0)) {
860 				s += 3;
861 				*vendor = simple_strtol(s, NULL, 16);
862 
863 				s += 5;
864 				*device = simple_strtol(s, NULL, 16);
865 
866 				return 0;
867 			}
868 		}
869 		list += (len + 1);
870 	}
871 
872 	return -ENOENT;
873 }
874 
ofnode_read_addr_cells(ofnode node)875 int ofnode_read_addr_cells(ofnode node)
876 {
877 	if (ofnode_is_np(node)) {
878 		return of_n_addr_cells(ofnode_to_np(node));
879 	} else {
880 		int parent = fdt_parent_offset(gd->fdt_blob,
881 					       ofnode_to_offset(node));
882 
883 		return fdt_address_cells(gd->fdt_blob, parent);
884 	}
885 }
886 
ofnode_read_size_cells(ofnode node)887 int ofnode_read_size_cells(ofnode node)
888 {
889 	if (ofnode_is_np(node)) {
890 		return of_n_size_cells(ofnode_to_np(node));
891 	} else {
892 		int parent = fdt_parent_offset(gd->fdt_blob,
893 					       ofnode_to_offset(node));
894 
895 		return fdt_size_cells(gd->fdt_blob, parent);
896 	}
897 }
898 
ofnode_read_simple_addr_cells(ofnode node)899 int ofnode_read_simple_addr_cells(ofnode node)
900 {
901 	if (ofnode_is_np(node))
902 		return of_simple_addr_cells(ofnode_to_np(node));
903 	else
904 		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
905 }
906 
ofnode_read_simple_size_cells(ofnode node)907 int ofnode_read_simple_size_cells(ofnode node)
908 {
909 	if (ofnode_is_np(node))
910 		return of_simple_size_cells(ofnode_to_np(node));
911 	else
912 		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
913 }
914 
ofnode_pre_reloc(ofnode node)915 bool ofnode_pre_reloc(ofnode node)
916 {
917 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
918 	/* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
919 	 * had property dm-pre-reloc or u-boot,dm-spl/tpl.
920 	 * They are removed in final dtb (fdtgrep 2nd pass)
921 	 */
922 	return true;
923 #else
924 	if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
925 		return true;
926 	if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
927 		return true;
928 
929 	/*
930 	 * In regular builds individual spl and tpl handling both
931 	 * count as handled pre-relocation for later second init.
932 	 */
933 	if (ofnode_read_bool(node, "u-boot,dm-spl") ||
934 	    ofnode_read_bool(node, "u-boot,dm-tpl"))
935 		return true;
936 
937 	return false;
938 #endif
939 }
940 
ofnode_read_resource(ofnode node,uint index,struct resource * res)941 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
942 {
943 	if (ofnode_is_np(node)) {
944 		return of_address_to_resource(ofnode_to_np(node), index, res);
945 	} else {
946 		struct fdt_resource fres;
947 		int ret;
948 
949 		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
950 				       "reg", index, &fres);
951 		if (ret < 0)
952 			return -EINVAL;
953 		memset(res, '\0', sizeof(*res));
954 		res->start = fres.start;
955 		res->end = fres.end;
956 
957 		return 0;
958 	}
959 }
960 
ofnode_read_resource_byname(ofnode node,const char * name,struct resource * res)961 int ofnode_read_resource_byname(ofnode node, const char *name,
962 				struct resource *res)
963 {
964 	int index;
965 
966 	index = ofnode_stringlist_search(node, "reg-names", name);
967 	if (index < 0)
968 		return index;
969 
970 	return ofnode_read_resource(node, index, res);
971 }
972 
ofnode_translate_address(ofnode node,const fdt32_t * in_addr)973 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
974 {
975 	if (ofnode_is_np(node))
976 		return of_translate_address(ofnode_to_np(node), in_addr);
977 	else
978 		return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
979 }
980 
ofnode_translate_dma_address(ofnode node,const fdt32_t * in_addr)981 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
982 {
983 	if (ofnode_is_np(node))
984 		return of_translate_dma_address(ofnode_to_np(node), in_addr);
985 	else
986 		return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
987 }
988 
ofnode_get_dma_range(ofnode node,phys_addr_t * cpu,dma_addr_t * bus,u64 * size)989 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
990 {
991 	if (ofnode_is_np(node))
992 		return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
993 	else
994 		return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
995 					 cpu, bus, size);
996 }
997 
ofnode_device_is_compatible(ofnode node,const char * compat)998 int ofnode_device_is_compatible(ofnode node, const char *compat)
999 {
1000 	if (ofnode_is_np(node))
1001 		return of_device_is_compatible(ofnode_to_np(node), compat,
1002 					       NULL, NULL);
1003 	else
1004 		return !fdt_node_check_compatible(gd->fdt_blob,
1005 						  ofnode_to_offset(node),
1006 						  compat);
1007 }
1008 
ofnode_by_compatible(ofnode from,const char * compat)1009 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1010 {
1011 	if (of_live_active()) {
1012 		return np_to_ofnode(of_find_compatible_node(
1013 			(struct device_node *)ofnode_to_np(from), NULL,
1014 			compat));
1015 	} else {
1016 		return offset_to_ofnode(fdt_node_offset_by_compatible(
1017 				gd->fdt_blob, ofnode_to_offset(from), compat));
1018 	}
1019 }
1020 
ofnode_by_prop_value(ofnode from,const char * propname,const void * propval,int proplen)1021 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1022 			    const void *propval, int proplen)
1023 {
1024 	if (of_live_active()) {
1025 		return np_to_ofnode(of_find_node_by_prop_value(
1026 			(struct device_node *)ofnode_to_np(from), propname,
1027 			propval, proplen));
1028 	} else {
1029 		return offset_to_ofnode(fdt_node_offset_by_prop_value(
1030 				gd->fdt_blob, ofnode_to_offset(from),
1031 				propname, propval, proplen));
1032 	}
1033 }
1034 
ofnode_write_prop(ofnode node,const char * propname,int len,const void * value)1035 int ofnode_write_prop(ofnode node, const char *propname, int len,
1036 		      const void *value)
1037 {
1038 	const struct device_node *np = ofnode_to_np(node);
1039 	struct property *pp;
1040 	struct property *pp_last = NULL;
1041 	struct property *new;
1042 
1043 	if (!of_live_active())
1044 		return -ENOSYS;
1045 
1046 	if (!np)
1047 		return -EINVAL;
1048 
1049 	for (pp = np->properties; pp; pp = pp->next) {
1050 		if (strcmp(pp->name, propname) == 0) {
1051 			/* Property exists -> change value */
1052 			pp->value = (void *)value;
1053 			pp->length = len;
1054 			return 0;
1055 		}
1056 		pp_last = pp;
1057 	}
1058 
1059 	if (!pp_last)
1060 		return -ENOENT;
1061 
1062 	/* Property does not exist -> append new property */
1063 	new = malloc(sizeof(struct property));
1064 	if (!new)
1065 		return -ENOMEM;
1066 
1067 	new->name = strdup(propname);
1068 	if (!new->name) {
1069 		free(new);
1070 		return -ENOMEM;
1071 	}
1072 
1073 	new->value = (void *)value;
1074 	new->length = len;
1075 	new->next = NULL;
1076 
1077 	pp_last->next = new;
1078 
1079 	return 0;
1080 }
1081 
ofnode_write_string(ofnode node,const char * propname,const char * value)1082 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1083 {
1084 	if (!of_live_active())
1085 		return -ENOSYS;
1086 
1087 	assert(ofnode_valid(node));
1088 
1089 	debug("%s: %s = %s", __func__, propname, value);
1090 
1091 	return ofnode_write_prop(node, propname, strlen(value) + 1, value);
1092 }
1093 
ofnode_set_enabled(ofnode node,bool value)1094 int ofnode_set_enabled(ofnode node, bool value)
1095 {
1096 	if (!of_live_active())
1097 		return -ENOSYS;
1098 
1099 	assert(ofnode_valid(node));
1100 
1101 	if (value)
1102 		return ofnode_write_string(node, "status", "okay");
1103 	else
1104 		return ofnode_write_string(node, "status", "disabled");
1105 }
1106 
ofnode_conf_read_bool(const char * prop_name)1107 bool ofnode_conf_read_bool(const char *prop_name)
1108 {
1109 	ofnode node;
1110 
1111 	node = ofnode_path("/config");
1112 	if (!ofnode_valid(node))
1113 		return false;
1114 
1115 	return ofnode_read_bool(node, prop_name);
1116 }
1117 
ofnode_conf_read_int(const char * prop_name,int default_val)1118 int ofnode_conf_read_int(const char *prop_name, int default_val)
1119 {
1120 	ofnode node;
1121 
1122 	node = ofnode_path("/config");
1123 	if (!ofnode_valid(node))
1124 		return default_val;
1125 
1126 	return ofnode_read_u32_default(node, prop_name, default_val);
1127 }
1128 
ofnode_conf_read_str(const char * prop_name)1129 const char *ofnode_conf_read_str(const char *prop_name)
1130 {
1131 	ofnode node;
1132 
1133 	node = ofnode_path("/config");
1134 	if (!ofnode_valid(node))
1135 		return NULL;
1136 
1137 	return ofnode_read_string(node, prop_name);
1138 }
1139