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