xref: /rk3399_rockchip-uboot/drivers/core/ofnode.c (revision e7ca7e39ee39e18448065e7f00e708262ecd3bdf)
1 /*
2  * Copyright (c) 2017 Google, Inc
3  * Written by Simon Glass <sjg@chromium.org>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <dm.h>
10 #include <fdtdec.h>
11 #include <fdt_support.h>
12 #include <libfdt.h>
13 #include <dm/of_access.h>
14 #include <dm/of_addr.h>
15 #include <dm/ofnode.h>
16 #include <linux/err.h>
17 #include <linux/ioport.h>
18 
19 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
20 {
21 	assert(ofnode_valid(node));
22 	debug("%s: %s: ", __func__, propname);
23 
24 	if (ofnode_is_np(node)) {
25 		return of_read_u32(ofnode_to_np(node), propname, outp);
26 	} else {
27 		const fdt32_t *cell;
28 		int len;
29 
30 		cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
31 				   propname, &len);
32 		if (!cell || len < sizeof(int)) {
33 			debug("(not found)\n");
34 			return -EINVAL;
35 		}
36 		*outp = fdt32_to_cpu(cell[0]);
37 	}
38 	debug("%#x (%d)\n", *outp, *outp);
39 
40 	return 0;
41 }
42 
43 int ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
44 {
45 	assert(ofnode_valid(node));
46 	ofnode_read_u32(node, propname, &def);
47 
48 	return def;
49 }
50 
51 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
52 {
53 	assert(ofnode_valid(node));
54 	ofnode_read_u32(node, propname, (u32 *)&def);
55 
56 	return def;
57 }
58 
59 bool ofnode_read_bool(ofnode node, const char *propname)
60 {
61 	const void *prop;
62 
63 	assert(ofnode_valid(node));
64 	debug("%s: %s: ", __func__, propname);
65 
66 	prop = ofnode_get_property(node, propname, NULL);
67 
68 	debug("%s\n", prop ? "true" : "false");
69 
70 	return prop ? true : false;
71 }
72 
73 const char *ofnode_read_string(ofnode node, const char *propname)
74 {
75 	const char *str = NULL;
76 	int len = -1;
77 
78 	assert(ofnode_valid(node));
79 	debug("%s: %s: ", __func__, propname);
80 
81 	if (ofnode_is_np(node)) {
82 		struct property *prop = of_find_property(
83 				ofnode_to_np(node), propname, NULL);
84 
85 		if (prop) {
86 			str = prop->value;
87 			len = prop->length;
88 		}
89 	} else {
90 		str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
91 				  propname, &len);
92 	}
93 	if (!str) {
94 		debug("<not found>\n");
95 		return NULL;
96 	}
97 	if (strnlen(str, len) >= len) {
98 		debug("<invalid>\n");
99 		return NULL;
100 	}
101 	debug("%s\n", str);
102 
103 	return str;
104 }
105 
106 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
107 {
108 	ofnode subnode;
109 
110 	assert(ofnode_valid(node));
111 	debug("%s: %s: ", __func__, subnode_name);
112 
113 	if (ofnode_is_np(node)) {
114 		const struct device_node *np = ofnode_to_np(node);
115 
116 		for (np = np->child; np; np = np->sibling) {
117 			if (!strcmp(subnode_name, np->name))
118 				break;
119 		}
120 		subnode = np_to_ofnode(np);
121 	} else {
122 		int ooffset = fdt_subnode_offset(gd->fdt_blob,
123 				ofnode_to_offset(node), subnode_name);
124 		subnode = offset_to_ofnode(ooffset);
125 	}
126 	debug("%s\n", ofnode_valid(subnode) ?
127 	      ofnode_get_name(subnode) : "<none>");
128 
129 	return subnode;
130 }
131 
132 int ofnode_read_u32_array(ofnode node, const char *propname,
133 			  u32 *out_values, size_t sz)
134 {
135 	assert(ofnode_valid(node));
136 	debug("%s: %s: ", __func__, propname);
137 
138 	if (ofnode_is_np(node)) {
139 		return of_read_u32_array(ofnode_to_np(node), propname,
140 					 out_values, sz);
141 	} else {
142 		return fdtdec_get_int_array(gd->fdt_blob,
143 					    ofnode_to_offset(node), propname,
144 					    out_values, sz);
145 	}
146 }
147 
148 ofnode ofnode_first_subnode(ofnode node)
149 {
150 	assert(ofnode_valid(node));
151 	if (ofnode_is_np(node))
152 		return np_to_ofnode(node.np->child);
153 
154 	return offset_to_ofnode(
155 		fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
156 }
157 
158 ofnode ofnode_next_subnode(ofnode node)
159 {
160 	assert(ofnode_valid(node));
161 	if (ofnode_is_np(node))
162 		return np_to_ofnode(node.np->sibling);
163 
164 	return offset_to_ofnode(
165 		fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
166 }
167 
168 ofnode ofnode_get_parent(ofnode node)
169 {
170 	ofnode parent;
171 
172 	assert(ofnode_valid(node));
173 	if (ofnode_is_np(node))
174 		parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
175 	else
176 		parent.of_offset = fdt_parent_offset(gd->fdt_blob,
177 						     ofnode_to_offset(node));
178 
179 	return parent;
180 }
181 
182 const char *ofnode_get_name(ofnode node)
183 {
184 	if(!ofnode_valid(node)){
185 		debug("%s node not valid\n", __func__);
186 		return NULL;
187 	}
188 	if (ofnode_is_np(node))
189 		return strrchr(node.np->full_name, '/') + 1;
190 
191 	return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
192 }
193 
194 ofnode ofnode_get_by_phandle(uint phandle)
195 {
196 	ofnode node;
197 
198 	if (of_live_active())
199 		node = np_to_ofnode(of_find_node_by_phandle(phandle));
200 	else
201 		node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
202 							    phandle);
203 
204 	return node;
205 }
206 
207 int ofnode_read_size(ofnode node, const char *propname)
208 {
209 	int len;
210 
211 	if (ofnode_is_np(node)) {
212 		struct property *prop = of_find_property(
213 				ofnode_to_np(node), propname, NULL);
214 
215 		if (prop)
216 			return prop->length;
217 	} else {
218 		if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
219 				&len))
220 			return len;
221 	}
222 
223 	return -EINVAL;
224 }
225 
226 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
227 {
228 	if (ofnode_is_np(node)) {
229 		const __be32 *prop_val;
230 		uint flags;
231 		u64 size;
232 		int na;
233 
234 		prop_val = of_get_address(ofnode_to_np(node), index, &size,
235 					  &flags);
236 		if (!prop_val)
237 			return FDT_ADDR_T_NONE;
238 		na = of_n_addr_cells(ofnode_to_np(node));
239 		return of_read_number(prop_val, na);
240 	} else {
241 		return fdt_get_base_address(gd->fdt_blob,
242 					    ofnode_to_offset(node));
243 	}
244 
245 	return FDT_ADDR_T_NONE;
246 }
247 
248 fdt_addr_t ofnode_get_addr(ofnode node)
249 {
250 	return ofnode_get_addr_index(node, 0);
251 }
252 
253 int ofnode_stringlist_search(ofnode node, const char *property,
254 			     const char *string)
255 {
256 	if (ofnode_is_np(node)) {
257 		return of_property_match_string(ofnode_to_np(node),
258 						property, string);
259 	} else {
260 		int ret;
261 
262 		ret = fdt_stringlist_search(gd->fdt_blob,
263 					    ofnode_to_offset(node), property,
264 					    string);
265 		if (ret == -FDT_ERR_NOTFOUND)
266 			return -ENODATA;
267 		else if (ret < 0)
268 			return -EINVAL;
269 
270 		return ret;
271 	}
272 }
273 
274 int ofnode_read_string_index(ofnode node, const char *property, int index,
275 			     const char **outp)
276 {
277 	if (ofnode_is_np(node)) {
278 		return of_property_read_string_index(ofnode_to_np(node),
279 						     property, index, outp);
280 	} else {
281 		int len;
282 
283 		*outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
284 					   property, index, &len);
285 		if (len < 0)
286 			return -EINVAL;
287 		return 0;
288 	}
289 }
290 
291 int ofnode_read_string_count(ofnode node, const char *property)
292 {
293 	if (ofnode_is_np(node)) {
294 		return of_property_count_strings(ofnode_to_np(node), property);
295 	} else {
296 		return fdt_stringlist_count(gd->fdt_blob,
297 					    ofnode_to_offset(node), property);
298 	}
299 }
300 
301 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
302 					    struct ofnode_phandle_args *out)
303 {
304 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
305 	out->node = offset_to_ofnode(in->node);
306 	out->args_count = in->args_count;
307 	memcpy(out->args, in->args, sizeof(out->args));
308 }
309 
310 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
311 					struct ofnode_phandle_args *out)
312 {
313 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
314 	out->node = np_to_ofnode(in->np);
315 	out->args_count = in->args_count;
316 	memcpy(out->args, in->args, sizeof(out->args));
317 }
318 
319 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
320 				   const char *cells_name, int cell_count,
321 				   int index,
322 				   struct ofnode_phandle_args *out_args)
323 {
324 	if (ofnode_is_np(node)) {
325 		struct of_phandle_args args;
326 		int ret;
327 
328 		ret = of_parse_phandle_with_args(ofnode_to_np(node),
329 				list_name, cells_name, index, &args);
330 		if (ret)
331 			return ret;
332 		ofnode_from_of_phandle_args(&args, out_args);
333 	} else {
334 		struct fdtdec_phandle_args args;
335 		int ret;
336 
337 		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
338 				ofnode_to_offset(node), list_name, cells_name,
339 				cell_count, index, &args);
340 		if (ret)
341 			return ret;
342 		ofnode_from_fdtdec_phandle_args(&args, out_args);
343 	}
344 
345 	return 0;
346 }
347 
348 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
349 				   const char *cells_name)
350 {
351 	if (ofnode_is_np(node))
352 		return of_count_phandle_with_args(ofnode_to_np(node),
353 				list_name, cells_name);
354 	else
355 		return fdtdec_parse_phandle_with_args(gd->fdt_blob,
356 				ofnode_to_offset(node), list_name, cells_name,
357 				0, -1, NULL);
358 }
359 
360 ofnode ofnode_path(const char *path)
361 {
362 	if (of_live_active())
363 		return np_to_ofnode(of_find_node_by_path(path));
364 	else
365 		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
366 }
367 
368 const char *ofnode_get_chosen_prop(const char *name)
369 {
370 	ofnode chosen_node;
371 
372 	chosen_node = ofnode_path("/chosen");
373 
374 	return ofnode_read_string(chosen_node, name);
375 }
376 
377 ofnode ofnode_get_chosen_node(const char *name)
378 {
379 	const char *prop;
380 
381 	prop = ofnode_get_chosen_prop(name);
382 	if (!prop)
383 		return ofnode_null();
384 
385 	return ofnode_path(prop);
386 }
387 
388 static int decode_timing_property(ofnode node, const char *name,
389 				  struct timing_entry *result)
390 {
391 	int length, ret = 0;
392 
393 	length = ofnode_read_size(node, name);
394 	if (length < 0) {
395 		debug("%s: could not find property %s\n",
396 		      ofnode_get_name(node), name);
397 		return length;
398 	}
399 
400 	if (length == sizeof(u32)) {
401 		result->typ = ofnode_read_u32_default(node, name, 0);
402 		result->min = result->typ;
403 		result->max = result->typ;
404 	} else {
405 		ret = ofnode_read_u32_array(node, name, &result->min, 3);
406 	}
407 
408 	return ret;
409 }
410 
411 int ofnode_decode_display_timing(ofnode parent, int index,
412 				 struct display_timing *dt)
413 {
414 	int i;
415 	ofnode timings, node;
416 	u32 val = 0;
417 	int ret = 0;
418 
419 	timings = ofnode_find_subnode(parent, "display-timings");
420 	if (!ofnode_valid(timings))
421 		return -EINVAL;
422 
423 	i = 0;
424 	ofnode_for_each_subnode(node, timings) {
425 		if (i++ == index)
426 			break;
427 	}
428 
429 	if (!ofnode_valid(node))
430 		return -EINVAL;
431 
432 	memset(dt, 0, sizeof(*dt));
433 
434 	ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
435 	ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
436 	ret |= decode_timing_property(node, "hactive", &dt->hactive);
437 	ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
438 	ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
439 	ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
440 	ret |= decode_timing_property(node, "vactive", &dt->vactive);
441 	ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
442 	ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
443 
444 	dt->flags = 0;
445 	val = ofnode_read_u32_default(node, "vsync-active", -1);
446 	if (val != -1) {
447 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
448 				DISPLAY_FLAGS_VSYNC_LOW;
449 	}
450 	val = ofnode_read_u32_default(node, "hsync-active", -1);
451 	if (val != -1) {
452 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
453 				DISPLAY_FLAGS_HSYNC_LOW;
454 	}
455 	val = ofnode_read_u32_default(node, "de-active", -1);
456 	if (val != -1) {
457 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
458 				DISPLAY_FLAGS_DE_LOW;
459 	}
460 	val = ofnode_read_u32_default(node, "pixelclk-active", -1);
461 	if (val != -1) {
462 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
463 				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
464 	}
465 
466 	if (ofnode_read_bool(node, "interlaced"))
467 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
468 	if (ofnode_read_bool(node, "doublescan"))
469 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
470 	if (ofnode_read_bool(node, "doubleclk"))
471 		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
472 
473 	return ret;
474 }
475 
476 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
477 {
478 	if (ofnode_is_np(node))
479 		return of_get_property(ofnode_to_np(node), propname, lenp);
480 	else
481 		return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
482 				   propname, lenp);
483 }
484 
485 bool ofnode_is_available(ofnode node)
486 {
487 	if (ofnode_is_np(node))
488 		return of_device_is_available(ofnode_to_np(node));
489 	else
490 		return fdtdec_get_is_enabled(gd->fdt_blob,
491 					     ofnode_to_offset(node));
492 }
493 
494 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
495 				fdt_size_t *sizep)
496 {
497 	if (ofnode_is_np(node)) {
498 		int na, ns;
499 		int psize;
500 		const struct device_node *np = ofnode_to_np(node);
501 		const __be32 *prop = of_get_property(np, property, &psize);
502 
503 		if (!prop)
504 			return FDT_ADDR_T_NONE;
505 		na = of_n_addr_cells(np);
506 		ns = of_n_addr_cells(np);
507 		*sizep = of_read_number(prop + na, ns);
508 		return of_read_number(prop, na);
509 	} else {
510 		return fdtdec_get_addr_size(gd->fdt_blob,
511 					    ofnode_to_offset(node), property,
512 					    sizep);
513 	}
514 }
515 
516 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
517 					size_t sz)
518 {
519 	if (ofnode_is_np(node)) {
520 		const struct device_node *np = ofnode_to_np(node);
521 		int psize;
522 		const __be32 *prop = of_get_property(np, propname, &psize);
523 
524 		if (!prop || sz != psize)
525 			return NULL;
526 		return (uint8_t *)prop;
527 
528 	} else {
529 		return fdtdec_locate_byte_array(gd->fdt_blob,
530 				ofnode_to_offset(node), propname, sz);
531 	}
532 }
533 
534 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
535 			 const char *propname, struct fdt_pci_addr *addr)
536 {
537 	const fdt32_t *cell;
538 	int len;
539 	int ret = -ENOENT;
540 
541 	debug("%s: %s: ", __func__, propname);
542 
543 	/*
544 	 * If we follow the pci bus bindings strictly, we should check
545 	 * the value of the node's parent node's #address-cells and
546 	 * #size-cells. They need to be 3 and 2 accordingly. However,
547 	 * for simplicity we skip the check here.
548 	 */
549 	cell = ofnode_get_property(node, propname, &len);
550 	if (!cell)
551 		goto fail;
552 
553 	if ((len % FDT_PCI_REG_SIZE) == 0) {
554 		int num = len / FDT_PCI_REG_SIZE;
555 		int i;
556 
557 		for (i = 0; i < num; i++) {
558 			debug("pci address #%d: %08lx %08lx %08lx\n", i,
559 			      (ulong)fdt32_to_cpu(cell[0]),
560 			      (ulong)fdt32_to_cpu(cell[1]),
561 			      (ulong)fdt32_to_cpu(cell[2]));
562 			if ((fdt32_to_cpu(*cell) & type) == type) {
563 				addr->phys_hi = fdt32_to_cpu(cell[0]);
564 				addr->phys_mid = fdt32_to_cpu(cell[1]);
565 				addr->phys_lo = fdt32_to_cpu(cell[1]);
566 				break;
567 			} else {
568 				cell += (FDT_PCI_ADDR_CELLS +
569 					 FDT_PCI_SIZE_CELLS);
570 			}
571 		}
572 
573 		if (i == num) {
574 			ret = -ENXIO;
575 			goto fail;
576 		}
577 
578 		return 0;
579 	} else {
580 		ret = -EINVAL;
581 	}
582 
583 fail:
584 	debug("(not found)\n");
585 	return ret;
586 }
587 
588 int ofnode_read_addr_cells(ofnode node)
589 {
590 	if (ofnode_is_np(node))
591 		return of_n_addr_cells(ofnode_to_np(node));
592 	else  /* NOTE: this call should walk up the parent stack */
593 		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
594 }
595 
596 int ofnode_read_size_cells(ofnode node)
597 {
598 	if (ofnode_is_np(node))
599 		return of_n_size_cells(ofnode_to_np(node));
600 	else  /* NOTE: this call should walk up the parent stack */
601 		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
602 }
603 
604 int ofnode_read_simple_addr_cells(ofnode node)
605 {
606 	if (ofnode_is_np(node))
607 		return of_simple_addr_cells(ofnode_to_np(node));
608 	else
609 		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
610 }
611 
612 int ofnode_read_simple_size_cells(ofnode node)
613 {
614 	if (ofnode_is_np(node))
615 		return of_simple_size_cells(ofnode_to_np(node));
616 	else
617 		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
618 }
619 
620 bool ofnode_pre_reloc(ofnode node)
621 {
622 	if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
623 		return true;
624 
625 #ifdef CONFIG_TPL_BUILD
626 	if (ofnode_read_bool(node, "u-boot,dm-tpl"))
627 		return true;
628 #elif defined(CONFIG_SPL_BUILD)
629 	if (ofnode_read_bool(node, "u-boot,dm-spl"))
630 		return true;
631 #else
632 	/*
633 	 * In regular builds individual spl and tpl handling both
634 	 * count as handled pre-relocation for later second init.
635 	 */
636 	if (ofnode_read_bool(node, "u-boot,dm-spl") ||
637 	    ofnode_read_bool(node, "u-boot,dm-tpl"))
638 		return true;
639 #endif
640 
641 	return false;
642 }
643 
644 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
645 {
646 	if (ofnode_is_np(node)) {
647 		return of_address_to_resource(ofnode_to_np(node), index, res);
648 	} else {
649 		struct fdt_resource fres;
650 		int ret;
651 
652 		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
653 				       "reg", index, &fres);
654 		if (ret < 0)
655 			return -EINVAL;
656 		memset(res, '\0', sizeof(*res));
657 		res->start = fres.start;
658 		res->end = fres.end;
659 
660 		return 0;
661 	}
662 }
663 
664 int ofnode_read_resource_byname(ofnode node, const char *name,
665 				struct resource *res)
666 {
667 	int index;
668 
669 	index = ofnode_stringlist_search(node, "reg-names", name);
670 	if (index < 0)
671 		return index;
672 
673 	return ofnode_read_resource(node, index, res);
674 }
675