"Das U-Boot" Source Tree
at master 2135 lines 48 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2017 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7#define LOG_CATEGORY LOGC_DT 8 9#include <dm.h> 10#include <fdtdec.h> 11#include <fdt_support.h> 12#include <log.h> 13#include <malloc.h> 14#include <of_live.h> 15#include <linux/libfdt.h> 16#include <dm/of_access.h> 17#include <dm/of_addr.h> 18#include <dm/ofnode.h> 19#include <dm/util.h> 20#include <linux/err.h> 21#include <linux/ioport.h> 22#include <asm/global_data.h> 23 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 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 61static oftree oftree_ensure(void *fdt) 62{ 63 oftree tree; 64 int i; 65 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 80 if (gd->flags & GD_FLG_RELOC) { 81 i = oftree_find(fdt); 82 if (i == -1) { 83 if (check_tree_count()) 84 return oftree_null(); 85 86 if (fdt_check_header(fdt)) { 87 log_err("Invalid device tree blob header\n"); 88 return oftree_null(); 89 } 90 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) { 98 log_debug("Only the control FDT can be accessed before relocation\n"); 99 return oftree_null(); 100 } 101 } 102 103 tree.fdt = fdt; 104 105 return tree; 106} 107 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 = 4096; 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 143void oftree_dispose(oftree tree) 144{ 145 if (of_live_active()) 146 of_live_free(tree.np); 147} 148 149void *ofnode_lookup_fdt(ofnode node) 150{ 151 if (gd->flags & GD_FLG_RELOC) { 152 uint i = OFTREE_TREE_ID(node.of_offset); 153 154 if (i >= oftree_count) { 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 205#ifdef OF_CHECKS 206 if (of_live_active()) 207 return oftree_null(); 208#endif 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 244int oftree_new(oftree *treep) 245{ 246 return -ENOSYS; 247} 248 249#endif /* OFNODE_MULTI_TREE */ 250 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 269/** 270 * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree) 271 * 272 * Looks up the tree and returns an ofnode with the correct of_offset (i.e. 273 * containing the tree ID). 274 * 275 * If @offset is < 0 then this returns an ofnode with that offset and no tree 276 * ID. 277 * 278 * @tree: tree to check 279 * @offset: offset within that tree (can be < 0) 280 * @return node for that offset, with the correct ID 281 */ 282static ofnode ofnode_from_tree_offset(oftree tree, int offset) 283{ 284 ofnode node; 285 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 } 295 296 return node; 297} 298 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 312bool ofnode_name_eq_unit(ofnode node, const char *name) 313{ 314 const char *node_name, *p; 315 int len; 316 317 assert(ofnode_valid(node)); 318 319 node_name = ofnode_get_name(node); 320 321 /* check the whole name */ 322 if (!strcmp(node_name, name)) 323 return true; 324 325 /* if @name has no unit address, try the node name without it */ 326 len = strlen(name); 327 p = strchr(node_name, '@'); 328 if (p && !strchr(name, '@') && len == p - node_name && 329 !strncmp(node_name, name, len)) 330 return true; 331 332 return false; 333} 334 335int ofnode_read_u8(ofnode node, const char *propname, u8 *outp) 336{ 337 const u8 *cell; 338 int len; 339 340 assert(ofnode_valid(node)); 341 log_debug("%s: %s: ", __func__, propname); 342 343 if (ofnode_is_np(node)) 344 return of_read_u8(ofnode_to_np(node), propname, outp); 345 346 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 347 &len); 348 if (!cell || len < sizeof(*cell)) { 349 log_debug("(not found)\n"); 350 return -EINVAL; 351 } 352 *outp = *cell; 353 log_debug("%#x (%u)\n", *outp, *outp); 354 355 return 0; 356} 357 358u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def) 359{ 360 assert(ofnode_valid(node)); 361 ofnode_read_u8(node, propname, &def); 362 363 return def; 364} 365 366int ofnode_read_u16(ofnode node, const char *propname, u16 *outp) 367{ 368 const fdt16_t *cell; 369 int len; 370 371 assert(ofnode_valid(node)); 372 log_debug("%s: %s: ", __func__, propname); 373 374 if (ofnode_is_np(node)) 375 return of_read_u16(ofnode_to_np(node), propname, outp); 376 377 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, 378 &len); 379 if (!cell || len < sizeof(*cell)) { 380 log_debug("(not found)\n"); 381 return -EINVAL; 382 } 383 *outp = be16_to_cpup(cell); 384 log_debug("%#x (%u)\n", *outp, *outp); 385 386 return 0; 387} 388 389u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def) 390{ 391 assert(ofnode_valid(node)); 392 ofnode_read_u16(node, propname, &def); 393 394 return def; 395} 396 397int ofnode_read_u32(ofnode node, const char *propname, u32 *outp) 398{ 399 return ofnode_read_u32_index(node, propname, 0, outp); 400} 401 402u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def) 403{ 404 assert(ofnode_valid(node)); 405 ofnode_read_u32_index(node, propname, 0, &def); 406 407 return def; 408} 409 410int ofnode_read_u32_index(ofnode node, const char *propname, int index, 411 u32 *outp) 412{ 413 const fdt32_t *cell; 414 int len; 415 416 assert(ofnode_valid(node)); 417 log_debug("%s: %s: ", __func__, propname); 418 419 if (ofnode_is_np(node)) 420 return of_read_u32_index(ofnode_to_np(node), propname, index, 421 outp); 422 423 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), 424 propname, &len); 425 if (!cell) { 426 log_debug("(not found)\n"); 427 return -EINVAL; 428 } 429 430 if (len < (sizeof(int) * (index + 1))) { 431 log_debug("(not large enough)\n"); 432 return -EOVERFLOW; 433 } 434 435 *outp = fdt32_to_cpu(cell[index]); 436 log_debug("%#x (%u)\n", *outp, *outp); 437 438 return 0; 439} 440 441int ofnode_read_u64_index(ofnode node, const char *propname, int index, 442 u64 *outp) 443{ 444 const fdt64_t *cell; 445 int len; 446 447 assert(ofnode_valid(node)); 448 449 if (ofnode_is_np(node)) 450 return of_read_u64_index(ofnode_to_np(node), propname, index, 451 outp); 452 453 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), 454 propname, &len); 455 if (!cell) { 456 log_debug("(not found)\n"); 457 return -EINVAL; 458 } 459 460 if (len < (sizeof(u64) * (index + 1))) { 461 log_debug("(not large enough)\n"); 462 return -EOVERFLOW; 463 } 464 465 *outp = fdt64_to_cpu(cell[index]); 466 log_debug("%#llx (%llu)\n", *outp, *outp); 467 468 return 0; 469} 470 471u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index, 472 u32 def) 473{ 474 assert(ofnode_valid(node)); 475 ofnode_read_u32_index(node, propname, index, &def); 476 477 return def; 478} 479 480int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) 481{ 482 assert(ofnode_valid(node)); 483 ofnode_read_u32(node, propname, (u32 *)&def); 484 485 return def; 486} 487 488int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) 489{ 490 const unaligned_fdt64_t *cell; 491 int len; 492 493 assert(ofnode_valid(node)); 494 log_debug("%s: %s: ", __func__, propname); 495 496 if (ofnode_is_np(node)) 497 return of_read_u64(ofnode_to_np(node), propname, outp); 498 499 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), 500 propname, &len); 501 if (!cell || len < sizeof(*cell)) { 502 log_debug("(not found)\n"); 503 return -EINVAL; 504 } 505 *outp = fdt64_to_cpu(cell[0]); 506 log_debug("%#llx (%llu)\n", (unsigned long long)*outp, 507 (unsigned long long)*outp); 508 509 return 0; 510} 511 512u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def) 513{ 514 assert(ofnode_valid(node)); 515 ofnode_read_u64(node, propname, &def); 516 517 return def; 518} 519 520bool ofnode_read_bool(ofnode node, const char *propname) 521{ 522 bool prop; 523 524 assert(ofnode_valid(node)); 525 log_debug("%s: %s: ", __func__, propname); 526 527 prop = ofnode_has_property(node, propname); 528 529 log_debug("%s\n", prop ? "true" : "false"); 530 531 return prop ? true : false; 532} 533 534const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep) 535{ 536 const char *val = NULL; 537 int len; 538 539 assert(ofnode_valid(node)); 540 log_debug("%s: %s: ", __func__, propname); 541 542 if (ofnode_is_np(node)) { 543 struct property *prop = of_find_property( 544 ofnode_to_np(node), propname, &len); 545 546 if (prop) { 547 val = prop->value; 548 len = prop->length; 549 } 550 } else { 551 val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), 552 propname, &len); 553 } 554 if (!val) { 555 log_debug("<not found>\n"); 556 if (sizep) 557 *sizep = -FDT_ERR_NOTFOUND; 558 return NULL; 559 } 560 if (sizep) 561 *sizep = len; 562 563 return val; 564} 565 566const char *ofnode_read_string(ofnode node, const char *propname) 567{ 568 const char *str; 569 int len; 570 571 str = ofnode_read_prop(node, propname, &len); 572 if (!str) 573 return NULL; 574 575 if (strnlen(str, len) >= len) { 576 dm_warn("<invalid>\n"); 577 return NULL; 578 } 579 log_debug("%s\n", str); 580 581 return str; 582} 583 584int ofnode_read_size(ofnode node, const char *propname) 585{ 586 int len; 587 588 if (!ofnode_read_prop(node, propname, &len)) 589 return -EINVAL; 590 591 return len; 592} 593 594ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) 595{ 596 ofnode subnode; 597 598 assert(ofnode_valid(node)); 599 log_debug("%s: %s: ", __func__, subnode_name); 600 601 if (ofnode_is_np(node)) { 602 subnode = ofnode_find_subnode_unit(node, subnode_name); 603 } else { 604 /* special case to avoid code-size increase */ 605 int ooffset = fdt_subnode_offset(ofnode_to_fdt(node), 606 ofnode_to_offset(node), subnode_name); 607 subnode = noffset_to_ofnode(node, ooffset); 608 } 609 log_debug("%s\n", ofnode_valid(subnode) ? 610 ofnode_get_name(subnode) : "<none>"); 611 612 return subnode; 613} 614 615ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name) 616{ 617 ofnode subnode, found = ofnode_null(); 618 619 assert(ofnode_valid(node)); 620 log_debug("%s: ", subnode_name); 621 622 ofnode_for_each_subnode(subnode, node) { 623 if (ofnode_name_eq_unit(subnode, subnode_name)) { 624 found = subnode; 625 break; 626 } 627 } 628 629 log_debug("%s\n", ofnode_valid(found) ? 630 ofnode_get_name(found) : "<none>"); 631 632 return found; 633} 634 635int ofnode_read_u32_array(ofnode node, const char *propname, 636 u32 *out_values, size_t sz) 637{ 638 assert(ofnode_valid(node)); 639 log_debug("%s: %s: ", __func__, propname); 640 641 if (ofnode_is_np(node)) { 642 return of_read_u32_array(ofnode_to_np(node), propname, 643 out_values, sz); 644 } else { 645 int ret; 646 647 ret = fdtdec_get_int_array(ofnode_to_fdt(node), 648 ofnode_to_offset(node), propname, 649 out_values, sz); 650 651 /* get the error right, but space is more important in SPL */ 652 if (!IS_ENABLED(CONFIG_XPL_BUILD)) { 653 if (ret == -FDT_ERR_NOTFOUND) 654 return -EINVAL; 655 else if (ret == -FDT_ERR_BADLAYOUT) 656 return -EOVERFLOW; 657 } 658 return ret; 659 } 660} 661 662#if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE) 663bool ofnode_is_enabled(ofnode node) 664{ 665 if (ofnode_is_np(node)) { 666 return of_device_is_available(ofnode_to_np(node)); 667 } else { 668 return fdtdec_get_is_enabled(ofnode_to_fdt(node), 669 ofnode_to_offset(node)); 670 } 671} 672 673ofnode ofnode_first_subnode(ofnode node) 674{ 675 assert(ofnode_valid(node)); 676 if (ofnode_is_np(node)) 677 return np_to_ofnode(node.np->child); 678 679 return noffset_to_ofnode(node, 680 fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node))); 681} 682 683ofnode ofnode_next_subnode(ofnode node) 684{ 685 assert(ofnode_valid(node)); 686 if (ofnode_is_np(node)) 687 return np_to_ofnode(node.np->sibling); 688 689 return noffset_to_ofnode(node, 690 fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node))); 691} 692#endif /* !DM_INLINE_OFNODE */ 693 694ofnode ofnode_get_parent(ofnode node) 695{ 696 ofnode parent; 697 698 assert(ofnode_valid(node)); 699 if (ofnode_is_np(node)) 700 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); 701 else 702 parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node), 703 ofnode_to_offset(node)); 704 705 return parent; 706} 707 708const char *ofnode_get_name(ofnode node) 709{ 710 if (!ofnode_valid(node)) { 711 dm_warn("%s node not valid\n", __func__); 712 return NULL; 713 } 714 715 if (ofnode_is_np(node)) 716 return node.np->name; 717 718 return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL); 719} 720 721int ofnode_get_path(ofnode node, char *buf, int buflen) 722{ 723 assert(ofnode_valid(node)); 724 725 if (ofnode_is_np(node)) { 726 if (strlen(node.np->full_name) >= buflen) 727 return -ENOSPC; 728 729 strcpy(buf, node.np->full_name); 730 731 return 0; 732 } else { 733 int res; 734 735 res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf, 736 buflen); 737 if (!res) 738 return res; 739 else if (res == -FDT_ERR_NOSPACE) 740 return -ENOSPC; 741 else 742 return -EINVAL; 743 } 744} 745 746ofnode ofnode_get_by_phandle(uint phandle) 747{ 748 ofnode node; 749 750 if (of_live_active()) 751 node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle)); 752 else 753 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, 754 phandle); 755 756 return node; 757} 758 759ofnode oftree_get_by_phandle(oftree tree, uint phandle) 760{ 761 ofnode node; 762 763 if (of_live_active()) 764 node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle)); 765 else 766 node = ofnode_from_tree_offset(tree, 767 fdt_node_offset_by_phandle(oftree_lookup_fdt(tree), 768 phandle)); 769 770 return node; 771} 772 773static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index, 774 fdt_size_t *size, bool translate) 775{ 776 int na, ns; 777 778 if (size) 779 *size = FDT_SIZE_T_NONE; 780 781 if (ofnode_is_np(node)) { 782 const __be32 *prop_val; 783 u64 size64; 784 uint flags; 785 786 prop_val = of_get_address(ofnode_to_np(node), index, &size64, 787 &flags); 788 if (!prop_val) 789 return FDT_ADDR_T_NONE; 790 791 if (size) 792 *size = size64; 793 794 ns = of_n_size_cells(ofnode_to_np(node)); 795 796 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) { 797 return of_translate_address(ofnode_to_np(node), prop_val); 798 } else { 799 na = of_n_addr_cells(ofnode_to_np(node)); 800 return of_read_number(prop_val, na); 801 } 802 } else { 803 ofnode parent = ofnode_get_parent(node); 804 na = ofnode_read_simple_addr_cells(parent); 805 ns = ofnode_read_simple_size_cells(parent); 806 return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node), 807 ofnode_to_offset(node), "reg", 808 index, na, ns, size, 809 translate); 810 } 811} 812 813fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size) 814{ 815 return __ofnode_get_addr_size_index(node, index, size, true); 816} 817 818fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index, 819 fdt_size_t *size) 820{ 821 return __ofnode_get_addr_size_index(node, index, size, false); 822} 823 824fdt_addr_t ofnode_get_addr_index(ofnode node, int index) 825{ 826 fdt_size_t size; 827 828 return ofnode_get_addr_size_index(node, index, &size); 829} 830 831fdt_addr_t ofnode_get_addr(ofnode node) 832{ 833 return ofnode_get_addr_index(node, 0); 834} 835 836fdt_size_t ofnode_get_size(ofnode node) 837{ 838 fdt_size_t size; 839 840 ofnode_get_addr_size_index(node, 0, &size); 841 842 return size; 843} 844 845int ofnode_stringlist_search(ofnode node, const char *property, 846 const char *string) 847{ 848 if (ofnode_is_np(node)) { 849 return of_property_match_string(ofnode_to_np(node), 850 property, string); 851 } else { 852 int ret; 853 854 ret = fdt_stringlist_search(ofnode_to_fdt(node), 855 ofnode_to_offset(node), property, 856 string); 857 if (ret == -FDT_ERR_NOTFOUND) 858 return -ENODATA; 859 else if (ret < 0) 860 return -EINVAL; 861 862 return ret; 863 } 864} 865 866int ofnode_read_string_index(ofnode node, const char *property, int index, 867 const char **outp) 868{ 869 if (ofnode_is_np(node)) { 870 return of_property_read_string_index(ofnode_to_np(node), 871 property, index, outp); 872 } else { 873 int len; 874 875 *outp = fdt_stringlist_get(ofnode_to_fdt(node), 876 ofnode_to_offset(node), 877 property, index, &len); 878 if (len < 0) 879 return -EINVAL; 880 return 0; 881 } 882} 883 884int ofnode_read_string_count(ofnode node, const char *property) 885{ 886 if (ofnode_is_np(node)) { 887 return of_property_count_strings(ofnode_to_np(node), property); 888 } else { 889 return fdt_stringlist_count(ofnode_to_fdt(node), 890 ofnode_to_offset(node), property); 891 } 892} 893 894int ofnode_read_string_list(ofnode node, const char *property, 895 const char ***listp) 896{ 897 const char **prop; 898 int count; 899 int i; 900 901 *listp = NULL; 902 count = ofnode_read_string_count(node, property); 903 if (count < 0) 904 return count; 905 if (!count) 906 return 0; 907 908 prop = calloc(count + 1, sizeof(char *)); 909 if (!prop) 910 return -ENOMEM; 911 912 for (i = 0; i < count; i++) 913 ofnode_read_string_index(node, property, i, &prop[i]); 914 prop[count] = NULL; 915 *listp = prop; 916 917 return count; 918} 919 920ofnode ofnode_parse_phandle(ofnode node, const char *phandle_name, 921 int index) 922{ 923 ofnode phandle; 924 925 if (ofnode_is_np(node)) { 926 struct device_node *np; 927 928 np = of_parse_phandle(ofnode_to_np(node), phandle_name, 929 index); 930 if (!np) 931 return ofnode_null(); 932 933 phandle = np_to_ofnode(np); 934 } else { 935 struct fdtdec_phandle_args args; 936 937 if (fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), 938 ofnode_to_offset(node), 939 phandle_name, NULL, 940 0, index, &args)) 941 return ofnode_null(); 942 943 phandle = offset_to_ofnode(args.node); 944 } 945 946 return phandle; 947} 948 949ofnode oftree_parse_phandle(oftree tree, ofnode node, const char *phandle_name, 950 int index) 951{ 952 ofnode phandle; 953 954 if (ofnode_is_np(node)) { 955 struct device_node *np; 956 957 np = of_root_parse_phandle(tree.np, ofnode_to_np(node), 958 phandle_name, index); 959 if (!np) 960 return ofnode_null(); 961 962 phandle = np_to_ofnode(np); 963 } else { 964 struct fdtdec_phandle_args args; 965 966 if (fdtdec_parse_phandle_with_args(tree.fdt, 967 ofnode_to_offset(node), 968 phandle_name, NULL, 969 0, index, &args)) 970 return ofnode_null(); 971 972 phandle = noffset_to_ofnode(node, args.node); 973 } 974 975 return phandle; 976} 977 978static void ofnode_from_fdtdec_phandle_args(ofnode node, struct fdtdec_phandle_args *in, 979 struct ofnode_phandle_args *out) 980{ 981 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 982 out->node = noffset_to_ofnode(node, in->node); 983 out->args_count = in->args_count; 984 memcpy(out->args, in->args, sizeof(out->args)); 985} 986 987static void ofnode_from_of_phandle_args(struct of_phandle_args *in, 988 struct ofnode_phandle_args *out) 989{ 990 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS); 991 out->node = np_to_ofnode(in->np); 992 out->args_count = in->args_count; 993 memcpy(out->args, in->args, sizeof(out->args)); 994} 995 996int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, 997 const char *cells_name, int cell_count, 998 int index, 999 struct ofnode_phandle_args *out_args) 1000{ 1001 if (ofnode_is_np(node)) { 1002 struct of_phandle_args args; 1003 int ret; 1004 1005 ret = of_parse_phandle_with_args(ofnode_to_np(node), 1006 list_name, cells_name, 1007 cell_count, index, 1008 &args); 1009 if (ret) 1010 return ret; 1011 ofnode_from_of_phandle_args(&args, out_args); 1012 } else { 1013 struct fdtdec_phandle_args args; 1014 int ret; 1015 1016 ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), 1017 ofnode_to_offset(node), 1018 list_name, cells_name, 1019 cell_count, index, &args); 1020 if (ret) 1021 return ret; 1022 ofnode_from_fdtdec_phandle_args(node, &args, out_args); 1023 } 1024 1025 return 0; 1026} 1027 1028int oftree_parse_phandle_with_args(oftree tree, ofnode node, const char *list_name, 1029 const char *cells_name, int cell_count, 1030 int index, 1031 struct ofnode_phandle_args *out_args) 1032{ 1033 if (ofnode_is_np(node)) { 1034 struct of_phandle_args args; 1035 int ret; 1036 1037 ret = of_root_parse_phandle_with_args(tree.np, 1038 ofnode_to_np(node), 1039 list_name, cells_name, 1040 cell_count, index, 1041 &args); 1042 if (ret) 1043 return ret; 1044 ofnode_from_of_phandle_args(&args, out_args); 1045 } else { 1046 struct fdtdec_phandle_args args; 1047 int ret; 1048 1049 ret = fdtdec_parse_phandle_with_args(tree.fdt, 1050 ofnode_to_offset(node), 1051 list_name, cells_name, 1052 cell_count, index, &args); 1053 if (ret) 1054 return ret; 1055 ofnode_from_fdtdec_phandle_args(node, &args, out_args); 1056 } 1057 1058 return 0; 1059} 1060 1061int ofnode_count_phandle_with_args(ofnode node, const char *list_name, 1062 const char *cells_name, int cell_count) 1063{ 1064 if (ofnode_is_np(node)) 1065 return of_count_phandle_with_args(ofnode_to_np(node), 1066 list_name, cells_name, cell_count); 1067 else 1068 return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), 1069 ofnode_to_offset(node), list_name, cells_name, 1070 cell_count, -1, NULL); 1071} 1072 1073int oftree_count_phandle_with_args(oftree tree, ofnode node, const char *list_name, 1074 const char *cells_name, int cell_count) 1075{ 1076 if (ofnode_is_np(node)) 1077 return of_root_count_phandle_with_args(tree.np, ofnode_to_np(node), 1078 list_name, cells_name, cell_count); 1079 else 1080 return fdtdec_parse_phandle_with_args(tree.fdt, 1081 ofnode_to_offset(node), list_name, cells_name, 1082 cell_count, -1, NULL); 1083} 1084 1085ofnode ofnode_path(const char *path) 1086{ 1087 if (of_live_active()) 1088 return np_to_ofnode(of_find_node_by_path(path)); 1089 else 1090 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); 1091} 1092 1093ofnode oftree_root(oftree tree) 1094{ 1095 if (of_live_active()) { 1096 return np_to_ofnode(tree.np); 1097 } else { 1098 return ofnode_from_tree_offset(tree, 0); 1099 } 1100} 1101 1102ofnode oftree_path(oftree tree, const char *path) 1103{ 1104 if (of_live_active()) { 1105 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path, 1106 NULL)); 1107 } else if (*path != '/' && tree.fdt != gd->fdt_blob) { 1108 return ofnode_null(); /* Aliases only on control FDT */ 1109 } else { 1110 int offset = fdt_path_offset(tree.fdt, path); 1111 1112 return ofnode_from_tree_offset(tree, offset); 1113 } 1114} 1115 1116const void *ofnode_read_chosen_prop(const char *propname, int *sizep) 1117{ 1118 ofnode chosen_node; 1119 1120 chosen_node = ofnode_path("/chosen"); 1121 1122 return ofnode_read_prop(chosen_node, propname, sizep); 1123} 1124 1125const char *ofnode_read_chosen_string(const char *propname) 1126{ 1127 return ofnode_read_chosen_prop(propname, NULL); 1128} 1129 1130ofnode ofnode_get_chosen_node(const char *name) 1131{ 1132 const char *prop; 1133 1134 prop = ofnode_read_chosen_prop(name, NULL); 1135 if (!prop) 1136 return ofnode_null(); 1137 1138 return ofnode_path(prop); 1139} 1140 1141int ofnode_read_baud(void) 1142{ 1143 const char *str, *p; 1144 u32 baud; 1145 1146 str = ofnode_read_chosen_string("stdout-path"); 1147 if (!str) 1148 return -EINVAL; 1149 1150 /* Parse string serial0:115200n8 */ 1151 p = strchr(str, ':'); 1152 if (!p) 1153 return -EINVAL; 1154 1155 baud = dectoul(p + 1, NULL); 1156 return baud; 1157} 1158 1159const void *ofnode_read_aliases_prop(const char *propname, int *sizep) 1160{ 1161 ofnode node; 1162 1163 node = ofnode_path("/aliases"); 1164 1165 return ofnode_read_prop(node, propname, sizep); 1166} 1167 1168ofnode ofnode_get_aliases_node(const char *name) 1169{ 1170 const char *prop; 1171 1172 prop = ofnode_read_aliases_prop(name, NULL); 1173 if (!prop) 1174 return ofnode_null(); 1175 1176 log_debug("%s: node_path: %s\n", __func__, prop); 1177 1178 return ofnode_path(prop); 1179} 1180 1181int ofnode_get_child_count(ofnode parent) 1182{ 1183 ofnode child; 1184 int num = 0; 1185 1186 ofnode_for_each_subnode(child, parent) 1187 num++; 1188 1189 return num; 1190} 1191 1192static int decode_timing_property(ofnode node, const char *name, 1193 struct timing_entry *result) 1194{ 1195 int length, ret = 0; 1196 1197 length = ofnode_read_size(node, name); 1198 if (length < 0) { 1199 dm_warn("%s: could not find property %s\n", 1200 ofnode_get_name(node), name); 1201 return length; 1202 } 1203 1204 if (length == sizeof(u32)) { 1205 result->typ = ofnode_read_u32_default(node, name, 0); 1206 result->min = result->typ; 1207 result->max = result->typ; 1208 } else { 1209 ret = ofnode_read_u32_array(node, name, &result->min, 3); 1210 } 1211 1212 return ret; 1213} 1214 1215int ofnode_decode_display_timing(ofnode parent, int index, 1216 struct display_timing *dt) 1217{ 1218 int i; 1219 ofnode timings, node; 1220 u32 val = 0; 1221 int ret = 0; 1222 1223 timings = ofnode_find_subnode(parent, "display-timings"); 1224 if (!ofnode_valid(timings)) 1225 return -EINVAL; 1226 1227 i = 0; 1228 ofnode_for_each_subnode(node, timings) { 1229 if (i++ == index) 1230 break; 1231 } 1232 1233 if (!ofnode_valid(node)) 1234 return -EINVAL; 1235 1236 memset(dt, 0, sizeof(*dt)); 1237 1238 ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch); 1239 ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch); 1240 ret |= decode_timing_property(node, "hactive", &dt->hactive); 1241 ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len); 1242 ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch); 1243 ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch); 1244 ret |= decode_timing_property(node, "vactive", &dt->vactive); 1245 ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len); 1246 ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock); 1247 1248 dt->flags = 0; 1249 val = ofnode_read_u32_default(node, "vsync-active", -1); 1250 if (val != -1) { 1251 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 1252 DISPLAY_FLAGS_VSYNC_LOW; 1253 } 1254 val = ofnode_read_u32_default(node, "hsync-active", -1); 1255 if (val != -1) { 1256 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 1257 DISPLAY_FLAGS_HSYNC_LOW; 1258 } 1259 val = ofnode_read_u32_default(node, "de-active", -1); 1260 if (val != -1) { 1261 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 1262 DISPLAY_FLAGS_DE_LOW; 1263 } 1264 val = ofnode_read_u32_default(node, "pixelclk-active", -1); 1265 if (val != -1) { 1266 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 1267 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 1268 } 1269 1270 if (ofnode_read_bool(node, "interlaced")) 1271 dt->flags |= DISPLAY_FLAGS_INTERLACED; 1272 if (ofnode_read_bool(node, "doublescan")) 1273 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 1274 if (ofnode_read_bool(node, "doubleclk")) 1275 dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 1276 1277 return ret; 1278} 1279 1280int ofnode_decode_panel_timing(ofnode parent, 1281 struct display_timing *dt) 1282{ 1283 ofnode timings; 1284 u32 val = 0; 1285 int ret = 0; 1286 1287 timings = ofnode_find_subnode(parent, "panel-timing"); 1288 if (!ofnode_valid(timings)) 1289 return -EINVAL; 1290 memset(dt, 0, sizeof(*dt)); 1291 ret |= decode_timing_property(timings, "hback-porch", &dt->hback_porch); 1292 ret |= decode_timing_property(timings, "hfront-porch", &dt->hfront_porch); 1293 ret |= decode_timing_property(timings, "hactive", &dt->hactive); 1294 ret |= decode_timing_property(timings, "hsync-len", &dt->hsync_len); 1295 ret |= decode_timing_property(timings, "vback-porch", &dt->vback_porch); 1296 ret |= decode_timing_property(timings, "vfront-porch", &dt->vfront_porch); 1297 ret |= decode_timing_property(timings, "vactive", &dt->vactive); 1298 ret |= decode_timing_property(timings, "vsync-len", &dt->vsync_len); 1299 ret |= decode_timing_property(timings, "clock-frequency", &dt->pixelclock); 1300 dt->flags = 0; 1301 if (!ofnode_read_u32(timings, "vsync-active", &val)) { 1302 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 1303 DISPLAY_FLAGS_VSYNC_LOW; 1304 } 1305 if (!ofnode_read_u32(timings, "hsync-active", &val)) { 1306 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 1307 DISPLAY_FLAGS_HSYNC_LOW; 1308 } 1309 if (!ofnode_read_u32(timings, "de-active", &val)) { 1310 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 1311 DISPLAY_FLAGS_DE_LOW; 1312 } 1313 if (!ofnode_read_u32(timings, "pixelclk-active", &val)) { 1314 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 1315 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 1316 } 1317 if (ofnode_read_bool(timings, "interlaced")) 1318 dt->flags |= DISPLAY_FLAGS_INTERLACED; 1319 if (ofnode_read_bool(timings, "doublescan")) 1320 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 1321 if (ofnode_read_bool(timings, "doubleclk")) 1322 dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 1323 1324 return ret; 1325} 1326 1327const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) 1328{ 1329 if (ofnode_is_np(node)) 1330 return of_get_property(ofnode_to_np(node), propname, lenp); 1331 else 1332 return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), 1333 propname, lenp); 1334} 1335 1336bool ofnode_has_property(ofnode node, const char *propname) 1337{ 1338 if (ofnode_is_np(node)) 1339 return of_find_property(ofnode_to_np(node), propname, NULL); 1340 else 1341 return ofnode_get_property(node, propname, NULL); 1342} 1343 1344int ofnode_first_property(ofnode node, struct ofprop *prop) 1345{ 1346 prop->node = node; 1347 1348 if (ofnode_is_np(node)) { 1349 prop->prop = of_get_first_property(ofnode_to_np(prop->node)); 1350 if (!prop->prop) 1351 return -FDT_ERR_NOTFOUND; 1352 } else { 1353 prop->offset = 1354 fdt_first_property_offset(ofnode_to_fdt(node), 1355 ofnode_to_offset(prop->node)); 1356 if (prop->offset < 0) 1357 return prop->offset; 1358 } 1359 1360 return 0; 1361} 1362 1363int ofnode_next_property(struct ofprop *prop) 1364{ 1365 if (ofnode_is_np(prop->node)) { 1366 prop->prop = of_get_next_property(ofnode_to_np(prop->node), 1367 prop->prop); 1368 if (!prop->prop) 1369 return -FDT_ERR_NOTFOUND; 1370 } else { 1371 prop->offset = 1372 fdt_next_property_offset(ofnode_to_fdt(prop->node), 1373 prop->offset); 1374 if (prop->offset < 0) 1375 return prop->offset; 1376 } 1377 1378 return 0; 1379} 1380 1381const void *ofprop_get_property(const struct ofprop *prop, 1382 const char **propname, int *lenp) 1383{ 1384 if (ofnode_is_np(prop->node)) 1385 return of_get_property_by_prop(ofnode_to_np(prop->node), 1386 prop->prop, propname, lenp); 1387 else 1388 return fdt_getprop_by_offset(ofnode_to_fdt(prop->node), 1389 prop->offset, 1390 propname, lenp); 1391} 1392 1393fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, 1394 fdt_size_t *sizep) 1395{ 1396 if (ofnode_is_np(node)) { 1397 int na, ns; 1398 int psize; 1399 const struct device_node *np = ofnode_to_np(node); 1400 const __be32 *prop = of_get_property(np, property, &psize); 1401 1402 if (!prop) 1403 return FDT_ADDR_T_NONE; 1404 na = of_n_addr_cells(np); 1405 ns = of_n_size_cells(np); 1406 *sizep = of_read_number(prop + na, ns); 1407 1408 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0) 1409 return of_translate_address(np, prop); 1410 else 1411 return of_read_number(prop, na); 1412 } else { 1413 return fdtdec_get_addr_size(ofnode_to_fdt(node), 1414 ofnode_to_offset(node), property, 1415 sizep); 1416 } 1417} 1418 1419const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, 1420 size_t sz) 1421{ 1422 if (ofnode_is_np(node)) { 1423 const struct device_node *np = ofnode_to_np(node); 1424 int psize; 1425 const __be32 *prop = of_get_property(np, propname, &psize); 1426 1427 if (!prop || sz != psize) 1428 return NULL; 1429 return (uint8_t *)prop; 1430 1431 } else { 1432 return fdtdec_locate_byte_array(ofnode_to_fdt(node), 1433 ofnode_to_offset(node), propname, sz); 1434 } 1435} 1436 1437int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type, 1438 const char *propname, struct fdt_pci_addr *addr, 1439 fdt_size_t *size) 1440{ 1441 const fdt32_t *cell; 1442 int len; 1443 int ret = -ENOENT; 1444 1445 log_debug("%s: %s: ", __func__, propname); 1446 1447 /* 1448 * If we follow the pci bus bindings strictly, we should check 1449 * the value of the node's parent node's #address-cells and 1450 * #size-cells. They need to be 3 and 2 accordingly. However, 1451 * for simplicity we skip the check here. 1452 */ 1453 cell = ofnode_get_property(node, propname, &len); 1454 if (!cell) 1455 goto fail; 1456 1457 if ((len % FDT_PCI_REG_SIZE) == 0) { 1458 int num = len / FDT_PCI_REG_SIZE; 1459 int i; 1460 1461 for (i = 0; i < num; i++) { 1462 log_debug("pci address #%d: %08lx %08lx %08lx\n", i, 1463 (ulong)fdt32_to_cpu(cell[0]), 1464 (ulong)fdt32_to_cpu(cell[1]), 1465 (ulong)fdt32_to_cpu(cell[2])); 1466 if ((fdt32_to_cpu(*cell) & type) == type) { 1467 const unaligned_fdt64_t *ptr; 1468 1469 addr->phys_hi = fdt32_to_cpu(cell[0]); 1470 addr->phys_mid = fdt32_to_cpu(cell[1]); 1471 addr->phys_lo = fdt32_to_cpu(cell[2]); 1472 ptr = (const unaligned_fdt64_t *)(cell + 3); 1473 if (size) 1474 *size = fdt64_to_cpu(*ptr); 1475 break; 1476 } 1477 1478 cell += FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS; 1479 } 1480 1481 if (i == num) { 1482 ret = -ENXIO; 1483 goto fail; 1484 } 1485 1486 return 0; 1487 } 1488 1489 ret = -EINVAL; 1490 1491fail: 1492 log_debug("(not found)\n"); 1493 return ret; 1494} 1495 1496int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device) 1497{ 1498 const char *list, *end; 1499 int len; 1500 1501 list = ofnode_get_property(node, "compatible", &len); 1502 if (!list) 1503 return -ENOENT; 1504 1505 end = list + len; 1506 while (list < end) { 1507 len = strlen(list); 1508 if (len >= strlen("pciVVVV,DDDD")) { 1509 char *s = strstr(list, "pci"); 1510 1511 /* 1512 * check if the string is something like pciVVVV,DDDD.RR 1513 * or just pciVVVV,DDDD 1514 */ 1515 if (s && s[7] == ',' && 1516 (s[12] == '.' || s[12] == 0)) { 1517 s += 3; 1518 *vendor = simple_strtol(s, NULL, 16); 1519 1520 s += 5; 1521 *device = simple_strtol(s, NULL, 16); 1522 1523 return 0; 1524 } 1525 } 1526 list += (len + 1); 1527 } 1528 1529 return -ENOENT; 1530} 1531 1532int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device) 1533{ 1534 const char *list, *end; 1535 int len; 1536 1537 list = ofnode_get_property(node, "compatible", &len); 1538 1539 if (!list) 1540 return -ENOENT; 1541 1542 end = list + len; 1543 while (list < end) { 1544 len = strlen(list); 1545 1546 if (len >= strlen("ethernet-phy-idVVVV.DDDD")) { 1547 char *s = strstr(list, "ethernet-phy-id"); 1548 1549 /* 1550 * check if the string is something like 1551 * ethernet-phy-idVVVV.DDDD 1552 */ 1553 if (s && s[19] == '.') { 1554 s += strlen("ethernet-phy-id"); 1555 *vendor = simple_strtol(s, NULL, 16); 1556 s += 5; 1557 *device = simple_strtol(s, NULL, 16); 1558 1559 return 0; 1560 } 1561 } 1562 list += (len + 1); 1563 } 1564 1565 return -ENOENT; 1566} 1567 1568int ofnode_read_addr_cells(ofnode node) 1569{ 1570 if (ofnode_is_np(node)) { 1571 return of_n_addr_cells(ofnode_to_np(node)); 1572 } else { 1573 int parent = fdt_parent_offset(ofnode_to_fdt(node), 1574 ofnode_to_offset(node)); 1575 1576 return fdt_address_cells(ofnode_to_fdt(node), parent); 1577 } 1578} 1579 1580int ofnode_read_size_cells(ofnode node) 1581{ 1582 if (ofnode_is_np(node)) { 1583 return of_n_size_cells(ofnode_to_np(node)); 1584 } else { 1585 int parent = fdt_parent_offset(ofnode_to_fdt(node), 1586 ofnode_to_offset(node)); 1587 1588 return fdt_size_cells(ofnode_to_fdt(node), parent); 1589 } 1590} 1591 1592int ofnode_read_simple_addr_cells(ofnode node) 1593{ 1594 if (ofnode_is_np(node)) 1595 return of_simple_addr_cells(ofnode_to_np(node)); 1596 else 1597 return fdt_address_cells(ofnode_to_fdt(node), 1598 ofnode_to_offset(node)); 1599} 1600 1601int ofnode_read_simple_size_cells(ofnode node) 1602{ 1603 if (ofnode_is_np(node)) 1604 return of_simple_size_cells(ofnode_to_np(node)); 1605 else 1606 return fdt_size_cells(ofnode_to_fdt(node), 1607 ofnode_to_offset(node)); 1608} 1609 1610bool ofnode_pre_reloc(ofnode node) 1611{ 1612#if defined(CONFIG_XPL_BUILD) || defined(CONFIG_TPL_BUILD) 1613 /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass 1614 * had property bootph-all or bootph-pre-sram/bootph-pre-ram. 1615 * They are removed in final dtb (fdtgrep 2nd pass) 1616 */ 1617 return true; 1618#else 1619 if (ofnode_read_bool(node, "bootph-all")) 1620 return true; 1621 if (ofnode_read_bool(node, "bootph-some-ram")) 1622 return true; 1623 1624 /* 1625 * In regular builds individual spl and tpl handling both 1626 * count as handled pre-relocation for later second init. 1627 */ 1628 if (ofnode_read_bool(node, "bootph-pre-ram") || 1629 ofnode_read_bool(node, "bootph-pre-sram")) 1630 return gd->flags & GD_FLG_RELOC; 1631 1632 if (IS_ENABLED(CONFIG_OF_TAG_MIGRATE)) { 1633 /* detect and handle old tags */ 1634 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc") || 1635 ofnode_read_bool(node, "u-boot,dm-pre-proper") || 1636 ofnode_read_bool(node, "u-boot,dm-spl") || 1637 ofnode_read_bool(node, "u-boot,dm-tpl") || 1638 ofnode_read_bool(node, "u-boot,dm-vpl")) { 1639 gd->flags |= GD_FLG_OF_TAG_MIGRATE; 1640 return true; 1641 } 1642 } 1643 1644 return false; 1645#endif 1646} 1647 1648int ofnode_read_resource(ofnode node, uint index, struct resource *res) 1649{ 1650 if (ofnode_is_np(node)) { 1651 return of_address_to_resource(ofnode_to_np(node), index, res); 1652 } else { 1653 struct fdt_resource fres; 1654 int ret; 1655 1656 ret = fdt_get_resource(ofnode_to_fdt(node), 1657 ofnode_to_offset(node), 1658 "reg", index, &fres); 1659 if (ret < 0) 1660 return -EINVAL; 1661 memset(res, '\0', sizeof(*res)); 1662 res->start = fres.start; 1663 res->end = fres.end; 1664 1665 return 0; 1666 } 1667} 1668 1669int ofnode_read_resource_byname(ofnode node, const char *name, 1670 struct resource *res) 1671{ 1672 int index; 1673 1674 index = ofnode_stringlist_search(node, "reg-names", name); 1675 if (index < 0) 1676 return index; 1677 1678 return ofnode_read_resource(node, index, res); 1679} 1680 1681u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr) 1682{ 1683 if (ofnode_is_np(node)) 1684 return of_translate_address(ofnode_to_np(node), in_addr); 1685 else 1686 return fdt_translate_address(ofnode_to_fdt(node), 1687 ofnode_to_offset(node), in_addr); 1688} 1689 1690u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr) 1691{ 1692 if (ofnode_is_np(node)) 1693 return of_translate_dma_address(ofnode_to_np(node), in_addr); 1694 else 1695 return fdt_translate_dma_address(ofnode_to_fdt(node), 1696 ofnode_to_offset(node), in_addr); 1697} 1698 1699int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size) 1700{ 1701 if (ofnode_is_np(node)) 1702 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size); 1703 else 1704 return fdt_get_dma_range(ofnode_to_fdt(node), 1705 ofnode_to_offset(node), 1706 cpu, bus, size); 1707} 1708 1709int ofnode_device_is_compatible(ofnode node, const char *compat) 1710{ 1711 if (ofnode_is_np(node)) 1712 return of_device_is_compatible(ofnode_to_np(node), compat, 1713 NULL, NULL); 1714 else 1715 return !fdt_node_check_compatible(ofnode_to_fdt(node), 1716 ofnode_to_offset(node), 1717 compat); 1718} 1719 1720ofnode ofnode_by_compatible(ofnode from, const char *compat) 1721{ 1722 if (of_live_active()) { 1723 return np_to_ofnode(of_find_compatible_node( 1724 (struct device_node *)ofnode_to_np(from), NULL, 1725 compat)); 1726 } else { 1727 return noffset_to_ofnode(from, 1728 fdt_node_offset_by_compatible(ofnode_to_fdt(from), 1729 ofnode_to_offset(from), compat)); 1730 } 1731} 1732 1733ofnode ofnode_by_prop_value(ofnode from, const char *propname, 1734 const void *propval, int proplen) 1735{ 1736 if (of_live_active()) { 1737 return np_to_ofnode(of_find_node_by_prop_value( 1738 (struct device_node *)ofnode_to_np(from), propname, 1739 propval, proplen)); 1740 } else { 1741 return noffset_to_ofnode(from, 1742 fdt_node_offset_by_prop_value(ofnode_to_fdt(from), 1743 ofnode_to_offset(from), propname, propval, 1744 proplen)); 1745 } 1746} 1747 1748int ofnode_write_prop(ofnode node, const char *propname, const void *value, 1749 int len, bool copy) 1750{ 1751 int ret; 1752 1753 if (of_live_active()) { 1754 void *newval; 1755 1756 if (copy) { 1757 newval = malloc(len); 1758 if (!newval) 1759 return log_ret(-ENOMEM); 1760 memcpy(newval, value, len); 1761 value = newval; 1762 } 1763 ret = of_write_prop(ofnode_to_np(node), propname, len, value); 1764 if (ret && copy) 1765 free(newval); 1766 return ret; 1767 } else { 1768 ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), 1769 propname, value, len); 1770 if (ret) 1771 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; 1772 1773 return 0; 1774 } 1775} 1776 1777int ofnode_write_string(ofnode node, const char *propname, const char *value) 1778{ 1779 assert(ofnode_valid(node)); 1780 1781 log_debug("%s: %s = %s", __func__, propname, value); 1782 1783 return ofnode_write_prop(node, propname, value, strlen(value) + 1, 1784 false); 1785} 1786 1787int ofnode_write_u32(ofnode node, const char *propname, u32 value) 1788{ 1789 fdt32_t *val; 1790 1791 assert(ofnode_valid(node)); 1792 1793 log_debug("%s = %x", propname, value); 1794 val = malloc(sizeof(*val)); 1795 if (!val) 1796 return -ENOMEM; 1797 *val = cpu_to_fdt32(value); 1798 1799 return ofnode_write_prop(node, propname, val, sizeof(value), true); 1800} 1801 1802int ofnode_write_u64(ofnode node, const char *propname, u64 value) 1803{ 1804 fdt64_t *val; 1805 1806 assert(ofnode_valid(node)); 1807 1808 log_debug("%s = %llx", propname, (unsigned long long)value); 1809 val = malloc(sizeof(*val)); 1810 if (!val) 1811 return -ENOMEM; 1812 *val = cpu_to_fdt64(value); 1813 1814 return ofnode_write_prop(node, propname, val, sizeof(value), true); 1815} 1816 1817int ofnode_write_bool(ofnode node, const char *propname, bool value) 1818{ 1819 if (value) 1820 return ofnode_write_prop(node, propname, NULL, 0, false); 1821 else 1822 return ofnode_delete_prop(node, propname); 1823} 1824 1825int ofnode_delete_prop(ofnode node, const char *propname) 1826{ 1827 if (ofnode_is_np(node)) { 1828 struct property *prop; 1829 int len; 1830 1831 prop = of_find_property(ofnode_to_np(node), propname, &len); 1832 if (prop) 1833 return of_remove_property(ofnode_to_np(node), prop); 1834 return 0; 1835 } else { 1836 return fdt_delprop(ofnode_to_fdt(node), ofnode_to_offset(node), 1837 propname); 1838 } 1839} 1840 1841int ofnode_set_enabled(ofnode node, bool value) 1842{ 1843 assert(ofnode_valid(node)); 1844 1845 if (value) 1846 return ofnode_write_string(node, "status", "okay"); 1847 else 1848 return ofnode_write_string(node, "status", "disabled"); 1849} 1850 1851bool ofnode_conf_read_bool(const char *prop_name) 1852{ 1853 ofnode node; 1854 1855 node = ofnode_path("/config"); 1856 if (!ofnode_valid(node)) 1857 return false; 1858 1859 return ofnode_read_bool(node, prop_name); 1860} 1861 1862int ofnode_conf_read_int(const char *prop_name, int default_val) 1863{ 1864 ofnode node; 1865 1866 node = ofnode_path("/config"); 1867 if (!ofnode_valid(node)) 1868 return default_val; 1869 1870 return ofnode_read_u32_default(node, prop_name, default_val); 1871} 1872 1873const char *ofnode_conf_read_str(const char *prop_name) 1874{ 1875 ofnode node; 1876 1877 node = ofnode_path("/config"); 1878 if (!ofnode_valid(node)) 1879 return NULL; 1880 1881 return ofnode_read_string(node, prop_name); 1882} 1883 1884bool ofnode_options_read_bool(const char *prop_name) 1885{ 1886 ofnode uboot; 1887 1888 uboot = ofnode_path("/options/u-boot"); 1889 if (!ofnode_valid(uboot)) 1890 return false; 1891 1892 return ofnode_read_bool(uboot, prop_name); 1893} 1894 1895int ofnode_options_read_int(const char *prop_name, int default_val) 1896{ 1897 ofnode uboot; 1898 1899 uboot = ofnode_path("/options/u-boot"); 1900 if (!ofnode_valid(uboot)) 1901 return default_val; 1902 1903 return ofnode_read_u32_default(uboot, prop_name, default_val); 1904} 1905 1906const char *ofnode_options_read_str(const char *prop_name) 1907{ 1908 ofnode uboot; 1909 1910 uboot = ofnode_path("/options/u-boot"); 1911 if (!ofnode_valid(uboot)) 1912 return NULL; 1913 1914 return ofnode_read_string(uboot, prop_name); 1915} 1916 1917int ofnode_options_get_by_phandle(const char *prop_name, ofnode *nodep) 1918{ 1919 ofnode uboot; 1920 1921 uboot = ofnode_path("/options/u-boot"); 1922 if (!ofnode_valid(uboot)) 1923 return -EINVAL; 1924 1925 *nodep = ofnode_parse_phandle(uboot, prop_name, 0); 1926 if (!ofnode_valid(*nodep)) 1927 return -EINVAL; 1928 1929 return 0; 1930} 1931 1932int ofnode_read_bootscript_address(u64 *bootscr_address, u64 *bootscr_offset) 1933{ 1934 int ret; 1935 ofnode uboot; 1936 1937 *bootscr_address = 0; 1938 *bootscr_offset = 0; 1939 1940 uboot = ofnode_path("/options/u-boot"); 1941 if (!ofnode_valid(uboot)) { 1942 dm_warn("%s: Missing /u-boot node\n", __func__); 1943 return -EINVAL; 1944 } 1945 1946 ret = ofnode_read_u64(uboot, "bootscr-address", bootscr_address); 1947 if (ret) { 1948 ret = ofnode_read_u64(uboot, "bootscr-ram-offset", 1949 bootscr_offset); 1950 if (ret) 1951 return -EINVAL; 1952 } 1953 1954 return 0; 1955} 1956 1957int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset, 1958 u64 *bootscr_flash_size) 1959{ 1960 int ret; 1961 ofnode uboot; 1962 1963 *bootscr_flash_offset = 0; 1964 *bootscr_flash_size = 0; 1965 1966 uboot = ofnode_path("/options/u-boot"); 1967 if (!ofnode_valid(uboot)) { 1968 dm_warn("%s: Missing /u-boot node\n", __func__); 1969 return -EINVAL; 1970 } 1971 1972 ret = ofnode_read_u64(uboot, "bootscr-flash-offset", 1973 bootscr_flash_offset); 1974 if (ret) 1975 return -EINVAL; 1976 1977 ret = ofnode_read_u64(uboot, "bootscr-flash-size", 1978 bootscr_flash_size); 1979 if (ret) 1980 return -EINVAL; 1981 1982 if (!bootscr_flash_size) { 1983 dm_warn("bootscr-flash-size is zero. Ignoring properties!\n"); 1984 *bootscr_flash_offset = 0; 1985 return -EINVAL; 1986 } 1987 1988 return 0; 1989} 1990 1991ofnode ofnode_get_phy_node(ofnode node) 1992{ 1993 /* DT node properties that reference a PHY node */ 1994 static const char * const phy_handle_str[] = { 1995 "phy-handle", "phy", "phy-device", 1996 }; 1997 struct ofnode_phandle_args args = { 1998 .node = ofnode_null() 1999 }; 2000 int i; 2001 2002 assert(ofnode_valid(node)); 2003 2004 for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++) 2005 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i], 2006 NULL, 0, 0, &args)) 2007 break; 2008 2009 return args.node; 2010} 2011 2012phy_interface_t ofnode_read_phy_mode(ofnode node) 2013{ 2014 const char *mode; 2015 int i; 2016 2017 assert(ofnode_valid(node)); 2018 2019 mode = ofnode_read_string(node, "phy-mode"); 2020 if (!mode) 2021 mode = ofnode_read_string(node, "phy-connection-type"); 2022 2023 if (!mode) 2024 return PHY_INTERFACE_MODE_NA; 2025 2026 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) 2027 if (!strcmp(mode, phy_interface_strings[i])) 2028 return i; 2029 2030 dm_warn("%s: Invalid PHY interface '%s'\n", __func__, mode); 2031 2032 return PHY_INTERFACE_MODE_NA; 2033} 2034 2035int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) 2036{ 2037 ofnode subnode; 2038 int ret = 0; 2039 2040 assert(ofnode_valid(node)); 2041 2042 if (ofnode_is_np(node)) { 2043 struct device_node *np, *child; 2044 2045 np = (struct device_node *)ofnode_to_np(node); 2046 ret = of_add_subnode(np, name, -1, &child); 2047 if (ret && ret != -EEXIST) 2048 return ret; 2049 subnode = np_to_ofnode(child); 2050 } else { 2051 void *fdt = ofnode_to_fdt(node); 2052 int poffset = ofnode_to_offset(node); 2053 int offset; 2054 2055 offset = fdt_add_subnode(fdt, poffset, name); 2056 if (offset == -FDT_ERR_EXISTS) { 2057 offset = fdt_subnode_offset(fdt, poffset, name); 2058 ret = -EEXIST; 2059 } 2060 if (offset < 0) 2061 return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; 2062 subnode = noffset_to_ofnode(node, offset); 2063 } 2064 2065 *subnodep = subnode; 2066 2067 return ret; /* 0 or -EEXIST */ 2068} 2069 2070int ofnode_delete(ofnode *nodep) 2071{ 2072 ofnode node = *nodep; 2073 int ret; 2074 2075 assert(ofnode_valid(node)); 2076 if (ofnode_is_np(node)) { 2077 ret = of_remove_node(ofnode_to_np(node)); 2078 } else { 2079 void *fdt = ofnode_to_fdt(node); 2080 int offset = ofnode_to_offset(node); 2081 2082 ret = fdt_del_node(fdt, offset); 2083 if (ret) 2084 ret = -EFAULT; 2085 } 2086 if (ret) 2087 return ret; 2088 *nodep = ofnode_null(); 2089 2090 return 0; 2091} 2092 2093int ofnode_copy_props(ofnode dst, ofnode src) 2094{ 2095 struct ofprop prop; 2096 2097 ofnode_for_each_prop(prop, src) { 2098 const char *name; 2099 const char *val; 2100 int len, ret; 2101 2102 val = ofprop_get_property(&prop, &name, &len); 2103 if (!val) { 2104 log_debug("Cannot read prop (err=%d)\n", len); 2105 return log_msg_ret("get", -EINVAL); 2106 } 2107 ret = ofnode_write_prop(dst, name, val, len, true); 2108 if (ret) { 2109 log_debug("Cannot write prop (err=%d)\n", ret); 2110 return log_msg_ret("wr", -EINVAL); 2111 } 2112 } 2113 2114 return 0; 2115} 2116 2117int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src, 2118 ofnode *nodep) 2119{ 2120 ofnode node; 2121 int ret; 2122 2123 ret = ofnode_add_subnode(dst_parent, name, &node); 2124 if (ret) { 2125 if (ret == -EEXIST) 2126 *nodep = node; 2127 return log_msg_ret("add", ret); 2128 } 2129 ret = ofnode_copy_props(node, src); 2130 if (ret) 2131 return log_msg_ret("cpy", ret); 2132 *nodep = node; 2133 2134 return 0; 2135}