197e873e5SStephen Rothwell /* 297e873e5SStephen Rothwell * Procedures for creating, accessing and interpreting the device tree. 397e873e5SStephen Rothwell * 497e873e5SStephen Rothwell * Paul Mackerras August 1996. 597e873e5SStephen Rothwell * Copyright (C) 1996-2005 Paul Mackerras. 697e873e5SStephen Rothwell * 797e873e5SStephen Rothwell * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 897e873e5SStephen Rothwell * {engebret|bergner}@us.ibm.com 997e873e5SStephen Rothwell * 1097e873e5SStephen Rothwell * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 1197e873e5SStephen Rothwell * 12e91edcf5SGrant Likely * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 13e91edcf5SGrant Likely * Grant Likely. 1497e873e5SStephen Rothwell * 1597e873e5SStephen Rothwell * This program is free software; you can redistribute it and/or 1697e873e5SStephen Rothwell * modify it under the terms of the GNU General Public License 1797e873e5SStephen Rothwell * as published by the Free Software Foundation; either version 1897e873e5SStephen Rothwell * 2 of the License, or (at your option) any later version. 1997e873e5SStephen Rothwell */ 20611cad72SShawn Guo #include <linux/ctype.h> 2197e873e5SStephen Rothwell #include <linux/module.h> 2297e873e5SStephen Rothwell #include <linux/of.h> 23581b605aSStephen Rothwell #include <linux/spinlock.h> 245a0e3ad6STejun Heo #include <linux/slab.h> 25a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 26581b605aSStephen Rothwell 27611cad72SShawn Guo /** 28611cad72SShawn Guo * struct alias_prop - Alias property in 'aliases' node 29611cad72SShawn Guo * @link: List node to link the structure in aliases_lookup list 30611cad72SShawn Guo * @alias: Alias property name 31611cad72SShawn Guo * @np: Pointer to device_node that the alias stands for 32611cad72SShawn Guo * @id: Index value from end of alias name 33611cad72SShawn Guo * @stem: Alias string without the index 34611cad72SShawn Guo * 35611cad72SShawn Guo * The structure represents one alias property of 'aliases' node as 36611cad72SShawn Guo * an entry in aliases_lookup list. 37611cad72SShawn Guo */ 38611cad72SShawn Guo struct alias_prop { 39611cad72SShawn Guo struct list_head link; 40611cad72SShawn Guo const char *alias; 41611cad72SShawn Guo struct device_node *np; 42611cad72SShawn Guo int id; 43611cad72SShawn Guo char stem[0]; 44611cad72SShawn Guo }; 45611cad72SShawn Guo 46611cad72SShawn Guo static LIST_HEAD(aliases_lookup); 47611cad72SShawn Guo 481ef4d424SStephen Rothwell struct device_node *allnodes; 49fc0bdae4SGrant Likely struct device_node *of_chosen; 50611cad72SShawn Guo struct device_node *of_aliases; 51611cad72SShawn Guo 52611cad72SShawn Guo static DEFINE_MUTEX(of_aliases_mutex); 531ef4d424SStephen Rothwell 54581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling, 55581b605aSStephen Rothwell * or parent members of struct device_node. 56581b605aSStephen Rothwell */ 57581b605aSStephen Rothwell DEFINE_RWLOCK(devtree_lock); 5897e873e5SStephen Rothwell 5997e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 6097e873e5SStephen Rothwell { 61a9fadeefSJeremy Kerr const __be32 *ip; 6297e873e5SStephen Rothwell 6397e873e5SStephen Rothwell do { 6497e873e5SStephen Rothwell if (np->parent) 6597e873e5SStephen Rothwell np = np->parent; 6697e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 6797e873e5SStephen Rothwell if (ip) 6833714881SJeremy Kerr return be32_to_cpup(ip); 6997e873e5SStephen Rothwell } while (np->parent); 7097e873e5SStephen Rothwell /* No #address-cells property for the root node */ 7197e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 7297e873e5SStephen Rothwell } 7397e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 7497e873e5SStephen Rothwell 7597e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 7697e873e5SStephen Rothwell { 77a9fadeefSJeremy Kerr const __be32 *ip; 7897e873e5SStephen Rothwell 7997e873e5SStephen Rothwell do { 8097e873e5SStephen Rothwell if (np->parent) 8197e873e5SStephen Rothwell np = np->parent; 8297e873e5SStephen Rothwell ip = of_get_property(np, "#size-cells", NULL); 8397e873e5SStephen Rothwell if (ip) 8433714881SJeremy Kerr return be32_to_cpup(ip); 8597e873e5SStephen Rothwell } while (np->parent); 8697e873e5SStephen Rothwell /* No #size-cells property for the root node */ 8797e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 8897e873e5SStephen Rothwell } 8997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 9097e873e5SStephen Rothwell 910f22dd39SGrant Likely #if defined(CONFIG_OF_DYNAMIC) 92923f7e30SGrant Likely /** 93923f7e30SGrant Likely * of_node_get - Increment refcount of a node 94923f7e30SGrant Likely * @node: Node to inc refcount, NULL is supported to 95923f7e30SGrant Likely * simplify writing of callers 96923f7e30SGrant Likely * 97923f7e30SGrant Likely * Returns node. 98923f7e30SGrant Likely */ 99923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node) 100923f7e30SGrant Likely { 101923f7e30SGrant Likely if (node) 102923f7e30SGrant Likely kref_get(&node->kref); 103923f7e30SGrant Likely return node; 104923f7e30SGrant Likely } 105923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get); 106923f7e30SGrant Likely 107923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref) 108923f7e30SGrant Likely { 109923f7e30SGrant Likely return container_of(kref, struct device_node, kref); 110923f7e30SGrant Likely } 111923f7e30SGrant Likely 112923f7e30SGrant Likely /** 113923f7e30SGrant Likely * of_node_release - release a dynamically allocated node 114923f7e30SGrant Likely * @kref: kref element of the node to be released 115923f7e30SGrant Likely * 116923f7e30SGrant Likely * In of_node_put() this function is passed to kref_put() 117923f7e30SGrant Likely * as the destructor. 118923f7e30SGrant Likely */ 119923f7e30SGrant Likely static void of_node_release(struct kref *kref) 120923f7e30SGrant Likely { 121923f7e30SGrant Likely struct device_node *node = kref_to_device_node(kref); 122923f7e30SGrant Likely struct property *prop = node->properties; 123923f7e30SGrant Likely 124923f7e30SGrant Likely /* We should never be releasing nodes that haven't been detached. */ 125923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DETACHED)) { 126923f7e30SGrant Likely pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); 127923f7e30SGrant Likely dump_stack(); 128923f7e30SGrant Likely kref_init(&node->kref); 129923f7e30SGrant Likely return; 130923f7e30SGrant Likely } 131923f7e30SGrant Likely 132923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DYNAMIC)) 133923f7e30SGrant Likely return; 134923f7e30SGrant Likely 135923f7e30SGrant Likely while (prop) { 136923f7e30SGrant Likely struct property *next = prop->next; 137923f7e30SGrant Likely kfree(prop->name); 138923f7e30SGrant Likely kfree(prop->value); 139923f7e30SGrant Likely kfree(prop); 140923f7e30SGrant Likely prop = next; 141923f7e30SGrant Likely 142923f7e30SGrant Likely if (!prop) { 143923f7e30SGrant Likely prop = node->deadprops; 144923f7e30SGrant Likely node->deadprops = NULL; 145923f7e30SGrant Likely } 146923f7e30SGrant Likely } 147923f7e30SGrant Likely kfree(node->full_name); 148923f7e30SGrant Likely kfree(node->data); 149923f7e30SGrant Likely kfree(node); 150923f7e30SGrant Likely } 151923f7e30SGrant Likely 152923f7e30SGrant Likely /** 153923f7e30SGrant Likely * of_node_put - Decrement refcount of a node 154923f7e30SGrant Likely * @node: Node to dec refcount, NULL is supported to 155923f7e30SGrant Likely * simplify writing of callers 156923f7e30SGrant Likely * 157923f7e30SGrant Likely */ 158923f7e30SGrant Likely void of_node_put(struct device_node *node) 159923f7e30SGrant Likely { 160923f7e30SGrant Likely if (node) 161923f7e30SGrant Likely kref_put(&node->kref, of_node_release); 162923f7e30SGrant Likely } 163923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put); 1640f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 165923f7e30SGrant Likely 166581b605aSStephen Rothwell struct property *of_find_property(const struct device_node *np, 167581b605aSStephen Rothwell const char *name, 168581b605aSStephen Rothwell int *lenp) 169581b605aSStephen Rothwell { 170581b605aSStephen Rothwell struct property *pp; 171581b605aSStephen Rothwell 17264e4566fSTimur Tabi if (!np) 17364e4566fSTimur Tabi return NULL; 17464e4566fSTimur Tabi 175581b605aSStephen Rothwell read_lock(&devtree_lock); 176a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 177581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 178a3a7cab1SSachin Kamat if (lenp) 179581b605aSStephen Rothwell *lenp = pp->length; 180581b605aSStephen Rothwell break; 181581b605aSStephen Rothwell } 182581b605aSStephen Rothwell } 183581b605aSStephen Rothwell read_unlock(&devtree_lock); 184581b605aSStephen Rothwell 185581b605aSStephen Rothwell return pp; 186581b605aSStephen Rothwell } 187581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 188581b605aSStephen Rothwell 189e91edcf5SGrant Likely /** 190e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 191e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 192e91edcf5SGrant Likely * of_node_put() will be called on it 193e91edcf5SGrant Likely * 194e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 195e91edcf5SGrant Likely * of_node_put() on it when done. 196e91edcf5SGrant Likely */ 197e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 198e91edcf5SGrant Likely { 199e91edcf5SGrant Likely struct device_node *np; 200e91edcf5SGrant Likely 201e91edcf5SGrant Likely read_lock(&devtree_lock); 202e91edcf5SGrant Likely np = prev ? prev->allnext : allnodes; 203e91edcf5SGrant Likely for (; np != NULL; np = np->allnext) 204e91edcf5SGrant Likely if (of_node_get(np)) 205e91edcf5SGrant Likely break; 206e91edcf5SGrant Likely of_node_put(prev); 207e91edcf5SGrant Likely read_unlock(&devtree_lock); 208e91edcf5SGrant Likely return np; 209e91edcf5SGrant Likely } 210e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 211e91edcf5SGrant Likely 21297e873e5SStephen Rothwell /* 21397e873e5SStephen Rothwell * Find a property with a given name for a given node 21497e873e5SStephen Rothwell * and return the value. 21597e873e5SStephen Rothwell */ 21697e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 21797e873e5SStephen Rothwell int *lenp) 21897e873e5SStephen Rothwell { 21997e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 22097e873e5SStephen Rothwell 22197e873e5SStephen Rothwell return pp ? pp->value : NULL; 22297e873e5SStephen Rothwell } 22397e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 2240081cbc3SStephen Rothwell 2250081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in 2260081cbc3SStephen Rothwell * the device's "compatible" property 2270081cbc3SStephen Rothwell */ 2280081cbc3SStephen Rothwell int of_device_is_compatible(const struct device_node *device, 2290081cbc3SStephen Rothwell const char *compat) 2300081cbc3SStephen Rothwell { 2310081cbc3SStephen Rothwell const char* cp; 2320081cbc3SStephen Rothwell int cplen, l; 2330081cbc3SStephen Rothwell 2340081cbc3SStephen Rothwell cp = of_get_property(device, "compatible", &cplen); 2350081cbc3SStephen Rothwell if (cp == NULL) 2360081cbc3SStephen Rothwell return 0; 2370081cbc3SStephen Rothwell while (cplen > 0) { 2380081cbc3SStephen Rothwell if (of_compat_cmp(cp, compat, strlen(compat)) == 0) 2390081cbc3SStephen Rothwell return 1; 2400081cbc3SStephen Rothwell l = strlen(cp) + 1; 2410081cbc3SStephen Rothwell cp += l; 2420081cbc3SStephen Rothwell cplen -= l; 2430081cbc3SStephen Rothwell } 2440081cbc3SStephen Rothwell 2450081cbc3SStephen Rothwell return 0; 2460081cbc3SStephen Rothwell } 2470081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 248e679c5f4SStephen Rothwell 249e679c5f4SStephen Rothwell /** 25071a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 2511f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 2521f43cfb9SGrant Likely * 2531f43cfb9SGrant Likely * Returns true if the root node has the given value in its 2541f43cfb9SGrant Likely * compatible property. 2551f43cfb9SGrant Likely */ 25671a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 2571f43cfb9SGrant Likely { 2581f43cfb9SGrant Likely struct device_node *root; 2591f43cfb9SGrant Likely int rc = 0; 2601f43cfb9SGrant Likely 2611f43cfb9SGrant Likely root = of_find_node_by_path("/"); 2621f43cfb9SGrant Likely if (root) { 2631f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 2641f43cfb9SGrant Likely of_node_put(root); 2651f43cfb9SGrant Likely } 2661f43cfb9SGrant Likely return rc; 2671f43cfb9SGrant Likely } 26871a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 2691f43cfb9SGrant Likely 2701f43cfb9SGrant Likely /** 271834d97d4SJosh Boyer * of_device_is_available - check if a device is available for use 272834d97d4SJosh Boyer * 273834d97d4SJosh Boyer * @device: Node to check for availability 274834d97d4SJosh Boyer * 275834d97d4SJosh Boyer * Returns 1 if the status property is absent or set to "okay" or "ok", 276834d97d4SJosh Boyer * 0 otherwise 277834d97d4SJosh Boyer */ 278834d97d4SJosh Boyer int of_device_is_available(const struct device_node *device) 279834d97d4SJosh Boyer { 280834d97d4SJosh Boyer const char *status; 281834d97d4SJosh Boyer int statlen; 282834d97d4SJosh Boyer 283834d97d4SJosh Boyer status = of_get_property(device, "status", &statlen); 284834d97d4SJosh Boyer if (status == NULL) 285834d97d4SJosh Boyer return 1; 286834d97d4SJosh Boyer 287834d97d4SJosh Boyer if (statlen > 0) { 288834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 289834d97d4SJosh Boyer return 1; 290834d97d4SJosh Boyer } 291834d97d4SJosh Boyer 292834d97d4SJosh Boyer return 0; 293834d97d4SJosh Boyer } 294834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 295834d97d4SJosh Boyer 296834d97d4SJosh Boyer /** 297e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 298e679c5f4SStephen Rothwell * @node: Node to get parent 299e679c5f4SStephen Rothwell * 300e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 301e679c5f4SStephen Rothwell * of_node_put() on it when done. 302e679c5f4SStephen Rothwell */ 303e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 304e679c5f4SStephen Rothwell { 305e679c5f4SStephen Rothwell struct device_node *np; 306e679c5f4SStephen Rothwell 307e679c5f4SStephen Rothwell if (!node) 308e679c5f4SStephen Rothwell return NULL; 309e679c5f4SStephen Rothwell 310e679c5f4SStephen Rothwell read_lock(&devtree_lock); 311e679c5f4SStephen Rothwell np = of_node_get(node->parent); 312e679c5f4SStephen Rothwell read_unlock(&devtree_lock); 313e679c5f4SStephen Rothwell return np; 314e679c5f4SStephen Rothwell } 315e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 316d1cd355aSStephen Rothwell 317d1cd355aSStephen Rothwell /** 318f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 319f4eb0107SMichael Ellerman * @node: Node to get parent of 320f4eb0107SMichael Ellerman * 321f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 322f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 323f4eb0107SMichael Ellerman * through a node's parents. 324f4eb0107SMichael Ellerman * 325f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 326f4eb0107SMichael Ellerman * of_node_put() on it when done. 327f4eb0107SMichael Ellerman */ 328f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 329f4eb0107SMichael Ellerman { 330f4eb0107SMichael Ellerman struct device_node *parent; 331f4eb0107SMichael Ellerman 332f4eb0107SMichael Ellerman if (!node) 333f4eb0107SMichael Ellerman return NULL; 334f4eb0107SMichael Ellerman 335f4eb0107SMichael Ellerman read_lock(&devtree_lock); 336f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 337f4eb0107SMichael Ellerman of_node_put(node); 338f4eb0107SMichael Ellerman read_unlock(&devtree_lock); 339f4eb0107SMichael Ellerman return parent; 340f4eb0107SMichael Ellerman } 341f4eb0107SMichael Ellerman 342f4eb0107SMichael Ellerman /** 343d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 344d1cd355aSStephen Rothwell * @node: parent node 345d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 346d1cd355aSStephen Rothwell * 347d1cd355aSStephen Rothwell * Returns a node pointer with refcount incremented, use 348d1cd355aSStephen Rothwell * of_node_put() on it when done. 349d1cd355aSStephen Rothwell */ 350d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 351d1cd355aSStephen Rothwell struct device_node *prev) 352d1cd355aSStephen Rothwell { 353d1cd355aSStephen Rothwell struct device_node *next; 354d1cd355aSStephen Rothwell 355d1cd355aSStephen Rothwell read_lock(&devtree_lock); 356d1cd355aSStephen Rothwell next = prev ? prev->sibling : node->child; 357d1cd355aSStephen Rothwell for (; next; next = next->sibling) 358d1cd355aSStephen Rothwell if (of_node_get(next)) 359d1cd355aSStephen Rothwell break; 360d1cd355aSStephen Rothwell of_node_put(prev); 361d1cd355aSStephen Rothwell read_unlock(&devtree_lock); 362d1cd355aSStephen Rothwell return next; 363d1cd355aSStephen Rothwell } 364d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 3651ef4d424SStephen Rothwell 3661ef4d424SStephen Rothwell /** 3671ef4d424SStephen Rothwell * of_find_node_by_path - Find a node matching a full OF path 3681ef4d424SStephen Rothwell * @path: The full path to match 3691ef4d424SStephen Rothwell * 3701ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 3711ef4d424SStephen Rothwell * of_node_put() on it when done. 3721ef4d424SStephen Rothwell */ 3731ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path) 3741ef4d424SStephen Rothwell { 3751ef4d424SStephen Rothwell struct device_node *np = allnodes; 3761ef4d424SStephen Rothwell 3771ef4d424SStephen Rothwell read_lock(&devtree_lock); 3781ef4d424SStephen Rothwell for (; np; np = np->allnext) { 3791ef4d424SStephen Rothwell if (np->full_name && (of_node_cmp(np->full_name, path) == 0) 3801ef4d424SStephen Rothwell && of_node_get(np)) 3811ef4d424SStephen Rothwell break; 3821ef4d424SStephen Rothwell } 3831ef4d424SStephen Rothwell read_unlock(&devtree_lock); 3841ef4d424SStephen Rothwell return np; 3851ef4d424SStephen Rothwell } 3861ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path); 3871ef4d424SStephen Rothwell 3881ef4d424SStephen Rothwell /** 3891ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 3901ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 3911ef4d424SStephen Rothwell * you pass will not be searched, only the next one 3921ef4d424SStephen Rothwell * will; typically, you pass what the previous call 3931ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 3941ef4d424SStephen Rothwell * @name: The name string to match against 3951ef4d424SStephen Rothwell * 3961ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 3971ef4d424SStephen Rothwell * of_node_put() on it when done. 3981ef4d424SStephen Rothwell */ 3991ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 4001ef4d424SStephen Rothwell const char *name) 4011ef4d424SStephen Rothwell { 4021ef4d424SStephen Rothwell struct device_node *np; 4031ef4d424SStephen Rothwell 4041ef4d424SStephen Rothwell read_lock(&devtree_lock); 4051ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 4061ef4d424SStephen Rothwell for (; np; np = np->allnext) 4071ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 4081ef4d424SStephen Rothwell && of_node_get(np)) 4091ef4d424SStephen Rothwell break; 4101ef4d424SStephen Rothwell of_node_put(from); 4111ef4d424SStephen Rothwell read_unlock(&devtree_lock); 4121ef4d424SStephen Rothwell return np; 4131ef4d424SStephen Rothwell } 4141ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 4151ef4d424SStephen Rothwell 4161ef4d424SStephen Rothwell /** 4171ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 4181ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 4191ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 4201ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 4211ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 4221ef4d424SStephen Rothwell * called on from for you. 4231ef4d424SStephen Rothwell * @type: The type string to match against 4241ef4d424SStephen Rothwell * 4251ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4261ef4d424SStephen Rothwell * of_node_put() on it when done. 4271ef4d424SStephen Rothwell */ 4281ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 4291ef4d424SStephen Rothwell const char *type) 4301ef4d424SStephen Rothwell { 4311ef4d424SStephen Rothwell struct device_node *np; 4321ef4d424SStephen Rothwell 4331ef4d424SStephen Rothwell read_lock(&devtree_lock); 4341ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 4351ef4d424SStephen Rothwell for (; np; np = np->allnext) 4361ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 4371ef4d424SStephen Rothwell && of_node_get(np)) 4381ef4d424SStephen Rothwell break; 4391ef4d424SStephen Rothwell of_node_put(from); 4401ef4d424SStephen Rothwell read_unlock(&devtree_lock); 4411ef4d424SStephen Rothwell return np; 4421ef4d424SStephen Rothwell } 4431ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 4441ef4d424SStephen Rothwell 4451ef4d424SStephen Rothwell /** 4461ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 4471ef4d424SStephen Rothwell * tokens in its "compatible" property 4481ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 4491ef4d424SStephen Rothwell * you pass will not be searched, only the next one 4501ef4d424SStephen Rothwell * will; typically, you pass what the previous call 4511ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 4521ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 4531ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 4541ef4d424SStephen Rothwell * "compatible" list. 4551ef4d424SStephen Rothwell * 4561ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4571ef4d424SStephen Rothwell * of_node_put() on it when done. 4581ef4d424SStephen Rothwell */ 4591ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 4601ef4d424SStephen Rothwell const char *type, const char *compatible) 4611ef4d424SStephen Rothwell { 4621ef4d424SStephen Rothwell struct device_node *np; 4631ef4d424SStephen Rothwell 4641ef4d424SStephen Rothwell read_lock(&devtree_lock); 4651ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 4661ef4d424SStephen Rothwell for (; np; np = np->allnext) { 4671ef4d424SStephen Rothwell if (type 4681ef4d424SStephen Rothwell && !(np->type && (of_node_cmp(np->type, type) == 0))) 4691ef4d424SStephen Rothwell continue; 4701ef4d424SStephen Rothwell if (of_device_is_compatible(np, compatible) && of_node_get(np)) 4711ef4d424SStephen Rothwell break; 4721ef4d424SStephen Rothwell } 4731ef4d424SStephen Rothwell of_node_put(from); 4741ef4d424SStephen Rothwell read_unlock(&devtree_lock); 4751ef4d424SStephen Rothwell return np; 4761ef4d424SStephen Rothwell } 4771ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 478283029d1SGrant Likely 479283029d1SGrant Likely /** 4801e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 4811e291b14SMichael Ellerman * the given name. 4821e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 4831e291b14SMichael Ellerman * you pass will not be searched, only the next one 4841e291b14SMichael Ellerman * will; typically, you pass what the previous call 4851e291b14SMichael Ellerman * returned. of_node_put() will be called on it 4861e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 4871e291b14SMichael Ellerman * 4881e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 4891e291b14SMichael Ellerman * of_node_put() on it when done. 4901e291b14SMichael Ellerman */ 4911e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 4921e291b14SMichael Ellerman const char *prop_name) 4931e291b14SMichael Ellerman { 4941e291b14SMichael Ellerman struct device_node *np; 4951e291b14SMichael Ellerman struct property *pp; 4961e291b14SMichael Ellerman 4971e291b14SMichael Ellerman read_lock(&devtree_lock); 4981e291b14SMichael Ellerman np = from ? from->allnext : allnodes; 4991e291b14SMichael Ellerman for (; np; np = np->allnext) { 500a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 5011e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 5021e291b14SMichael Ellerman of_node_get(np); 5031e291b14SMichael Ellerman goto out; 5041e291b14SMichael Ellerman } 5051e291b14SMichael Ellerman } 5061e291b14SMichael Ellerman } 5071e291b14SMichael Ellerman out: 5081e291b14SMichael Ellerman of_node_put(from); 5091e291b14SMichael Ellerman read_unlock(&devtree_lock); 5101e291b14SMichael Ellerman return np; 5111e291b14SMichael Ellerman } 5121e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 5131e291b14SMichael Ellerman 5141e291b14SMichael Ellerman /** 515283029d1SGrant Likely * of_match_node - Tell if an device_node has a matching of_match structure 516283029d1SGrant Likely * @matches: array of of device match structures to search in 517283029d1SGrant Likely * @node: the of device structure to match against 518283029d1SGrant Likely * 519283029d1SGrant Likely * Low level utility function used by device matching. 520283029d1SGrant Likely */ 521283029d1SGrant Likely const struct of_device_id *of_match_node(const struct of_device_id *matches, 522283029d1SGrant Likely const struct device_node *node) 523283029d1SGrant Likely { 524a52f07ecSGrant Likely if (!matches) 525a52f07ecSGrant Likely return NULL; 526a52f07ecSGrant Likely 527283029d1SGrant Likely while (matches->name[0] || matches->type[0] || matches->compatible[0]) { 528283029d1SGrant Likely int match = 1; 529283029d1SGrant Likely if (matches->name[0]) 530283029d1SGrant Likely match &= node->name 531283029d1SGrant Likely && !strcmp(matches->name, node->name); 532283029d1SGrant Likely if (matches->type[0]) 533283029d1SGrant Likely match &= node->type 534283029d1SGrant Likely && !strcmp(matches->type, node->type); 535283029d1SGrant Likely if (matches->compatible[0]) 536283029d1SGrant Likely match &= of_device_is_compatible(node, 537283029d1SGrant Likely matches->compatible); 538283029d1SGrant Likely if (match) 539283029d1SGrant Likely return matches; 540283029d1SGrant Likely matches++; 541283029d1SGrant Likely } 542283029d1SGrant Likely return NULL; 543283029d1SGrant Likely } 544283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 545283029d1SGrant Likely 546283029d1SGrant Likely /** 547283029d1SGrant Likely * of_find_matching_node - Find a node based on an of_device_id match 548283029d1SGrant Likely * table. 549283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 550283029d1SGrant Likely * you pass will not be searched, only the next one 551283029d1SGrant Likely * will; typically, you pass what the previous call 552283029d1SGrant Likely * returned. of_node_put() will be called on it 553283029d1SGrant Likely * @matches: array of of device match structures to search in 554283029d1SGrant Likely * 555283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 556283029d1SGrant Likely * of_node_put() on it when done. 557283029d1SGrant Likely */ 558283029d1SGrant Likely struct device_node *of_find_matching_node(struct device_node *from, 559283029d1SGrant Likely const struct of_device_id *matches) 560283029d1SGrant Likely { 561283029d1SGrant Likely struct device_node *np; 562283029d1SGrant Likely 563283029d1SGrant Likely read_lock(&devtree_lock); 564283029d1SGrant Likely np = from ? from->allnext : allnodes; 565283029d1SGrant Likely for (; np; np = np->allnext) { 566283029d1SGrant Likely if (of_match_node(matches, np) && of_node_get(np)) 567283029d1SGrant Likely break; 568283029d1SGrant Likely } 569283029d1SGrant Likely of_node_put(from); 570283029d1SGrant Likely read_unlock(&devtree_lock); 571283029d1SGrant Likely return np; 572283029d1SGrant Likely } 573283029d1SGrant Likely EXPORT_SYMBOL(of_find_matching_node); 5743f07af49SGrant Likely 5753f07af49SGrant Likely /** 5763f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 5773f07af49SGrant Likely * @node: pointer to a device tree node 5783f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 5793f07af49SGrant Likely * @len: Length of modalias value 5803f07af49SGrant Likely * 5812ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 5822ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 5832ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 5842ffe8c5fSGrant Likely * from the first entry in the compatible list property. 5853f07af49SGrant Likely * 5862ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 5873f07af49SGrant Likely */ 5883f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 5893f07af49SGrant Likely { 5902ffe8c5fSGrant Likely const char *compatible, *p; 5912ffe8c5fSGrant Likely int cplen; 5923f07af49SGrant Likely 5933f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 5942ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 5953f07af49SGrant Likely return -ENODEV; 5963f07af49SGrant Likely p = strchr(compatible, ','); 5972ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 5983f07af49SGrant Likely return 0; 5993f07af49SGrant Likely } 6003f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 6013f07af49SGrant Likely 60264b60e09SAnton Vorontsov /** 60389751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 60489751a7cSJeremy Kerr * @handle: phandle of the node to find 60589751a7cSJeremy Kerr * 60689751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 60789751a7cSJeremy Kerr * of_node_put() on it when done. 60889751a7cSJeremy Kerr */ 60989751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 61089751a7cSJeremy Kerr { 61189751a7cSJeremy Kerr struct device_node *np; 61289751a7cSJeremy Kerr 61389751a7cSJeremy Kerr read_lock(&devtree_lock); 61489751a7cSJeremy Kerr for (np = allnodes; np; np = np->allnext) 61589751a7cSJeremy Kerr if (np->phandle == handle) 61689751a7cSJeremy Kerr break; 61789751a7cSJeremy Kerr of_node_get(np); 61889751a7cSJeremy Kerr read_unlock(&devtree_lock); 61989751a7cSJeremy Kerr return np; 62089751a7cSJeremy Kerr } 62189751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 62289751a7cSJeremy Kerr 62389751a7cSJeremy Kerr /** 6240e373639SRob Herring * of_property_read_u32_array - Find and read an array of 32 bit integers 6250e373639SRob Herring * from a property. 6260e373639SRob Herring * 627a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 628a3b85363SThomas Abraham * @propname: name of the property to be searched. 629a3b85363SThomas Abraham * @out_value: pointer to return value, modified only if return value is 0. 630a3b85363SThomas Abraham * 6310e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 632a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 633a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 634a3b85363SThomas Abraham * property data isn't large enough. 635a3b85363SThomas Abraham * 636a3b85363SThomas Abraham * The out_value is modified only if a valid u32 value can be decoded. 637a3b85363SThomas Abraham */ 638aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np, 639aac285c6SJamie Iles const char *propname, u32 *out_values, 640aac285c6SJamie Iles size_t sz) 641a3b85363SThomas Abraham { 642a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 6430e373639SRob Herring const __be32 *val; 644a3b85363SThomas Abraham 645a3b85363SThomas Abraham if (!prop) 646a3b85363SThomas Abraham return -EINVAL; 647a3b85363SThomas Abraham if (!prop->value) 648a3b85363SThomas Abraham return -ENODATA; 6490e373639SRob Herring if ((sz * sizeof(*out_values)) > prop->length) 650a3b85363SThomas Abraham return -EOVERFLOW; 6510e373639SRob Herring 6520e373639SRob Herring val = prop->value; 6530e373639SRob Herring while (sz--) 6540e373639SRob Herring *out_values++ = be32_to_cpup(val++); 655a3b85363SThomas Abraham return 0; 656a3b85363SThomas Abraham } 6570e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array); 658a3b85363SThomas Abraham 659a3b85363SThomas Abraham /** 6604cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 6614cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 6624cd7f7a3SJamie Iles * @propname: name of the property to be searched. 6634cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 6644cd7f7a3SJamie Iles * 6654cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 6664cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 6674cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 6684cd7f7a3SJamie Iles * property data isn't large enough. 6694cd7f7a3SJamie Iles * 6704cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 6714cd7f7a3SJamie Iles */ 6724cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 6734cd7f7a3SJamie Iles u64 *out_value) 6744cd7f7a3SJamie Iles { 6754cd7f7a3SJamie Iles struct property *prop = of_find_property(np, propname, NULL); 6764cd7f7a3SJamie Iles 6774cd7f7a3SJamie Iles if (!prop) 6784cd7f7a3SJamie Iles return -EINVAL; 6794cd7f7a3SJamie Iles if (!prop->value) 6804cd7f7a3SJamie Iles return -ENODATA; 6814cd7f7a3SJamie Iles if (sizeof(*out_value) > prop->length) 6824cd7f7a3SJamie Iles return -EOVERFLOW; 6834cd7f7a3SJamie Iles *out_value = of_read_number(prop->value, 2); 6844cd7f7a3SJamie Iles return 0; 6854cd7f7a3SJamie Iles } 6864cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 6874cd7f7a3SJamie Iles 6884cd7f7a3SJamie Iles /** 689a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 690a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 691a3b85363SThomas Abraham * @propname: name of the property to be searched. 692a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 693a3b85363SThomas Abraham * return value is 0. 694a3b85363SThomas Abraham * 695a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 696a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 697a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 698a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 699a3b85363SThomas Abraham * within the length of the property data. 700a3b85363SThomas Abraham * 701a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 702a3b85363SThomas Abraham */ 703aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname, 704f09bc831SShawn Guo const char **out_string) 705a3b85363SThomas Abraham { 706a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 707a3b85363SThomas Abraham if (!prop) 708a3b85363SThomas Abraham return -EINVAL; 709a3b85363SThomas Abraham if (!prop->value) 710a3b85363SThomas Abraham return -ENODATA; 711a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 712a3b85363SThomas Abraham return -EILSEQ; 713a3b85363SThomas Abraham *out_string = prop->value; 714a3b85363SThomas Abraham return 0; 715a3b85363SThomas Abraham } 716a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 717a3b85363SThomas Abraham 718a3b85363SThomas Abraham /** 7194fcd15a0SBenoit Cousson * of_property_read_string_index - Find and read a string from a multiple 7204fcd15a0SBenoit Cousson * strings property. 7214fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 7224fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 7234fcd15a0SBenoit Cousson * @index: index of the string in the list of strings 7244fcd15a0SBenoit Cousson * @out_string: pointer to null terminated return string, modified only if 7254fcd15a0SBenoit Cousson * return value is 0. 7264fcd15a0SBenoit Cousson * 7274fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve a null 7284fcd15a0SBenoit Cousson * terminated string value (pointer to data, not a copy) in the list of strings 7294fcd15a0SBenoit Cousson * contained in that property. 7304fcd15a0SBenoit Cousson * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if 7314fcd15a0SBenoit Cousson * property does not have a value, and -EILSEQ if the string is not 7324fcd15a0SBenoit Cousson * null-terminated within the length of the property data. 7334fcd15a0SBenoit Cousson * 7344fcd15a0SBenoit Cousson * The out_string pointer is modified only if a valid string can be decoded. 7354fcd15a0SBenoit Cousson */ 7364fcd15a0SBenoit Cousson int of_property_read_string_index(struct device_node *np, const char *propname, 7374fcd15a0SBenoit Cousson int index, const char **output) 7384fcd15a0SBenoit Cousson { 7394fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 7404fcd15a0SBenoit Cousson int i = 0; 7414fcd15a0SBenoit Cousson size_t l = 0, total = 0; 7424fcd15a0SBenoit Cousson const char *p; 7434fcd15a0SBenoit Cousson 7444fcd15a0SBenoit Cousson if (!prop) 7454fcd15a0SBenoit Cousson return -EINVAL; 7464fcd15a0SBenoit Cousson if (!prop->value) 7474fcd15a0SBenoit Cousson return -ENODATA; 7484fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 7494fcd15a0SBenoit Cousson return -EILSEQ; 7504fcd15a0SBenoit Cousson 7514fcd15a0SBenoit Cousson p = prop->value; 7524fcd15a0SBenoit Cousson 7534fcd15a0SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l) { 7544fcd15a0SBenoit Cousson l = strlen(p) + 1; 75588af7f58SBenoit Cousson if (i++ == index) { 7564fcd15a0SBenoit Cousson *output = p; 7574fcd15a0SBenoit Cousson return 0; 7584fcd15a0SBenoit Cousson } 7594fcd15a0SBenoit Cousson } 7604fcd15a0SBenoit Cousson return -ENODATA; 7614fcd15a0SBenoit Cousson } 7624fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_read_string_index); 7634fcd15a0SBenoit Cousson 7647aff0fe3SGrant Likely /** 7657aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 7667aff0fe3SGrant Likely * @np: pointer to node containing string list property 7677aff0fe3SGrant Likely * @propname: string list property name 7687aff0fe3SGrant Likely * @string: pointer to string to search for in string list 7697aff0fe3SGrant Likely * 7707aff0fe3SGrant Likely * This function searches a string list property and returns the index 7717aff0fe3SGrant Likely * of a specific string value. 7727aff0fe3SGrant Likely */ 7737aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname, 7747aff0fe3SGrant Likely const char *string) 7757aff0fe3SGrant Likely { 7767aff0fe3SGrant Likely struct property *prop = of_find_property(np, propname, NULL); 7777aff0fe3SGrant Likely size_t l; 7787aff0fe3SGrant Likely int i; 7797aff0fe3SGrant Likely const char *p, *end; 7807aff0fe3SGrant Likely 7817aff0fe3SGrant Likely if (!prop) 7827aff0fe3SGrant Likely return -EINVAL; 7837aff0fe3SGrant Likely if (!prop->value) 7847aff0fe3SGrant Likely return -ENODATA; 7857aff0fe3SGrant Likely 7867aff0fe3SGrant Likely p = prop->value; 7877aff0fe3SGrant Likely end = p + prop->length; 7887aff0fe3SGrant Likely 7897aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 7907aff0fe3SGrant Likely l = strlen(p) + 1; 7917aff0fe3SGrant Likely if (p + l > end) 7927aff0fe3SGrant Likely return -EILSEQ; 7937aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 7947aff0fe3SGrant Likely if (strcmp(string, p) == 0) 7957aff0fe3SGrant Likely return i; /* Found it; return index */ 7967aff0fe3SGrant Likely } 7977aff0fe3SGrant Likely return -ENODATA; 7987aff0fe3SGrant Likely } 7997aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 8004fcd15a0SBenoit Cousson 8014fcd15a0SBenoit Cousson /** 8024fcd15a0SBenoit Cousson * of_property_count_strings - Find and return the number of strings from a 8034fcd15a0SBenoit Cousson * multiple strings property. 8044fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 8054fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 8064fcd15a0SBenoit Cousson * 8074fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve the number of null 8084fcd15a0SBenoit Cousson * terminated string contain in it. Returns the number of strings on 8094fcd15a0SBenoit Cousson * success, -EINVAL if the property does not exist, -ENODATA if property 8104fcd15a0SBenoit Cousson * does not have a value, and -EILSEQ if the string is not null-terminated 8114fcd15a0SBenoit Cousson * within the length of the property data. 8124fcd15a0SBenoit Cousson */ 8134fcd15a0SBenoit Cousson int of_property_count_strings(struct device_node *np, const char *propname) 8144fcd15a0SBenoit Cousson { 8154fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 8164fcd15a0SBenoit Cousson int i = 0; 8174fcd15a0SBenoit Cousson size_t l = 0, total = 0; 8184fcd15a0SBenoit Cousson const char *p; 8194fcd15a0SBenoit Cousson 8204fcd15a0SBenoit Cousson if (!prop) 8214fcd15a0SBenoit Cousson return -EINVAL; 8224fcd15a0SBenoit Cousson if (!prop->value) 8234fcd15a0SBenoit Cousson return -ENODATA; 8244fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 8254fcd15a0SBenoit Cousson return -EILSEQ; 8264fcd15a0SBenoit Cousson 8274fcd15a0SBenoit Cousson p = prop->value; 8284fcd15a0SBenoit Cousson 82988af7f58SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l, i++) 8304fcd15a0SBenoit Cousson l = strlen(p) + 1; 83188af7f58SBenoit Cousson 8324fcd15a0SBenoit Cousson return i; 8334fcd15a0SBenoit Cousson } 8344fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_count_strings); 8354fcd15a0SBenoit Cousson 8364fcd15a0SBenoit Cousson /** 837739649c5SGrant Likely * of_parse_phandle - Resolve a phandle property to a device_node pointer 838739649c5SGrant Likely * @np: Pointer to device node holding phandle property 839739649c5SGrant Likely * @phandle_name: Name of property holding a phandle value 840739649c5SGrant Likely * @index: For properties holding a table of phandles, this is the index into 841739649c5SGrant Likely * the table 842739649c5SGrant Likely * 843739649c5SGrant Likely * Returns the device_node pointer with refcount incremented. Use 844739649c5SGrant Likely * of_node_put() on it when done. 845739649c5SGrant Likely */ 846739649c5SGrant Likely struct device_node * 847739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index) 848739649c5SGrant Likely { 8499a6b2e58SGrant Likely const __be32 *phandle; 850739649c5SGrant Likely int size; 851739649c5SGrant Likely 852739649c5SGrant Likely phandle = of_get_property(np, phandle_name, &size); 853739649c5SGrant Likely if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) 854739649c5SGrant Likely return NULL; 855739649c5SGrant Likely 8569a6b2e58SGrant Likely return of_find_node_by_phandle(be32_to_cpup(phandle + index)); 857739649c5SGrant Likely } 858739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle); 859739649c5SGrant Likely 860739649c5SGrant Likely /** 86115c9a0acSGrant Likely * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 86264b60e09SAnton Vorontsov * @np: pointer to a device tree node containing a list 86364b60e09SAnton Vorontsov * @list_name: property name that contains a list 86464b60e09SAnton Vorontsov * @cells_name: property name that specifies phandles' arguments count 86564b60e09SAnton Vorontsov * @index: index of a phandle to parse out 86615c9a0acSGrant Likely * @out_args: optional pointer to output arguments structure (will be filled) 86764b60e09SAnton Vorontsov * 86864b60e09SAnton Vorontsov * This function is useful to parse lists of phandles and their arguments. 86915c9a0acSGrant Likely * Returns 0 on success and fills out_args, on error returns appropriate 87015c9a0acSGrant Likely * errno value. 87115c9a0acSGrant Likely * 87215c9a0acSGrant Likely * Caller is responsible to call of_node_put() on the returned out_args->node 87315c9a0acSGrant Likely * pointer. 87464b60e09SAnton Vorontsov * 87564b60e09SAnton Vorontsov * Example: 87664b60e09SAnton Vorontsov * 87764b60e09SAnton Vorontsov * phandle1: node1 { 87864b60e09SAnton Vorontsov * #list-cells = <2>; 87964b60e09SAnton Vorontsov * } 88064b60e09SAnton Vorontsov * 88164b60e09SAnton Vorontsov * phandle2: node2 { 88264b60e09SAnton Vorontsov * #list-cells = <1>; 88364b60e09SAnton Vorontsov * } 88464b60e09SAnton Vorontsov * 88564b60e09SAnton Vorontsov * node3 { 88664b60e09SAnton Vorontsov * list = <&phandle1 1 2 &phandle2 3>; 88764b60e09SAnton Vorontsov * } 88864b60e09SAnton Vorontsov * 88964b60e09SAnton Vorontsov * To get a device_node of the `node2' node you may call this: 89015c9a0acSGrant Likely * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 89164b60e09SAnton Vorontsov */ 89215c9a0acSGrant Likely int of_parse_phandle_with_args(struct device_node *np, const char *list_name, 89364b60e09SAnton Vorontsov const char *cells_name, int index, 89415c9a0acSGrant Likely struct of_phandle_args *out_args) 89564b60e09SAnton Vorontsov { 89615c9a0acSGrant Likely const __be32 *list, *list_end; 89715c9a0acSGrant Likely int size, cur_index = 0; 89815c9a0acSGrant Likely uint32_t count = 0; 89964b60e09SAnton Vorontsov struct device_node *node = NULL; 9009a6b2e58SGrant Likely phandle phandle; 90164b60e09SAnton Vorontsov 90215c9a0acSGrant Likely /* Retrieve the phandle list property */ 90315c9a0acSGrant Likely list = of_get_property(np, list_name, &size); 90415c9a0acSGrant Likely if (!list) 9051af4c7f1SAlexandre Courbot return -ENOENT; 90615c9a0acSGrant Likely list_end = list + size / sizeof(*list); 90715c9a0acSGrant Likely 90815c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 90915c9a0acSGrant Likely while (list < list_end) { 91015c9a0acSGrant Likely count = 0; 91115c9a0acSGrant Likely 91215c9a0acSGrant Likely /* 91315c9a0acSGrant Likely * If phandle is 0, then it is an empty entry with no 91415c9a0acSGrant Likely * arguments. Skip forward to the next entry. 91515c9a0acSGrant Likely */ 9169a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 91715c9a0acSGrant Likely if (phandle) { 91815c9a0acSGrant Likely /* 91915c9a0acSGrant Likely * Find the provider node and parse the #*-cells 92015c9a0acSGrant Likely * property to determine the argument length 92115c9a0acSGrant Likely */ 9229a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 92364b60e09SAnton Vorontsov if (!node) { 92415c9a0acSGrant Likely pr_err("%s: could not find phandle\n", 92564b60e09SAnton Vorontsov np->full_name); 92664b60e09SAnton Vorontsov break; 92715c9a0acSGrant Likely } 92815c9a0acSGrant Likely if (of_property_read_u32(node, cells_name, &count)) { 92915c9a0acSGrant Likely pr_err("%s: could not get %s for %s\n", 93015c9a0acSGrant Likely np->full_name, cells_name, 93115c9a0acSGrant Likely node->full_name); 93215c9a0acSGrant Likely break; 93315c9a0acSGrant Likely } 93415c9a0acSGrant Likely 93515c9a0acSGrant Likely /* 93615c9a0acSGrant Likely * Make sure that the arguments actually fit in the 93715c9a0acSGrant Likely * remaining property data length 93815c9a0acSGrant Likely */ 93915c9a0acSGrant Likely if (list + count > list_end) { 94015c9a0acSGrant Likely pr_err("%s: arguments longer than property\n", 94115c9a0acSGrant Likely np->full_name); 94215c9a0acSGrant Likely break; 94315c9a0acSGrant Likely } 94415c9a0acSGrant Likely } 94515c9a0acSGrant Likely 94615c9a0acSGrant Likely /* 94715c9a0acSGrant Likely * All of the error cases above bail out of the loop, so at 94815c9a0acSGrant Likely * this point, the parsing is successful. If the requested 94915c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 95015c9a0acSGrant Likely * or return -ENOENT for an empty entry. 95115c9a0acSGrant Likely */ 95215c9a0acSGrant Likely if (cur_index == index) { 95315c9a0acSGrant Likely if (!phandle) 95415c9a0acSGrant Likely return -ENOENT; 95515c9a0acSGrant Likely 95615c9a0acSGrant Likely if (out_args) { 95715c9a0acSGrant Likely int i; 95815c9a0acSGrant Likely if (WARN_ON(count > MAX_PHANDLE_ARGS)) 95915c9a0acSGrant Likely count = MAX_PHANDLE_ARGS; 96015c9a0acSGrant Likely out_args->np = node; 96115c9a0acSGrant Likely out_args->args_count = count; 96215c9a0acSGrant Likely for (i = 0; i < count; i++) 96315c9a0acSGrant Likely out_args->args[i] = be32_to_cpup(list++); 96415c9a0acSGrant Likely } 96515c9a0acSGrant Likely return 0; 96615c9a0acSGrant Likely } 96764b60e09SAnton Vorontsov 96864b60e09SAnton Vorontsov of_node_put(node); 96964b60e09SAnton Vorontsov node = NULL; 97015c9a0acSGrant Likely list += count; 97164b60e09SAnton Vorontsov cur_index++; 97264b60e09SAnton Vorontsov } 97364b60e09SAnton Vorontsov 97415c9a0acSGrant Likely /* Loop exited without finding a valid entry; return an error */ 97515c9a0acSGrant Likely if (node) 97664b60e09SAnton Vorontsov of_node_put(node); 97715c9a0acSGrant Likely return -EINVAL; 97864b60e09SAnton Vorontsov } 97915c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 98002af11b0SGrant Likely 98102af11b0SGrant Likely /** 98202af11b0SGrant Likely * prom_add_property - Add a property to a node 98302af11b0SGrant Likely */ 98402af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop) 98502af11b0SGrant Likely { 98602af11b0SGrant Likely struct property **next; 98702af11b0SGrant Likely unsigned long flags; 98802af11b0SGrant Likely 98902af11b0SGrant Likely prop->next = NULL; 99002af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 99102af11b0SGrant Likely next = &np->properties; 99202af11b0SGrant Likely while (*next) { 99302af11b0SGrant Likely if (strcmp(prop->name, (*next)->name) == 0) { 99402af11b0SGrant Likely /* duplicate ! don't insert it */ 99502af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 99602af11b0SGrant Likely return -1; 99702af11b0SGrant Likely } 99802af11b0SGrant Likely next = &(*next)->next; 99902af11b0SGrant Likely } 100002af11b0SGrant Likely *next = prop; 100102af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 100202af11b0SGrant Likely 100302af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 100402af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 100502af11b0SGrant Likely if (np->pde) 100602af11b0SGrant Likely proc_device_tree_add_prop(np->pde, prop); 100702af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 100802af11b0SGrant Likely 100902af11b0SGrant Likely return 0; 101002af11b0SGrant Likely } 101102af11b0SGrant Likely 101202af11b0SGrant Likely /** 101302af11b0SGrant Likely * prom_remove_property - Remove a property from a node. 101402af11b0SGrant Likely * 101502af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 101602af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 101702af11b0SGrant Likely * Instead we just move the property to the "dead properties" 101802af11b0SGrant Likely * list, so it won't be found any more. 101902af11b0SGrant Likely */ 102002af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop) 102102af11b0SGrant Likely { 102202af11b0SGrant Likely struct property **next; 102302af11b0SGrant Likely unsigned long flags; 102402af11b0SGrant Likely int found = 0; 102502af11b0SGrant Likely 102602af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 102702af11b0SGrant Likely next = &np->properties; 102802af11b0SGrant Likely while (*next) { 102902af11b0SGrant Likely if (*next == prop) { 103002af11b0SGrant Likely /* found the node */ 103102af11b0SGrant Likely *next = prop->next; 103202af11b0SGrant Likely prop->next = np->deadprops; 103302af11b0SGrant Likely np->deadprops = prop; 103402af11b0SGrant Likely found = 1; 103502af11b0SGrant Likely break; 103602af11b0SGrant Likely } 103702af11b0SGrant Likely next = &(*next)->next; 103802af11b0SGrant Likely } 103902af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 104002af11b0SGrant Likely 104102af11b0SGrant Likely if (!found) 104202af11b0SGrant Likely return -ENODEV; 104302af11b0SGrant Likely 104402af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 104502af11b0SGrant Likely /* try to remove the proc node as well */ 104602af11b0SGrant Likely if (np->pde) 104702af11b0SGrant Likely proc_device_tree_remove_prop(np->pde, prop); 104802af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 104902af11b0SGrant Likely 105002af11b0SGrant Likely return 0; 105102af11b0SGrant Likely } 105202af11b0SGrant Likely 105302af11b0SGrant Likely /* 105402af11b0SGrant Likely * prom_update_property - Update a property in a node. 105502af11b0SGrant Likely * 105602af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 105702af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 105802af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 105902af11b0SGrant Likely * and add the new property to the property list 106002af11b0SGrant Likely */ 106102af11b0SGrant Likely int prom_update_property(struct device_node *np, 106202af11b0SGrant Likely struct property *newprop, 106302af11b0SGrant Likely struct property *oldprop) 106402af11b0SGrant Likely { 106502af11b0SGrant Likely struct property **next; 106602af11b0SGrant Likely unsigned long flags; 106702af11b0SGrant Likely int found = 0; 106802af11b0SGrant Likely 106902af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 107002af11b0SGrant Likely next = &np->properties; 107102af11b0SGrant Likely while (*next) { 107202af11b0SGrant Likely if (*next == oldprop) { 107302af11b0SGrant Likely /* found the node */ 107402af11b0SGrant Likely newprop->next = oldprop->next; 107502af11b0SGrant Likely *next = newprop; 107602af11b0SGrant Likely oldprop->next = np->deadprops; 107702af11b0SGrant Likely np->deadprops = oldprop; 107802af11b0SGrant Likely found = 1; 107902af11b0SGrant Likely break; 108002af11b0SGrant Likely } 108102af11b0SGrant Likely next = &(*next)->next; 108202af11b0SGrant Likely } 108302af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 108402af11b0SGrant Likely 108502af11b0SGrant Likely if (!found) 108602af11b0SGrant Likely return -ENODEV; 108702af11b0SGrant Likely 108802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 108902af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 109002af11b0SGrant Likely if (np->pde) 109102af11b0SGrant Likely proc_device_tree_update_prop(np->pde, newprop, oldprop); 109202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 109302af11b0SGrant Likely 109402af11b0SGrant Likely return 0; 109502af11b0SGrant Likely } 1096fcdeb7feSGrant Likely 1097fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC) 1098fcdeb7feSGrant Likely /* 1099fcdeb7feSGrant Likely * Support for dynamic device trees. 1100fcdeb7feSGrant Likely * 1101fcdeb7feSGrant Likely * On some platforms, the device tree can be manipulated at runtime. 1102fcdeb7feSGrant Likely * The routines in this section support adding, removing and changing 1103fcdeb7feSGrant Likely * device tree nodes. 1104fcdeb7feSGrant Likely */ 1105fcdeb7feSGrant Likely 1106fcdeb7feSGrant Likely /** 1107fcdeb7feSGrant Likely * of_attach_node - Plug a device node into the tree and global list. 1108fcdeb7feSGrant Likely */ 1109fcdeb7feSGrant Likely void of_attach_node(struct device_node *np) 1110fcdeb7feSGrant Likely { 1111fcdeb7feSGrant Likely unsigned long flags; 1112fcdeb7feSGrant Likely 1113fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 1114fcdeb7feSGrant Likely np->sibling = np->parent->child; 1115fcdeb7feSGrant Likely np->allnext = allnodes; 1116fcdeb7feSGrant Likely np->parent->child = np; 1117fcdeb7feSGrant Likely allnodes = np; 1118fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 1119fcdeb7feSGrant Likely } 1120fcdeb7feSGrant Likely 1121fcdeb7feSGrant Likely /** 1122fcdeb7feSGrant Likely * of_detach_node - "Unplug" a node from the device tree. 1123fcdeb7feSGrant Likely * 1124fcdeb7feSGrant Likely * The caller must hold a reference to the node. The memory associated with 1125fcdeb7feSGrant Likely * the node is not freed until its refcount goes to zero. 1126fcdeb7feSGrant Likely */ 1127fcdeb7feSGrant Likely void of_detach_node(struct device_node *np) 1128fcdeb7feSGrant Likely { 1129fcdeb7feSGrant Likely struct device_node *parent; 1130fcdeb7feSGrant Likely unsigned long flags; 1131fcdeb7feSGrant Likely 1132fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 1133fcdeb7feSGrant Likely 1134fcdeb7feSGrant Likely parent = np->parent; 1135fcdeb7feSGrant Likely if (!parent) 1136fcdeb7feSGrant Likely goto out_unlock; 1137fcdeb7feSGrant Likely 1138fcdeb7feSGrant Likely if (allnodes == np) 1139fcdeb7feSGrant Likely allnodes = np->allnext; 1140fcdeb7feSGrant Likely else { 1141fcdeb7feSGrant Likely struct device_node *prev; 1142fcdeb7feSGrant Likely for (prev = allnodes; 1143fcdeb7feSGrant Likely prev->allnext != np; 1144fcdeb7feSGrant Likely prev = prev->allnext) 1145fcdeb7feSGrant Likely ; 1146fcdeb7feSGrant Likely prev->allnext = np->allnext; 1147fcdeb7feSGrant Likely } 1148fcdeb7feSGrant Likely 1149fcdeb7feSGrant Likely if (parent->child == np) 1150fcdeb7feSGrant Likely parent->child = np->sibling; 1151fcdeb7feSGrant Likely else { 1152fcdeb7feSGrant Likely struct device_node *prevsib; 1153fcdeb7feSGrant Likely for (prevsib = np->parent->child; 1154fcdeb7feSGrant Likely prevsib->sibling != np; 1155fcdeb7feSGrant Likely prevsib = prevsib->sibling) 1156fcdeb7feSGrant Likely ; 1157fcdeb7feSGrant Likely prevsib->sibling = np->sibling; 1158fcdeb7feSGrant Likely } 1159fcdeb7feSGrant Likely 1160fcdeb7feSGrant Likely of_node_set_flag(np, OF_DETACHED); 1161fcdeb7feSGrant Likely 1162fcdeb7feSGrant Likely out_unlock: 1163fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 1164fcdeb7feSGrant Likely } 1165fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */ 1166fcdeb7feSGrant Likely 1167611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1168611cad72SShawn Guo int id, const char *stem, int stem_len) 1169611cad72SShawn Guo { 1170611cad72SShawn Guo ap->np = np; 1171611cad72SShawn Guo ap->id = id; 1172611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1173611cad72SShawn Guo ap->stem[stem_len] = 0; 1174611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1175611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 117674a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 1177611cad72SShawn Guo } 1178611cad72SShawn Guo 1179611cad72SShawn Guo /** 1180611cad72SShawn Guo * of_alias_scan - Scan all properties of 'aliases' node 1181611cad72SShawn Guo * 1182611cad72SShawn Guo * The function scans all the properties of 'aliases' node and populate 1183611cad72SShawn Guo * the the global lookup table with the properties. It returns the 1184611cad72SShawn Guo * number of alias_prop found, or error code in error case. 1185611cad72SShawn Guo * 1186611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 1187611cad72SShawn Guo * for the resulting tree 1188611cad72SShawn Guo */ 1189611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1190611cad72SShawn Guo { 1191611cad72SShawn Guo struct property *pp; 1192611cad72SShawn Guo 1193611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1194611cad72SShawn Guo if (of_chosen == NULL) 1195611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 1196611cad72SShawn Guo of_aliases = of_find_node_by_path("/aliases"); 1197611cad72SShawn Guo if (!of_aliases) 1198611cad72SShawn Guo return; 1199611cad72SShawn Guo 12008af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1201611cad72SShawn Guo const char *start = pp->name; 1202611cad72SShawn Guo const char *end = start + strlen(start); 1203611cad72SShawn Guo struct device_node *np; 1204611cad72SShawn Guo struct alias_prop *ap; 1205611cad72SShawn Guo int id, len; 1206611cad72SShawn Guo 1207611cad72SShawn Guo /* Skip those we do not want to proceed */ 1208611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1209611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1210611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1211611cad72SShawn Guo continue; 1212611cad72SShawn Guo 1213611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1214611cad72SShawn Guo if (!np) 1215611cad72SShawn Guo continue; 1216611cad72SShawn Guo 1217611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1218611cad72SShawn Guo * the 'stem' string */ 1219611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1220611cad72SShawn Guo end--; 1221611cad72SShawn Guo len = end - start; 1222611cad72SShawn Guo 1223611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1224611cad72SShawn Guo continue; 1225611cad72SShawn Guo 1226611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1227611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1228611cad72SShawn Guo if (!ap) 1229611cad72SShawn Guo continue; 1230611cad72SShawn Guo ap->alias = start; 1231611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1232611cad72SShawn Guo } 1233611cad72SShawn Guo } 1234611cad72SShawn Guo 1235611cad72SShawn Guo /** 1236611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1237611cad72SShawn Guo * @np: Pointer to the given device_node 1238611cad72SShawn Guo * @stem: Alias stem of the given device_node 1239611cad72SShawn Guo * 1240611cad72SShawn Guo * The function travels the lookup table to get alias id for the given 1241611cad72SShawn Guo * device_node and alias stem. It returns the alias id if find it. 1242611cad72SShawn Guo */ 1243611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1244611cad72SShawn Guo { 1245611cad72SShawn Guo struct alias_prop *app; 1246611cad72SShawn Guo int id = -ENODEV; 1247611cad72SShawn Guo 1248611cad72SShawn Guo mutex_lock(&of_aliases_mutex); 1249611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1250611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1251611cad72SShawn Guo continue; 1252611cad72SShawn Guo 1253611cad72SShawn Guo if (np == app->np) { 1254611cad72SShawn Guo id = app->id; 1255611cad72SShawn Guo break; 1256611cad72SShawn Guo } 1257611cad72SShawn Guo } 1258611cad72SShawn Guo mutex_unlock(&of_aliases_mutex); 1259611cad72SShawn Guo 1260611cad72SShawn Guo return id; 1261611cad72SShawn Guo } 1262611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1263c541adc6SStephen Warren 1264c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 1265c541adc6SStephen Warren u32 *pu) 1266c541adc6SStephen Warren { 1267c541adc6SStephen Warren const void *curv = cur; 1268c541adc6SStephen Warren 1269c541adc6SStephen Warren if (!prop) 1270c541adc6SStephen Warren return NULL; 1271c541adc6SStephen Warren 1272c541adc6SStephen Warren if (!cur) { 1273c541adc6SStephen Warren curv = prop->value; 1274c541adc6SStephen Warren goto out_val; 1275c541adc6SStephen Warren } 1276c541adc6SStephen Warren 1277c541adc6SStephen Warren curv += sizeof(*cur); 1278c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1279c541adc6SStephen Warren return NULL; 1280c541adc6SStephen Warren 1281c541adc6SStephen Warren out_val: 1282c541adc6SStephen Warren *pu = be32_to_cpup(curv); 1283c541adc6SStephen Warren return curv; 1284c541adc6SStephen Warren } 1285c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 1286c541adc6SStephen Warren 1287c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 1288c541adc6SStephen Warren { 1289c541adc6SStephen Warren const void *curv = cur; 1290c541adc6SStephen Warren 1291c541adc6SStephen Warren if (!prop) 1292c541adc6SStephen Warren return NULL; 1293c541adc6SStephen Warren 1294c541adc6SStephen Warren if (!cur) 1295c541adc6SStephen Warren return prop->value; 1296c541adc6SStephen Warren 1297c541adc6SStephen Warren curv += strlen(cur) + 1; 1298c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1299c541adc6SStephen Warren return NULL; 1300c541adc6SStephen Warren 1301c541adc6SStephen Warren return curv; 1302c541adc6SStephen Warren } 1303c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 1304