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 */ 2097e873e5SStephen Rothwell #include <linux/module.h> 2197e873e5SStephen Rothwell #include <linux/of.h> 22581b605aSStephen Rothwell #include <linux/spinlock.h> 235a0e3ad6STejun Heo #include <linux/slab.h> 24a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 25581b605aSStephen Rothwell 261ef4d424SStephen Rothwell struct device_node *allnodes; 27fc0bdae4SGrant Likely struct device_node *of_chosen; 281ef4d424SStephen Rothwell 29581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling, 30581b605aSStephen Rothwell * or parent members of struct device_node. 31581b605aSStephen Rothwell */ 32581b605aSStephen Rothwell DEFINE_RWLOCK(devtree_lock); 3397e873e5SStephen Rothwell 3497e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 3597e873e5SStephen Rothwell { 36a9fadeefSJeremy Kerr const __be32 *ip; 3797e873e5SStephen Rothwell 3897e873e5SStephen Rothwell do { 3997e873e5SStephen Rothwell if (np->parent) 4097e873e5SStephen Rothwell np = np->parent; 4197e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 4297e873e5SStephen Rothwell if (ip) 4333714881SJeremy Kerr return be32_to_cpup(ip); 4497e873e5SStephen Rothwell } while (np->parent); 4597e873e5SStephen Rothwell /* No #address-cells property for the root node */ 4697e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 4797e873e5SStephen Rothwell } 4897e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 4997e873e5SStephen Rothwell 5097e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 5197e873e5SStephen Rothwell { 52a9fadeefSJeremy Kerr const __be32 *ip; 5397e873e5SStephen Rothwell 5497e873e5SStephen Rothwell do { 5597e873e5SStephen Rothwell if (np->parent) 5697e873e5SStephen Rothwell np = np->parent; 5797e873e5SStephen Rothwell ip = of_get_property(np, "#size-cells", NULL); 5897e873e5SStephen Rothwell if (ip) 5933714881SJeremy Kerr return be32_to_cpup(ip); 6097e873e5SStephen Rothwell } while (np->parent); 6197e873e5SStephen Rothwell /* No #size-cells property for the root node */ 6297e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 6397e873e5SStephen Rothwell } 6497e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 6597e873e5SStephen Rothwell 66923f7e30SGrant Likely #if !defined(CONFIG_SPARC) /* SPARC doesn't do ref counting (yet) */ 67923f7e30SGrant Likely /** 68923f7e30SGrant Likely * of_node_get - Increment refcount of a node 69923f7e30SGrant Likely * @node: Node to inc refcount, NULL is supported to 70923f7e30SGrant Likely * simplify writing of callers 71923f7e30SGrant Likely * 72923f7e30SGrant Likely * Returns node. 73923f7e30SGrant Likely */ 74923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node) 75923f7e30SGrant Likely { 76923f7e30SGrant Likely if (node) 77923f7e30SGrant Likely kref_get(&node->kref); 78923f7e30SGrant Likely return node; 79923f7e30SGrant Likely } 80923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get); 81923f7e30SGrant Likely 82923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref) 83923f7e30SGrant Likely { 84923f7e30SGrant Likely return container_of(kref, struct device_node, kref); 85923f7e30SGrant Likely } 86923f7e30SGrant Likely 87923f7e30SGrant Likely /** 88923f7e30SGrant Likely * of_node_release - release a dynamically allocated node 89923f7e30SGrant Likely * @kref: kref element of the node to be released 90923f7e30SGrant Likely * 91923f7e30SGrant Likely * In of_node_put() this function is passed to kref_put() 92923f7e30SGrant Likely * as the destructor. 93923f7e30SGrant Likely */ 94923f7e30SGrant Likely static void of_node_release(struct kref *kref) 95923f7e30SGrant Likely { 96923f7e30SGrant Likely struct device_node *node = kref_to_device_node(kref); 97923f7e30SGrant Likely struct property *prop = node->properties; 98923f7e30SGrant Likely 99923f7e30SGrant Likely /* We should never be releasing nodes that haven't been detached. */ 100923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DETACHED)) { 101923f7e30SGrant Likely pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); 102923f7e30SGrant Likely dump_stack(); 103923f7e30SGrant Likely kref_init(&node->kref); 104923f7e30SGrant Likely return; 105923f7e30SGrant Likely } 106923f7e30SGrant Likely 107923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DYNAMIC)) 108923f7e30SGrant Likely return; 109923f7e30SGrant Likely 110923f7e30SGrant Likely while (prop) { 111923f7e30SGrant Likely struct property *next = prop->next; 112923f7e30SGrant Likely kfree(prop->name); 113923f7e30SGrant Likely kfree(prop->value); 114923f7e30SGrant Likely kfree(prop); 115923f7e30SGrant Likely prop = next; 116923f7e30SGrant Likely 117923f7e30SGrant Likely if (!prop) { 118923f7e30SGrant Likely prop = node->deadprops; 119923f7e30SGrant Likely node->deadprops = NULL; 120923f7e30SGrant Likely } 121923f7e30SGrant Likely } 122923f7e30SGrant Likely kfree(node->full_name); 123923f7e30SGrant Likely kfree(node->data); 124923f7e30SGrant Likely kfree(node); 125923f7e30SGrant Likely } 126923f7e30SGrant Likely 127923f7e30SGrant Likely /** 128923f7e30SGrant Likely * of_node_put - Decrement refcount of a node 129923f7e30SGrant Likely * @node: Node to dec refcount, NULL is supported to 130923f7e30SGrant Likely * simplify writing of callers 131923f7e30SGrant Likely * 132923f7e30SGrant Likely */ 133923f7e30SGrant Likely void of_node_put(struct device_node *node) 134923f7e30SGrant Likely { 135923f7e30SGrant Likely if (node) 136923f7e30SGrant Likely kref_put(&node->kref, of_node_release); 137923f7e30SGrant Likely } 138923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put); 139923f7e30SGrant Likely #endif /* !CONFIG_SPARC */ 140923f7e30SGrant Likely 141581b605aSStephen Rothwell struct property *of_find_property(const struct device_node *np, 142581b605aSStephen Rothwell const char *name, 143581b605aSStephen Rothwell int *lenp) 144581b605aSStephen Rothwell { 145581b605aSStephen Rothwell struct property *pp; 146581b605aSStephen Rothwell 14764e4566fSTimur Tabi if (!np) 14864e4566fSTimur Tabi return NULL; 14964e4566fSTimur Tabi 150581b605aSStephen Rothwell read_lock(&devtree_lock); 151581b605aSStephen Rothwell for (pp = np->properties; pp != 0; pp = pp->next) { 152581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 153581b605aSStephen Rothwell if (lenp != 0) 154581b605aSStephen Rothwell *lenp = pp->length; 155581b605aSStephen Rothwell break; 156581b605aSStephen Rothwell } 157581b605aSStephen Rothwell } 158581b605aSStephen Rothwell read_unlock(&devtree_lock); 159581b605aSStephen Rothwell 160581b605aSStephen Rothwell return pp; 161581b605aSStephen Rothwell } 162581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 163581b605aSStephen Rothwell 164e91edcf5SGrant Likely /** 165e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 166e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 167e91edcf5SGrant Likely * of_node_put() will be called on it 168e91edcf5SGrant Likely * 169e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 170e91edcf5SGrant Likely * of_node_put() on it when done. 171e91edcf5SGrant Likely */ 172e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 173e91edcf5SGrant Likely { 174e91edcf5SGrant Likely struct device_node *np; 175e91edcf5SGrant Likely 176e91edcf5SGrant Likely read_lock(&devtree_lock); 177e91edcf5SGrant Likely np = prev ? prev->allnext : allnodes; 178e91edcf5SGrant Likely for (; np != NULL; np = np->allnext) 179e91edcf5SGrant Likely if (of_node_get(np)) 180e91edcf5SGrant Likely break; 181e91edcf5SGrant Likely of_node_put(prev); 182e91edcf5SGrant Likely read_unlock(&devtree_lock); 183e91edcf5SGrant Likely return np; 184e91edcf5SGrant Likely } 185e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 186e91edcf5SGrant Likely 18797e873e5SStephen Rothwell /* 18897e873e5SStephen Rothwell * Find a property with a given name for a given node 18997e873e5SStephen Rothwell * and return the value. 19097e873e5SStephen Rothwell */ 19197e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 19297e873e5SStephen Rothwell int *lenp) 19397e873e5SStephen Rothwell { 19497e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 19597e873e5SStephen Rothwell 19697e873e5SStephen Rothwell return pp ? pp->value : NULL; 19797e873e5SStephen Rothwell } 19897e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 1990081cbc3SStephen Rothwell 2000081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in 2010081cbc3SStephen Rothwell * the device's "compatible" property 2020081cbc3SStephen Rothwell */ 2030081cbc3SStephen Rothwell int of_device_is_compatible(const struct device_node *device, 2040081cbc3SStephen Rothwell const char *compat) 2050081cbc3SStephen Rothwell { 2060081cbc3SStephen Rothwell const char* cp; 2070081cbc3SStephen Rothwell int cplen, l; 2080081cbc3SStephen Rothwell 2090081cbc3SStephen Rothwell cp = of_get_property(device, "compatible", &cplen); 2100081cbc3SStephen Rothwell if (cp == NULL) 2110081cbc3SStephen Rothwell return 0; 2120081cbc3SStephen Rothwell while (cplen > 0) { 2130081cbc3SStephen Rothwell if (of_compat_cmp(cp, compat, strlen(compat)) == 0) 2140081cbc3SStephen Rothwell return 1; 2150081cbc3SStephen Rothwell l = strlen(cp) + 1; 2160081cbc3SStephen Rothwell cp += l; 2170081cbc3SStephen Rothwell cplen -= l; 2180081cbc3SStephen Rothwell } 2190081cbc3SStephen Rothwell 2200081cbc3SStephen Rothwell return 0; 2210081cbc3SStephen Rothwell } 2220081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 223e679c5f4SStephen Rothwell 224e679c5f4SStephen Rothwell /** 22571a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 2261f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 2271f43cfb9SGrant Likely * 2281f43cfb9SGrant Likely * Returns true if the root node has the given value in its 2291f43cfb9SGrant Likely * compatible property. 2301f43cfb9SGrant Likely */ 23171a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 2321f43cfb9SGrant Likely { 2331f43cfb9SGrant Likely struct device_node *root; 2341f43cfb9SGrant Likely int rc = 0; 2351f43cfb9SGrant Likely 2361f43cfb9SGrant Likely root = of_find_node_by_path("/"); 2371f43cfb9SGrant Likely if (root) { 2381f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 2391f43cfb9SGrant Likely of_node_put(root); 2401f43cfb9SGrant Likely } 2411f43cfb9SGrant Likely return rc; 2421f43cfb9SGrant Likely } 24371a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 2441f43cfb9SGrant Likely 2451f43cfb9SGrant Likely /** 246834d97d4SJosh Boyer * of_device_is_available - check if a device is available for use 247834d97d4SJosh Boyer * 248834d97d4SJosh Boyer * @device: Node to check for availability 249834d97d4SJosh Boyer * 250834d97d4SJosh Boyer * Returns 1 if the status property is absent or set to "okay" or "ok", 251834d97d4SJosh Boyer * 0 otherwise 252834d97d4SJosh Boyer */ 253834d97d4SJosh Boyer int of_device_is_available(const struct device_node *device) 254834d97d4SJosh Boyer { 255834d97d4SJosh Boyer const char *status; 256834d97d4SJosh Boyer int statlen; 257834d97d4SJosh Boyer 258834d97d4SJosh Boyer status = of_get_property(device, "status", &statlen); 259834d97d4SJosh Boyer if (status == NULL) 260834d97d4SJosh Boyer return 1; 261834d97d4SJosh Boyer 262834d97d4SJosh Boyer if (statlen > 0) { 263834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 264834d97d4SJosh Boyer return 1; 265834d97d4SJosh Boyer } 266834d97d4SJosh Boyer 267834d97d4SJosh Boyer return 0; 268834d97d4SJosh Boyer } 269834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 270834d97d4SJosh Boyer 271834d97d4SJosh Boyer /** 272e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 273e679c5f4SStephen Rothwell * @node: Node to get parent 274e679c5f4SStephen Rothwell * 275e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 276e679c5f4SStephen Rothwell * of_node_put() on it when done. 277e679c5f4SStephen Rothwell */ 278e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 279e679c5f4SStephen Rothwell { 280e679c5f4SStephen Rothwell struct device_node *np; 281e679c5f4SStephen Rothwell 282e679c5f4SStephen Rothwell if (!node) 283e679c5f4SStephen Rothwell return NULL; 284e679c5f4SStephen Rothwell 285e679c5f4SStephen Rothwell read_lock(&devtree_lock); 286e679c5f4SStephen Rothwell np = of_node_get(node->parent); 287e679c5f4SStephen Rothwell read_unlock(&devtree_lock); 288e679c5f4SStephen Rothwell return np; 289e679c5f4SStephen Rothwell } 290e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 291d1cd355aSStephen Rothwell 292d1cd355aSStephen Rothwell /** 293f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 294f4eb0107SMichael Ellerman * @node: Node to get parent of 295f4eb0107SMichael Ellerman * 296f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 297f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 298f4eb0107SMichael Ellerman * through a node's parents. 299f4eb0107SMichael Ellerman * 300f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 301f4eb0107SMichael Ellerman * of_node_put() on it when done. 302f4eb0107SMichael Ellerman */ 303f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 304f4eb0107SMichael Ellerman { 305f4eb0107SMichael Ellerman struct device_node *parent; 306f4eb0107SMichael Ellerman 307f4eb0107SMichael Ellerman if (!node) 308f4eb0107SMichael Ellerman return NULL; 309f4eb0107SMichael Ellerman 310f4eb0107SMichael Ellerman read_lock(&devtree_lock); 311f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 312f4eb0107SMichael Ellerman of_node_put(node); 313f4eb0107SMichael Ellerman read_unlock(&devtree_lock); 314f4eb0107SMichael Ellerman return parent; 315f4eb0107SMichael Ellerman } 316f4eb0107SMichael Ellerman 317f4eb0107SMichael Ellerman /** 318d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 319d1cd355aSStephen Rothwell * @node: parent node 320d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 321d1cd355aSStephen Rothwell * 322d1cd355aSStephen Rothwell * Returns a node pointer with refcount incremented, use 323d1cd355aSStephen Rothwell * of_node_put() on it when done. 324d1cd355aSStephen Rothwell */ 325d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 326d1cd355aSStephen Rothwell struct device_node *prev) 327d1cd355aSStephen Rothwell { 328d1cd355aSStephen Rothwell struct device_node *next; 329d1cd355aSStephen Rothwell 330d1cd355aSStephen Rothwell read_lock(&devtree_lock); 331d1cd355aSStephen Rothwell next = prev ? prev->sibling : node->child; 332d1cd355aSStephen Rothwell for (; next; next = next->sibling) 333d1cd355aSStephen Rothwell if (of_node_get(next)) 334d1cd355aSStephen Rothwell break; 335d1cd355aSStephen Rothwell of_node_put(prev); 336d1cd355aSStephen Rothwell read_unlock(&devtree_lock); 337d1cd355aSStephen Rothwell return next; 338d1cd355aSStephen Rothwell } 339d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 3401ef4d424SStephen Rothwell 3411ef4d424SStephen Rothwell /** 3421ef4d424SStephen Rothwell * of_find_node_by_path - Find a node matching a full OF path 3431ef4d424SStephen Rothwell * @path: The full path to match 3441ef4d424SStephen Rothwell * 3451ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 3461ef4d424SStephen Rothwell * of_node_put() on it when done. 3471ef4d424SStephen Rothwell */ 3481ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path) 3491ef4d424SStephen Rothwell { 3501ef4d424SStephen Rothwell struct device_node *np = allnodes; 3511ef4d424SStephen Rothwell 3521ef4d424SStephen Rothwell read_lock(&devtree_lock); 3531ef4d424SStephen Rothwell for (; np; np = np->allnext) { 3541ef4d424SStephen Rothwell if (np->full_name && (of_node_cmp(np->full_name, path) == 0) 3551ef4d424SStephen Rothwell && of_node_get(np)) 3561ef4d424SStephen Rothwell break; 3571ef4d424SStephen Rothwell } 3581ef4d424SStephen Rothwell read_unlock(&devtree_lock); 3591ef4d424SStephen Rothwell return np; 3601ef4d424SStephen Rothwell } 3611ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path); 3621ef4d424SStephen Rothwell 3631ef4d424SStephen Rothwell /** 3641ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 3651ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 3661ef4d424SStephen Rothwell * you pass will not be searched, only the next one 3671ef4d424SStephen Rothwell * will; typically, you pass what the previous call 3681ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 3691ef4d424SStephen Rothwell * @name: The name string to match against 3701ef4d424SStephen Rothwell * 3711ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 3721ef4d424SStephen Rothwell * of_node_put() on it when done. 3731ef4d424SStephen Rothwell */ 3741ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 3751ef4d424SStephen Rothwell const char *name) 3761ef4d424SStephen Rothwell { 3771ef4d424SStephen Rothwell struct device_node *np; 3781ef4d424SStephen Rothwell 3791ef4d424SStephen Rothwell read_lock(&devtree_lock); 3801ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 3811ef4d424SStephen Rothwell for (; np; np = np->allnext) 3821ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 3831ef4d424SStephen Rothwell && of_node_get(np)) 3841ef4d424SStephen Rothwell break; 3851ef4d424SStephen Rothwell of_node_put(from); 3861ef4d424SStephen Rothwell read_unlock(&devtree_lock); 3871ef4d424SStephen Rothwell return np; 3881ef4d424SStephen Rothwell } 3891ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 3901ef4d424SStephen Rothwell 3911ef4d424SStephen Rothwell /** 3921ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 3931ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 3941ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 3951ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 3961ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 3971ef4d424SStephen Rothwell * called on from for you. 3981ef4d424SStephen Rothwell * @type: The type string to match against 3991ef4d424SStephen Rothwell * 4001ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4011ef4d424SStephen Rothwell * of_node_put() on it when done. 4021ef4d424SStephen Rothwell */ 4031ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 4041ef4d424SStephen Rothwell const char *type) 4051ef4d424SStephen Rothwell { 4061ef4d424SStephen Rothwell struct device_node *np; 4071ef4d424SStephen Rothwell 4081ef4d424SStephen Rothwell read_lock(&devtree_lock); 4091ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 4101ef4d424SStephen Rothwell for (; np; np = np->allnext) 4111ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 4121ef4d424SStephen Rothwell && of_node_get(np)) 4131ef4d424SStephen Rothwell break; 4141ef4d424SStephen Rothwell of_node_put(from); 4151ef4d424SStephen Rothwell read_unlock(&devtree_lock); 4161ef4d424SStephen Rothwell return np; 4171ef4d424SStephen Rothwell } 4181ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 4191ef4d424SStephen Rothwell 4201ef4d424SStephen Rothwell /** 4211ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 4221ef4d424SStephen Rothwell * tokens in its "compatible" property 4231ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 4241ef4d424SStephen Rothwell * you pass will not be searched, only the next one 4251ef4d424SStephen Rothwell * will; typically, you pass what the previous call 4261ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 4271ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 4281ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 4291ef4d424SStephen Rothwell * "compatible" list. 4301ef4d424SStephen Rothwell * 4311ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4321ef4d424SStephen Rothwell * of_node_put() on it when done. 4331ef4d424SStephen Rothwell */ 4341ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 4351ef4d424SStephen Rothwell const char *type, const char *compatible) 4361ef4d424SStephen Rothwell { 4371ef4d424SStephen Rothwell struct device_node *np; 4381ef4d424SStephen Rothwell 4391ef4d424SStephen Rothwell read_lock(&devtree_lock); 4401ef4d424SStephen Rothwell np = from ? from->allnext : allnodes; 4411ef4d424SStephen Rothwell for (; np; np = np->allnext) { 4421ef4d424SStephen Rothwell if (type 4431ef4d424SStephen Rothwell && !(np->type && (of_node_cmp(np->type, type) == 0))) 4441ef4d424SStephen Rothwell continue; 4451ef4d424SStephen Rothwell if (of_device_is_compatible(np, compatible) && of_node_get(np)) 4461ef4d424SStephen Rothwell break; 4471ef4d424SStephen Rothwell } 4481ef4d424SStephen Rothwell of_node_put(from); 4491ef4d424SStephen Rothwell read_unlock(&devtree_lock); 4501ef4d424SStephen Rothwell return np; 4511ef4d424SStephen Rothwell } 4521ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 453283029d1SGrant Likely 454283029d1SGrant Likely /** 4551e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 4561e291b14SMichael Ellerman * the given name. 4571e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 4581e291b14SMichael Ellerman * you pass will not be searched, only the next one 4591e291b14SMichael Ellerman * will; typically, you pass what the previous call 4601e291b14SMichael Ellerman * returned. of_node_put() will be called on it 4611e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 4621e291b14SMichael Ellerman * 4631e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 4641e291b14SMichael Ellerman * of_node_put() on it when done. 4651e291b14SMichael Ellerman */ 4661e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 4671e291b14SMichael Ellerman const char *prop_name) 4681e291b14SMichael Ellerman { 4691e291b14SMichael Ellerman struct device_node *np; 4701e291b14SMichael Ellerman struct property *pp; 4711e291b14SMichael Ellerman 4721e291b14SMichael Ellerman read_lock(&devtree_lock); 4731e291b14SMichael Ellerman np = from ? from->allnext : allnodes; 4741e291b14SMichael Ellerman for (; np; np = np->allnext) { 4751e291b14SMichael Ellerman for (pp = np->properties; pp != 0; pp = pp->next) { 4761e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 4771e291b14SMichael Ellerman of_node_get(np); 4781e291b14SMichael Ellerman goto out; 4791e291b14SMichael Ellerman } 4801e291b14SMichael Ellerman } 4811e291b14SMichael Ellerman } 4821e291b14SMichael Ellerman out: 4831e291b14SMichael Ellerman of_node_put(from); 4841e291b14SMichael Ellerman read_unlock(&devtree_lock); 4851e291b14SMichael Ellerman return np; 4861e291b14SMichael Ellerman } 4871e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 4881e291b14SMichael Ellerman 4891e291b14SMichael Ellerman /** 490283029d1SGrant Likely * of_match_node - Tell if an device_node has a matching of_match structure 491283029d1SGrant Likely * @matches: array of of device match structures to search in 492283029d1SGrant Likely * @node: the of device structure to match against 493283029d1SGrant Likely * 494283029d1SGrant Likely * Low level utility function used by device matching. 495283029d1SGrant Likely */ 496283029d1SGrant Likely const struct of_device_id *of_match_node(const struct of_device_id *matches, 497283029d1SGrant Likely const struct device_node *node) 498283029d1SGrant Likely { 499a52f07ecSGrant Likely if (!matches) 500a52f07ecSGrant Likely return NULL; 501a52f07ecSGrant Likely 502283029d1SGrant Likely while (matches->name[0] || matches->type[0] || matches->compatible[0]) { 503283029d1SGrant Likely int match = 1; 504283029d1SGrant Likely if (matches->name[0]) 505283029d1SGrant Likely match &= node->name 506283029d1SGrant Likely && !strcmp(matches->name, node->name); 507283029d1SGrant Likely if (matches->type[0]) 508283029d1SGrant Likely match &= node->type 509283029d1SGrant Likely && !strcmp(matches->type, node->type); 510283029d1SGrant Likely if (matches->compatible[0]) 511283029d1SGrant Likely match &= of_device_is_compatible(node, 512283029d1SGrant Likely matches->compatible); 513283029d1SGrant Likely if (match) 514283029d1SGrant Likely return matches; 515283029d1SGrant Likely matches++; 516283029d1SGrant Likely } 517283029d1SGrant Likely return NULL; 518283029d1SGrant Likely } 519283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 520283029d1SGrant Likely 521283029d1SGrant Likely /** 522283029d1SGrant Likely * of_find_matching_node - Find a node based on an of_device_id match 523283029d1SGrant Likely * table. 524283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 525283029d1SGrant Likely * you pass will not be searched, only the next one 526283029d1SGrant Likely * will; typically, you pass what the previous call 527283029d1SGrant Likely * returned. of_node_put() will be called on it 528283029d1SGrant Likely * @matches: array of of device match structures to search in 529283029d1SGrant Likely * 530283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 531283029d1SGrant Likely * of_node_put() on it when done. 532283029d1SGrant Likely */ 533283029d1SGrant Likely struct device_node *of_find_matching_node(struct device_node *from, 534283029d1SGrant Likely const struct of_device_id *matches) 535283029d1SGrant Likely { 536283029d1SGrant Likely struct device_node *np; 537283029d1SGrant Likely 538283029d1SGrant Likely read_lock(&devtree_lock); 539283029d1SGrant Likely np = from ? from->allnext : allnodes; 540283029d1SGrant Likely for (; np; np = np->allnext) { 541283029d1SGrant Likely if (of_match_node(matches, np) && of_node_get(np)) 542283029d1SGrant Likely break; 543283029d1SGrant Likely } 544283029d1SGrant Likely of_node_put(from); 545283029d1SGrant Likely read_unlock(&devtree_lock); 546283029d1SGrant Likely return np; 547283029d1SGrant Likely } 548283029d1SGrant Likely EXPORT_SYMBOL(of_find_matching_node); 5493f07af49SGrant Likely 5503f07af49SGrant Likely /** 5513f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 5523f07af49SGrant Likely * @node: pointer to a device tree node 5533f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 5543f07af49SGrant Likely * @len: Length of modalias value 5553f07af49SGrant Likely * 5562ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 5572ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 5582ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 5592ffe8c5fSGrant Likely * from the first entry in the compatible list property. 5603f07af49SGrant Likely * 5612ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 5623f07af49SGrant Likely */ 5633f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 5643f07af49SGrant Likely { 5652ffe8c5fSGrant Likely const char *compatible, *p; 5662ffe8c5fSGrant Likely int cplen; 5673f07af49SGrant Likely 5683f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 5692ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 5703f07af49SGrant Likely return -ENODEV; 5713f07af49SGrant Likely p = strchr(compatible, ','); 5722ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 5733f07af49SGrant Likely return 0; 5743f07af49SGrant Likely } 5753f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 5763f07af49SGrant Likely 57764b60e09SAnton Vorontsov /** 57889751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 57989751a7cSJeremy Kerr * @handle: phandle of the node to find 58089751a7cSJeremy Kerr * 58189751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 58289751a7cSJeremy Kerr * of_node_put() on it when done. 58389751a7cSJeremy Kerr */ 58489751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 58589751a7cSJeremy Kerr { 58689751a7cSJeremy Kerr struct device_node *np; 58789751a7cSJeremy Kerr 58889751a7cSJeremy Kerr read_lock(&devtree_lock); 58989751a7cSJeremy Kerr for (np = allnodes; np; np = np->allnext) 59089751a7cSJeremy Kerr if (np->phandle == handle) 59189751a7cSJeremy Kerr break; 59289751a7cSJeremy Kerr of_node_get(np); 59389751a7cSJeremy Kerr read_unlock(&devtree_lock); 59489751a7cSJeremy Kerr return np; 59589751a7cSJeremy Kerr } 59689751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 59789751a7cSJeremy Kerr 59889751a7cSJeremy Kerr /** 599a3b85363SThomas Abraham * of_property_read_u32 - Find and read a 32 bit integer from a property 600a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 601a3b85363SThomas Abraham * @propname: name of the property to be searched. 602a3b85363SThomas Abraham * @out_value: pointer to return value, modified only if return value is 0. 603a3b85363SThomas Abraham * 604a3b85363SThomas Abraham * Search for a property in a device node and read a 32-bit value from 605a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 606a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 607a3b85363SThomas Abraham * property data isn't large enough. 608a3b85363SThomas Abraham * 609a3b85363SThomas Abraham * The out_value is modified only if a valid u32 value can be decoded. 610a3b85363SThomas Abraham */ 611a3b85363SThomas Abraham int of_property_read_u32(struct device_node *np, char *propname, u32 *out_value) 612a3b85363SThomas Abraham { 613a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 614a3b85363SThomas Abraham 615a3b85363SThomas Abraham if (!prop) 616a3b85363SThomas Abraham return -EINVAL; 617a3b85363SThomas Abraham if (!prop->value) 618a3b85363SThomas Abraham return -ENODATA; 619a3b85363SThomas Abraham if (sizeof(*out_value) > prop->length) 620a3b85363SThomas Abraham return -EOVERFLOW; 621a3b85363SThomas Abraham *out_value = be32_to_cpup(prop->value); 622a3b85363SThomas Abraham return 0; 623a3b85363SThomas Abraham } 624a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_u32); 625a3b85363SThomas Abraham 626a3b85363SThomas Abraham /** 627a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 628a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 629a3b85363SThomas Abraham * @propname: name of the property to be searched. 630a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 631a3b85363SThomas Abraham * return value is 0. 632a3b85363SThomas Abraham * 633a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 634a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 635a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 636a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 637a3b85363SThomas Abraham * within the length of the property data. 638a3b85363SThomas Abraham * 639a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 640a3b85363SThomas Abraham */ 641a3b85363SThomas Abraham int of_property_read_string(struct device_node *np, char *propname, 642a3b85363SThomas Abraham char **out_string) 643a3b85363SThomas Abraham { 644a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 645a3b85363SThomas Abraham if (!prop) 646a3b85363SThomas Abraham return -EINVAL; 647a3b85363SThomas Abraham if (!prop->value) 648a3b85363SThomas Abraham return -ENODATA; 649a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 650a3b85363SThomas Abraham return -EILSEQ; 651a3b85363SThomas Abraham *out_string = prop->value; 652a3b85363SThomas Abraham return 0; 653a3b85363SThomas Abraham } 654a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 655a3b85363SThomas Abraham 656a3b85363SThomas Abraham /** 657739649c5SGrant Likely * of_parse_phandle - Resolve a phandle property to a device_node pointer 658739649c5SGrant Likely * @np: Pointer to device node holding phandle property 659739649c5SGrant Likely * @phandle_name: Name of property holding a phandle value 660739649c5SGrant Likely * @index: For properties holding a table of phandles, this is the index into 661739649c5SGrant Likely * the table 662739649c5SGrant Likely * 663739649c5SGrant Likely * Returns the device_node pointer with refcount incremented. Use 664739649c5SGrant Likely * of_node_put() on it when done. 665739649c5SGrant Likely */ 666739649c5SGrant Likely struct device_node * 667739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index) 668739649c5SGrant Likely { 6699a6b2e58SGrant Likely const __be32 *phandle; 670739649c5SGrant Likely int size; 671739649c5SGrant Likely 672739649c5SGrant Likely phandle = of_get_property(np, phandle_name, &size); 673739649c5SGrant Likely if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) 674739649c5SGrant Likely return NULL; 675739649c5SGrant Likely 6769a6b2e58SGrant Likely return of_find_node_by_phandle(be32_to_cpup(phandle + index)); 677739649c5SGrant Likely } 678739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle); 679739649c5SGrant Likely 680739649c5SGrant Likely /** 68164b60e09SAnton Vorontsov * of_parse_phandles_with_args - Find a node pointed by phandle in a list 68264b60e09SAnton Vorontsov * @np: pointer to a device tree node containing a list 68364b60e09SAnton Vorontsov * @list_name: property name that contains a list 68464b60e09SAnton Vorontsov * @cells_name: property name that specifies phandles' arguments count 68564b60e09SAnton Vorontsov * @index: index of a phandle to parse out 6867736a3dbSAnton Vorontsov * @out_node: optional pointer to device_node struct pointer (will be filled) 6877736a3dbSAnton Vorontsov * @out_args: optional pointer to arguments pointer (will be filled) 68864b60e09SAnton Vorontsov * 68964b60e09SAnton Vorontsov * This function is useful to parse lists of phandles and their arguments. 69064b60e09SAnton Vorontsov * Returns 0 on success and fills out_node and out_args, on error returns 69164b60e09SAnton Vorontsov * appropriate errno value. 69264b60e09SAnton Vorontsov * 69364b60e09SAnton Vorontsov * Example: 69464b60e09SAnton Vorontsov * 69564b60e09SAnton Vorontsov * phandle1: node1 { 69664b60e09SAnton Vorontsov * #list-cells = <2>; 69764b60e09SAnton Vorontsov * } 69864b60e09SAnton Vorontsov * 69964b60e09SAnton Vorontsov * phandle2: node2 { 70064b60e09SAnton Vorontsov * #list-cells = <1>; 70164b60e09SAnton Vorontsov * } 70264b60e09SAnton Vorontsov * 70364b60e09SAnton Vorontsov * node3 { 70464b60e09SAnton Vorontsov * list = <&phandle1 1 2 &phandle2 3>; 70564b60e09SAnton Vorontsov * } 70664b60e09SAnton Vorontsov * 70764b60e09SAnton Vorontsov * To get a device_node of the `node2' node you may call this: 70864b60e09SAnton Vorontsov * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args); 70964b60e09SAnton Vorontsov */ 71064b60e09SAnton Vorontsov int of_parse_phandles_with_args(struct device_node *np, const char *list_name, 71164b60e09SAnton Vorontsov const char *cells_name, int index, 71264b60e09SAnton Vorontsov struct device_node **out_node, 71364b60e09SAnton Vorontsov const void **out_args) 71464b60e09SAnton Vorontsov { 71564b60e09SAnton Vorontsov int ret = -EINVAL; 71633714881SJeremy Kerr const __be32 *list; 71733714881SJeremy Kerr const __be32 *list_end; 71864b60e09SAnton Vorontsov int size; 71964b60e09SAnton Vorontsov int cur_index = 0; 72064b60e09SAnton Vorontsov struct device_node *node = NULL; 7217736a3dbSAnton Vorontsov const void *args = NULL; 72264b60e09SAnton Vorontsov 72364b60e09SAnton Vorontsov list = of_get_property(np, list_name, &size); 72464b60e09SAnton Vorontsov if (!list) { 72564b60e09SAnton Vorontsov ret = -ENOENT; 72664b60e09SAnton Vorontsov goto err0; 72764b60e09SAnton Vorontsov } 72864b60e09SAnton Vorontsov list_end = list + size / sizeof(*list); 72964b60e09SAnton Vorontsov 73064b60e09SAnton Vorontsov while (list < list_end) { 73133714881SJeremy Kerr const __be32 *cells; 7329a6b2e58SGrant Likely phandle phandle; 73364b60e09SAnton Vorontsov 7349a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 735c1bb7c6dSAnton Vorontsov args = list; 73664b60e09SAnton Vorontsov 73764b60e09SAnton Vorontsov /* one cell hole in the list = <>; */ 7389a6b2e58SGrant Likely if (!phandle) 73964b60e09SAnton Vorontsov goto next; 74064b60e09SAnton Vorontsov 7419a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 74264b60e09SAnton Vorontsov if (!node) { 74364b60e09SAnton Vorontsov pr_debug("%s: could not find phandle\n", 74464b60e09SAnton Vorontsov np->full_name); 74564b60e09SAnton Vorontsov goto err0; 74664b60e09SAnton Vorontsov } 74764b60e09SAnton Vorontsov 74864b60e09SAnton Vorontsov cells = of_get_property(node, cells_name, &size); 74964b60e09SAnton Vorontsov if (!cells || size != sizeof(*cells)) { 75064b60e09SAnton Vorontsov pr_debug("%s: could not get %s for %s\n", 75164b60e09SAnton Vorontsov np->full_name, cells_name, node->full_name); 75264b60e09SAnton Vorontsov goto err1; 75364b60e09SAnton Vorontsov } 75464b60e09SAnton Vorontsov 75533714881SJeremy Kerr list += be32_to_cpup(cells); 75664b60e09SAnton Vorontsov if (list > list_end) { 75764b60e09SAnton Vorontsov pr_debug("%s: insufficient arguments length\n", 75864b60e09SAnton Vorontsov np->full_name); 75964b60e09SAnton Vorontsov goto err1; 76064b60e09SAnton Vorontsov } 76164b60e09SAnton Vorontsov next: 76264b60e09SAnton Vorontsov if (cur_index == index) 76364b60e09SAnton Vorontsov break; 76464b60e09SAnton Vorontsov 76564b60e09SAnton Vorontsov of_node_put(node); 76664b60e09SAnton Vorontsov node = NULL; 7677736a3dbSAnton Vorontsov args = NULL; 76864b60e09SAnton Vorontsov cur_index++; 76964b60e09SAnton Vorontsov } 77064b60e09SAnton Vorontsov 77164b60e09SAnton Vorontsov if (!node) { 7727736a3dbSAnton Vorontsov /* 7737736a3dbSAnton Vorontsov * args w/o node indicates that the loop above has stopped at 7747736a3dbSAnton Vorontsov * the 'hole' cell. Report this differently. 7757736a3dbSAnton Vorontsov */ 7767736a3dbSAnton Vorontsov if (args) 7777736a3dbSAnton Vorontsov ret = -EEXIST; 7787736a3dbSAnton Vorontsov else 77964b60e09SAnton Vorontsov ret = -ENOENT; 78064b60e09SAnton Vorontsov goto err0; 78164b60e09SAnton Vorontsov } 78264b60e09SAnton Vorontsov 7837736a3dbSAnton Vorontsov if (out_node) 78464b60e09SAnton Vorontsov *out_node = node; 7857736a3dbSAnton Vorontsov if (out_args) 78664b60e09SAnton Vorontsov *out_args = args; 78764b60e09SAnton Vorontsov 78864b60e09SAnton Vorontsov return 0; 78964b60e09SAnton Vorontsov err1: 79064b60e09SAnton Vorontsov of_node_put(node); 79164b60e09SAnton Vorontsov err0: 79264b60e09SAnton Vorontsov pr_debug("%s failed with status %d\n", __func__, ret); 79364b60e09SAnton Vorontsov return ret; 79464b60e09SAnton Vorontsov } 79564b60e09SAnton Vorontsov EXPORT_SYMBOL(of_parse_phandles_with_args); 79602af11b0SGrant Likely 79702af11b0SGrant Likely /** 79802af11b0SGrant Likely * prom_add_property - Add a property to a node 79902af11b0SGrant Likely */ 80002af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop) 80102af11b0SGrant Likely { 80202af11b0SGrant Likely struct property **next; 80302af11b0SGrant Likely unsigned long flags; 80402af11b0SGrant Likely 80502af11b0SGrant Likely prop->next = NULL; 80602af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 80702af11b0SGrant Likely next = &np->properties; 80802af11b0SGrant Likely while (*next) { 80902af11b0SGrant Likely if (strcmp(prop->name, (*next)->name) == 0) { 81002af11b0SGrant Likely /* duplicate ! don't insert it */ 81102af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 81202af11b0SGrant Likely return -1; 81302af11b0SGrant Likely } 81402af11b0SGrant Likely next = &(*next)->next; 81502af11b0SGrant Likely } 81602af11b0SGrant Likely *next = prop; 81702af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 81802af11b0SGrant Likely 81902af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 82002af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 82102af11b0SGrant Likely if (np->pde) 82202af11b0SGrant Likely proc_device_tree_add_prop(np->pde, prop); 82302af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 82402af11b0SGrant Likely 82502af11b0SGrant Likely return 0; 82602af11b0SGrant Likely } 82702af11b0SGrant Likely 82802af11b0SGrant Likely /** 82902af11b0SGrant Likely * prom_remove_property - Remove a property from a node. 83002af11b0SGrant Likely * 83102af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 83202af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 83302af11b0SGrant Likely * Instead we just move the property to the "dead properties" 83402af11b0SGrant Likely * list, so it won't be found any more. 83502af11b0SGrant Likely */ 83602af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop) 83702af11b0SGrant Likely { 83802af11b0SGrant Likely struct property **next; 83902af11b0SGrant Likely unsigned long flags; 84002af11b0SGrant Likely int found = 0; 84102af11b0SGrant Likely 84202af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 84302af11b0SGrant Likely next = &np->properties; 84402af11b0SGrant Likely while (*next) { 84502af11b0SGrant Likely if (*next == prop) { 84602af11b0SGrant Likely /* found the node */ 84702af11b0SGrant Likely *next = prop->next; 84802af11b0SGrant Likely prop->next = np->deadprops; 84902af11b0SGrant Likely np->deadprops = prop; 85002af11b0SGrant Likely found = 1; 85102af11b0SGrant Likely break; 85202af11b0SGrant Likely } 85302af11b0SGrant Likely next = &(*next)->next; 85402af11b0SGrant Likely } 85502af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 85602af11b0SGrant Likely 85702af11b0SGrant Likely if (!found) 85802af11b0SGrant Likely return -ENODEV; 85902af11b0SGrant Likely 86002af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 86102af11b0SGrant Likely /* try to remove the proc node as well */ 86202af11b0SGrant Likely if (np->pde) 86302af11b0SGrant Likely proc_device_tree_remove_prop(np->pde, prop); 86402af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 86502af11b0SGrant Likely 86602af11b0SGrant Likely return 0; 86702af11b0SGrant Likely } 86802af11b0SGrant Likely 86902af11b0SGrant Likely /* 87002af11b0SGrant Likely * prom_update_property - Update a property in a node. 87102af11b0SGrant Likely * 87202af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 87302af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 87402af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 87502af11b0SGrant Likely * and add the new property to the property list 87602af11b0SGrant Likely */ 87702af11b0SGrant Likely int prom_update_property(struct device_node *np, 87802af11b0SGrant Likely struct property *newprop, 87902af11b0SGrant Likely struct property *oldprop) 88002af11b0SGrant Likely { 88102af11b0SGrant Likely struct property **next; 88202af11b0SGrant Likely unsigned long flags; 88302af11b0SGrant Likely int found = 0; 88402af11b0SGrant Likely 88502af11b0SGrant Likely write_lock_irqsave(&devtree_lock, flags); 88602af11b0SGrant Likely next = &np->properties; 88702af11b0SGrant Likely while (*next) { 88802af11b0SGrant Likely if (*next == oldprop) { 88902af11b0SGrant Likely /* found the node */ 89002af11b0SGrant Likely newprop->next = oldprop->next; 89102af11b0SGrant Likely *next = newprop; 89202af11b0SGrant Likely oldprop->next = np->deadprops; 89302af11b0SGrant Likely np->deadprops = oldprop; 89402af11b0SGrant Likely found = 1; 89502af11b0SGrant Likely break; 89602af11b0SGrant Likely } 89702af11b0SGrant Likely next = &(*next)->next; 89802af11b0SGrant Likely } 89902af11b0SGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 90002af11b0SGrant Likely 90102af11b0SGrant Likely if (!found) 90202af11b0SGrant Likely return -ENODEV; 90302af11b0SGrant Likely 90402af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 90502af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 90602af11b0SGrant Likely if (np->pde) 90702af11b0SGrant Likely proc_device_tree_update_prop(np->pde, newprop, oldprop); 90802af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 90902af11b0SGrant Likely 91002af11b0SGrant Likely return 0; 91102af11b0SGrant Likely } 912fcdeb7feSGrant Likely 913fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC) 914fcdeb7feSGrant Likely /* 915fcdeb7feSGrant Likely * Support for dynamic device trees. 916fcdeb7feSGrant Likely * 917fcdeb7feSGrant Likely * On some platforms, the device tree can be manipulated at runtime. 918fcdeb7feSGrant Likely * The routines in this section support adding, removing and changing 919fcdeb7feSGrant Likely * device tree nodes. 920fcdeb7feSGrant Likely */ 921fcdeb7feSGrant Likely 922fcdeb7feSGrant Likely /** 923fcdeb7feSGrant Likely * of_attach_node - Plug a device node into the tree and global list. 924fcdeb7feSGrant Likely */ 925fcdeb7feSGrant Likely void of_attach_node(struct device_node *np) 926fcdeb7feSGrant Likely { 927fcdeb7feSGrant Likely unsigned long flags; 928fcdeb7feSGrant Likely 929fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 930fcdeb7feSGrant Likely np->sibling = np->parent->child; 931fcdeb7feSGrant Likely np->allnext = allnodes; 932fcdeb7feSGrant Likely np->parent->child = np; 933fcdeb7feSGrant Likely allnodes = np; 934fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 935fcdeb7feSGrant Likely } 936fcdeb7feSGrant Likely 937fcdeb7feSGrant Likely /** 938fcdeb7feSGrant Likely * of_detach_node - "Unplug" a node from the device tree. 939fcdeb7feSGrant Likely * 940fcdeb7feSGrant Likely * The caller must hold a reference to the node. The memory associated with 941fcdeb7feSGrant Likely * the node is not freed until its refcount goes to zero. 942fcdeb7feSGrant Likely */ 943fcdeb7feSGrant Likely void of_detach_node(struct device_node *np) 944fcdeb7feSGrant Likely { 945fcdeb7feSGrant Likely struct device_node *parent; 946fcdeb7feSGrant Likely unsigned long flags; 947fcdeb7feSGrant Likely 948fcdeb7feSGrant Likely write_lock_irqsave(&devtree_lock, flags); 949fcdeb7feSGrant Likely 950fcdeb7feSGrant Likely parent = np->parent; 951fcdeb7feSGrant Likely if (!parent) 952fcdeb7feSGrant Likely goto out_unlock; 953fcdeb7feSGrant Likely 954fcdeb7feSGrant Likely if (allnodes == np) 955fcdeb7feSGrant Likely allnodes = np->allnext; 956fcdeb7feSGrant Likely else { 957fcdeb7feSGrant Likely struct device_node *prev; 958fcdeb7feSGrant Likely for (prev = allnodes; 959fcdeb7feSGrant Likely prev->allnext != np; 960fcdeb7feSGrant Likely prev = prev->allnext) 961fcdeb7feSGrant Likely ; 962fcdeb7feSGrant Likely prev->allnext = np->allnext; 963fcdeb7feSGrant Likely } 964fcdeb7feSGrant Likely 965fcdeb7feSGrant Likely if (parent->child == np) 966fcdeb7feSGrant Likely parent->child = np->sibling; 967fcdeb7feSGrant Likely else { 968fcdeb7feSGrant Likely struct device_node *prevsib; 969fcdeb7feSGrant Likely for (prevsib = np->parent->child; 970fcdeb7feSGrant Likely prevsib->sibling != np; 971fcdeb7feSGrant Likely prevsib = prevsib->sibling) 972fcdeb7feSGrant Likely ; 973fcdeb7feSGrant Likely prevsib->sibling = np->sibling; 974fcdeb7feSGrant Likely } 975fcdeb7feSGrant Likely 976fcdeb7feSGrant Likely of_node_set_flag(np, OF_DETACHED); 977fcdeb7feSGrant Likely 978fcdeb7feSGrant Likely out_unlock: 979fcdeb7feSGrant Likely write_unlock_irqrestore(&devtree_lock, flags); 980fcdeb7feSGrant Likely } 981fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */ 982fcdeb7feSGrant Likely 983