1644ec0a9SSimon Glass /* 2644ec0a9SSimon Glass * Originally from Linux v4.9 3644ec0a9SSimon Glass * Paul Mackerras August 1996. 4644ec0a9SSimon Glass * Copyright (C) 1996-2005 Paul Mackerras. 5644ec0a9SSimon Glass * 6644ec0a9SSimon Glass * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 7644ec0a9SSimon Glass * {engebret|bergner}@us.ibm.com 8644ec0a9SSimon Glass * 9644ec0a9SSimon Glass * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 10644ec0a9SSimon Glass * 11644ec0a9SSimon Glass * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 12644ec0a9SSimon Glass * Grant Likely. 13644ec0a9SSimon Glass * 14644ec0a9SSimon Glass * Modified for U-Boot 15644ec0a9SSimon Glass * Copyright (c) 2017 Google, Inc 16644ec0a9SSimon Glass * 17644ec0a9SSimon Glass * This file follows drivers/of/base.c with functions in the same order as the 18644ec0a9SSimon Glass * Linux version. 19644ec0a9SSimon Glass * 20644ec0a9SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 21644ec0a9SSimon Glass */ 22644ec0a9SSimon Glass 23644ec0a9SSimon Glass #include <common.h> 240e00a84cSMasahiro Yamada #include <linux/libfdt.h> 25644ec0a9SSimon Glass #include <dm/of_access.h> 26644ec0a9SSimon Glass #include <linux/ctype.h> 27644ec0a9SSimon Glass #include <linux/err.h> 28644ec0a9SSimon Glass #include <linux/ioport.h> 29644ec0a9SSimon Glass 30644ec0a9SSimon Glass DECLARE_GLOBAL_DATA_PTR; 31644ec0a9SSimon Glass 32644ec0a9SSimon Glass /* list of struct alias_prop aliases */ 33644ec0a9SSimon Glass LIST_HEAD(aliases_lookup); 34644ec0a9SSimon Glass 35644ec0a9SSimon Glass /* "/aliaes" node */ 36644ec0a9SSimon Glass static struct device_node *of_aliases; 37644ec0a9SSimon Glass 38644ec0a9SSimon Glass /* "/chosen" node */ 39644ec0a9SSimon Glass static struct device_node *of_chosen; 40644ec0a9SSimon Glass 41644ec0a9SSimon Glass /* node pointed to by the stdout-path alias */ 42644ec0a9SSimon Glass static struct device_node *of_stdout; 43644ec0a9SSimon Glass 44644ec0a9SSimon Glass /* pointer to options given after the alias (separated by :) or NULL if none */ 45644ec0a9SSimon Glass static const char *of_stdout_options; 46644ec0a9SSimon Glass 47644ec0a9SSimon Glass /** 48644ec0a9SSimon Glass * struct alias_prop - Alias property in 'aliases' node 49644ec0a9SSimon Glass * 50644ec0a9SSimon Glass * The structure represents one alias property of 'aliases' node as 51644ec0a9SSimon Glass * an entry in aliases_lookup list. 52644ec0a9SSimon Glass * 53644ec0a9SSimon Glass * @link: List node to link the structure in aliases_lookup list 54644ec0a9SSimon Glass * @alias: Alias property name 55644ec0a9SSimon Glass * @np: Pointer to device_node that the alias stands for 56644ec0a9SSimon Glass * @id: Index value from end of alias name 57644ec0a9SSimon Glass * @stem: Alias string without the index 58644ec0a9SSimon Glass */ 59644ec0a9SSimon Glass struct alias_prop { 60644ec0a9SSimon Glass struct list_head link; 61644ec0a9SSimon Glass const char *alias; 62644ec0a9SSimon Glass struct device_node *np; 63644ec0a9SSimon Glass int id; 64644ec0a9SSimon Glass char stem[0]; 65644ec0a9SSimon Glass }; 66644ec0a9SSimon Glass 67644ec0a9SSimon Glass int of_n_addr_cells(const struct device_node *np) 68644ec0a9SSimon Glass { 69644ec0a9SSimon Glass const __be32 *ip; 70644ec0a9SSimon Glass 71644ec0a9SSimon Glass do { 72644ec0a9SSimon Glass if (np->parent) 73644ec0a9SSimon Glass np = np->parent; 74644ec0a9SSimon Glass ip = of_get_property(np, "#address-cells", NULL); 75644ec0a9SSimon Glass if (ip) 76644ec0a9SSimon Glass return be32_to_cpup(ip); 77644ec0a9SSimon Glass } while (np->parent); 78644ec0a9SSimon Glass 79644ec0a9SSimon Glass /* No #address-cells property for the root node */ 80644ec0a9SSimon Glass return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 81644ec0a9SSimon Glass } 82644ec0a9SSimon Glass 83644ec0a9SSimon Glass int of_n_size_cells(const struct device_node *np) 84644ec0a9SSimon Glass { 85644ec0a9SSimon Glass const __be32 *ip; 86644ec0a9SSimon Glass 87644ec0a9SSimon Glass do { 88644ec0a9SSimon Glass if (np->parent) 89644ec0a9SSimon Glass np = np->parent; 90644ec0a9SSimon Glass ip = of_get_property(np, "#size-cells", NULL); 91644ec0a9SSimon Glass if (ip) 92644ec0a9SSimon Glass return be32_to_cpup(ip); 93644ec0a9SSimon Glass } while (np->parent); 94644ec0a9SSimon Glass 95644ec0a9SSimon Glass /* No #size-cells property for the root node */ 96644ec0a9SSimon Glass return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 97644ec0a9SSimon Glass } 98644ec0a9SSimon Glass 99878d68c0SSimon Glass int of_simple_addr_cells(const struct device_node *np) 100878d68c0SSimon Glass { 101878d68c0SSimon Glass const __be32 *ip; 102878d68c0SSimon Glass 103878d68c0SSimon Glass ip = of_get_property(np, "#address-cells", NULL); 104878d68c0SSimon Glass if (ip) 105878d68c0SSimon Glass return be32_to_cpup(ip); 106878d68c0SSimon Glass 107878d68c0SSimon Glass /* Return a default of 2 to match fdt_address_cells()*/ 108878d68c0SSimon Glass return 2; 109878d68c0SSimon Glass } 110878d68c0SSimon Glass 111878d68c0SSimon Glass int of_simple_size_cells(const struct device_node *np) 112878d68c0SSimon Glass { 113878d68c0SSimon Glass const __be32 *ip; 114878d68c0SSimon Glass 115878d68c0SSimon Glass ip = of_get_property(np, "#size-cells", NULL); 116878d68c0SSimon Glass if (ip) 117878d68c0SSimon Glass return be32_to_cpup(ip); 118878d68c0SSimon Glass 119878d68c0SSimon Glass /* Return a default of 2 to match fdt_size_cells()*/ 120878d68c0SSimon Glass return 2; 121878d68c0SSimon Glass } 122878d68c0SSimon Glass 123644ec0a9SSimon Glass struct property *of_find_property(const struct device_node *np, 124644ec0a9SSimon Glass const char *name, int *lenp) 125644ec0a9SSimon Glass { 126644ec0a9SSimon Glass struct property *pp; 127644ec0a9SSimon Glass 128644ec0a9SSimon Glass if (!np) 129644ec0a9SSimon Glass return NULL; 130644ec0a9SSimon Glass 131644ec0a9SSimon Glass for (pp = np->properties; pp; pp = pp->next) { 132644ec0a9SSimon Glass if (strcmp(pp->name, name) == 0) { 133644ec0a9SSimon Glass if (lenp) 134644ec0a9SSimon Glass *lenp = pp->length; 135644ec0a9SSimon Glass break; 136644ec0a9SSimon Glass } 137644ec0a9SSimon Glass } 138644ec0a9SSimon Glass if (!pp && lenp) 139644ec0a9SSimon Glass *lenp = -FDT_ERR_NOTFOUND; 140644ec0a9SSimon Glass 141644ec0a9SSimon Glass return pp; 142644ec0a9SSimon Glass } 143644ec0a9SSimon Glass 144644ec0a9SSimon Glass struct device_node *of_find_all_nodes(struct device_node *prev) 145644ec0a9SSimon Glass { 146644ec0a9SSimon Glass struct device_node *np; 147644ec0a9SSimon Glass 148644ec0a9SSimon Glass if (!prev) { 149644ec0a9SSimon Glass np = gd->of_root; 150644ec0a9SSimon Glass } else if (prev->child) { 151644ec0a9SSimon Glass np = prev->child; 152644ec0a9SSimon Glass } else { 153644ec0a9SSimon Glass /* 154644ec0a9SSimon Glass * Walk back up looking for a sibling, or the end of the 155644ec0a9SSimon Glass * structure 156644ec0a9SSimon Glass */ 157644ec0a9SSimon Glass np = prev; 158644ec0a9SSimon Glass while (np->parent && !np->sibling) 159644ec0a9SSimon Glass np = np->parent; 160644ec0a9SSimon Glass np = np->sibling; /* Might be null at the end of the tree */ 161644ec0a9SSimon Glass } 162644ec0a9SSimon Glass 163644ec0a9SSimon Glass return np; 164644ec0a9SSimon Glass } 165644ec0a9SSimon Glass 166644ec0a9SSimon Glass const void *of_get_property(const struct device_node *np, const char *name, 167644ec0a9SSimon Glass int *lenp) 168644ec0a9SSimon Glass { 169644ec0a9SSimon Glass struct property *pp = of_find_property(np, name, lenp); 170644ec0a9SSimon Glass 171644ec0a9SSimon Glass return pp ? pp->value : NULL; 172644ec0a9SSimon Glass } 173644ec0a9SSimon Glass 174644ec0a9SSimon Glass static const char *of_prop_next_string(struct property *prop, const char *cur) 175644ec0a9SSimon Glass { 176644ec0a9SSimon Glass const void *curv = cur; 177644ec0a9SSimon Glass 178644ec0a9SSimon Glass if (!prop) 179644ec0a9SSimon Glass return NULL; 180644ec0a9SSimon Glass 181644ec0a9SSimon Glass if (!cur) 182644ec0a9SSimon Glass return prop->value; 183644ec0a9SSimon Glass 184644ec0a9SSimon Glass curv += strlen(cur) + 1; 185644ec0a9SSimon Glass if (curv >= prop->value + prop->length) 186644ec0a9SSimon Glass return NULL; 187644ec0a9SSimon Glass 188644ec0a9SSimon Glass return curv; 189644ec0a9SSimon Glass } 190644ec0a9SSimon Glass 191644ec0a9SSimon Glass int of_device_is_compatible(const struct device_node *device, 192644ec0a9SSimon Glass const char *compat, const char *type, 193644ec0a9SSimon Glass const char *name) 194644ec0a9SSimon Glass { 195644ec0a9SSimon Glass struct property *prop; 196644ec0a9SSimon Glass const char *cp; 197644ec0a9SSimon Glass int index = 0, score = 0; 198644ec0a9SSimon Glass 199644ec0a9SSimon Glass /* Compatible match has highest priority */ 200644ec0a9SSimon Glass if (compat && compat[0]) { 201644ec0a9SSimon Glass prop = of_find_property(device, "compatible", NULL); 202644ec0a9SSimon Glass for (cp = of_prop_next_string(prop, NULL); cp; 203644ec0a9SSimon Glass cp = of_prop_next_string(prop, cp), index++) { 204644ec0a9SSimon Glass if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 205644ec0a9SSimon Glass score = INT_MAX/2 - (index << 2); 206644ec0a9SSimon Glass break; 207644ec0a9SSimon Glass } 208644ec0a9SSimon Glass } 209644ec0a9SSimon Glass if (!score) 210644ec0a9SSimon Glass return 0; 211644ec0a9SSimon Glass } 212644ec0a9SSimon Glass 213644ec0a9SSimon Glass /* Matching type is better than matching name */ 214644ec0a9SSimon Glass if (type && type[0]) { 215644ec0a9SSimon Glass if (!device->type || of_node_cmp(type, device->type)) 216644ec0a9SSimon Glass return 0; 217644ec0a9SSimon Glass score += 2; 218644ec0a9SSimon Glass } 219644ec0a9SSimon Glass 220644ec0a9SSimon Glass /* Matching name is a bit better than not */ 221644ec0a9SSimon Glass if (name && name[0]) { 222644ec0a9SSimon Glass if (!device->name || of_node_cmp(name, device->name)) 223644ec0a9SSimon Glass return 0; 224644ec0a9SSimon Glass score++; 225644ec0a9SSimon Glass } 226644ec0a9SSimon Glass 227644ec0a9SSimon Glass return score; 228644ec0a9SSimon Glass } 229644ec0a9SSimon Glass 230644ec0a9SSimon Glass bool of_device_is_available(const struct device_node *device) 231644ec0a9SSimon Glass { 232644ec0a9SSimon Glass const char *status; 233644ec0a9SSimon Glass int statlen; 234644ec0a9SSimon Glass 235644ec0a9SSimon Glass if (!device) 236644ec0a9SSimon Glass return false; 237644ec0a9SSimon Glass 238644ec0a9SSimon Glass status = of_get_property(device, "status", &statlen); 239644ec0a9SSimon Glass if (status == NULL) 240644ec0a9SSimon Glass return true; 241644ec0a9SSimon Glass 242644ec0a9SSimon Glass if (statlen > 0) { 243644ec0a9SSimon Glass if (!strcmp(status, "okay")) 244644ec0a9SSimon Glass return true; 245644ec0a9SSimon Glass } 246644ec0a9SSimon Glass 247644ec0a9SSimon Glass return false; 248644ec0a9SSimon Glass } 249644ec0a9SSimon Glass 250644ec0a9SSimon Glass struct device_node *of_get_parent(const struct device_node *node) 251644ec0a9SSimon Glass { 252644ec0a9SSimon Glass const struct device_node *np; 253644ec0a9SSimon Glass 254644ec0a9SSimon Glass if (!node) 255644ec0a9SSimon Glass return NULL; 256644ec0a9SSimon Glass 257644ec0a9SSimon Glass np = of_node_get(node->parent); 258644ec0a9SSimon Glass 259644ec0a9SSimon Glass return (struct device_node *)np; 260644ec0a9SSimon Glass } 261644ec0a9SSimon Glass 262644ec0a9SSimon Glass static struct device_node *__of_get_next_child(const struct device_node *node, 263644ec0a9SSimon Glass struct device_node *prev) 264644ec0a9SSimon Glass { 265644ec0a9SSimon Glass struct device_node *next; 266644ec0a9SSimon Glass 267644ec0a9SSimon Glass if (!node) 268644ec0a9SSimon Glass return NULL; 269644ec0a9SSimon Glass 270644ec0a9SSimon Glass next = prev ? prev->sibling : node->child; 27173027a85SSimon Glass /* 27273027a85SSimon Glass * coverity[dead_error_line : FALSE] 27373027a85SSimon Glass * Dead code here since our current implementation of of_node_get() 27473027a85SSimon Glass * always returns NULL (Coverity CID 163245). But we leave it as is 27573027a85SSimon Glass * since we may want to implement get/put later. 27673027a85SSimon Glass */ 277644ec0a9SSimon Glass for (; next; next = next->sibling) 278644ec0a9SSimon Glass if (of_node_get(next)) 279644ec0a9SSimon Glass break; 280644ec0a9SSimon Glass of_node_put(prev); 281644ec0a9SSimon Glass return next; 282644ec0a9SSimon Glass } 283644ec0a9SSimon Glass 284644ec0a9SSimon Glass #define __for_each_child_of_node(parent, child) \ 285644ec0a9SSimon Glass for (child = __of_get_next_child(parent, NULL); child != NULL; \ 286644ec0a9SSimon Glass child = __of_get_next_child(parent, child)) 287644ec0a9SSimon Glass 288644ec0a9SSimon Glass static struct device_node *__of_find_node_by_path(struct device_node *parent, 289644ec0a9SSimon Glass const char *path) 290644ec0a9SSimon Glass { 291644ec0a9SSimon Glass struct device_node *child; 292644ec0a9SSimon Glass int len; 293644ec0a9SSimon Glass 294644ec0a9SSimon Glass len = strcspn(path, "/:"); 295644ec0a9SSimon Glass if (!len) 296644ec0a9SSimon Glass return NULL; 297644ec0a9SSimon Glass 298644ec0a9SSimon Glass __for_each_child_of_node(parent, child) { 299644ec0a9SSimon Glass const char *name = strrchr(child->full_name, '/'); 300644ec0a9SSimon Glass 301644ec0a9SSimon Glass name++; 302644ec0a9SSimon Glass if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 303644ec0a9SSimon Glass return child; 304644ec0a9SSimon Glass } 305644ec0a9SSimon Glass return NULL; 306644ec0a9SSimon Glass } 307644ec0a9SSimon Glass 308644ec0a9SSimon Glass #define for_each_property_of_node(dn, pp) \ 309644ec0a9SSimon Glass for (pp = dn->properties; pp != NULL; pp = pp->next) 310644ec0a9SSimon Glass 311644ec0a9SSimon Glass struct device_node *of_find_node_opts_by_path(const char *path, 312644ec0a9SSimon Glass const char **opts) 313644ec0a9SSimon Glass { 314644ec0a9SSimon Glass struct device_node *np = NULL; 315644ec0a9SSimon Glass struct property *pp; 316644ec0a9SSimon Glass const char *separator = strchr(path, ':'); 317644ec0a9SSimon Glass 318644ec0a9SSimon Glass if (opts) 319644ec0a9SSimon Glass *opts = separator ? separator + 1 : NULL; 320644ec0a9SSimon Glass 321644ec0a9SSimon Glass if (strcmp(path, "/") == 0) 322644ec0a9SSimon Glass return of_node_get(gd->of_root); 323644ec0a9SSimon Glass 324644ec0a9SSimon Glass /* The path could begin with an alias */ 325644ec0a9SSimon Glass if (*path != '/') { 326644ec0a9SSimon Glass int len; 327644ec0a9SSimon Glass const char *p = separator; 328644ec0a9SSimon Glass 329644ec0a9SSimon Glass if (!p) 330644ec0a9SSimon Glass p = strchrnul(path, '/'); 331644ec0a9SSimon Glass len = p - path; 332644ec0a9SSimon Glass 333644ec0a9SSimon Glass /* of_aliases must not be NULL */ 334644ec0a9SSimon Glass if (!of_aliases) 335644ec0a9SSimon Glass return NULL; 336644ec0a9SSimon Glass 337644ec0a9SSimon Glass for_each_property_of_node(of_aliases, pp) { 338644ec0a9SSimon Glass if (strlen(pp->name) == len && !strncmp(pp->name, path, 339644ec0a9SSimon Glass len)) { 340644ec0a9SSimon Glass np = of_find_node_by_path(pp->value); 341644ec0a9SSimon Glass break; 342644ec0a9SSimon Glass } 343644ec0a9SSimon Glass } 344644ec0a9SSimon Glass if (!np) 345644ec0a9SSimon Glass return NULL; 346644ec0a9SSimon Glass path = p; 347644ec0a9SSimon Glass } 348644ec0a9SSimon Glass 349644ec0a9SSimon Glass /* Step down the tree matching path components */ 350644ec0a9SSimon Glass if (!np) 351644ec0a9SSimon Glass np = of_node_get(gd->of_root); 352644ec0a9SSimon Glass while (np && *path == '/') { 353644ec0a9SSimon Glass struct device_node *tmp = np; 354644ec0a9SSimon Glass 355644ec0a9SSimon Glass path++; /* Increment past '/' delimiter */ 356644ec0a9SSimon Glass np = __of_find_node_by_path(np, path); 357644ec0a9SSimon Glass of_node_put(tmp); 358644ec0a9SSimon Glass path = strchrnul(path, '/'); 359644ec0a9SSimon Glass if (separator && separator < path) 360644ec0a9SSimon Glass break; 361644ec0a9SSimon Glass } 362644ec0a9SSimon Glass 363644ec0a9SSimon Glass return np; 364644ec0a9SSimon Glass } 365644ec0a9SSimon Glass 366644ec0a9SSimon Glass struct device_node *of_find_compatible_node(struct device_node *from, 367644ec0a9SSimon Glass const char *type, const char *compatible) 368644ec0a9SSimon Glass { 369644ec0a9SSimon Glass struct device_node *np; 370644ec0a9SSimon Glass 371644ec0a9SSimon Glass for_each_of_allnodes_from(from, np) 372644ec0a9SSimon Glass if (of_device_is_compatible(np, compatible, type, NULL) && 373644ec0a9SSimon Glass of_node_get(np)) 374644ec0a9SSimon Glass break; 375644ec0a9SSimon Glass of_node_put(from); 376644ec0a9SSimon Glass 377644ec0a9SSimon Glass return np; 378644ec0a9SSimon Glass } 379644ec0a9SSimon Glass 380644ec0a9SSimon Glass struct device_node *of_find_node_by_phandle(phandle handle) 381644ec0a9SSimon Glass { 382644ec0a9SSimon Glass struct device_node *np; 383644ec0a9SSimon Glass 384644ec0a9SSimon Glass if (!handle) 385644ec0a9SSimon Glass return NULL; 386644ec0a9SSimon Glass 387644ec0a9SSimon Glass for_each_of_allnodes(np) 388644ec0a9SSimon Glass if (np->phandle == handle) 389644ec0a9SSimon Glass break; 390*d9da4b44SJoseph Chen 391*d9da4b44SJoseph Chen #ifdef CONFIG_USING_KERNEL_DTB_V2 392*d9da4b44SJoseph Chen /* If not find in kernel fdt, traverse u-boot fdt */ 393*d9da4b44SJoseph Chen if (!np) { 394*d9da4b44SJoseph Chen for (np = gd->of_root_f; np; np = of_find_all_nodes(np)) { 395*d9da4b44SJoseph Chen if (np->phandle == handle) 396*d9da4b44SJoseph Chen break; 397*d9da4b44SJoseph Chen } 398*d9da4b44SJoseph Chen } 399*d9da4b44SJoseph Chen #endif 400644ec0a9SSimon Glass (void)of_node_get(np); 401644ec0a9SSimon Glass 402644ec0a9SSimon Glass return np; 403644ec0a9SSimon Glass } 404644ec0a9SSimon Glass 405644ec0a9SSimon Glass /** 406644ec0a9SSimon Glass * of_find_property_value_of_size() - find property of given size 407644ec0a9SSimon Glass * 408644ec0a9SSimon Glass * Search for a property in a device node and validate the requested size. 409644ec0a9SSimon Glass * 410644ec0a9SSimon Glass * @np: device node from which the property value is to be read. 411644ec0a9SSimon Glass * @propname: name of the property to be searched. 412644ec0a9SSimon Glass * @len: requested length of property value 413644ec0a9SSimon Glass * 414644ec0a9SSimon Glass * @return the property value on success, -EINVAL if the property does not 415644ec0a9SSimon Glass * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 416644ec0a9SSimon Glass * property data isn't large enough. 417644ec0a9SSimon Glass */ 418644ec0a9SSimon Glass static void *of_find_property_value_of_size(const struct device_node *np, 419644ec0a9SSimon Glass const char *propname, u32 len) 420644ec0a9SSimon Glass { 421644ec0a9SSimon Glass struct property *prop = of_find_property(np, propname, NULL); 422644ec0a9SSimon Glass 423644ec0a9SSimon Glass if (!prop) 424644ec0a9SSimon Glass return ERR_PTR(-EINVAL); 425644ec0a9SSimon Glass if (!prop->value) 426644ec0a9SSimon Glass return ERR_PTR(-ENODATA); 427644ec0a9SSimon Glass if (len > prop->length) 428644ec0a9SSimon Glass return ERR_PTR(-EOVERFLOW); 429644ec0a9SSimon Glass 430644ec0a9SSimon Glass return prop->value; 431644ec0a9SSimon Glass } 432644ec0a9SSimon Glass 433644ec0a9SSimon Glass int of_read_u32(const struct device_node *np, const char *propname, u32 *outp) 434644ec0a9SSimon Glass { 435644ec0a9SSimon Glass const __be32 *val; 436644ec0a9SSimon Glass 437644ec0a9SSimon Glass debug("%s: %s: ", __func__, propname); 438644ec0a9SSimon Glass if (!np) 439644ec0a9SSimon Glass return -EINVAL; 440644ec0a9SSimon Glass val = of_find_property_value_of_size(np, propname, sizeof(*outp)); 441644ec0a9SSimon Glass if (IS_ERR(val)) { 442644ec0a9SSimon Glass debug("(not found)\n"); 443644ec0a9SSimon Glass return PTR_ERR(val); 444644ec0a9SSimon Glass } 445644ec0a9SSimon Glass 446644ec0a9SSimon Glass *outp = be32_to_cpup(val); 447644ec0a9SSimon Glass debug("%#x (%d)\n", *outp, *outp); 448644ec0a9SSimon Glass 449644ec0a9SSimon Glass return 0; 450644ec0a9SSimon Glass } 451644ec0a9SSimon Glass 452d59cf5aeSJoseph Chen /** 453d59cf5aeSJoseph Chen * of_property_read_u64 - Find and read a 64 bit integer from a property 454d59cf5aeSJoseph Chen * @np: device node from which the property value is to be read. 455d59cf5aeSJoseph Chen * @propname: name of the property to be searched. 456d59cf5aeSJoseph Chen * @out_value: pointer to return value, modified only if return value is 0. 457d59cf5aeSJoseph Chen * 458d59cf5aeSJoseph Chen * Search for a property in a device node and read a 64-bit value from 459d59cf5aeSJoseph Chen * it. Returns 0 on success, -EINVAL if the property does not exist, 460d59cf5aeSJoseph Chen * -ENODATA if property does not have a value, and -EOVERFLOW if the 461d59cf5aeSJoseph Chen * property data isn't large enough. 462d59cf5aeSJoseph Chen * 463d59cf5aeSJoseph Chen * The out_value is modified only if a valid u64 value can be decoded. 464d59cf5aeSJoseph Chen */ 465d59cf5aeSJoseph Chen int of_property_read_u64(const struct device_node *np, const char *propname, 466d59cf5aeSJoseph Chen u64 *out_value) 467d59cf5aeSJoseph Chen { 468d59cf5aeSJoseph Chen const __be32 *val = of_find_property_value_of_size(np, propname, 469d59cf5aeSJoseph Chen sizeof(*out_value)); 470d59cf5aeSJoseph Chen 471d59cf5aeSJoseph Chen if (IS_ERR(val)) 472d59cf5aeSJoseph Chen return PTR_ERR(val); 473d59cf5aeSJoseph Chen 474d59cf5aeSJoseph Chen *out_value = of_read_number(val, 2); 475d59cf5aeSJoseph Chen 476d59cf5aeSJoseph Chen return 0; 477d59cf5aeSJoseph Chen } 478d59cf5aeSJoseph Chen 479644ec0a9SSimon Glass int of_read_u32_array(const struct device_node *np, const char *propname, 480644ec0a9SSimon Glass u32 *out_values, size_t sz) 481644ec0a9SSimon Glass { 482644ec0a9SSimon Glass const __be32 *val; 483644ec0a9SSimon Glass 484644ec0a9SSimon Glass debug("%s: %s: ", __func__, propname); 485644ec0a9SSimon Glass val = of_find_property_value_of_size(np, propname, 486644ec0a9SSimon Glass sz * sizeof(*out_values)); 487644ec0a9SSimon Glass 488644ec0a9SSimon Glass if (IS_ERR(val)) 489644ec0a9SSimon Glass return PTR_ERR(val); 490644ec0a9SSimon Glass 491644ec0a9SSimon Glass debug("size %zd\n", sz); 492644ec0a9SSimon Glass while (sz--) 493644ec0a9SSimon Glass *out_values++ = be32_to_cpup(val++); 494644ec0a9SSimon Glass 495644ec0a9SSimon Glass return 0; 496644ec0a9SSimon Glass } 497644ec0a9SSimon Glass 49804539b46SJoseph Chen int of_write_u32_array(const struct device_node *np, const char *propname, 49904539b46SJoseph Chen u32 *values, size_t sz) 50004539b46SJoseph Chen { 50104539b46SJoseph Chen __be32 *val; 50204539b46SJoseph Chen 50304539b46SJoseph Chen debug("%s: %s: ", __func__, propname); 50404539b46SJoseph Chen val = of_find_property_value_of_size(np, propname, 50504539b46SJoseph Chen sz * sizeof(*values)); 50604539b46SJoseph Chen 50704539b46SJoseph Chen if (IS_ERR(val)) 50804539b46SJoseph Chen return PTR_ERR(val); 50904539b46SJoseph Chen 51004539b46SJoseph Chen debug("size %zd\n", sz); 51104539b46SJoseph Chen while (sz--) 51204539b46SJoseph Chen *val++ = cpu_to_be32p(values++); 51304539b46SJoseph Chen 51404539b46SJoseph Chen return 0; 51504539b46SJoseph Chen } 51604539b46SJoseph Chen 517644ec0a9SSimon Glass int of_property_match_string(const struct device_node *np, const char *propname, 518644ec0a9SSimon Glass const char *string) 519644ec0a9SSimon Glass { 520644ec0a9SSimon Glass const struct property *prop = of_find_property(np, propname, NULL); 521644ec0a9SSimon Glass size_t l; 522644ec0a9SSimon Glass int i; 523644ec0a9SSimon Glass const char *p, *end; 524644ec0a9SSimon Glass 525644ec0a9SSimon Glass if (!prop) 526644ec0a9SSimon Glass return -EINVAL; 527644ec0a9SSimon Glass if (!prop->value) 528644ec0a9SSimon Glass return -ENODATA; 529644ec0a9SSimon Glass 530644ec0a9SSimon Glass p = prop->value; 531644ec0a9SSimon Glass end = p + prop->length; 532644ec0a9SSimon Glass 533644ec0a9SSimon Glass for (i = 0; p < end; i++, p += l) { 534644ec0a9SSimon Glass l = strnlen(p, end - p) + 1; 535644ec0a9SSimon Glass if (p + l > end) 536644ec0a9SSimon Glass return -EILSEQ; 537644ec0a9SSimon Glass debug("comparing %s with %s\n", string, p); 538644ec0a9SSimon Glass if (strcmp(string, p) == 0) 539644ec0a9SSimon Glass return i; /* Found it; return index */ 540644ec0a9SSimon Glass } 541644ec0a9SSimon Glass return -ENODATA; 542644ec0a9SSimon Glass } 543644ec0a9SSimon Glass 544644ec0a9SSimon Glass /** 545644ec0a9SSimon Glass * of_property_read_string_helper() - Utility helper for parsing string properties 546644ec0a9SSimon Glass * @np: device node from which the property value is to be read. 547644ec0a9SSimon Glass * @propname: name of the property to be searched. 548644ec0a9SSimon Glass * @out_strs: output array of string pointers. 549644ec0a9SSimon Glass * @sz: number of array elements to read. 550644ec0a9SSimon Glass * @skip: Number of strings to skip over at beginning of list. 551644ec0a9SSimon Glass * 552644ec0a9SSimon Glass * Don't call this function directly. It is a utility helper for the 553644ec0a9SSimon Glass * of_property_read_string*() family of functions. 554644ec0a9SSimon Glass */ 555644ec0a9SSimon Glass int of_property_read_string_helper(const struct device_node *np, 556644ec0a9SSimon Glass const char *propname, const char **out_strs, 557644ec0a9SSimon Glass size_t sz, int skip) 558644ec0a9SSimon Glass { 559644ec0a9SSimon Glass const struct property *prop = of_find_property(np, propname, NULL); 560644ec0a9SSimon Glass int l = 0, i = 0; 561644ec0a9SSimon Glass const char *p, *end; 562644ec0a9SSimon Glass 563644ec0a9SSimon Glass if (!prop) 564644ec0a9SSimon Glass return -EINVAL; 565644ec0a9SSimon Glass if (!prop->value) 566644ec0a9SSimon Glass return -ENODATA; 567644ec0a9SSimon Glass p = prop->value; 568644ec0a9SSimon Glass end = p + prop->length; 569644ec0a9SSimon Glass 570644ec0a9SSimon Glass for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 571644ec0a9SSimon Glass l = strnlen(p, end - p) + 1; 572644ec0a9SSimon Glass if (p + l > end) 573644ec0a9SSimon Glass return -EILSEQ; 574644ec0a9SSimon Glass if (out_strs && i >= skip) 575644ec0a9SSimon Glass *out_strs++ = p; 576644ec0a9SSimon Glass } 577644ec0a9SSimon Glass i -= skip; 578644ec0a9SSimon Glass return i <= 0 ? -ENODATA : i; 579644ec0a9SSimon Glass } 580644ec0a9SSimon Glass 581644ec0a9SSimon Glass static int __of_parse_phandle_with_args(const struct device_node *np, 582644ec0a9SSimon Glass const char *list_name, 583644ec0a9SSimon Glass const char *cells_name, 584644ec0a9SSimon Glass int cell_count, int index, 585644ec0a9SSimon Glass struct of_phandle_args *out_args) 586644ec0a9SSimon Glass { 587644ec0a9SSimon Glass const __be32 *list, *list_end; 588644ec0a9SSimon Glass int rc = 0, cur_index = 0; 589644ec0a9SSimon Glass uint32_t count = 0; 590644ec0a9SSimon Glass struct device_node *node = NULL; 591644ec0a9SSimon Glass phandle phandle; 592644ec0a9SSimon Glass int size; 593644ec0a9SSimon Glass 594644ec0a9SSimon Glass /* Retrieve the phandle list property */ 595644ec0a9SSimon Glass list = of_get_property(np, list_name, &size); 596644ec0a9SSimon Glass if (!list) 597644ec0a9SSimon Glass return -ENOENT; 598644ec0a9SSimon Glass list_end = list + size / sizeof(*list); 599644ec0a9SSimon Glass 600644ec0a9SSimon Glass /* Loop over the phandles until all the requested entry is found */ 601644ec0a9SSimon Glass while (list < list_end) { 602644ec0a9SSimon Glass rc = -EINVAL; 603644ec0a9SSimon Glass count = 0; 604644ec0a9SSimon Glass 605644ec0a9SSimon Glass /* 606644ec0a9SSimon Glass * If phandle is 0, then it is an empty entry with no 607644ec0a9SSimon Glass * arguments. Skip forward to the next entry. 608644ec0a9SSimon Glass */ 609644ec0a9SSimon Glass phandle = be32_to_cpup(list++); 610644ec0a9SSimon Glass if (phandle) { 611644ec0a9SSimon Glass /* 612644ec0a9SSimon Glass * Find the provider node and parse the #*-cells 613644ec0a9SSimon Glass * property to determine the argument length. 614644ec0a9SSimon Glass * 615644ec0a9SSimon Glass * This is not needed if the cell count is hard-coded 616644ec0a9SSimon Glass * (i.e. cells_name not set, but cell_count is set), 617644ec0a9SSimon Glass * except when we're going to return the found node 618644ec0a9SSimon Glass * below. 619644ec0a9SSimon Glass */ 620644ec0a9SSimon Glass if (cells_name || cur_index == index) { 621644ec0a9SSimon Glass node = of_find_node_by_phandle(phandle); 622644ec0a9SSimon Glass if (!node) { 623644ec0a9SSimon Glass debug("%s: could not find phandle\n", 624644ec0a9SSimon Glass np->full_name); 625644ec0a9SSimon Glass goto err; 626644ec0a9SSimon Glass } 627644ec0a9SSimon Glass } 628644ec0a9SSimon Glass 629644ec0a9SSimon Glass if (cells_name) { 630644ec0a9SSimon Glass if (of_read_u32(node, cells_name, &count)) { 631644ec0a9SSimon Glass debug("%s: could not get %s for %s\n", 632644ec0a9SSimon Glass np->full_name, cells_name, 633644ec0a9SSimon Glass node->full_name); 634644ec0a9SSimon Glass goto err; 635644ec0a9SSimon Glass } 636644ec0a9SSimon Glass } else { 637644ec0a9SSimon Glass count = cell_count; 638644ec0a9SSimon Glass } 639644ec0a9SSimon Glass 640644ec0a9SSimon Glass /* 641644ec0a9SSimon Glass * Make sure that the arguments actually fit in the 642644ec0a9SSimon Glass * remaining property data length 643644ec0a9SSimon Glass */ 644644ec0a9SSimon Glass if (list + count > list_end) { 645644ec0a9SSimon Glass debug("%s: arguments longer than property\n", 646644ec0a9SSimon Glass np->full_name); 647644ec0a9SSimon Glass goto err; 648644ec0a9SSimon Glass } 649644ec0a9SSimon Glass } 650644ec0a9SSimon Glass 651644ec0a9SSimon Glass /* 652644ec0a9SSimon Glass * All of the error cases above bail out of the loop, so at 653644ec0a9SSimon Glass * this point, the parsing is successful. If the requested 654644ec0a9SSimon Glass * index matches, then fill the out_args structure and return, 655644ec0a9SSimon Glass * or return -ENOENT for an empty entry. 656644ec0a9SSimon Glass */ 657644ec0a9SSimon Glass rc = -ENOENT; 658644ec0a9SSimon Glass if (cur_index == index) { 659644ec0a9SSimon Glass if (!phandle) 660644ec0a9SSimon Glass goto err; 661644ec0a9SSimon Glass 662644ec0a9SSimon Glass if (out_args) { 663644ec0a9SSimon Glass int i; 664644ec0a9SSimon Glass if (WARN_ON(count > OF_MAX_PHANDLE_ARGS)) 665644ec0a9SSimon Glass count = OF_MAX_PHANDLE_ARGS; 666644ec0a9SSimon Glass out_args->np = node; 667644ec0a9SSimon Glass out_args->args_count = count; 668644ec0a9SSimon Glass for (i = 0; i < count; i++) 669644ec0a9SSimon Glass out_args->args[i] = 670644ec0a9SSimon Glass be32_to_cpup(list++); 671644ec0a9SSimon Glass } else { 672644ec0a9SSimon Glass of_node_put(node); 673644ec0a9SSimon Glass } 674644ec0a9SSimon Glass 675644ec0a9SSimon Glass /* Found it! return success */ 676644ec0a9SSimon Glass return 0; 677644ec0a9SSimon Glass } 678644ec0a9SSimon Glass 679644ec0a9SSimon Glass of_node_put(node); 680644ec0a9SSimon Glass node = NULL; 681644ec0a9SSimon Glass list += count; 682644ec0a9SSimon Glass cur_index++; 683644ec0a9SSimon Glass } 684644ec0a9SSimon Glass 685644ec0a9SSimon Glass /* 686644ec0a9SSimon Glass * Unlock node before returning result; will be one of: 687644ec0a9SSimon Glass * -ENOENT : index is for empty phandle 688644ec0a9SSimon Glass * -EINVAL : parsing error on data 689644ec0a9SSimon Glass * [1..n] : Number of phandle (count mode; when index = -1) 690644ec0a9SSimon Glass */ 691644ec0a9SSimon Glass rc = index < 0 ? cur_index : -ENOENT; 692644ec0a9SSimon Glass err: 693644ec0a9SSimon Glass if (node) 694644ec0a9SSimon Glass of_node_put(node); 695644ec0a9SSimon Glass return rc; 696644ec0a9SSimon Glass } 697644ec0a9SSimon Glass 698644ec0a9SSimon Glass struct device_node *of_parse_phandle(const struct device_node *np, 699644ec0a9SSimon Glass const char *phandle_name, int index) 700644ec0a9SSimon Glass { 701644ec0a9SSimon Glass struct of_phandle_args args; 702644ec0a9SSimon Glass 703644ec0a9SSimon Glass if (index < 0) 704644ec0a9SSimon Glass return NULL; 705644ec0a9SSimon Glass 706644ec0a9SSimon Glass if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index, 707644ec0a9SSimon Glass &args)) 708644ec0a9SSimon Glass return NULL; 709644ec0a9SSimon Glass 710644ec0a9SSimon Glass return args.np; 711644ec0a9SSimon Glass } 712644ec0a9SSimon Glass 713644ec0a9SSimon Glass int of_parse_phandle_with_args(const struct device_node *np, 714644ec0a9SSimon Glass const char *list_name, const char *cells_name, 715644ec0a9SSimon Glass int index, struct of_phandle_args *out_args) 716644ec0a9SSimon Glass { 717644ec0a9SSimon Glass if (index < 0) 718644ec0a9SSimon Glass return -EINVAL; 719644ec0a9SSimon Glass 720644ec0a9SSimon Glass return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 721644ec0a9SSimon Glass index, out_args); 722644ec0a9SSimon Glass } 723644ec0a9SSimon Glass 724642346aeSPatrice Chotard int of_count_phandle_with_args(const struct device_node *np, 725642346aeSPatrice Chotard const char *list_name, const char *cells_name) 726642346aeSPatrice Chotard { 727642346aeSPatrice Chotard return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 728642346aeSPatrice Chotard -1, NULL); 729642346aeSPatrice Chotard } 730642346aeSPatrice Chotard 731644ec0a9SSimon Glass static void of_alias_add(struct alias_prop *ap, struct device_node *np, 732644ec0a9SSimon Glass int id, const char *stem, int stem_len) 733644ec0a9SSimon Glass { 734f935b6dcSJoseph Chen struct alias_prop *oldap; 735644ec0a9SSimon Glass ap->np = np; 736644ec0a9SSimon Glass ap->id = id; 737644ec0a9SSimon Glass strncpy(ap->stem, stem, stem_len); 738644ec0a9SSimon Glass ap->stem[stem_len] = 0; 739f935b6dcSJoseph Chen 740f935b6dcSJoseph Chen /* Delete U-Boot alias which is same with kernel */ 741f935b6dcSJoseph Chen mutex_lock(&of_mutex); 742f935b6dcSJoseph Chen list_for_each_entry(oldap, &aliases_lookup, link) { 743f935b6dcSJoseph Chen if (stem && !strcmp(stem, oldap->alias) && (id == oldap->id)) { 74433273e09SJoseph Chen /* Always use from U-Boot aliase */ 74533273e09SJoseph Chen if (strcmp(stem, "mmc")) 74633273e09SJoseph Chen continue; 74733273e09SJoseph Chen 748f935b6dcSJoseph Chen list_del(&oldap->link); 749f935b6dcSJoseph Chen break; 750f935b6dcSJoseph Chen } 751f935b6dcSJoseph Chen } 752f935b6dcSJoseph Chen mutex_unlock(&of_mutex); 753f935b6dcSJoseph Chen 754644ec0a9SSimon Glass list_add_tail(&ap->link, &aliases_lookup); 755644ec0a9SSimon Glass debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 756644ec0a9SSimon Glass ap->alias, ap->stem, ap->id, of_node_full_name(np)); 757644ec0a9SSimon Glass } 758644ec0a9SSimon Glass 759644ec0a9SSimon Glass int of_alias_scan(void) 760644ec0a9SSimon Glass { 761644ec0a9SSimon Glass struct property *pp; 762644ec0a9SSimon Glass 763644ec0a9SSimon Glass of_aliases = of_find_node_by_path("/aliases"); 764644ec0a9SSimon Glass of_chosen = of_find_node_by_path("/chosen"); 765644ec0a9SSimon Glass if (of_chosen == NULL) 766644ec0a9SSimon Glass of_chosen = of_find_node_by_path("/chosen@0"); 767644ec0a9SSimon Glass 768644ec0a9SSimon Glass if (of_chosen) { 769644ec0a9SSimon Glass const char *name; 770644ec0a9SSimon Glass 771644ec0a9SSimon Glass name = of_get_property(of_chosen, "stdout-path", NULL); 772644ec0a9SSimon Glass if (name) 773644ec0a9SSimon Glass of_stdout = of_find_node_opts_by_path(name, 774644ec0a9SSimon Glass &of_stdout_options); 775644ec0a9SSimon Glass } 776644ec0a9SSimon Glass 777644ec0a9SSimon Glass if (!of_aliases) 778644ec0a9SSimon Glass return 0; 779644ec0a9SSimon Glass 780644ec0a9SSimon Glass for_each_property_of_node(of_aliases, pp) { 781644ec0a9SSimon Glass const char *start = pp->name; 782644ec0a9SSimon Glass const char *end = start + strlen(start); 783644ec0a9SSimon Glass struct device_node *np; 784644ec0a9SSimon Glass struct alias_prop *ap; 785644ec0a9SSimon Glass ulong id; 786644ec0a9SSimon Glass int len; 787644ec0a9SSimon Glass 788644ec0a9SSimon Glass /* Skip those we do not want to proceed */ 789644ec0a9SSimon Glass if (!strcmp(pp->name, "name") || 790644ec0a9SSimon Glass !strcmp(pp->name, "phandle") || 791644ec0a9SSimon Glass !strcmp(pp->name, "linux,phandle")) 792644ec0a9SSimon Glass continue; 793644ec0a9SSimon Glass 794644ec0a9SSimon Glass np = of_find_node_by_path(pp->value); 795644ec0a9SSimon Glass if (!np) 796644ec0a9SSimon Glass continue; 797644ec0a9SSimon Glass 798644ec0a9SSimon Glass /* 799644ec0a9SSimon Glass * walk the alias backwards to extract the id and work out 800644ec0a9SSimon Glass * the 'stem' string 801644ec0a9SSimon Glass */ 802644ec0a9SSimon Glass while (isdigit(*(end-1)) && end > start) 803644ec0a9SSimon Glass end--; 804644ec0a9SSimon Glass len = end - start; 805644ec0a9SSimon Glass 806644ec0a9SSimon Glass if (strict_strtoul(end, 10, &id) < 0) 807644ec0a9SSimon Glass continue; 808644ec0a9SSimon Glass 809644ec0a9SSimon Glass /* Allocate an alias_prop with enough space for the stem */ 810644ec0a9SSimon Glass ap = malloc(sizeof(*ap) + len + 1); 811644ec0a9SSimon Glass if (!ap) 812644ec0a9SSimon Glass return -ENOMEM; 813644ec0a9SSimon Glass memset(ap, 0, sizeof(*ap) + len + 1); 814644ec0a9SSimon Glass ap->alias = start; 815644ec0a9SSimon Glass of_alias_add(ap, np, id, start, len); 816644ec0a9SSimon Glass } 817644ec0a9SSimon Glass 818644ec0a9SSimon Glass return 0; 819644ec0a9SSimon Glass } 820644ec0a9SSimon Glass 821644ec0a9SSimon Glass int of_alias_get_id(const struct device_node *np, const char *stem) 822644ec0a9SSimon Glass { 823644ec0a9SSimon Glass struct alias_prop *app; 824644ec0a9SSimon Glass int id = -ENODEV; 825644ec0a9SSimon Glass 826644ec0a9SSimon Glass mutex_lock(&of_mutex); 827644ec0a9SSimon Glass list_for_each_entry(app, &aliases_lookup, link) { 828644ec0a9SSimon Glass if (strcmp(app->stem, stem) != 0) 829644ec0a9SSimon Glass continue; 830644ec0a9SSimon Glass 831644ec0a9SSimon Glass if (np == app->np) { 832644ec0a9SSimon Glass id = app->id; 833644ec0a9SSimon Glass break; 834644ec0a9SSimon Glass } 835644ec0a9SSimon Glass } 836644ec0a9SSimon Glass mutex_unlock(&of_mutex); 837644ec0a9SSimon Glass 838644ec0a9SSimon Glass return id; 839644ec0a9SSimon Glass } 840644ec0a9SSimon Glass 8412e02c4e2SJoseph Chen struct device_node *of_alias_get_dev(const char *stem, int id) 8422e02c4e2SJoseph Chen { 8432e02c4e2SJoseph Chen struct alias_prop *app; 8442e02c4e2SJoseph Chen struct device_node *np = NULL; 8452e02c4e2SJoseph Chen 8462e02c4e2SJoseph Chen mutex_lock(&of_mutex); 8472e02c4e2SJoseph Chen list_for_each_entry(app, &aliases_lookup, link) { 8482e02c4e2SJoseph Chen if (strcmp(app->stem, stem) != 0) 8492e02c4e2SJoseph Chen continue; 8502e02c4e2SJoseph Chen 8512e02c4e2SJoseph Chen if (id == app->id) { 8522e02c4e2SJoseph Chen np = app->np; 8532e02c4e2SJoseph Chen break; 8542e02c4e2SJoseph Chen } 8552e02c4e2SJoseph Chen } 8562e02c4e2SJoseph Chen mutex_unlock(&of_mutex); 8572e02c4e2SJoseph Chen 8582e02c4e2SJoseph Chen return np; 8592e02c4e2SJoseph Chen } 8602e02c4e2SJoseph Chen 8612e02c4e2SJoseph Chen struct device_node *of_alias_dump(void) 8622e02c4e2SJoseph Chen { 8632e02c4e2SJoseph Chen struct alias_prop *app; 8642e02c4e2SJoseph Chen struct device_node *np = NULL; 8652e02c4e2SJoseph Chen 8662e02c4e2SJoseph Chen mutex_lock(&of_mutex); 8672e02c4e2SJoseph Chen list_for_each_entry(app, &aliases_lookup, link) { 868028a3c08SJoseph Chen printf("%10s%d: %20s, phandle=%d %4s\n", 8692e02c4e2SJoseph Chen app->stem, app->id, 870028a3c08SJoseph Chen app->np->full_name, app->np->phandle, 871028a3c08SJoseph Chen of_get_property(app->np, "u-boot,dm-pre-reloc", NULL) || 872028a3c08SJoseph Chen of_get_property(app->np, "u-boot,dm-spl", NULL) ? "*" : ""); 8732e02c4e2SJoseph Chen } 8742e02c4e2SJoseph Chen mutex_unlock(&of_mutex); 8752e02c4e2SJoseph Chen 8762e02c4e2SJoseph Chen return np; 8772e02c4e2SJoseph Chen } 8782e02c4e2SJoseph Chen 879644ec0a9SSimon Glass struct device_node *of_get_stdout(void) 880644ec0a9SSimon Glass { 881644ec0a9SSimon Glass return of_stdout; 882644ec0a9SSimon Glass } 883