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