xref: /rk3399_rockchip-uboot/drivers/core/ofnode.c (revision dcf988525f6e2045b9122ba7c3bf6a9bf44f146e)
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 const char *ofnode_get_name(ofnode node)
169 {
170 	assert(ofnode_valid(node));
171 	if (ofnode_is_np(node))
172 		return strrchr(node.np->full_name, '/') + 1;
173 
174 	return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
175 }
176 
177 int ofnode_read_size(ofnode node, const char *propname)
178 {
179 	int len;
180 
181 	if (ofnode_is_np(node)) {
182 		struct property *prop = of_find_property(
183 				ofnode_to_np(node), propname, NULL);
184 
185 		if (prop)
186 			return prop->length;
187 	} else {
188 		if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
189 				&len))
190 			return len;
191 	}
192 
193 	return -EINVAL;
194 }
195 
196 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
197 {
198 	if (ofnode_is_np(node)) {
199 		const __be32 *prop_val;
200 		uint flags;
201 		u64 size;
202 
203 		prop_val = of_get_address(
204 			(struct device_node *)ofnode_to_np(node), index,
205 			&size, &flags);
206 		if (!prop_val)
207 			return FDT_ADDR_T_NONE;
208 		return  be32_to_cpup(prop_val);
209 	} else {
210 		return fdt_get_base_address(gd->fdt_blob,
211 					    ofnode_to_offset(node));
212 	}
213 
214 	return FDT_ADDR_T_NONE;
215 }
216 
217 fdt_addr_t ofnode_get_addr(ofnode node)
218 {
219 	return ofnode_get_addr_index(node, 0);
220 }
221 
222 int ofnode_stringlist_search(ofnode node, const char *property,
223 			     const char *string)
224 {
225 	if (ofnode_is_np(node)) {
226 		return of_property_match_string(ofnode_to_np(node),
227 						property, string);
228 	} else {
229 		int ret;
230 
231 		ret = fdt_stringlist_search(gd->fdt_blob,
232 					    ofnode_to_offset(node), property,
233 					    string);
234 		if (ret == -FDT_ERR_NOTFOUND)
235 			return -ENODATA;
236 		else if (ret < 0)
237 			return -EINVAL;
238 
239 		return ret;
240 	}
241 }
242 
243 int ofnode_read_string_index(ofnode node, const char *property, int index,
244 			     const char **outp)
245 {
246 	if (ofnode_is_np(node)) {
247 		return of_property_read_string_index(ofnode_to_np(node),
248 						     property, index, outp);
249 	} else {
250 		int len;
251 
252 		*outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
253 					   property, index, &len);
254 		if (len < 0)
255 			return -EINVAL;
256 		return 0;
257 	}
258 }
259 
260 int ofnode_read_string_count(ofnode node, const char *property)
261 {
262 	if (ofnode_is_np(node)) {
263 		return of_property_count_strings(ofnode_to_np(node), property);
264 	} else {
265 		return fdt_stringlist_count(gd->fdt_blob,
266 					    ofnode_to_offset(node), property);
267 	}
268 }
269 
270 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
271 					    struct ofnode_phandle_args *out)
272 {
273 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
274 	out->node = offset_to_ofnode(in->node);
275 	out->args_count = in->args_count;
276 	memcpy(out->args, in->args, sizeof(out->args));
277 }
278 
279 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
280 					struct ofnode_phandle_args *out)
281 {
282 	assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
283 	out->node = np_to_ofnode(in->np);
284 	out->args_count = in->args_count;
285 	memcpy(out->args, in->args, sizeof(out->args));
286 }
287 
288 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
289 				   const char *cells_name, int cell_count,
290 				   int index,
291 				   struct ofnode_phandle_args *out_args)
292 {
293 	if (ofnode_is_np(node)) {
294 		struct of_phandle_args args;
295 		int ret;
296 
297 		ret = of_parse_phandle_with_args(ofnode_to_np(node),
298 				list_name, cells_name, index, &args);
299 		if (ret)
300 			return ret;
301 		ofnode_from_of_phandle_args(&args, out_args);
302 	} else {
303 		struct fdtdec_phandle_args args;
304 		int ret;
305 
306 		ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
307 				ofnode_to_offset(node), list_name, cells_name,
308 				cell_count, index, &args);
309 		if (ret)
310 			return ret;
311 		ofnode_from_fdtdec_phandle_args(&args, out_args);
312 	}
313 
314 	return 0;
315 }
316 
317 ofnode ofnode_path(const char *path)
318 {
319 	if (of_live_active())
320 		return np_to_ofnode(of_find_node_by_path(path));
321 	else
322 		return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
323 }
324 
325 const char *ofnode_get_chosen_prop(const char *name)
326 {
327 	ofnode chosen_node;
328 
329 	chosen_node = ofnode_path("/chosen");
330 
331 	return ofnode_read_string(chosen_node, name);
332 }
333 
334 ofnode ofnode_get_chosen_node(const char *name)
335 {
336 	const char *prop;
337 
338 	prop = ofnode_get_chosen_prop(name);
339 	if (!prop)
340 		return ofnode_null();
341 
342 	return ofnode_path(prop);
343 }
344 
345 static int decode_timing_property(ofnode node, const char *name,
346 				  struct timing_entry *result)
347 {
348 	int length, ret = 0;
349 
350 	length = ofnode_read_size(node, name);
351 	if (length < 0) {
352 		debug("%s: could not find property %s\n",
353 		      ofnode_get_name(node), name);
354 		return length;
355 	}
356 
357 	if (length == sizeof(u32)) {
358 		result->typ = ofnode_read_u32_default(node, name, 0);
359 		result->min = result->typ;
360 		result->max = result->typ;
361 	} else {
362 		ret = ofnode_read_u32_array(node, name, &result->min, 3);
363 	}
364 
365 	return ret;
366 }
367 
368 int ofnode_decode_display_timing(ofnode parent, int index,
369 				 struct display_timing *dt)
370 {
371 	int i;
372 	ofnode timings, node;
373 	u32 val = 0;
374 	int ret = 0;
375 
376 	timings = ofnode_find_subnode(parent, "display-timings");
377 	if (!ofnode_valid(timings))
378 		return -EINVAL;
379 
380 	for (i = 0, node = ofnode_first_subnode(timings);
381 	     ofnode_valid(node) && i != index;
382 	     node = ofnode_first_subnode(node))
383 		i++;
384 
385 	if (!ofnode_valid(node))
386 		return -EINVAL;
387 
388 	memset(dt, 0, sizeof(*dt));
389 
390 	ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
391 	ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
392 	ret |= decode_timing_property(node, "hactive", &dt->hactive);
393 	ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
394 	ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
395 	ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
396 	ret |= decode_timing_property(node, "vactive", &dt->vactive);
397 	ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
398 	ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
399 
400 	dt->flags = 0;
401 	val = ofnode_read_u32_default(node, "vsync-active", -1);
402 	if (val != -1) {
403 		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
404 				DISPLAY_FLAGS_VSYNC_LOW;
405 	}
406 	val = ofnode_read_u32_default(node, "hsync-active", -1);
407 	if (val != -1) {
408 		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
409 				DISPLAY_FLAGS_HSYNC_LOW;
410 	}
411 	val = ofnode_read_u32_default(node, "de-active", -1);
412 	if (val != -1) {
413 		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
414 				DISPLAY_FLAGS_DE_LOW;
415 	}
416 	val = ofnode_read_u32_default(node, "pixelclk-active", -1);
417 	if (val != -1) {
418 		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
419 				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
420 	}
421 
422 	if (ofnode_read_bool(node, "interlaced"))
423 		dt->flags |= DISPLAY_FLAGS_INTERLACED;
424 	if (ofnode_read_bool(node, "doublescan"))
425 		dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
426 	if (ofnode_read_bool(node, "doubleclk"))
427 		dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
428 
429 	return ret;
430 }
431 
432 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
433 {
434 	if (ofnode_is_np(node))
435 		return of_get_property(ofnode_to_np(node), propname, lenp);
436 	else
437 		return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
438 				   propname, lenp);
439 }
440 
441 bool ofnode_is_available(ofnode node)
442 {
443 	if (ofnode_is_np(node))
444 		return of_device_is_available(ofnode_to_np(node));
445 	else
446 		return fdtdec_get_is_enabled(gd->fdt_blob,
447 					     ofnode_to_offset(node));
448 }
449 
450 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
451 				fdt_size_t *sizep)
452 {
453 	if (ofnode_is_np(node)) {
454 		int na, ns;
455 		int psize;
456 		const struct device_node *np = ofnode_to_np(node);
457 		const __be32 *prop = of_get_property(np, "reg", &psize);
458 
459 		na = of_n_addr_cells(np);
460 		ns = of_n_addr_cells(np);
461 		*sizep = of_read_number(prop + na, ns);
462 		return of_read_number(prop, na);
463 	} else {
464 		return fdtdec_get_addr_size(gd->fdt_blob,
465 					    ofnode_to_offset(node), property,
466 					    sizep);
467 	}
468 }
469 
470 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
471 					size_t sz)
472 {
473 	if (ofnode_is_np(node)) {
474 		const struct device_node *np = ofnode_to_np(node);
475 		int psize;
476 		const __be32 *prop = of_get_property(np, propname, &psize);
477 
478 		if (!prop || sz != psize)
479 			return NULL;
480 		return (uint8_t *)prop;
481 
482 	} else {
483 		return fdtdec_locate_byte_array(gd->fdt_blob,
484 				ofnode_to_offset(node), propname, sz);
485 	}
486 }
487 
488 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
489 			 const char *propname, struct fdt_pci_addr *addr)
490 {
491 	const fdt32_t *cell;
492 	int len;
493 	int ret = -ENOENT;
494 
495 	debug("%s: %s: ", __func__, propname);
496 
497 	/*
498 	 * If we follow the pci bus bindings strictly, we should check
499 	 * the value of the node's parent node's #address-cells and
500 	 * #size-cells. They need to be 3 and 2 accordingly. However,
501 	 * for simplicity we skip the check here.
502 	 */
503 	cell = ofnode_get_property(node, propname, &len);
504 	if (!cell)
505 		goto fail;
506 
507 	if ((len % FDT_PCI_REG_SIZE) == 0) {
508 		int num = len / FDT_PCI_REG_SIZE;
509 		int i;
510 
511 		for (i = 0; i < num; i++) {
512 			debug("pci address #%d: %08lx %08lx %08lx\n", i,
513 			      (ulong)fdt32_to_cpu(cell[0]),
514 			      (ulong)fdt32_to_cpu(cell[1]),
515 			      (ulong)fdt32_to_cpu(cell[2]));
516 			if ((fdt32_to_cpu(*cell) & type) == type) {
517 				addr->phys_hi = fdt32_to_cpu(cell[0]);
518 				addr->phys_mid = fdt32_to_cpu(cell[1]);
519 				addr->phys_lo = fdt32_to_cpu(cell[1]);
520 				break;
521 			} else {
522 				cell += (FDT_PCI_ADDR_CELLS +
523 					 FDT_PCI_SIZE_CELLS);
524 			}
525 		}
526 
527 		if (i == num) {
528 			ret = -ENXIO;
529 			goto fail;
530 		}
531 
532 		return 0;
533 	} else {
534 		ret = -EINVAL;
535 	}
536 
537 fail:
538 	debug("(not found)\n");
539 	return ret;
540 }
541 
542 int ofnode_read_addr_cells(ofnode node)
543 {
544 	if (ofnode_is_np(node))
545 		return of_n_addr_cells(ofnode_to_np(node));
546 	else  /* NOTE: this call should walk up the parent stack */
547 		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
548 }
549 
550 int ofnode_read_size_cells(ofnode node)
551 {
552 	if (ofnode_is_np(node))
553 		return of_n_size_cells(ofnode_to_np(node));
554 	else  /* NOTE: this call should walk up the parent stack */
555 		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
556 }
557 
558 int ofnode_read_simple_addr_cells(ofnode node)
559 {
560 	if (ofnode_is_np(node))
561 		return of_simple_addr_cells(ofnode_to_np(node));
562 	else
563 		return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
564 }
565 
566 int ofnode_read_simple_size_cells(ofnode node)
567 {
568 	if (ofnode_is_np(node))
569 		return of_simple_size_cells(ofnode_to_np(node));
570 	else
571 		return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
572 }
573 
574 bool ofnode_pre_reloc(ofnode node)
575 {
576 	if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
577 		return true;
578 
579 #ifdef CONFIG_TPL_BUILD
580 	if (ofnode_read_bool(node, "u-boot,dm-tpl"))
581 		return true;
582 #elif defined(CONFIG_SPL_BUILD)
583 	if (ofnode_read_bool(node, "u-boot,dm-spl"))
584 		return true;
585 #else
586 	/*
587 	 * In regular builds individual spl and tpl handling both
588 	 * count as handled pre-relocation for later second init.
589 	 */
590 	if (ofnode_read_bool(node, "u-boot,dm-spl") ||
591 	    ofnode_read_bool(node, "u-boot,dm-tpl"))
592 		return true;
593 #endif
594 
595 	return false;
596 }
597 
598 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
599 {
600 	if (ofnode_is_np(node)) {
601 		return of_address_to_resource(ofnode_to_np(node), index, res);
602 	} else {
603 		struct fdt_resource fres;
604 		int ret;
605 
606 		ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
607 				       "reg", index, &fres);
608 		if (ret < 0)
609 			return -EINVAL;
610 		memset(res, '\0', sizeof(*res));
611 		res->start = fres.start;
612 		res->end = fres.end;
613 
614 		return 0;
615 	}
616 }
617