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