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 91923f7e30SGrant Likely #if !defined(CONFIG_SPARC) /* SPARC doesn't do ref counting (yet) */ 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); 164923f7e30SGrant Likely #endif /* !CONFIG_SPARC */ 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); 176581b605aSStephen Rothwell for (pp = np->properties; pp != 0; pp = pp->next) { 177581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 178581b605aSStephen Rothwell if (lenp != 0) 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) { 5001e291b14SMichael Ellerman for (pp = np->properties; pp != 0; 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 /** 719739649c5SGrant Likely * of_parse_phandle - Resolve a phandle property to a device_node pointer 720739649c5SGrant Likely * @np: Pointer to device node holding phandle property 721739649c5SGrant Likely * @phandle_name: Name of property holding a phandle value 722739649c5SGrant Likely * @index: For properties holding a table of phandles, this is the index into 723739649c5SGrant Likely * the table 724739649c5SGrant Likely * 725739649c5SGrant Likely * Returns the device_node pointer with refcount incremented. Use 726739649c5SGrant Likely * of_node_put() on it when done. 727739649c5SGrant Likely */ 728739649c5SGrant Likely struct device_node * 729739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index) 730739649c5SGrant Likely { 7319a6b2e58SGrant Likely const __be32 *phandle; 732739649c5SGrant Likely int size; 733739649c5SGrant Likely 734739649c5SGrant Likely phandle = of_get_property(np, phandle_name, &size); 735739649c5SGrant Likely if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) 736739649c5SGrant Likely return NULL; 737739649c5SGrant Likely 7389a6b2e58SGrant Likely return of_find_node_by_phandle(be32_to_cpup(phandle + index)); 739739649c5SGrant Likely } 740739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle); 741739649c5SGrant Likely 742739649c5SGrant Likely /** 74364b60e09SAnton Vorontsov * of_parse_phandles_with_args - Find a node pointed by phandle in a list 74464b60e09SAnton Vorontsov * @np: pointer to a device tree node containing a list 74564b60e09SAnton Vorontsov * @list_name: property name that contains a list 74664b60e09SAnton Vorontsov * @cells_name: property name that specifies phandles' arguments count 74764b60e09SAnton Vorontsov * @index: index of a phandle to parse out 7487736a3dbSAnton Vorontsov * @out_node: optional pointer to device_node struct pointer (will be filled) 7497736a3dbSAnton Vorontsov * @out_args: optional pointer to arguments pointer (will be filled) 75064b60e09SAnton Vorontsov * 75164b60e09SAnton Vorontsov * This function is useful to parse lists of phandles and their arguments. 75264b60e09SAnton Vorontsov * Returns 0 on success and fills out_node and out_args, on error returns 75364b60e09SAnton Vorontsov * appropriate errno value. 75464b60e09SAnton Vorontsov * 75564b60e09SAnton Vorontsov * Example: 75664b60e09SAnton Vorontsov * 75764b60e09SAnton Vorontsov * phandle1: node1 { 75864b60e09SAnton Vorontsov * #list-cells = <2>; 75964b60e09SAnton Vorontsov * } 76064b60e09SAnton Vorontsov * 76164b60e09SAnton Vorontsov * phandle2: node2 { 76264b60e09SAnton Vorontsov * #list-cells = <1>; 76364b60e09SAnton Vorontsov * } 76464b60e09SAnton Vorontsov * 76564b60e09SAnton Vorontsov * node3 { 76664b60e09SAnton Vorontsov * list = <&phandle1 1 2 &phandle2 3>; 76764b60e09SAnton Vorontsov * } 76864b60e09SAnton Vorontsov * 76964b60e09SAnton Vorontsov * To get a device_node of the `node2' node you may call this: 77064b60e09SAnton Vorontsov * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args); 77164b60e09SAnton Vorontsov */ 77264b60e09SAnton Vorontsov int of_parse_phandles_with_args(struct device_node *np, const char *list_name, 77364b60e09SAnton Vorontsov const char *cells_name, int index, 77464b60e09SAnton Vorontsov struct device_node **out_node, 77564b60e09SAnton Vorontsov const void **out_args) 77664b60e09SAnton Vorontsov { 77764b60e09SAnton Vorontsov int ret = -EINVAL; 77833714881SJeremy Kerr const __be32 *list; 77933714881SJeremy Kerr const __be32 *list_end; 78064b60e09SAnton Vorontsov int size; 78164b60e09SAnton Vorontsov int cur_index = 0; 78264b60e09SAnton Vorontsov struct device_node *node = NULL; 7837736a3dbSAnton Vorontsov const void *args = NULL; 78464b60e09SAnton Vorontsov 78564b60e09SAnton Vorontsov list = of_get_property(np, list_name, &size); 78664b60e09SAnton Vorontsov if (!list) { 78764b60e09SAnton Vorontsov ret = -ENOENT; 78864b60e09SAnton Vorontsov goto err0; 78964b60e09SAnton Vorontsov } 79064b60e09SAnton Vorontsov list_end = list + size / sizeof(*list); 79164b60e09SAnton Vorontsov 79264b60e09SAnton Vorontsov while (list < list_end) { 79333714881SJeremy Kerr const __be32 *cells; 7949a6b2e58SGrant Likely phandle phandle; 79564b60e09SAnton Vorontsov 7969a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 797c1bb7c6dSAnton Vorontsov args = list; 79864b60e09SAnton Vorontsov 79964b60e09SAnton Vorontsov /* one cell hole in the list = <>; */ 8009a6b2e58SGrant Likely if (!phandle) 80164b60e09SAnton Vorontsov goto next; 80264b60e09SAnton Vorontsov 8039a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 80464b60e09SAnton Vorontsov if (!node) { 80564b60e09SAnton Vorontsov pr_debug("%s: could not find phandle\n", 80664b60e09SAnton Vorontsov np->full_name); 80764b60e09SAnton Vorontsov goto err0; 80864b60e09SAnton Vorontsov } 80964b60e09SAnton Vorontsov 81064b60e09SAnton Vorontsov cells = of_get_property(node, cells_name, &size); 81164b60e09SAnton Vorontsov if (!cells || size != sizeof(*cells)) { 81264b60e09SAnton Vorontsov pr_debug("%s: could not get %s for %s\n", 81364b60e09SAnton Vorontsov np->full_name, cells_name, node->full_name); 81464b60e09SAnton Vorontsov goto err1; 81564b60e09SAnton Vorontsov } 81664b60e09SAnton Vorontsov 81733714881SJeremy Kerr list += be32_to_cpup(cells); 81864b60e09SAnton Vorontsov if (list > list_end) { 81964b60e09SAnton Vorontsov pr_debug("%s: insufficient arguments length\n", 82064b60e09SAnton Vorontsov np->full_name); 82164b60e09SAnton Vorontsov goto err1; 82264b60e09SAnton Vorontsov } 82364b60e09SAnton Vorontsov next: 82464b60e09SAnton Vorontsov if (cur_index == index) 82564b60e09SAnton Vorontsov break; 82664b60e09SAnton Vorontsov 82764b60e09SAnton Vorontsov of_node_put(node); 82864b60e09SAnton Vorontsov node = NULL; 8297736a3dbSAnton Vorontsov args = NULL; 83064b60e09SAnton Vorontsov cur_index++; 83164b60e09SAnton Vorontsov } 83264b60e09SAnton Vorontsov 83364b60e09SAnton Vorontsov if (!node) { 8347736a3dbSAnton Vorontsov /* 8357736a3dbSAnton Vorontsov * args w/o node indicates that the loop above has stopped at 8367736a3dbSAnton Vorontsov * the 'hole' cell. Report this differently. 8377736a3dbSAnton Vorontsov */ 8387736a3dbSAnton Vorontsov if (args) 8397736a3dbSAnton Vorontsov ret = -EEXIST; 8407736a3dbSAnton Vorontsov else 84164b60e09SAnton Vorontsov ret = -ENOENT; 84264b60e09SAnton Vorontsov goto err0; 84364b60e09SAnton Vorontsov } 84464b60e09SAnton Vorontsov 8457736a3dbSAnton Vorontsov if (out_node) 84664b60e09SAnton Vorontsov *out_node = node; 8477736a3dbSAnton Vorontsov if (out_args) 84864b60e09SAnton Vorontsov *out_args = args; 84964b60e09SAnton Vorontsov 85064b60e09SAnton Vorontsov return 0; 85164b60e09SAnton Vorontsov err1: 85264b60e09SAnton Vorontsov of_node_put(node); 85364b60e09SAnton Vorontsov err0: 85464b60e09SAnton Vorontsov pr_debug("%s failed with status %d\n", __func__, ret); 85564b60e09SAnton Vorontsov return ret; 85664b60e09SAnton Vorontsov } 85764b60e09SAnton Vorontsov EXPORT_SYMBOL(of_parse_phandles_with_args); 85802af11b0SGrant Likely 85902af11b0SGrant Likely /** 86002af11b0SGrant Likely * prom_add_property - Add a property to a node 86102af11b0SGrant Likely */ 86202af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop) 86302af11b0SGrant Likely { 86402af11b0SGrant Likely struct property **next; 86502af11b0SGrant Likely unsigned long flags; 86602af11b0SGrant Likely 86702af11b0SGrant Likely prop->next = NULL; 86802af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 86902af11b0SGrant Likely next = &np->properties; 87002af11b0SGrant Likely while (*next) { 87102af11b0SGrant Likely if (strcmp(prop->name, (*next)->name) == 0) { 87202af11b0SGrant Likely /* duplicate ! don't insert it */ 87302af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 87402af11b0SGrant Likely return -1; 87502af11b0SGrant Likely } 87602af11b0SGrant Likely next = &(*next)->next; 87702af11b0SGrant Likely } 87802af11b0SGrant Likely *next = prop; 87902af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 88002af11b0SGrant Likely 88102af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 88202af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 88302af11b0SGrant Likely if (np->pde) 88402af11b0SGrant Likely proc_device_tree_add_prop(np->pde, prop); 88502af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 88602af11b0SGrant Likely 88702af11b0SGrant Likely return 0; 88802af11b0SGrant Likely } 88902af11b0SGrant Likely 89002af11b0SGrant Likely /** 89102af11b0SGrant Likely * prom_remove_property - Remove a property from a node. 89202af11b0SGrant Likely * 89302af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 89402af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 89502af11b0SGrant Likely * Instead we just move the property to the "dead properties" 89602af11b0SGrant Likely * list, so it won't be found any more. 89702af11b0SGrant Likely */ 89802af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop) 89902af11b0SGrant Likely { 90002af11b0SGrant Likely struct property **next; 90102af11b0SGrant Likely unsigned long flags; 90202af11b0SGrant Likely int found = 0; 90302af11b0SGrant Likely 90402af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 90502af11b0SGrant Likely next = &np->properties; 90602af11b0SGrant Likely while (*next) { 90702af11b0SGrant Likely if (*next == prop) { 90802af11b0SGrant Likely /* found the node */ 90902af11b0SGrant Likely *next = prop->next; 91002af11b0SGrant Likely prop->next = np->deadprops; 91102af11b0SGrant Likely np->deadprops = prop; 91202af11b0SGrant Likely found = 1; 91302af11b0SGrant Likely break; 91402af11b0SGrant Likely } 91502af11b0SGrant Likely next = &(*next)->next; 91602af11b0SGrant Likely } 91702af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 91802af11b0SGrant Likely 91902af11b0SGrant Likely if (!found) 92002af11b0SGrant Likely return -ENODEV; 92102af11b0SGrant Likely 92202af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 92302af11b0SGrant Likely /* try to remove the proc node as well */ 92402af11b0SGrant Likely if (np->pde) 92502af11b0SGrant Likely proc_device_tree_remove_prop(np->pde, prop); 92602af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 92702af11b0SGrant Likely 92802af11b0SGrant Likely return 0; 92902af11b0SGrant Likely } 93002af11b0SGrant Likely 93102af11b0SGrant Likely /* 93202af11b0SGrant Likely * prom_update_property - Update a property in a node. 93302af11b0SGrant Likely * 93402af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 93502af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 93602af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 93702af11b0SGrant Likely * and add the new property to the property list 93802af11b0SGrant Likely */ 93902af11b0SGrant Likely int prom_update_property(struct device_node *np, 94002af11b0SGrant Likely struct property *newprop, 94102af11b0SGrant Likely struct property *oldprop) 94202af11b0SGrant Likely { 94302af11b0SGrant Likely struct property **next; 94402af11b0SGrant Likely unsigned long flags; 94502af11b0SGrant Likely int found = 0; 94602af11b0SGrant Likely 94702af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 94802af11b0SGrant Likely next = &np->properties; 94902af11b0SGrant Likely while (*next) { 95002af11b0SGrant Likely if (*next == oldprop) { 95102af11b0SGrant Likely /* found the node */ 95202af11b0SGrant Likely newprop->next = oldprop->next; 95302af11b0SGrant Likely *next = newprop; 95402af11b0SGrant Likely oldprop->next = np->deadprops; 95502af11b0SGrant Likely np->deadprops = oldprop; 95602af11b0SGrant Likely found = 1; 95702af11b0SGrant Likely break; 95802af11b0SGrant Likely } 95902af11b0SGrant Likely next = &(*next)->next; 96002af11b0SGrant Likely } 96102af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 96202af11b0SGrant Likely 96302af11b0SGrant Likely if (!found) 96402af11b0SGrant Likely return -ENODEV; 96502af11b0SGrant Likely 96602af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 96702af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 96802af11b0SGrant Likely if (np->pde) 96902af11b0SGrant Likely proc_device_tree_update_prop(np->pde, newprop, oldprop); 97002af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 97102af11b0SGrant Likely 97202af11b0SGrant Likely return 0; 97302af11b0SGrant Likely } 974fcdeb7feSGrant Likely 975fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC) 976fcdeb7feSGrant Likely /* 977fcdeb7feSGrant Likely * Support for dynamic device trees. 978fcdeb7feSGrant Likely * 979fcdeb7feSGrant Likely * On some platforms, the device tree can be manipulated at runtime. 980fcdeb7feSGrant Likely * The routines in this section support adding, removing and changing 981fcdeb7feSGrant Likely * device tree nodes. 982fcdeb7feSGrant Likely */ 983fcdeb7feSGrant Likely 984fcdeb7feSGrant Likely /** 985fcdeb7feSGrant Likely * of_attach_node - Plug a device node into the tree and global list. 986fcdeb7feSGrant Likely */ 987fcdeb7feSGrant Likely void of_attach_node(struct device_node *np) 988fcdeb7feSGrant Likely { 989fcdeb7feSGrant Likely unsigned long flags; 990fcdeb7feSGrant Likely 991fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 992fcdeb7feSGrant Likely np->sibling = np->parent->child; 993fcdeb7feSGrant Likely np->allnext = allnodes; 994fcdeb7feSGrant Likely np->parent->child = np; 995fcdeb7feSGrant Likely allnodes = np; 996fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 997fcdeb7feSGrant Likely } 998fcdeb7feSGrant Likely 999fcdeb7feSGrant Likely /** 1000fcdeb7feSGrant Likely * of_detach_node - "Unplug" a node from the device tree. 1001fcdeb7feSGrant Likely * 1002fcdeb7feSGrant Likely * The caller must hold a reference to the node. The memory associated with 1003fcdeb7feSGrant Likely * the node is not freed until its refcount goes to zero. 1004fcdeb7feSGrant Likely */ 1005fcdeb7feSGrant Likely void of_detach_node(struct device_node *np) 1006fcdeb7feSGrant Likely { 1007fcdeb7feSGrant Likely struct device_node *parent; 1008fcdeb7feSGrant Likely unsigned long flags; 1009fcdeb7feSGrant Likely 1010fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 1011fcdeb7feSGrant Likely 1012fcdeb7feSGrant Likely parent = np->parent; 1013fcdeb7feSGrant Likely if (!parent) 1014fcdeb7feSGrant Likely goto out_unlock; 1015fcdeb7feSGrant Likely 1016fcdeb7feSGrant Likely if (allnodes == np) 1017fcdeb7feSGrant Likely allnodes = np->allnext; 1018fcdeb7feSGrant Likely else { 1019fcdeb7feSGrant Likely struct device_node *prev; 1020fcdeb7feSGrant Likely for (prev = allnodes; 1021fcdeb7feSGrant Likely prev->allnext != np; 1022fcdeb7feSGrant Likely prev = prev->allnext) 1023fcdeb7feSGrant Likely ; 1024fcdeb7feSGrant Likely prev->allnext = np->allnext; 1025fcdeb7feSGrant Likely } 1026fcdeb7feSGrant Likely 1027fcdeb7feSGrant Likely if (parent->child == np) 1028fcdeb7feSGrant Likely parent->child = np->sibling; 1029fcdeb7feSGrant Likely else { 1030fcdeb7feSGrant Likely struct device_node *prevsib; 1031fcdeb7feSGrant Likely for (prevsib = np->parent->child; 1032fcdeb7feSGrant Likely prevsib->sibling != np; 1033fcdeb7feSGrant Likely prevsib = prevsib->sibling) 1034fcdeb7feSGrant Likely ; 1035fcdeb7feSGrant Likely prevsib->sibling = np->sibling; 1036fcdeb7feSGrant Likely } 1037fcdeb7feSGrant Likely 1038fcdeb7feSGrant Likely of_node_set_flag(np, OF_DETACHED); 1039fcdeb7feSGrant Likely 1040fcdeb7feSGrant Likely out_unlock: 1041fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 1042fcdeb7feSGrant Likely } 1043fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */ 1044fcdeb7feSGrant Likely 1045611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1046611cad72SShawn Guo int id, const char *stem, int stem_len) 1047611cad72SShawn Guo { 1048611cad72SShawn Guo ap->np = np; 1049611cad72SShawn Guo ap->id = id; 1050611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1051611cad72SShawn Guo ap->stem[stem_len] = 0; 1052611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1053611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 1054611cad72SShawn Guo ap->alias, ap->stem, ap->id, np ? np->full_name : NULL); 1055611cad72SShawn Guo } 1056611cad72SShawn Guo 1057611cad72SShawn Guo /** 1058611cad72SShawn Guo * of_alias_scan - Scan all properties of 'aliases' node 1059611cad72SShawn Guo * 1060611cad72SShawn Guo * The function scans all the properties of 'aliases' node and populate 1061611cad72SShawn Guo * the the global lookup table with the properties. It returns the 1062611cad72SShawn Guo * number of alias_prop found, or error code in error case. 1063611cad72SShawn Guo * 1064611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 1065611cad72SShawn Guo * for the resulting tree 1066611cad72SShawn Guo */ 1067611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1068611cad72SShawn Guo { 1069611cad72SShawn Guo struct property *pp; 1070611cad72SShawn Guo 1071611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1072611cad72SShawn Guo if (of_chosen == NULL) 1073611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 1074611cad72SShawn Guo of_aliases = of_find_node_by_path("/aliases"); 1075611cad72SShawn Guo if (!of_aliases) 1076611cad72SShawn Guo return; 1077611cad72SShawn Guo 1078611cad72SShawn Guo for_each_property(pp, of_aliases->properties) { 1079611cad72SShawn Guo const char *start = pp->name; 1080611cad72SShawn Guo const char *end = start + strlen(start); 1081611cad72SShawn Guo struct device_node *np; 1082611cad72SShawn Guo struct alias_prop *ap; 1083611cad72SShawn Guo int id, len; 1084611cad72SShawn Guo 1085611cad72SShawn Guo /* Skip those we do not want to proceed */ 1086611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1087611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1088611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1089611cad72SShawn Guo continue; 1090611cad72SShawn Guo 1091611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1092611cad72SShawn Guo if (!np) 1093611cad72SShawn Guo continue; 1094611cad72SShawn Guo 1095611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1096611cad72SShawn Guo * the 'stem' string */ 1097611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1098611cad72SShawn Guo end--; 1099611cad72SShawn Guo len = end - start; 1100611cad72SShawn Guo 1101611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1102611cad72SShawn Guo continue; 1103611cad72SShawn Guo 1104611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1105611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1106611cad72SShawn Guo if (!ap) 1107611cad72SShawn Guo continue; 1108611cad72SShawn Guo ap->alias = start; 1109611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1110611cad72SShawn Guo } 1111611cad72SShawn Guo } 1112611cad72SShawn Guo 1113611cad72SShawn Guo /** 1114611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1115611cad72SShawn Guo * @np: Pointer to the given device_node 1116611cad72SShawn Guo * @stem: Alias stem of the given device_node 1117611cad72SShawn Guo * 1118611cad72SShawn Guo * The function travels the lookup table to get alias id for the given 1119611cad72SShawn Guo * device_node and alias stem. It returns the alias id if find it. 1120611cad72SShawn Guo */ 1121611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1122611cad72SShawn Guo { 1123611cad72SShawn Guo struct alias_prop *app; 1124611cad72SShawn Guo int id = -ENODEV; 1125611cad72SShawn Guo 1126611cad72SShawn Guo mutex_lock(&of_aliases_mutex); 1127611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1128611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1129611cad72SShawn Guo continue; 1130611cad72SShawn Guo 1131611cad72SShawn Guo if (np == app->np) { 1132611cad72SShawn Guo id = app->id; 1133611cad72SShawn Guo break; 1134611cad72SShawn Guo } 1135611cad72SShawn Guo } 1136611cad72SShawn Guo mutex_unlock(&of_aliases_mutex); 1137611cad72SShawn Guo 1138611cad72SShawn Guo return id; 1139611cad72SShawn Guo } 1140611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1141