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