1 /* 2 * Originally from Linux v4.9 3 * Paul Mackerras August 1996. 4 * Copyright (C) 1996-2005 Paul Mackerras. 5 * 6 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 7 * {engebret|bergner}@us.ibm.com 8 * 9 * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 10 * 11 * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 12 * Grant Likely. 13 * 14 * Modified for U-Boot 15 * Copyright (c) 2017 Google, Inc 16 * 17 * This file follows drivers/of/base.c with functions in the same order as the 18 * Linux version. 19 * 20 * SPDX-License-Identifier: GPL-2.0+ 21 */ 22 23 #include <common.h> 24 #include <linux/libfdt.h> 25 #include <dm/of_access.h> 26 #include <linux/ctype.h> 27 #include <linux/err.h> 28 #include <linux/ioport.h> 29 30 DECLARE_GLOBAL_DATA_PTR; 31 32 #define PROP_HIDE_MAGIC 1 33 34 /* list of struct alias_prop aliases */ 35 LIST_HEAD(aliases_lookup); 36 37 /* "/aliaes" node */ 38 static struct device_node *of_aliases; 39 40 /* "/chosen" node */ 41 static struct device_node *of_chosen; 42 43 /* node pointed to by the stdout-path alias */ 44 static struct device_node *of_stdout; 45 46 /* pointer to options given after the alias (separated by :) or NULL if none */ 47 static const char *of_stdout_options; 48 49 /** 50 * struct alias_prop - Alias property in 'aliases' node 51 * 52 * The structure represents one alias property of 'aliases' node as 53 * an entry in aliases_lookup list. 54 * 55 * @link: List node to link the structure in aliases_lookup list 56 * @alias: Alias property name 57 * @np: Pointer to device_node that the alias stands for 58 * @id: Index value from end of alias name 59 * @stem: Alias string without the index 60 */ 61 struct alias_prop { 62 struct list_head link; 63 const char *alias; 64 struct device_node *np; 65 int id; 66 char stem[0]; 67 }; 68 69 int of_n_addr_cells(const struct device_node *np) 70 { 71 const __be32 *ip; 72 73 do { 74 if (np->parent) 75 np = np->parent; 76 ip = of_get_property(np, "#address-cells", NULL); 77 if (ip) 78 return be32_to_cpup(ip); 79 } while (np->parent); 80 81 /* No #address-cells property for the root node */ 82 return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 83 } 84 85 int of_n_size_cells(const struct device_node *np) 86 { 87 const __be32 *ip; 88 89 do { 90 if (np->parent) 91 np = np->parent; 92 ip = of_get_property(np, "#size-cells", NULL); 93 if (ip) 94 return be32_to_cpup(ip); 95 } while (np->parent); 96 97 /* No #size-cells property for the root node */ 98 return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 99 } 100 101 int of_simple_addr_cells(const struct device_node *np) 102 { 103 const __be32 *ip; 104 105 ip = of_get_property(np, "#address-cells", NULL); 106 if (ip) 107 return be32_to_cpup(ip); 108 109 /* Return a default of 2 to match fdt_address_cells()*/ 110 return 2; 111 } 112 113 int of_simple_size_cells(const struct device_node *np) 114 { 115 const __be32 *ip; 116 117 ip = of_get_property(np, "#size-cells", NULL); 118 if (ip) 119 return be32_to_cpup(ip); 120 121 /* Return a default of 2 to match fdt_size_cells()*/ 122 return 2; 123 } 124 125 struct property *of_find_property(const struct device_node *np, 126 const char *name, int *lenp) 127 { 128 struct property *pp; 129 130 if (!np) 131 return NULL; 132 133 for (pp = np->properties; pp; pp = pp->next) { 134 if (strcmp(pp->name, name) == 0) { 135 if (lenp) 136 *lenp = pp->length; 137 break; 138 } 139 } 140 if (!pp && lenp) 141 *lenp = -FDT_ERR_NOTFOUND; 142 143 return pp; 144 } 145 146 struct device_node *of_find_all_nodes(struct device_node *prev) 147 { 148 struct device_node *np; 149 150 if (!prev) { 151 np = gd->of_root; 152 } else if (prev->child) { 153 np = prev->child; 154 } else { 155 /* 156 * Walk back up looking for a sibling, or the end of the 157 * structure 158 */ 159 np = prev; 160 while (np->parent && !np->sibling) 161 np = np->parent; 162 np = np->sibling; /* Might be null at the end of the tree */ 163 } 164 165 return np; 166 } 167 168 const void *of_get_property(const struct device_node *np, const char *name, 169 int *lenp) 170 { 171 struct property *pp = of_find_property(np, name, lenp); 172 173 return pp ? pp->value : NULL; 174 } 175 176 const char *of_hide_property(struct device_node *np, const char *name) 177 { 178 struct property *pp; 179 180 if (!np) 181 return NULL; 182 183 for (pp = np->properties; pp; pp = pp->next) { 184 if (strcmp(pp->name, name) == 0) { 185 pp->name[0] += PROP_HIDE_MAGIC; 186 return (const char *)pp->name; 187 } 188 } 189 190 return NULL; 191 } 192 193 int of_present_property(struct device_node *np, const char *name) 194 { 195 struct property *pp; 196 197 if (!np) 198 return -FDT_ERR_NOTFOUND; 199 200 for (pp = np->properties; pp; pp = pp->next) { 201 if (strcmp(pp->name, name) == 0) { 202 pp->name[0] -= PROP_HIDE_MAGIC; 203 break; 204 } 205 } 206 207 return 0; 208 } 209 210 static const char *of_prop_next_string(struct property *prop, const char *cur) 211 { 212 const void *curv = cur; 213 214 if (!prop) 215 return NULL; 216 217 if (!cur) 218 return prop->value; 219 220 curv += strlen(cur) + 1; 221 if (curv >= prop->value + prop->length) 222 return NULL; 223 224 return curv; 225 } 226 227 int of_device_is_compatible(const struct device_node *device, 228 const char *compat, const char *type, 229 const char *name) 230 { 231 struct property *prop; 232 const char *cp; 233 int index = 0, score = 0; 234 235 /* Compatible match has highest priority */ 236 if (compat && compat[0]) { 237 prop = of_find_property(device, "compatible", NULL); 238 for (cp = of_prop_next_string(prop, NULL); cp; 239 cp = of_prop_next_string(prop, cp), index++) { 240 if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 241 score = INT_MAX/2 - (index << 2); 242 break; 243 } 244 } 245 if (!score) 246 return 0; 247 } 248 249 /* Matching type is better than matching name */ 250 if (type && type[0]) { 251 if (!device->type || of_node_cmp(type, device->type)) 252 return 0; 253 score += 2; 254 } 255 256 /* Matching name is a bit better than not */ 257 if (name && name[0]) { 258 if (!device->name || of_node_cmp(name, device->name)) 259 return 0; 260 score++; 261 } 262 263 return score; 264 } 265 266 bool of_device_is_available(const struct device_node *device) 267 { 268 const char *status; 269 int statlen; 270 271 if (!device) 272 return false; 273 274 status = of_get_property(device, "status", &statlen); 275 if (status == NULL) 276 return true; 277 278 if (statlen > 0) { 279 if (!strcmp(status, "okay")) 280 return true; 281 } 282 283 return false; 284 } 285 286 struct device_node *of_get_parent(const struct device_node *node) 287 { 288 const struct device_node *np; 289 290 if (!node) 291 return NULL; 292 293 np = of_node_get(node->parent); 294 295 return (struct device_node *)np; 296 } 297 298 static struct device_node *__of_get_next_child(const struct device_node *node, 299 struct device_node *prev) 300 { 301 struct device_node *next; 302 303 if (!node) 304 return NULL; 305 306 next = prev ? prev->sibling : node->child; 307 /* 308 * coverity[dead_error_line : FALSE] 309 * Dead code here since our current implementation of of_node_get() 310 * always returns NULL (Coverity CID 163245). But we leave it as is 311 * since we may want to implement get/put later. 312 */ 313 for (; next; next = next->sibling) 314 if (of_node_get(next)) 315 break; 316 of_node_put(prev); 317 return next; 318 } 319 320 #define __for_each_child_of_node(parent, child) \ 321 for (child = __of_get_next_child(parent, NULL); child != NULL; \ 322 child = __of_get_next_child(parent, child)) 323 324 static struct device_node *__of_find_node_by_path(struct device_node *parent, 325 const char *path) 326 { 327 struct device_node *child; 328 int len; 329 330 len = strcspn(path, "/:"); 331 if (!len) 332 return NULL; 333 334 __for_each_child_of_node(parent, child) { 335 const char *name = strrchr(child->full_name, '/'); 336 337 name++; 338 if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 339 return child; 340 } 341 return NULL; 342 } 343 344 #define for_each_property_of_node(dn, pp) \ 345 for (pp = dn->properties; pp != NULL; pp = pp->next) 346 347 struct device_node *of_find_node_opts_by_path(const char *path, 348 const char **opts) 349 { 350 struct device_node *np = NULL; 351 struct property *pp; 352 const char *separator = strchr(path, ':'); 353 354 if (opts) 355 *opts = separator ? separator + 1 : NULL; 356 357 if (strcmp(path, "/") == 0) 358 return of_node_get(gd->of_root); 359 360 /* The path could begin with an alias */ 361 if (*path != '/') { 362 int len; 363 const char *p = separator; 364 365 if (!p) 366 p = strchrnul(path, '/'); 367 len = p - path; 368 369 /* of_aliases must not be NULL */ 370 if (!of_aliases) 371 return NULL; 372 373 for_each_property_of_node(of_aliases, pp) { 374 if (strlen(pp->name) == len && !strncmp(pp->name, path, 375 len)) { 376 np = of_find_node_by_path(pp->value); 377 break; 378 } 379 } 380 if (!np) 381 return NULL; 382 path = p; 383 } 384 385 /* Step down the tree matching path components */ 386 if (!np) 387 np = of_node_get(gd->of_root); 388 while (np && *path == '/') { 389 struct device_node *tmp = np; 390 391 path++; /* Increment past '/' delimiter */ 392 np = __of_find_node_by_path(np, path); 393 of_node_put(tmp); 394 path = strchrnul(path, '/'); 395 if (separator && separator < path) 396 break; 397 } 398 399 return np; 400 } 401 402 struct device_node *of_find_compatible_node(struct device_node *from, 403 const char *type, const char *compatible) 404 { 405 struct device_node *np; 406 407 for_each_of_allnodes_from(from, np) 408 if (of_device_is_compatible(np, compatible, type, NULL) && 409 of_node_get(np)) 410 break; 411 of_node_put(from); 412 413 return np; 414 } 415 416 struct device_node *of_find_node_by_phandle(phandle handle) 417 { 418 struct device_node *np; 419 420 if (!handle) 421 return NULL; 422 423 for_each_of_allnodes(np) 424 if (np->phandle == handle) 425 break; 426 (void)of_node_get(np); 427 428 return np; 429 } 430 431 /** 432 * of_find_property_value_of_size() - find property of given size 433 * 434 * Search for a property in a device node and validate the requested size. 435 * 436 * @np: device node from which the property value is to be read. 437 * @propname: name of the property to be searched. 438 * @len: requested length of property value 439 * 440 * @return the property value on success, -EINVAL if the property does not 441 * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 442 * property data isn't large enough. 443 */ 444 static void *of_find_property_value_of_size(const struct device_node *np, 445 const char *propname, u32 len) 446 { 447 struct property *prop = of_find_property(np, propname, NULL); 448 449 if (!prop) 450 return ERR_PTR(-EINVAL); 451 if (!prop->value) 452 return ERR_PTR(-ENODATA); 453 if (len > prop->length) 454 return ERR_PTR(-EOVERFLOW); 455 456 return prop->value; 457 } 458 459 int of_read_u32(const struct device_node *np, const char *propname, u32 *outp) 460 { 461 const __be32 *val; 462 463 debug("%s: %s: ", __func__, propname); 464 if (!np) 465 return -EINVAL; 466 val = of_find_property_value_of_size(np, propname, sizeof(*outp)); 467 if (IS_ERR(val)) { 468 debug("(not found)\n"); 469 return PTR_ERR(val); 470 } 471 472 *outp = be32_to_cpup(val); 473 debug("%#x (%d)\n", *outp, *outp); 474 475 return 0; 476 } 477 478 /** 479 * of_property_read_u64 - Find and read a 64 bit integer from a property 480 * @np: device node from which the property value is to be read. 481 * @propname: name of the property to be searched. 482 * @out_value: pointer to return value, modified only if return value is 0. 483 * 484 * Search for a property in a device node and read a 64-bit value from 485 * it. Returns 0 on success, -EINVAL if the property does not exist, 486 * -ENODATA if property does not have a value, and -EOVERFLOW if the 487 * property data isn't large enough. 488 * 489 * The out_value is modified only if a valid u64 value can be decoded. 490 */ 491 int of_property_read_u64(const struct device_node *np, const char *propname, 492 u64 *out_value) 493 { 494 const __be32 *val = of_find_property_value_of_size(np, propname, 495 sizeof(*out_value)); 496 497 if (IS_ERR(val)) 498 return PTR_ERR(val); 499 500 *out_value = of_read_number(val, 2); 501 502 return 0; 503 } 504 505 int of_read_u32_array(const struct device_node *np, const char *propname, 506 u32 *out_values, size_t sz) 507 { 508 const __be32 *val; 509 510 debug("%s: %s: ", __func__, propname); 511 val = of_find_property_value_of_size(np, propname, 512 sz * sizeof(*out_values)); 513 514 if (IS_ERR(val)) 515 return PTR_ERR(val); 516 517 debug("size %zd\n", sz); 518 while (sz--) 519 *out_values++ = be32_to_cpup(val++); 520 521 return 0; 522 } 523 524 int of_write_u32_array(const struct device_node *np, const char *propname, 525 u32 *values, size_t sz) 526 { 527 __be32 *val; 528 529 debug("%s: %s: ", __func__, propname); 530 val = of_find_property_value_of_size(np, propname, 531 sz * sizeof(*values)); 532 533 if (IS_ERR(val)) 534 return PTR_ERR(val); 535 536 debug("size %zd\n", sz); 537 while (sz--) 538 *val++ = cpu_to_be32p(values++); 539 540 return 0; 541 } 542 543 int of_property_match_string(const struct device_node *np, const char *propname, 544 const char *string) 545 { 546 const struct property *prop = of_find_property(np, propname, NULL); 547 size_t l; 548 int i; 549 const char *p, *end; 550 551 if (!prop) 552 return -EINVAL; 553 if (!prop->value) 554 return -ENODATA; 555 556 p = prop->value; 557 end = p + prop->length; 558 559 for (i = 0; p < end; i++, p += l) { 560 l = strnlen(p, end - p) + 1; 561 if (p + l > end) 562 return -EILSEQ; 563 debug("comparing %s with %s\n", string, p); 564 if (strcmp(string, p) == 0) 565 return i; /* Found it; return index */ 566 } 567 return -ENODATA; 568 } 569 570 /** 571 * of_property_read_string_helper() - Utility helper for parsing string properties 572 * @np: device node from which the property value is to be read. 573 * @propname: name of the property to be searched. 574 * @out_strs: output array of string pointers. 575 * @sz: number of array elements to read. 576 * @skip: Number of strings to skip over at beginning of list. 577 * 578 * Don't call this function directly. It is a utility helper for the 579 * of_property_read_string*() family of functions. 580 */ 581 int of_property_read_string_helper(const struct device_node *np, 582 const char *propname, const char **out_strs, 583 size_t sz, int skip) 584 { 585 const struct property *prop = of_find_property(np, propname, NULL); 586 int l = 0, i = 0; 587 const char *p, *end; 588 589 if (!prop) 590 return -EINVAL; 591 if (!prop->value) 592 return -ENODATA; 593 p = prop->value; 594 end = p + prop->length; 595 596 for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 597 l = strnlen(p, end - p) + 1; 598 if (p + l > end) 599 return -EILSEQ; 600 if (out_strs && i >= skip) 601 *out_strs++ = p; 602 } 603 i -= skip; 604 return i <= 0 ? -ENODATA : i; 605 } 606 607 static int __of_parse_phandle_with_args(const struct device_node *np, 608 const char *list_name, 609 const char *cells_name, 610 int cell_count, int index, 611 struct of_phandle_args *out_args) 612 { 613 const __be32 *list, *list_end; 614 int rc = 0, cur_index = 0; 615 uint32_t count = 0; 616 struct device_node *node = NULL; 617 phandle phandle; 618 int size; 619 620 /* Retrieve the phandle list property */ 621 list = of_get_property(np, list_name, &size); 622 if (!list) 623 return -ENOENT; 624 list_end = list + size / sizeof(*list); 625 626 /* Loop over the phandles until all the requested entry is found */ 627 while (list < list_end) { 628 rc = -EINVAL; 629 count = 0; 630 631 /* 632 * If phandle is 0, then it is an empty entry with no 633 * arguments. Skip forward to the next entry. 634 */ 635 phandle = be32_to_cpup(list++); 636 if (phandle) { 637 /* 638 * Find the provider node and parse the #*-cells 639 * property to determine the argument length. 640 * 641 * This is not needed if the cell count is hard-coded 642 * (i.e. cells_name not set, but cell_count is set), 643 * except when we're going to return the found node 644 * below. 645 */ 646 if (cells_name || cur_index == index) { 647 node = of_find_node_by_phandle(phandle); 648 if (!node) { 649 debug("%s: could not find phandle\n", 650 np->full_name); 651 goto err; 652 } 653 } 654 655 if (cells_name) { 656 if (of_read_u32(node, cells_name, &count)) { 657 debug("%s: could not get %s for %s\n", 658 np->full_name, cells_name, 659 node->full_name); 660 goto err; 661 } 662 } else { 663 count = cell_count; 664 } 665 666 /* 667 * Make sure that the arguments actually fit in the 668 * remaining property data length 669 */ 670 if (list + count > list_end) { 671 debug("%s: arguments longer than property\n", 672 np->full_name); 673 goto err; 674 } 675 } 676 677 /* 678 * All of the error cases above bail out of the loop, so at 679 * this point, the parsing is successful. If the requested 680 * index matches, then fill the out_args structure and return, 681 * or return -ENOENT for an empty entry. 682 */ 683 rc = -ENOENT; 684 if (cur_index == index) { 685 if (!phandle) 686 goto err; 687 688 if (out_args) { 689 int i; 690 if (WARN_ON(count > OF_MAX_PHANDLE_ARGS)) 691 count = OF_MAX_PHANDLE_ARGS; 692 out_args->np = node; 693 out_args->args_count = count; 694 for (i = 0; i < count; i++) 695 out_args->args[i] = 696 be32_to_cpup(list++); 697 } else { 698 of_node_put(node); 699 } 700 701 /* Found it! return success */ 702 return 0; 703 } 704 705 of_node_put(node); 706 node = NULL; 707 list += count; 708 cur_index++; 709 } 710 711 /* 712 * Unlock node before returning result; will be one of: 713 * -ENOENT : index is for empty phandle 714 * -EINVAL : parsing error on data 715 * [1..n] : Number of phandle (count mode; when index = -1) 716 */ 717 rc = index < 0 ? cur_index : -ENOENT; 718 err: 719 if (node) 720 of_node_put(node); 721 return rc; 722 } 723 724 struct device_node *of_parse_phandle(const struct device_node *np, 725 const char *phandle_name, int index) 726 { 727 struct of_phandle_args args; 728 729 if (index < 0) 730 return NULL; 731 732 if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index, 733 &args)) 734 return NULL; 735 736 return args.np; 737 } 738 739 int of_parse_phandle_with_args(const struct device_node *np, 740 const char *list_name, const char *cells_name, 741 int index, struct of_phandle_args *out_args) 742 { 743 if (index < 0) 744 return -EINVAL; 745 746 return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 747 index, out_args); 748 } 749 750 int of_count_phandle_with_args(const struct device_node *np, 751 const char *list_name, const char *cells_name) 752 { 753 return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 754 -1, NULL); 755 } 756 757 static void of_alias_add(struct alias_prop *ap, struct device_node *np, 758 int id, const char *stem, int stem_len) 759 { 760 struct alias_prop *oldap; 761 ap->np = np; 762 ap->id = id; 763 strncpy(ap->stem, stem, stem_len); 764 ap->stem[stem_len] = 0; 765 766 /* Delete U-Boot alias which is same with kernel */ 767 mutex_lock(&of_mutex); 768 list_for_each_entry(oldap, &aliases_lookup, link) { 769 if (stem && !strcmp(stem, oldap->alias) && (id == oldap->id)) { 770 list_del(&oldap->link); 771 break; 772 } 773 } 774 mutex_unlock(&of_mutex); 775 776 list_add_tail(&ap->link, &aliases_lookup); 777 debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 778 ap->alias, ap->stem, ap->id, of_node_full_name(np)); 779 } 780 781 int of_alias_scan(void) 782 { 783 struct property *pp; 784 785 of_aliases = of_find_node_by_path("/aliases"); 786 of_chosen = of_find_node_by_path("/chosen"); 787 if (of_chosen == NULL) 788 of_chosen = of_find_node_by_path("/chosen@0"); 789 790 if (of_chosen) { 791 const char *name; 792 793 name = of_get_property(of_chosen, "stdout-path", NULL); 794 if (name) 795 of_stdout = of_find_node_opts_by_path(name, 796 &of_stdout_options); 797 } 798 799 if (!of_aliases) 800 return 0; 801 802 for_each_property_of_node(of_aliases, pp) { 803 const char *start = pp->name; 804 const char *end = start + strlen(start); 805 struct device_node *np; 806 struct alias_prop *ap; 807 ulong id; 808 int len; 809 810 /* Skip those we do not want to proceed */ 811 if (!strcmp(pp->name, "name") || 812 !strcmp(pp->name, "phandle") || 813 !strcmp(pp->name, "linux,phandle")) 814 continue; 815 816 np = of_find_node_by_path(pp->value); 817 if (!np) 818 continue; 819 820 /* 821 * walk the alias backwards to extract the id and work out 822 * the 'stem' string 823 */ 824 while (isdigit(*(end-1)) && end > start) 825 end--; 826 len = end - start; 827 828 if (strict_strtoul(end, 10, &id) < 0) 829 continue; 830 831 /* Allocate an alias_prop with enough space for the stem */ 832 ap = malloc(sizeof(*ap) + len + 1); 833 if (!ap) 834 return -ENOMEM; 835 memset(ap, 0, sizeof(*ap) + len + 1); 836 ap->alias = start; 837 of_alias_add(ap, np, id, start, len); 838 } 839 840 return 0; 841 } 842 843 int of_alias_get_id(const struct device_node *np, const char *stem) 844 { 845 struct alias_prop *app; 846 int id = -ENODEV; 847 848 mutex_lock(&of_mutex); 849 list_for_each_entry(app, &aliases_lookup, link) { 850 if (strcmp(app->stem, stem) != 0) 851 continue; 852 853 if (np == app->np) { 854 id = app->id; 855 break; 856 } 857 } 858 mutex_unlock(&of_mutex); 859 860 return id; 861 } 862 863 struct device_node *of_alias_get_dev(const char *stem, int id) 864 { 865 struct alias_prop *app; 866 struct device_node *np = NULL; 867 868 mutex_lock(&of_mutex); 869 list_for_each_entry(app, &aliases_lookup, link) { 870 if (strcmp(app->stem, stem) != 0) 871 continue; 872 873 if (id == app->id) { 874 np = app->np; 875 break; 876 } 877 } 878 mutex_unlock(&of_mutex); 879 880 return np; 881 } 882 883 struct device_node *of_alias_dump(void) 884 { 885 struct alias_prop *app; 886 struct device_node *np = NULL; 887 888 mutex_lock(&of_mutex); 889 list_for_each_entry(app, &aliases_lookup, link) { 890 printf("%10s%d: %20s, phandle=%d %4s\n", 891 app->stem, app->id, 892 app->np->full_name, app->np->phandle, 893 of_get_property(app->np, "u-boot,dm-pre-reloc", NULL) || 894 of_get_property(app->np, "u-boot,dm-spl", NULL) ? "*" : ""); 895 } 896 mutex_unlock(&of_mutex); 897 898 return np; 899 } 900 901 struct device_node *of_get_stdout(void) 902 { 903 struct device_node *np; 904 905 if (gd && gd->serial.using_pre_serial) { 906 np = of_alias_get_dev("serial", gd->serial.id); 907 if (!np) 908 printf("Can't find alias serial%d\n", gd->serial.id); 909 else 910 debug("Find alias serial: %s\n", np->full_name); 911 912 of_stdout = np; 913 } 914 915 return of_stdout; 916 } 917