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 27ced4eec9SStepan Moskovchenko #include "of_private.h" 28611cad72SShawn Guo 29ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 30611cad72SShawn Guo 31465aac6dSRandy Dunlap struct device_node *of_allnodes; 32465aac6dSRandy Dunlap EXPORT_SYMBOL(of_allnodes); 33fc0bdae4SGrant Likely struct device_node *of_chosen; 34611cad72SShawn Guo struct device_node *of_aliases; 35611cad72SShawn Guo 36ced4eec9SStepan Moskovchenko DEFINE_MUTEX(of_aliases_mutex); 371ef4d424SStephen Rothwell 38581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling, 39581b605aSStephen Rothwell * or parent members of struct device_node. 40581b605aSStephen Rothwell */ 41d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 4297e873e5SStephen Rothwell 4397e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 4497e873e5SStephen Rothwell { 45a9fadeefSJeremy Kerr const __be32 *ip; 4697e873e5SStephen Rothwell 4797e873e5SStephen Rothwell do { 4897e873e5SStephen Rothwell if (np->parent) 4997e873e5SStephen Rothwell np = np->parent; 5097e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 5197e873e5SStephen Rothwell if (ip) 5233714881SJeremy Kerr return be32_to_cpup(ip); 5397e873e5SStephen Rothwell } while (np->parent); 5497e873e5SStephen Rothwell /* No #address-cells property for the root node */ 5597e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 5697e873e5SStephen Rothwell } 5797e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 5897e873e5SStephen Rothwell 5997e873e5SStephen Rothwell int of_n_size_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, "#size-cells", NULL); 6797e873e5SStephen Rothwell if (ip) 6833714881SJeremy Kerr return be32_to_cpup(ip); 6997e873e5SStephen Rothwell } while (np->parent); 7097e873e5SStephen Rothwell /* No #size-cells property for the root node */ 7197e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 7297e873e5SStephen Rothwell } 7397e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 7497e873e5SStephen Rothwell 750f22dd39SGrant Likely #if defined(CONFIG_OF_DYNAMIC) 76923f7e30SGrant Likely /** 77923f7e30SGrant Likely * of_node_get - Increment refcount of a node 78923f7e30SGrant Likely * @node: Node to inc refcount, NULL is supported to 79923f7e30SGrant Likely * simplify writing of callers 80923f7e30SGrant Likely * 81923f7e30SGrant Likely * Returns node. 82923f7e30SGrant Likely */ 83923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node) 84923f7e30SGrant Likely { 85923f7e30SGrant Likely if (node) 86923f7e30SGrant Likely kref_get(&node->kref); 87923f7e30SGrant Likely return node; 88923f7e30SGrant Likely } 89923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get); 90923f7e30SGrant Likely 91923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref) 92923f7e30SGrant Likely { 93923f7e30SGrant Likely return container_of(kref, struct device_node, kref); 94923f7e30SGrant Likely } 95923f7e30SGrant Likely 96923f7e30SGrant Likely /** 97923f7e30SGrant Likely * of_node_release - release a dynamically allocated node 98923f7e30SGrant Likely * @kref: kref element of the node to be released 99923f7e30SGrant Likely * 100923f7e30SGrant Likely * In of_node_put() this function is passed to kref_put() 101923f7e30SGrant Likely * as the destructor. 102923f7e30SGrant Likely */ 103923f7e30SGrant Likely static void of_node_release(struct kref *kref) 104923f7e30SGrant Likely { 105923f7e30SGrant Likely struct device_node *node = kref_to_device_node(kref); 106923f7e30SGrant Likely struct property *prop = node->properties; 107923f7e30SGrant Likely 108923f7e30SGrant Likely /* We should never be releasing nodes that haven't been detached. */ 109923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DETACHED)) { 110923f7e30SGrant Likely pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); 111923f7e30SGrant Likely dump_stack(); 112923f7e30SGrant Likely kref_init(&node->kref); 113923f7e30SGrant Likely return; 114923f7e30SGrant Likely } 115923f7e30SGrant Likely 116923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DYNAMIC)) 117923f7e30SGrant Likely return; 118923f7e30SGrant Likely 119923f7e30SGrant Likely while (prop) { 120923f7e30SGrant Likely struct property *next = prop->next; 121923f7e30SGrant Likely kfree(prop->name); 122923f7e30SGrant Likely kfree(prop->value); 123923f7e30SGrant Likely kfree(prop); 124923f7e30SGrant Likely prop = next; 125923f7e30SGrant Likely 126923f7e30SGrant Likely if (!prop) { 127923f7e30SGrant Likely prop = node->deadprops; 128923f7e30SGrant Likely node->deadprops = NULL; 129923f7e30SGrant Likely } 130923f7e30SGrant Likely } 131923f7e30SGrant Likely kfree(node->full_name); 132923f7e30SGrant Likely kfree(node->data); 133923f7e30SGrant Likely kfree(node); 134923f7e30SGrant Likely } 135923f7e30SGrant Likely 136923f7e30SGrant Likely /** 137923f7e30SGrant Likely * of_node_put - Decrement refcount of a node 138923f7e30SGrant Likely * @node: Node to dec refcount, NULL is supported to 139923f7e30SGrant Likely * simplify writing of callers 140923f7e30SGrant Likely * 141923f7e30SGrant Likely */ 142923f7e30SGrant Likely void of_node_put(struct device_node *node) 143923f7e30SGrant Likely { 144923f7e30SGrant Likely if (node) 145923f7e30SGrant Likely kref_put(&node->kref, of_node_release); 146923f7e30SGrant Likely } 147923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put); 1480f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 149923f7e30SGrant Likely 15028d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 15128d0e36bSThomas Gleixner const char *name, int *lenp) 152581b605aSStephen Rothwell { 153581b605aSStephen Rothwell struct property *pp; 154581b605aSStephen Rothwell 15564e4566fSTimur Tabi if (!np) 15664e4566fSTimur Tabi return NULL; 15764e4566fSTimur Tabi 158a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 159581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 160a3a7cab1SSachin Kamat if (lenp) 161581b605aSStephen Rothwell *lenp = pp->length; 162581b605aSStephen Rothwell break; 163581b605aSStephen Rothwell } 164581b605aSStephen Rothwell } 16528d0e36bSThomas Gleixner 16628d0e36bSThomas Gleixner return pp; 16728d0e36bSThomas Gleixner } 16828d0e36bSThomas Gleixner 16928d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 17028d0e36bSThomas Gleixner const char *name, 17128d0e36bSThomas Gleixner int *lenp) 17228d0e36bSThomas Gleixner { 17328d0e36bSThomas Gleixner struct property *pp; 174d6d3c4e6SThomas Gleixner unsigned long flags; 17528d0e36bSThomas Gleixner 176d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 17728d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 178d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 179581b605aSStephen Rothwell 180581b605aSStephen Rothwell return pp; 181581b605aSStephen Rothwell } 182581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 183581b605aSStephen Rothwell 184e91edcf5SGrant Likely /** 185e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 186e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 187e91edcf5SGrant Likely * of_node_put() will be called on it 188e91edcf5SGrant Likely * 189e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 190e91edcf5SGrant Likely * of_node_put() on it when done. 191e91edcf5SGrant Likely */ 192e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 193e91edcf5SGrant Likely { 194e91edcf5SGrant Likely struct device_node *np; 195d25d8694SBenjamin Herrenschmidt unsigned long flags; 196e91edcf5SGrant Likely 197d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 198465aac6dSRandy Dunlap np = prev ? prev->allnext : of_allnodes; 199e91edcf5SGrant Likely for (; np != NULL; np = np->allnext) 200e91edcf5SGrant Likely if (of_node_get(np)) 201e91edcf5SGrant Likely break; 202e91edcf5SGrant Likely of_node_put(prev); 203d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 204e91edcf5SGrant Likely return np; 205e91edcf5SGrant Likely } 206e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 207e91edcf5SGrant Likely 20897e873e5SStephen Rothwell /* 20997e873e5SStephen Rothwell * Find a property with a given name for a given node 21097e873e5SStephen Rothwell * and return the value. 21197e873e5SStephen Rothwell */ 21228d0e36bSThomas Gleixner static const void *__of_get_property(const struct device_node *np, 21328d0e36bSThomas Gleixner const char *name, int *lenp) 21428d0e36bSThomas Gleixner { 21528d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 21628d0e36bSThomas Gleixner 21728d0e36bSThomas Gleixner return pp ? pp->value : NULL; 21828d0e36bSThomas Gleixner } 21928d0e36bSThomas Gleixner 22028d0e36bSThomas Gleixner /* 22128d0e36bSThomas Gleixner * Find a property with a given name for a given node 22228d0e36bSThomas Gleixner * and return the value. 22328d0e36bSThomas Gleixner */ 22497e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 22597e873e5SStephen Rothwell int *lenp) 22697e873e5SStephen Rothwell { 22797e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 22897e873e5SStephen Rothwell 22997e873e5SStephen Rothwell return pp ? pp->value : NULL; 23097e873e5SStephen Rothwell } 23197e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 2320081cbc3SStephen Rothwell 2330081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in 2340081cbc3SStephen Rothwell * the device's "compatible" property 2350081cbc3SStephen Rothwell */ 23628d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 2370081cbc3SStephen Rothwell const char *compat) 2380081cbc3SStephen Rothwell { 2390081cbc3SStephen Rothwell const char* cp; 2400081cbc3SStephen Rothwell int cplen, l; 2410081cbc3SStephen Rothwell 24228d0e36bSThomas Gleixner cp = __of_get_property(device, "compatible", &cplen); 2430081cbc3SStephen Rothwell if (cp == NULL) 2440081cbc3SStephen Rothwell return 0; 2450081cbc3SStephen Rothwell while (cplen > 0) { 2460081cbc3SStephen Rothwell if (of_compat_cmp(cp, compat, strlen(compat)) == 0) 2470081cbc3SStephen Rothwell return 1; 2480081cbc3SStephen Rothwell l = strlen(cp) + 1; 2490081cbc3SStephen Rothwell cp += l; 2500081cbc3SStephen Rothwell cplen -= l; 2510081cbc3SStephen Rothwell } 2520081cbc3SStephen Rothwell 2530081cbc3SStephen Rothwell return 0; 2540081cbc3SStephen Rothwell } 25528d0e36bSThomas Gleixner 25628d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 25728d0e36bSThomas Gleixner * the device's "compatible" property 25828d0e36bSThomas Gleixner */ 25928d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 26028d0e36bSThomas Gleixner const char *compat) 26128d0e36bSThomas Gleixner { 262d6d3c4e6SThomas Gleixner unsigned long flags; 26328d0e36bSThomas Gleixner int res; 26428d0e36bSThomas Gleixner 265d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 26628d0e36bSThomas Gleixner res = __of_device_is_compatible(device, compat); 267d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 26828d0e36bSThomas Gleixner return res; 26928d0e36bSThomas Gleixner } 2700081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 271e679c5f4SStephen Rothwell 272e679c5f4SStephen Rothwell /** 27371a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 2741f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 2751f43cfb9SGrant Likely * 2761f43cfb9SGrant Likely * Returns true if the root node has the given value in its 2771f43cfb9SGrant Likely * compatible property. 2781f43cfb9SGrant Likely */ 27971a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 2801f43cfb9SGrant Likely { 2811f43cfb9SGrant Likely struct device_node *root; 2821f43cfb9SGrant Likely int rc = 0; 2831f43cfb9SGrant Likely 2841f43cfb9SGrant Likely root = of_find_node_by_path("/"); 2851f43cfb9SGrant Likely if (root) { 2861f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 2871f43cfb9SGrant Likely of_node_put(root); 2881f43cfb9SGrant Likely } 2891f43cfb9SGrant Likely return rc; 2901f43cfb9SGrant Likely } 29171a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 2921f43cfb9SGrant Likely 2931f43cfb9SGrant Likely /** 294c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 295834d97d4SJosh Boyer * 296c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 297834d97d4SJosh Boyer * 298834d97d4SJosh Boyer * Returns 1 if the status property is absent or set to "okay" or "ok", 299834d97d4SJosh Boyer * 0 otherwise 300834d97d4SJosh Boyer */ 301c31a0c05SStephen Warren static int __of_device_is_available(const struct device_node *device) 302834d97d4SJosh Boyer { 303834d97d4SJosh Boyer const char *status; 304834d97d4SJosh Boyer int statlen; 305834d97d4SJosh Boyer 306c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 307834d97d4SJosh Boyer if (status == NULL) 308834d97d4SJosh Boyer return 1; 309834d97d4SJosh Boyer 310834d97d4SJosh Boyer if (statlen > 0) { 311834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 312834d97d4SJosh Boyer return 1; 313834d97d4SJosh Boyer } 314834d97d4SJosh Boyer 315834d97d4SJosh Boyer return 0; 316834d97d4SJosh Boyer } 317c31a0c05SStephen Warren 318c31a0c05SStephen Warren /** 319c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 320c31a0c05SStephen Warren * 321c31a0c05SStephen Warren * @device: Node to check for availability 322c31a0c05SStephen Warren * 323c31a0c05SStephen Warren * Returns 1 if the status property is absent or set to "okay" or "ok", 324c31a0c05SStephen Warren * 0 otherwise 325c31a0c05SStephen Warren */ 326c31a0c05SStephen Warren int of_device_is_available(const struct device_node *device) 327c31a0c05SStephen Warren { 328c31a0c05SStephen Warren unsigned long flags; 329c31a0c05SStephen Warren int res; 330c31a0c05SStephen Warren 331c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 332c31a0c05SStephen Warren res = __of_device_is_available(device); 333c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 334c31a0c05SStephen Warren return res; 335c31a0c05SStephen Warren 336c31a0c05SStephen Warren } 337834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 338834d97d4SJosh Boyer 339834d97d4SJosh Boyer /** 340e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 341e679c5f4SStephen Rothwell * @node: Node to get parent 342e679c5f4SStephen Rothwell * 343e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 344e679c5f4SStephen Rothwell * of_node_put() on it when done. 345e679c5f4SStephen Rothwell */ 346e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 347e679c5f4SStephen Rothwell { 348e679c5f4SStephen Rothwell struct device_node *np; 349d6d3c4e6SThomas Gleixner unsigned long flags; 350e679c5f4SStephen Rothwell 351e679c5f4SStephen Rothwell if (!node) 352e679c5f4SStephen Rothwell return NULL; 353e679c5f4SStephen Rothwell 354d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 355e679c5f4SStephen Rothwell np = of_node_get(node->parent); 356d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 357e679c5f4SStephen Rothwell return np; 358e679c5f4SStephen Rothwell } 359e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 360d1cd355aSStephen Rothwell 361d1cd355aSStephen Rothwell /** 362f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 363f4eb0107SMichael Ellerman * @node: Node to get parent of 364f4eb0107SMichael Ellerman * 365f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 366f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 367f4eb0107SMichael Ellerman * through a node's parents. 368f4eb0107SMichael Ellerman * 369f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 370f4eb0107SMichael Ellerman * of_node_put() on it when done. 371f4eb0107SMichael Ellerman */ 372f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 373f4eb0107SMichael Ellerman { 374f4eb0107SMichael Ellerman struct device_node *parent; 375d6d3c4e6SThomas Gleixner unsigned long flags; 376f4eb0107SMichael Ellerman 377f4eb0107SMichael Ellerman if (!node) 378f4eb0107SMichael Ellerman return NULL; 379f4eb0107SMichael Ellerman 380d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 381f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 382f4eb0107SMichael Ellerman of_node_put(node); 383d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 384f4eb0107SMichael Ellerman return parent; 385f4eb0107SMichael Ellerman } 3866695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 387f4eb0107SMichael Ellerman 388f4eb0107SMichael Ellerman /** 389d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 390d1cd355aSStephen Rothwell * @node: parent node 391d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 392d1cd355aSStephen Rothwell * 393d1cd355aSStephen Rothwell * Returns a node pointer with refcount incremented, use 394d1cd355aSStephen Rothwell * of_node_put() on it when done. 395d1cd355aSStephen Rothwell */ 396d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 397d1cd355aSStephen Rothwell struct device_node *prev) 398d1cd355aSStephen Rothwell { 399d1cd355aSStephen Rothwell struct device_node *next; 400d6d3c4e6SThomas Gleixner unsigned long flags; 401d1cd355aSStephen Rothwell 402d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 403d1cd355aSStephen Rothwell next = prev ? prev->sibling : node->child; 404d1cd355aSStephen Rothwell for (; next; next = next->sibling) 405d1cd355aSStephen Rothwell if (of_node_get(next)) 406d1cd355aSStephen Rothwell break; 407d1cd355aSStephen Rothwell of_node_put(prev); 408d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 409d1cd355aSStephen Rothwell return next; 410d1cd355aSStephen Rothwell } 411d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 4121ef4d424SStephen Rothwell 4131ef4d424SStephen Rothwell /** 4143296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 4153296193dSTimur Tabi * @node: parent node 4163296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 4173296193dSTimur Tabi * 4183296193dSTimur Tabi * This function is like of_get_next_child(), except that it 4193296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 4203296193dSTimur Tabi */ 4213296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 4223296193dSTimur Tabi struct device_node *prev) 4233296193dSTimur Tabi { 4243296193dSTimur Tabi struct device_node *next; 425d25d8694SBenjamin Herrenschmidt unsigned long flags; 4263296193dSTimur Tabi 427d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 4283296193dSTimur Tabi next = prev ? prev->sibling : node->child; 4293296193dSTimur Tabi for (; next; next = next->sibling) { 430c31a0c05SStephen Warren if (!__of_device_is_available(next)) 4313296193dSTimur Tabi continue; 4323296193dSTimur Tabi if (of_node_get(next)) 4333296193dSTimur Tabi break; 4343296193dSTimur Tabi } 4353296193dSTimur Tabi of_node_put(prev); 436d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 4373296193dSTimur Tabi return next; 4383296193dSTimur Tabi } 4393296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 4403296193dSTimur Tabi 4413296193dSTimur Tabi /** 4429c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 4439c19761aSSrinivas Kandagatla * @node: parent node 4449c19761aSSrinivas Kandagatla * @name: child name to look for. 4459c19761aSSrinivas Kandagatla * 4469c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 4479c19761aSSrinivas Kandagatla * 4489c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 4499c19761aSSrinivas Kandagatla * of_node_put() on it when done. 4509c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 4519c19761aSSrinivas Kandagatla */ 4529c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 4539c19761aSSrinivas Kandagatla const char *name) 4549c19761aSSrinivas Kandagatla { 4559c19761aSSrinivas Kandagatla struct device_node *child; 4569c19761aSSrinivas Kandagatla 4579c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 4589c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 4599c19761aSSrinivas Kandagatla break; 4609c19761aSSrinivas Kandagatla return child; 4619c19761aSSrinivas Kandagatla } 4629c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 4639c19761aSSrinivas Kandagatla 4649c19761aSSrinivas Kandagatla /** 4651ef4d424SStephen Rothwell * of_find_node_by_path - Find a node matching a full OF path 4661ef4d424SStephen Rothwell * @path: The full path to match 4671ef4d424SStephen Rothwell * 4681ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4691ef4d424SStephen Rothwell * of_node_put() on it when done. 4701ef4d424SStephen Rothwell */ 4711ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path) 4721ef4d424SStephen Rothwell { 473465aac6dSRandy Dunlap struct device_node *np = of_allnodes; 474d6d3c4e6SThomas Gleixner unsigned long flags; 4751ef4d424SStephen Rothwell 476d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 4771ef4d424SStephen Rothwell for (; np; np = np->allnext) { 4781ef4d424SStephen Rothwell if (np->full_name && (of_node_cmp(np->full_name, path) == 0) 4791ef4d424SStephen Rothwell && of_node_get(np)) 4801ef4d424SStephen Rothwell break; 4811ef4d424SStephen Rothwell } 482d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 4831ef4d424SStephen Rothwell return np; 4841ef4d424SStephen Rothwell } 4851ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path); 4861ef4d424SStephen Rothwell 4871ef4d424SStephen Rothwell /** 4881ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 4891ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 4901ef4d424SStephen Rothwell * you pass will not be searched, only the next one 4911ef4d424SStephen Rothwell * will; typically, you pass what the previous call 4921ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 4931ef4d424SStephen Rothwell * @name: The name string to match against 4941ef4d424SStephen Rothwell * 4951ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 4961ef4d424SStephen Rothwell * of_node_put() on it when done. 4971ef4d424SStephen Rothwell */ 4981ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 4991ef4d424SStephen Rothwell const char *name) 5001ef4d424SStephen Rothwell { 5011ef4d424SStephen Rothwell struct device_node *np; 502d6d3c4e6SThomas Gleixner unsigned long flags; 5031ef4d424SStephen Rothwell 504d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 505465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 5061ef4d424SStephen Rothwell for (; np; np = np->allnext) 5071ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 5081ef4d424SStephen Rothwell && of_node_get(np)) 5091ef4d424SStephen Rothwell break; 5101ef4d424SStephen Rothwell of_node_put(from); 511d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 5121ef4d424SStephen Rothwell return np; 5131ef4d424SStephen Rothwell } 5141ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 5151ef4d424SStephen Rothwell 5161ef4d424SStephen Rothwell /** 5171ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 5181ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 5191ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 5201ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 5211ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 5221ef4d424SStephen Rothwell * called on from for you. 5231ef4d424SStephen Rothwell * @type: The type string to match against 5241ef4d424SStephen Rothwell * 5251ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 5261ef4d424SStephen Rothwell * of_node_put() on it when done. 5271ef4d424SStephen Rothwell */ 5281ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 5291ef4d424SStephen Rothwell const char *type) 5301ef4d424SStephen Rothwell { 5311ef4d424SStephen Rothwell struct device_node *np; 532d6d3c4e6SThomas Gleixner unsigned long flags; 5331ef4d424SStephen Rothwell 534d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 535465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 5361ef4d424SStephen Rothwell for (; np; np = np->allnext) 5371ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 5381ef4d424SStephen Rothwell && of_node_get(np)) 5391ef4d424SStephen Rothwell break; 5401ef4d424SStephen Rothwell of_node_put(from); 541d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 5421ef4d424SStephen Rothwell return np; 5431ef4d424SStephen Rothwell } 5441ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 5451ef4d424SStephen Rothwell 5461ef4d424SStephen Rothwell /** 5471ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 5481ef4d424SStephen Rothwell * tokens in its "compatible" property 5491ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 5501ef4d424SStephen Rothwell * you pass will not be searched, only the next one 5511ef4d424SStephen Rothwell * will; typically, you pass what the previous call 5521ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 5531ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 5541ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 5551ef4d424SStephen Rothwell * "compatible" list. 5561ef4d424SStephen Rothwell * 5571ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 5581ef4d424SStephen Rothwell * of_node_put() on it when done. 5591ef4d424SStephen Rothwell */ 5601ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 5611ef4d424SStephen Rothwell const char *type, const char *compatible) 5621ef4d424SStephen Rothwell { 5631ef4d424SStephen Rothwell struct device_node *np; 564d6d3c4e6SThomas Gleixner unsigned long flags; 5651ef4d424SStephen Rothwell 566d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 567465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 5681ef4d424SStephen Rothwell for (; np; np = np->allnext) { 5691ef4d424SStephen Rothwell if (type 5701ef4d424SStephen Rothwell && !(np->type && (of_node_cmp(np->type, type) == 0))) 5711ef4d424SStephen Rothwell continue; 57228d0e36bSThomas Gleixner if (__of_device_is_compatible(np, compatible) && 57328d0e36bSThomas Gleixner of_node_get(np)) 5741ef4d424SStephen Rothwell break; 5751ef4d424SStephen Rothwell } 5761ef4d424SStephen Rothwell of_node_put(from); 577d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 5781ef4d424SStephen Rothwell return np; 5791ef4d424SStephen Rothwell } 5801ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 581283029d1SGrant Likely 582283029d1SGrant Likely /** 5831e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 5841e291b14SMichael Ellerman * the given name. 5851e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 5861e291b14SMichael Ellerman * you pass will not be searched, only the next one 5871e291b14SMichael Ellerman * will; typically, you pass what the previous call 5881e291b14SMichael Ellerman * returned. of_node_put() will be called on it 5891e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 5901e291b14SMichael Ellerman * 5911e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 5921e291b14SMichael Ellerman * of_node_put() on it when done. 5931e291b14SMichael Ellerman */ 5941e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 5951e291b14SMichael Ellerman const char *prop_name) 5961e291b14SMichael Ellerman { 5971e291b14SMichael Ellerman struct device_node *np; 5981e291b14SMichael Ellerman struct property *pp; 599d6d3c4e6SThomas Gleixner unsigned long flags; 6001e291b14SMichael Ellerman 601d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 602465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 6031e291b14SMichael Ellerman for (; np; np = np->allnext) { 604a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 6051e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 6061e291b14SMichael Ellerman of_node_get(np); 6071e291b14SMichael Ellerman goto out; 6081e291b14SMichael Ellerman } 6091e291b14SMichael Ellerman } 6101e291b14SMichael Ellerman } 6111e291b14SMichael Ellerman out: 6121e291b14SMichael Ellerman of_node_put(from); 613d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 6141e291b14SMichael Ellerman return np; 6151e291b14SMichael Ellerman } 6161e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 6171e291b14SMichael Ellerman 61828d0e36bSThomas Gleixner static 61928d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 620283029d1SGrant Likely const struct device_node *node) 621283029d1SGrant Likely { 622a52f07ecSGrant Likely if (!matches) 623a52f07ecSGrant Likely return NULL; 624a52f07ecSGrant Likely 625283029d1SGrant Likely while (matches->name[0] || matches->type[0] || matches->compatible[0]) { 626283029d1SGrant Likely int match = 1; 627283029d1SGrant Likely if (matches->name[0]) 628283029d1SGrant Likely match &= node->name 629283029d1SGrant Likely && !strcmp(matches->name, node->name); 630283029d1SGrant Likely if (matches->type[0]) 631283029d1SGrant Likely match &= node->type 632283029d1SGrant Likely && !strcmp(matches->type, node->type); 633bc51b0c2SLinus Torvalds if (matches->compatible[0]) 63428d0e36bSThomas Gleixner match &= __of_device_is_compatible(node, 635bc51b0c2SLinus Torvalds matches->compatible); 636bc51b0c2SLinus Torvalds if (match) 637283029d1SGrant Likely return matches; 638283029d1SGrant Likely matches++; 639283029d1SGrant Likely } 640283029d1SGrant Likely return NULL; 641283029d1SGrant Likely } 64228d0e36bSThomas Gleixner 64328d0e36bSThomas Gleixner /** 64428d0e36bSThomas Gleixner * of_match_node - Tell if an device_node has a matching of_match structure 64528d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 64628d0e36bSThomas Gleixner * @node: the of device structure to match against 64728d0e36bSThomas Gleixner * 64828d0e36bSThomas Gleixner * Low level utility function used by device matching. 64928d0e36bSThomas Gleixner */ 65028d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 65128d0e36bSThomas Gleixner const struct device_node *node) 65228d0e36bSThomas Gleixner { 65328d0e36bSThomas Gleixner const struct of_device_id *match; 654d6d3c4e6SThomas Gleixner unsigned long flags; 65528d0e36bSThomas Gleixner 656d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 65728d0e36bSThomas Gleixner match = __of_match_node(matches, node); 658d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 65928d0e36bSThomas Gleixner return match; 66028d0e36bSThomas Gleixner } 661283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 662283029d1SGrant Likely 663283029d1SGrant Likely /** 66450c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 66550c8af4cSStephen Warren * match table. 666283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 667283029d1SGrant Likely * you pass will not be searched, only the next one 668283029d1SGrant Likely * will; typically, you pass what the previous call 669283029d1SGrant Likely * returned. of_node_put() will be called on it 670283029d1SGrant Likely * @matches: array of of device match structures to search in 67150c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 672283029d1SGrant Likely * 673283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 674283029d1SGrant Likely * of_node_put() on it when done. 675283029d1SGrant Likely */ 67650c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 67750c8af4cSStephen Warren const struct of_device_id *matches, 67850c8af4cSStephen Warren const struct of_device_id **match) 679283029d1SGrant Likely { 680283029d1SGrant Likely struct device_node *np; 681dc71bcf1SThomas Abraham const struct of_device_id *m; 682d6d3c4e6SThomas Gleixner unsigned long flags; 683283029d1SGrant Likely 68450c8af4cSStephen Warren if (match) 68550c8af4cSStephen Warren *match = NULL; 68650c8af4cSStephen Warren 687d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 688465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 689283029d1SGrant Likely for (; np; np = np->allnext) { 69028d0e36bSThomas Gleixner m = __of_match_node(matches, np); 691dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 69250c8af4cSStephen Warren if (match) 693dc71bcf1SThomas Abraham *match = m; 694283029d1SGrant Likely break; 695283029d1SGrant Likely } 69650c8af4cSStephen Warren } 697283029d1SGrant Likely of_node_put(from); 698d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 699283029d1SGrant Likely return np; 700283029d1SGrant Likely } 70180c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 7023f07af49SGrant Likely 7033f07af49SGrant Likely /** 7043f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 7053f07af49SGrant Likely * @node: pointer to a device tree node 7063f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 7073f07af49SGrant Likely * @len: Length of modalias value 7083f07af49SGrant Likely * 7092ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 7102ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 7112ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 7122ffe8c5fSGrant Likely * from the first entry in the compatible list property. 7133f07af49SGrant Likely * 7142ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 7153f07af49SGrant Likely */ 7163f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 7173f07af49SGrant Likely { 7182ffe8c5fSGrant Likely const char *compatible, *p; 7192ffe8c5fSGrant Likely int cplen; 7203f07af49SGrant Likely 7213f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 7222ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 7233f07af49SGrant Likely return -ENODEV; 7243f07af49SGrant Likely p = strchr(compatible, ','); 7252ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 7263f07af49SGrant Likely return 0; 7273f07af49SGrant Likely } 7283f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 7293f07af49SGrant Likely 73064b60e09SAnton Vorontsov /** 73189751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 73289751a7cSJeremy Kerr * @handle: phandle of the node to find 73389751a7cSJeremy Kerr * 73489751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 73589751a7cSJeremy Kerr * of_node_put() on it when done. 73689751a7cSJeremy Kerr */ 73789751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 73889751a7cSJeremy Kerr { 73989751a7cSJeremy Kerr struct device_node *np; 740d25d8694SBenjamin Herrenschmidt unsigned long flags; 74189751a7cSJeremy Kerr 742d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 743465aac6dSRandy Dunlap for (np = of_allnodes; np; np = np->allnext) 74489751a7cSJeremy Kerr if (np->phandle == handle) 74589751a7cSJeremy Kerr break; 74689751a7cSJeremy Kerr of_node_get(np); 747d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 74889751a7cSJeremy Kerr return np; 74989751a7cSJeremy Kerr } 75089751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 75189751a7cSJeremy Kerr 75289751a7cSJeremy Kerr /** 753daeec1f0STony Prisk * of_find_property_value_of_size 754daeec1f0STony Prisk * 755daeec1f0STony Prisk * @np: device node from which the property value is to be read. 756daeec1f0STony Prisk * @propname: name of the property to be searched. 757daeec1f0STony Prisk * @len: requested length of property value 758daeec1f0STony Prisk * 759daeec1f0STony Prisk * Search for a property in a device node and valid the requested size. 760daeec1f0STony Prisk * Returns the property value on success, -EINVAL if the property does not 761daeec1f0STony Prisk * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 762daeec1f0STony Prisk * property data isn't large enough. 763daeec1f0STony Prisk * 764daeec1f0STony Prisk */ 765daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np, 766daeec1f0STony Prisk const char *propname, u32 len) 767daeec1f0STony Prisk { 768daeec1f0STony Prisk struct property *prop = of_find_property(np, propname, NULL); 769daeec1f0STony Prisk 770daeec1f0STony Prisk if (!prop) 771daeec1f0STony Prisk return ERR_PTR(-EINVAL); 772daeec1f0STony Prisk if (!prop->value) 773daeec1f0STony Prisk return ERR_PTR(-ENODATA); 774daeec1f0STony Prisk if (len > prop->length) 775daeec1f0STony Prisk return ERR_PTR(-EOVERFLOW); 776daeec1f0STony Prisk 777daeec1f0STony Prisk return prop->value; 778daeec1f0STony Prisk } 779daeec1f0STony Prisk 780daeec1f0STony Prisk /** 7813daf3726STony Prisk * of_property_read_u32_index - Find and read a u32 from a multi-value property. 7823daf3726STony Prisk * 7833daf3726STony Prisk * @np: device node from which the property value is to be read. 7843daf3726STony Prisk * @propname: name of the property to be searched. 7853daf3726STony Prisk * @index: index of the u32 in the list of values 7863daf3726STony Prisk * @out_value: pointer to return value, modified only if no error. 7873daf3726STony Prisk * 7883daf3726STony Prisk * Search for a property in a device node and read nth 32-bit value from 7893daf3726STony Prisk * it. Returns 0 on success, -EINVAL if the property does not exist, 7903daf3726STony Prisk * -ENODATA if property does not have a value, and -EOVERFLOW if the 7913daf3726STony Prisk * property data isn't large enough. 7923daf3726STony Prisk * 7933daf3726STony Prisk * The out_value is modified only if a valid u32 value can be decoded. 7943daf3726STony Prisk */ 7953daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np, 7963daf3726STony Prisk const char *propname, 7973daf3726STony Prisk u32 index, u32 *out_value) 7983daf3726STony Prisk { 799daeec1f0STony Prisk const u32 *val = of_find_property_value_of_size(np, propname, 800daeec1f0STony Prisk ((index + 1) * sizeof(*out_value))); 8013daf3726STony Prisk 802daeec1f0STony Prisk if (IS_ERR(val)) 803daeec1f0STony Prisk return PTR_ERR(val); 8043daf3726STony Prisk 805daeec1f0STony Prisk *out_value = be32_to_cpup(((__be32 *)val) + index); 8063daf3726STony Prisk return 0; 8073daf3726STony Prisk } 8083daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index); 8093daf3726STony Prisk 8103daf3726STony Prisk /** 811be193249SViresh Kumar * of_property_read_u8_array - Find and read an array of u8 from a property. 812be193249SViresh Kumar * 813be193249SViresh Kumar * @np: device node from which the property value is to be read. 814be193249SViresh Kumar * @propname: name of the property to be searched. 815792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 816be193249SViresh Kumar * @sz: number of array elements to read 817be193249SViresh Kumar * 818be193249SViresh Kumar * Search for a property in a device node and read 8-bit value(s) from 819be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 820be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 821be193249SViresh Kumar * property data isn't large enough. 822be193249SViresh Kumar * 823be193249SViresh Kumar * dts entry of array should be like: 824be193249SViresh Kumar * property = /bits/ 8 <0x50 0x60 0x70>; 825be193249SViresh Kumar * 826792efb84SLad, Prabhakar * The out_values is modified only if a valid u8 value can be decoded. 827be193249SViresh Kumar */ 828be193249SViresh Kumar int of_property_read_u8_array(const struct device_node *np, 829be193249SViresh Kumar const char *propname, u8 *out_values, size_t sz) 830be193249SViresh Kumar { 831daeec1f0STony Prisk const u8 *val = of_find_property_value_of_size(np, propname, 832daeec1f0STony Prisk (sz * sizeof(*out_values))); 833be193249SViresh Kumar 834daeec1f0STony Prisk if (IS_ERR(val)) 835daeec1f0STony Prisk return PTR_ERR(val); 836be193249SViresh Kumar 837be193249SViresh Kumar while (sz--) 838be193249SViresh Kumar *out_values++ = *val++; 839be193249SViresh Kumar return 0; 840be193249SViresh Kumar } 841be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u8_array); 842be193249SViresh Kumar 843be193249SViresh Kumar /** 844be193249SViresh Kumar * of_property_read_u16_array - Find and read an array of u16 from a property. 845be193249SViresh Kumar * 846be193249SViresh Kumar * @np: device node from which the property value is to be read. 847be193249SViresh Kumar * @propname: name of the property to be searched. 848792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 849be193249SViresh Kumar * @sz: number of array elements to read 850be193249SViresh Kumar * 851be193249SViresh Kumar * Search for a property in a device node and read 16-bit value(s) from 852be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 853be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 854be193249SViresh Kumar * property data isn't large enough. 855be193249SViresh Kumar * 856be193249SViresh Kumar * dts entry of array should be like: 857be193249SViresh Kumar * property = /bits/ 16 <0x5000 0x6000 0x7000>; 858be193249SViresh Kumar * 859792efb84SLad, Prabhakar * The out_values is modified only if a valid u16 value can be decoded. 860be193249SViresh Kumar */ 861be193249SViresh Kumar int of_property_read_u16_array(const struct device_node *np, 862be193249SViresh Kumar const char *propname, u16 *out_values, size_t sz) 863be193249SViresh Kumar { 864daeec1f0STony Prisk const __be16 *val = of_find_property_value_of_size(np, propname, 865daeec1f0STony Prisk (sz * sizeof(*out_values))); 866be193249SViresh Kumar 867daeec1f0STony Prisk if (IS_ERR(val)) 868daeec1f0STony Prisk return PTR_ERR(val); 869be193249SViresh Kumar 870be193249SViresh Kumar while (sz--) 871be193249SViresh Kumar *out_values++ = be16_to_cpup(val++); 872be193249SViresh Kumar return 0; 873be193249SViresh Kumar } 874be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u16_array); 875be193249SViresh Kumar 876be193249SViresh Kumar /** 8770e373639SRob Herring * of_property_read_u32_array - Find and read an array of 32 bit integers 8780e373639SRob Herring * from a property. 8790e373639SRob Herring * 880a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 881a3b85363SThomas Abraham * @propname: name of the property to be searched. 882792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 883be193249SViresh Kumar * @sz: number of array elements to read 884a3b85363SThomas Abraham * 8850e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 886a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 887a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 888a3b85363SThomas Abraham * property data isn't large enough. 889a3b85363SThomas Abraham * 890792efb84SLad, Prabhakar * The out_values is modified only if a valid u32 value can be decoded. 891a3b85363SThomas Abraham */ 892aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np, 893aac285c6SJamie Iles const char *propname, u32 *out_values, 894aac285c6SJamie Iles size_t sz) 895a3b85363SThomas Abraham { 896daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 897daeec1f0STony Prisk (sz * sizeof(*out_values))); 898a3b85363SThomas Abraham 899daeec1f0STony Prisk if (IS_ERR(val)) 900daeec1f0STony Prisk return PTR_ERR(val); 9010e373639SRob Herring 9020e373639SRob Herring while (sz--) 9030e373639SRob Herring *out_values++ = be32_to_cpup(val++); 904a3b85363SThomas Abraham return 0; 905a3b85363SThomas Abraham } 9060e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array); 907a3b85363SThomas Abraham 908a3b85363SThomas Abraham /** 9094cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 9104cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 9114cd7f7a3SJamie Iles * @propname: name of the property to be searched. 9124cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 9134cd7f7a3SJamie Iles * 9144cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 9154cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 9164cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 9174cd7f7a3SJamie Iles * property data isn't large enough. 9184cd7f7a3SJamie Iles * 9194cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 9204cd7f7a3SJamie Iles */ 9214cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 9224cd7f7a3SJamie Iles u64 *out_value) 9234cd7f7a3SJamie Iles { 924daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 925daeec1f0STony Prisk sizeof(*out_value)); 9264cd7f7a3SJamie Iles 927daeec1f0STony Prisk if (IS_ERR(val)) 928daeec1f0STony Prisk return PTR_ERR(val); 929daeec1f0STony Prisk 930daeec1f0STony Prisk *out_value = of_read_number(val, 2); 9314cd7f7a3SJamie Iles return 0; 9324cd7f7a3SJamie Iles } 9334cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 9344cd7f7a3SJamie Iles 9354cd7f7a3SJamie Iles /** 936a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 937a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 938a3b85363SThomas Abraham * @propname: name of the property to be searched. 939a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 940a3b85363SThomas Abraham * return value is 0. 941a3b85363SThomas Abraham * 942a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 943a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 944a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 945a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 946a3b85363SThomas Abraham * within the length of the property data. 947a3b85363SThomas Abraham * 948a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 949a3b85363SThomas Abraham */ 950aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname, 951f09bc831SShawn Guo const char **out_string) 952a3b85363SThomas Abraham { 953a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 954a3b85363SThomas Abraham if (!prop) 955a3b85363SThomas Abraham return -EINVAL; 956a3b85363SThomas Abraham if (!prop->value) 957a3b85363SThomas Abraham return -ENODATA; 958a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 959a3b85363SThomas Abraham return -EILSEQ; 960a3b85363SThomas Abraham *out_string = prop->value; 961a3b85363SThomas Abraham return 0; 962a3b85363SThomas Abraham } 963a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 964a3b85363SThomas Abraham 965a3b85363SThomas Abraham /** 9664fcd15a0SBenoit Cousson * of_property_read_string_index - Find and read a string from a multiple 9674fcd15a0SBenoit Cousson * strings property. 9684fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 9694fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 9704fcd15a0SBenoit Cousson * @index: index of the string in the list of strings 9714fcd15a0SBenoit Cousson * @out_string: pointer to null terminated return string, modified only if 9724fcd15a0SBenoit Cousson * return value is 0. 9734fcd15a0SBenoit Cousson * 9744fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve a null 9754fcd15a0SBenoit Cousson * terminated string value (pointer to data, not a copy) in the list of strings 9764fcd15a0SBenoit Cousson * contained in that property. 9774fcd15a0SBenoit Cousson * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if 9784fcd15a0SBenoit Cousson * property does not have a value, and -EILSEQ if the string is not 9794fcd15a0SBenoit Cousson * null-terminated within the length of the property data. 9804fcd15a0SBenoit Cousson * 9814fcd15a0SBenoit Cousson * The out_string pointer is modified only if a valid string can be decoded. 9824fcd15a0SBenoit Cousson */ 9834fcd15a0SBenoit Cousson int of_property_read_string_index(struct device_node *np, const char *propname, 9844fcd15a0SBenoit Cousson int index, const char **output) 9854fcd15a0SBenoit Cousson { 9864fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 9874fcd15a0SBenoit Cousson int i = 0; 9884fcd15a0SBenoit Cousson size_t l = 0, total = 0; 9894fcd15a0SBenoit Cousson const char *p; 9904fcd15a0SBenoit Cousson 9914fcd15a0SBenoit Cousson if (!prop) 9924fcd15a0SBenoit Cousson return -EINVAL; 9934fcd15a0SBenoit Cousson if (!prop->value) 9944fcd15a0SBenoit Cousson return -ENODATA; 9954fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 9964fcd15a0SBenoit Cousson return -EILSEQ; 9974fcd15a0SBenoit Cousson 9984fcd15a0SBenoit Cousson p = prop->value; 9994fcd15a0SBenoit Cousson 10004fcd15a0SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l) { 10014fcd15a0SBenoit Cousson l = strlen(p) + 1; 100288af7f58SBenoit Cousson if (i++ == index) { 10034fcd15a0SBenoit Cousson *output = p; 10044fcd15a0SBenoit Cousson return 0; 10054fcd15a0SBenoit Cousson } 10064fcd15a0SBenoit Cousson } 10074fcd15a0SBenoit Cousson return -ENODATA; 10084fcd15a0SBenoit Cousson } 10094fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_read_string_index); 10104fcd15a0SBenoit Cousson 10117aff0fe3SGrant Likely /** 10127aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 10137aff0fe3SGrant Likely * @np: pointer to node containing string list property 10147aff0fe3SGrant Likely * @propname: string list property name 10157aff0fe3SGrant Likely * @string: pointer to string to search for in string list 10167aff0fe3SGrant Likely * 10177aff0fe3SGrant Likely * This function searches a string list property and returns the index 10187aff0fe3SGrant Likely * of a specific string value. 10197aff0fe3SGrant Likely */ 10207aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname, 10217aff0fe3SGrant Likely const char *string) 10227aff0fe3SGrant Likely { 10237aff0fe3SGrant Likely struct property *prop = of_find_property(np, propname, NULL); 10247aff0fe3SGrant Likely size_t l; 10257aff0fe3SGrant Likely int i; 10267aff0fe3SGrant Likely const char *p, *end; 10277aff0fe3SGrant Likely 10287aff0fe3SGrant Likely if (!prop) 10297aff0fe3SGrant Likely return -EINVAL; 10307aff0fe3SGrant Likely if (!prop->value) 10317aff0fe3SGrant Likely return -ENODATA; 10327aff0fe3SGrant Likely 10337aff0fe3SGrant Likely p = prop->value; 10347aff0fe3SGrant Likely end = p + prop->length; 10357aff0fe3SGrant Likely 10367aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 10377aff0fe3SGrant Likely l = strlen(p) + 1; 10387aff0fe3SGrant Likely if (p + l > end) 10397aff0fe3SGrant Likely return -EILSEQ; 10407aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 10417aff0fe3SGrant Likely if (strcmp(string, p) == 0) 10427aff0fe3SGrant Likely return i; /* Found it; return index */ 10437aff0fe3SGrant Likely } 10447aff0fe3SGrant Likely return -ENODATA; 10457aff0fe3SGrant Likely } 10467aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 10474fcd15a0SBenoit Cousson 10484fcd15a0SBenoit Cousson /** 10494fcd15a0SBenoit Cousson * of_property_count_strings - Find and return the number of strings from a 10504fcd15a0SBenoit Cousson * multiple strings property. 10514fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 10524fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 10534fcd15a0SBenoit Cousson * 10544fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve the number of null 10554fcd15a0SBenoit Cousson * terminated string contain in it. Returns the number of strings on 10564fcd15a0SBenoit Cousson * success, -EINVAL if the property does not exist, -ENODATA if property 10574fcd15a0SBenoit Cousson * does not have a value, and -EILSEQ if the string is not null-terminated 10584fcd15a0SBenoit Cousson * within the length of the property data. 10594fcd15a0SBenoit Cousson */ 10604fcd15a0SBenoit Cousson int of_property_count_strings(struct device_node *np, const char *propname) 10614fcd15a0SBenoit Cousson { 10624fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 10634fcd15a0SBenoit Cousson int i = 0; 10644fcd15a0SBenoit Cousson size_t l = 0, total = 0; 10654fcd15a0SBenoit Cousson const char *p; 10664fcd15a0SBenoit Cousson 10674fcd15a0SBenoit Cousson if (!prop) 10684fcd15a0SBenoit Cousson return -EINVAL; 10694fcd15a0SBenoit Cousson if (!prop->value) 10704fcd15a0SBenoit Cousson return -ENODATA; 10714fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 10724fcd15a0SBenoit Cousson return -EILSEQ; 10734fcd15a0SBenoit Cousson 10744fcd15a0SBenoit Cousson p = prop->value; 10754fcd15a0SBenoit Cousson 107688af7f58SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l, i++) 10774fcd15a0SBenoit Cousson l = strlen(p) + 1; 107888af7f58SBenoit Cousson 10794fcd15a0SBenoit Cousson return i; 10804fcd15a0SBenoit Cousson } 10814fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_count_strings); 10824fcd15a0SBenoit Cousson 1083bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1084bd69f73fSGrant Likely const char *list_name, 108564b60e09SAnton Vorontsov const char *cells_name, int index, 108615c9a0acSGrant Likely struct of_phandle_args *out_args) 108764b60e09SAnton Vorontsov { 108815c9a0acSGrant Likely const __be32 *list, *list_end; 108923ce04c0SGrant Likely int rc = 0, size, cur_index = 0; 109015c9a0acSGrant Likely uint32_t count = 0; 109164b60e09SAnton Vorontsov struct device_node *node = NULL; 10929a6b2e58SGrant Likely phandle phandle; 109364b60e09SAnton Vorontsov 109415c9a0acSGrant Likely /* Retrieve the phandle list property */ 109515c9a0acSGrant Likely list = of_get_property(np, list_name, &size); 109615c9a0acSGrant Likely if (!list) 10971af4c7f1SAlexandre Courbot return -ENOENT; 109815c9a0acSGrant Likely list_end = list + size / sizeof(*list); 109915c9a0acSGrant Likely 110015c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 110115c9a0acSGrant Likely while (list < list_end) { 110223ce04c0SGrant Likely rc = -EINVAL; 110315c9a0acSGrant Likely count = 0; 110415c9a0acSGrant Likely 110515c9a0acSGrant Likely /* 110615c9a0acSGrant Likely * If phandle is 0, then it is an empty entry with no 110715c9a0acSGrant Likely * arguments. Skip forward to the next entry. 110815c9a0acSGrant Likely */ 11099a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 111015c9a0acSGrant Likely if (phandle) { 111115c9a0acSGrant Likely /* 111215c9a0acSGrant Likely * Find the provider node and parse the #*-cells 111315c9a0acSGrant Likely * property to determine the argument length 111415c9a0acSGrant Likely */ 11159a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 111664b60e09SAnton Vorontsov if (!node) { 111715c9a0acSGrant Likely pr_err("%s: could not find phandle\n", 111864b60e09SAnton Vorontsov np->full_name); 111923ce04c0SGrant Likely goto err; 112015c9a0acSGrant Likely } 112115c9a0acSGrant Likely if (of_property_read_u32(node, cells_name, &count)) { 112215c9a0acSGrant Likely pr_err("%s: could not get %s for %s\n", 112315c9a0acSGrant Likely np->full_name, cells_name, 112415c9a0acSGrant Likely node->full_name); 112523ce04c0SGrant Likely goto err; 112615c9a0acSGrant Likely } 112715c9a0acSGrant Likely 112815c9a0acSGrant Likely /* 112915c9a0acSGrant Likely * Make sure that the arguments actually fit in the 113015c9a0acSGrant Likely * remaining property data length 113115c9a0acSGrant Likely */ 113215c9a0acSGrant Likely if (list + count > list_end) { 113315c9a0acSGrant Likely pr_err("%s: arguments longer than property\n", 113415c9a0acSGrant Likely np->full_name); 113523ce04c0SGrant Likely goto err; 113615c9a0acSGrant Likely } 113715c9a0acSGrant Likely } 113815c9a0acSGrant Likely 113915c9a0acSGrant Likely /* 114015c9a0acSGrant Likely * All of the error cases above bail out of the loop, so at 114115c9a0acSGrant Likely * this point, the parsing is successful. If the requested 114215c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 114315c9a0acSGrant Likely * or return -ENOENT for an empty entry. 114415c9a0acSGrant Likely */ 114523ce04c0SGrant Likely rc = -ENOENT; 114615c9a0acSGrant Likely if (cur_index == index) { 114715c9a0acSGrant Likely if (!phandle) 114823ce04c0SGrant Likely goto err; 114915c9a0acSGrant Likely 115015c9a0acSGrant Likely if (out_args) { 115115c9a0acSGrant Likely int i; 115215c9a0acSGrant Likely if (WARN_ON(count > MAX_PHANDLE_ARGS)) 115315c9a0acSGrant Likely count = MAX_PHANDLE_ARGS; 115415c9a0acSGrant Likely out_args->np = node; 115515c9a0acSGrant Likely out_args->args_count = count; 115615c9a0acSGrant Likely for (i = 0; i < count; i++) 115715c9a0acSGrant Likely out_args->args[i] = be32_to_cpup(list++); 1158b855f16bSTang Yuantian } else { 1159b855f16bSTang Yuantian of_node_put(node); 116015c9a0acSGrant Likely } 116123ce04c0SGrant Likely 116223ce04c0SGrant Likely /* Found it! return success */ 116315c9a0acSGrant Likely return 0; 116415c9a0acSGrant Likely } 116564b60e09SAnton Vorontsov 116664b60e09SAnton Vorontsov of_node_put(node); 116764b60e09SAnton Vorontsov node = NULL; 116815c9a0acSGrant Likely list += count; 116964b60e09SAnton Vorontsov cur_index++; 117064b60e09SAnton Vorontsov } 117164b60e09SAnton Vorontsov 117223ce04c0SGrant Likely /* 117323ce04c0SGrant Likely * Unlock node before returning result; will be one of: 117423ce04c0SGrant Likely * -ENOENT : index is for empty phandle 117523ce04c0SGrant Likely * -EINVAL : parsing error on data 1176bd69f73fSGrant Likely * [1..n] : Number of phandle (count mode; when index = -1) 117723ce04c0SGrant Likely */ 1178bd69f73fSGrant Likely rc = index < 0 ? cur_index : -ENOENT; 117923ce04c0SGrant Likely err: 118015c9a0acSGrant Likely if (node) 118164b60e09SAnton Vorontsov of_node_put(node); 118223ce04c0SGrant Likely return rc; 118364b60e09SAnton Vorontsov } 1184bd69f73fSGrant Likely 1185eded9dd4SStephen Warren /** 11865fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 11875fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 11885fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 11895fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 11905fba49e3SStephen Warren * the table 11915fba49e3SStephen Warren * 11925fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 11935fba49e3SStephen Warren * of_node_put() on it when done. 11945fba49e3SStephen Warren */ 11955fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 11965fba49e3SStephen Warren const char *phandle_name, int index) 11975fba49e3SStephen Warren { 11985fba49e3SStephen Warren const __be32 *phandle; 11995fba49e3SStephen Warren int size; 12005fba49e3SStephen Warren 12015fba49e3SStephen Warren phandle = of_get_property(np, phandle_name, &size); 12025fba49e3SStephen Warren if ((!phandle) || (size < sizeof(*phandle) * (index + 1))) 12035fba49e3SStephen Warren return NULL; 12045fba49e3SStephen Warren 12055fba49e3SStephen Warren return of_find_node_by_phandle(be32_to_cpup(phandle + index)); 12065fba49e3SStephen Warren } 12075fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 12085fba49e3SStephen Warren 12095fba49e3SStephen Warren /** 1210eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1211eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1212eded9dd4SStephen Warren * @list_name: property name that contains a list 1213eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1214eded9dd4SStephen Warren * @index: index of a phandle to parse out 1215eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1216eded9dd4SStephen Warren * 1217eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1218eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1219eded9dd4SStephen Warren * errno value. 1220eded9dd4SStephen Warren * 1221eded9dd4SStephen Warren * Caller is responsible to call of_node_put() on the returned out_args->node 1222eded9dd4SStephen Warren * pointer. 1223eded9dd4SStephen Warren * 1224eded9dd4SStephen Warren * Example: 1225eded9dd4SStephen Warren * 1226eded9dd4SStephen Warren * phandle1: node1 { 1227eded9dd4SStephen Warren * #list-cells = <2>; 1228eded9dd4SStephen Warren * } 1229eded9dd4SStephen Warren * 1230eded9dd4SStephen Warren * phandle2: node2 { 1231eded9dd4SStephen Warren * #list-cells = <1>; 1232eded9dd4SStephen Warren * } 1233eded9dd4SStephen Warren * 1234eded9dd4SStephen Warren * node3 { 1235eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1236eded9dd4SStephen Warren * } 1237eded9dd4SStephen Warren * 1238eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1239eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1240eded9dd4SStephen Warren */ 1241bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1242bd69f73fSGrant Likely const char *cells_name, int index, 1243bd69f73fSGrant Likely struct of_phandle_args *out_args) 1244bd69f73fSGrant Likely { 1245bd69f73fSGrant Likely if (index < 0) 1246bd69f73fSGrant Likely return -EINVAL; 1247bd69f73fSGrant Likely return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args); 1248bd69f73fSGrant Likely } 124915c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 125002af11b0SGrant Likely 1251bd69f73fSGrant Likely /** 1252bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1253bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1254bd69f73fSGrant Likely * @list_name: property name that contains a list 1255bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1256bd69f73fSGrant Likely * 1257bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1258bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1259bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1260bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1261bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1262bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1263bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1264bd69f73fSGrant Likely * phandle. 1265bd69f73fSGrant Likely */ 1266bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1267bd69f73fSGrant Likely const char *cells_name) 1268bd69f73fSGrant Likely { 1269bd69f73fSGrant Likely return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL); 1270bd69f73fSGrant Likely } 1271bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1272bd69f73fSGrant Likely 12731cf3d8b3SNathan Fontenot #if defined(CONFIG_OF_DYNAMIC) 12741cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np, 12751cf3d8b3SNathan Fontenot struct property *prop) 12761cf3d8b3SNathan Fontenot { 12771cf3d8b3SNathan Fontenot struct of_prop_reconfig pr; 12781cf3d8b3SNathan Fontenot 12791cf3d8b3SNathan Fontenot pr.dn = np; 12801cf3d8b3SNathan Fontenot pr.prop = prop; 12811cf3d8b3SNathan Fontenot return of_reconfig_notify(action, &pr); 12821cf3d8b3SNathan Fontenot } 12831cf3d8b3SNathan Fontenot #else 12841cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np, 12851cf3d8b3SNathan Fontenot struct property *prop) 12861cf3d8b3SNathan Fontenot { 12871cf3d8b3SNathan Fontenot return 0; 12881cf3d8b3SNathan Fontenot } 12891cf3d8b3SNathan Fontenot #endif 12901cf3d8b3SNathan Fontenot 129102af11b0SGrant Likely /** 129279d1c712SNathan Fontenot * of_add_property - Add a property to a node 129302af11b0SGrant Likely */ 129479d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 129502af11b0SGrant Likely { 129602af11b0SGrant Likely struct property **next; 129702af11b0SGrant Likely unsigned long flags; 12981cf3d8b3SNathan Fontenot int rc; 12991cf3d8b3SNathan Fontenot 13001cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); 13011cf3d8b3SNathan Fontenot if (rc) 13021cf3d8b3SNathan Fontenot return rc; 130302af11b0SGrant Likely 130402af11b0SGrant Likely prop->next = NULL; 1305d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 130602af11b0SGrant Likely next = &np->properties; 130702af11b0SGrant Likely while (*next) { 130802af11b0SGrant Likely if (strcmp(prop->name, (*next)->name) == 0) { 130902af11b0SGrant Likely /* duplicate ! don't insert it */ 1310d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 131102af11b0SGrant Likely return -1; 131202af11b0SGrant Likely } 131302af11b0SGrant Likely next = &(*next)->next; 131402af11b0SGrant Likely } 131502af11b0SGrant Likely *next = prop; 1316d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 131702af11b0SGrant Likely 131802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 131902af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 132002af11b0SGrant Likely if (np->pde) 132102af11b0SGrant Likely proc_device_tree_add_prop(np->pde, prop); 132202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 132302af11b0SGrant Likely 132402af11b0SGrant Likely return 0; 132502af11b0SGrant Likely } 132602af11b0SGrant Likely 132702af11b0SGrant Likely /** 132879d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 132902af11b0SGrant Likely * 133002af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 133102af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 133202af11b0SGrant Likely * Instead we just move the property to the "dead properties" 133302af11b0SGrant Likely * list, so it won't be found any more. 133402af11b0SGrant Likely */ 133579d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 133602af11b0SGrant Likely { 133702af11b0SGrant Likely struct property **next; 133802af11b0SGrant Likely unsigned long flags; 133902af11b0SGrant Likely int found = 0; 13401cf3d8b3SNathan Fontenot int rc; 13411cf3d8b3SNathan Fontenot 13421cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); 13431cf3d8b3SNathan Fontenot if (rc) 13441cf3d8b3SNathan Fontenot return rc; 134502af11b0SGrant Likely 1346d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 134702af11b0SGrant Likely next = &np->properties; 134802af11b0SGrant Likely while (*next) { 134902af11b0SGrant Likely if (*next == prop) { 135002af11b0SGrant Likely /* found the node */ 135102af11b0SGrant Likely *next = prop->next; 135202af11b0SGrant Likely prop->next = np->deadprops; 135302af11b0SGrant Likely np->deadprops = prop; 135402af11b0SGrant Likely found = 1; 135502af11b0SGrant Likely break; 135602af11b0SGrant Likely } 135702af11b0SGrant Likely next = &(*next)->next; 135802af11b0SGrant Likely } 1359d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 136002af11b0SGrant Likely 136102af11b0SGrant Likely if (!found) 136202af11b0SGrant Likely return -ENODEV; 136302af11b0SGrant Likely 136402af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 136502af11b0SGrant Likely /* try to remove the proc node as well */ 136602af11b0SGrant Likely if (np->pde) 136702af11b0SGrant Likely proc_device_tree_remove_prop(np->pde, prop); 136802af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 136902af11b0SGrant Likely 137002af11b0SGrant Likely return 0; 137102af11b0SGrant Likely } 137202af11b0SGrant Likely 137302af11b0SGrant Likely /* 137479d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1375475d0094SDong Aisheng * not exist, add it. 137602af11b0SGrant Likely * 137702af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 137802af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 137902af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 138002af11b0SGrant Likely * and add the new property to the property list 138102af11b0SGrant Likely */ 138279d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 138302af11b0SGrant Likely { 1384475d0094SDong Aisheng struct property **next, *oldprop; 138502af11b0SGrant Likely unsigned long flags; 13861cf3d8b3SNathan Fontenot int rc, found = 0; 13871cf3d8b3SNathan Fontenot 13881cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); 13891cf3d8b3SNathan Fontenot if (rc) 13901cf3d8b3SNathan Fontenot return rc; 139102af11b0SGrant Likely 1392475d0094SDong Aisheng if (!newprop->name) 1393475d0094SDong Aisheng return -EINVAL; 1394475d0094SDong Aisheng 1395475d0094SDong Aisheng oldprop = of_find_property(np, newprop->name, NULL); 1396475d0094SDong Aisheng if (!oldprop) 139779d1c712SNathan Fontenot return of_add_property(np, newprop); 1398475d0094SDong Aisheng 1399d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 140002af11b0SGrant Likely next = &np->properties; 140102af11b0SGrant Likely while (*next) { 140202af11b0SGrant Likely if (*next == oldprop) { 140302af11b0SGrant Likely /* found the node */ 140402af11b0SGrant Likely newprop->next = oldprop->next; 140502af11b0SGrant Likely *next = newprop; 140602af11b0SGrant Likely oldprop->next = np->deadprops; 140702af11b0SGrant Likely np->deadprops = oldprop; 140802af11b0SGrant Likely found = 1; 140902af11b0SGrant Likely break; 141002af11b0SGrant Likely } 141102af11b0SGrant Likely next = &(*next)->next; 141202af11b0SGrant Likely } 1413d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 141402af11b0SGrant Likely 141502af11b0SGrant Likely if (!found) 141602af11b0SGrant Likely return -ENODEV; 141702af11b0SGrant Likely 141802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 141902af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 142002af11b0SGrant Likely if (np->pde) 142102af11b0SGrant Likely proc_device_tree_update_prop(np->pde, newprop, oldprop); 142202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 142302af11b0SGrant Likely 142402af11b0SGrant Likely return 0; 142502af11b0SGrant Likely } 1426fcdeb7feSGrant Likely 1427fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC) 1428fcdeb7feSGrant Likely /* 1429fcdeb7feSGrant Likely * Support for dynamic device trees. 1430fcdeb7feSGrant Likely * 1431fcdeb7feSGrant Likely * On some platforms, the device tree can be manipulated at runtime. 1432fcdeb7feSGrant Likely * The routines in this section support adding, removing and changing 1433fcdeb7feSGrant Likely * device tree nodes. 1434fcdeb7feSGrant Likely */ 1435fcdeb7feSGrant Likely 14361cf3d8b3SNathan Fontenot static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); 14371cf3d8b3SNathan Fontenot 14381cf3d8b3SNathan Fontenot int of_reconfig_notifier_register(struct notifier_block *nb) 14391cf3d8b3SNathan Fontenot { 14401cf3d8b3SNathan Fontenot return blocking_notifier_chain_register(&of_reconfig_chain, nb); 14411cf3d8b3SNathan Fontenot } 14421a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); 14431cf3d8b3SNathan Fontenot 14441cf3d8b3SNathan Fontenot int of_reconfig_notifier_unregister(struct notifier_block *nb) 14451cf3d8b3SNathan Fontenot { 14461cf3d8b3SNathan Fontenot return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); 14471cf3d8b3SNathan Fontenot } 14481a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); 14491cf3d8b3SNathan Fontenot 14501cf3d8b3SNathan Fontenot int of_reconfig_notify(unsigned long action, void *p) 14511cf3d8b3SNathan Fontenot { 14521cf3d8b3SNathan Fontenot int rc; 14531cf3d8b3SNathan Fontenot 14541cf3d8b3SNathan Fontenot rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); 14551cf3d8b3SNathan Fontenot return notifier_to_errno(rc); 14561cf3d8b3SNathan Fontenot } 14571cf3d8b3SNathan Fontenot 1458e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE 1459e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn) 1460e81b3295SNathan Fontenot { 1461e81b3295SNathan Fontenot struct proc_dir_entry *ent; 1462e81b3295SNathan Fontenot 1463e81b3295SNathan Fontenot ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); 1464e81b3295SNathan Fontenot if (ent) 1465e81b3295SNathan Fontenot proc_device_tree_add_node(dn, ent); 1466e81b3295SNathan Fontenot } 1467e81b3295SNathan Fontenot #else 1468e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn) 1469e81b3295SNathan Fontenot { 1470e81b3295SNathan Fontenot return; 1471e81b3295SNathan Fontenot } 1472e81b3295SNathan Fontenot #endif 1473e81b3295SNathan Fontenot 1474fcdeb7feSGrant Likely /** 1475fcdeb7feSGrant Likely * of_attach_node - Plug a device node into the tree and global list. 1476fcdeb7feSGrant Likely */ 14771cf3d8b3SNathan Fontenot int of_attach_node(struct device_node *np) 1478fcdeb7feSGrant Likely { 1479fcdeb7feSGrant Likely unsigned long flags; 14801cf3d8b3SNathan Fontenot int rc; 14811cf3d8b3SNathan Fontenot 14821cf3d8b3SNathan Fontenot rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); 14831cf3d8b3SNathan Fontenot if (rc) 14841cf3d8b3SNathan Fontenot return rc; 1485fcdeb7feSGrant Likely 1486d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1487fcdeb7feSGrant Likely np->sibling = np->parent->child; 1488465aac6dSRandy Dunlap np->allnext = of_allnodes; 1489fcdeb7feSGrant Likely np->parent->child = np; 1490465aac6dSRandy Dunlap of_allnodes = np; 1491d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1492e81b3295SNathan Fontenot 1493e81b3295SNathan Fontenot of_add_proc_dt_entry(np); 14941cf3d8b3SNathan Fontenot return 0; 1495fcdeb7feSGrant Likely } 1496fcdeb7feSGrant Likely 1497e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE 1498e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn) 1499e81b3295SNathan Fontenot { 1500a8ca16eaSDavid Howells proc_remove(dn->pde); 1501e81b3295SNathan Fontenot } 1502e81b3295SNathan Fontenot #else 1503e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn) 1504e81b3295SNathan Fontenot { 1505e81b3295SNathan Fontenot return; 1506e81b3295SNathan Fontenot } 1507e81b3295SNathan Fontenot #endif 1508e81b3295SNathan Fontenot 1509fcdeb7feSGrant Likely /** 1510fcdeb7feSGrant Likely * of_detach_node - "Unplug" a node from the device tree. 1511fcdeb7feSGrant Likely * 1512fcdeb7feSGrant Likely * The caller must hold a reference to the node. The memory associated with 1513fcdeb7feSGrant Likely * the node is not freed until its refcount goes to zero. 1514fcdeb7feSGrant Likely */ 15151cf3d8b3SNathan Fontenot int of_detach_node(struct device_node *np) 1516fcdeb7feSGrant Likely { 1517fcdeb7feSGrant Likely struct device_node *parent; 1518fcdeb7feSGrant Likely unsigned long flags; 15191cf3d8b3SNathan Fontenot int rc = 0; 15201cf3d8b3SNathan Fontenot 15211cf3d8b3SNathan Fontenot rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); 15221cf3d8b3SNathan Fontenot if (rc) 15231cf3d8b3SNathan Fontenot return rc; 1524fcdeb7feSGrant Likely 1525d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1526fcdeb7feSGrant Likely 1527e81b3295SNathan Fontenot if (of_node_check_flag(np, OF_DETACHED)) { 1528e81b3295SNathan Fontenot /* someone already detached it */ 1529d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 15301cf3d8b3SNathan Fontenot return rc; 1531e81b3295SNathan Fontenot } 1532e81b3295SNathan Fontenot 1533fcdeb7feSGrant Likely parent = np->parent; 1534e81b3295SNathan Fontenot if (!parent) { 1535d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 15361cf3d8b3SNathan Fontenot return rc; 1537e81b3295SNathan Fontenot } 1538fcdeb7feSGrant Likely 1539465aac6dSRandy Dunlap if (of_allnodes == np) 1540465aac6dSRandy Dunlap of_allnodes = np->allnext; 1541fcdeb7feSGrant Likely else { 1542fcdeb7feSGrant Likely struct device_node *prev; 1543465aac6dSRandy Dunlap for (prev = of_allnodes; 1544fcdeb7feSGrant Likely prev->allnext != np; 1545fcdeb7feSGrant Likely prev = prev->allnext) 1546fcdeb7feSGrant Likely ; 1547fcdeb7feSGrant Likely prev->allnext = np->allnext; 1548fcdeb7feSGrant Likely } 1549fcdeb7feSGrant Likely 1550fcdeb7feSGrant Likely if (parent->child == np) 1551fcdeb7feSGrant Likely parent->child = np->sibling; 1552fcdeb7feSGrant Likely else { 1553fcdeb7feSGrant Likely struct device_node *prevsib; 1554fcdeb7feSGrant Likely for (prevsib = np->parent->child; 1555fcdeb7feSGrant Likely prevsib->sibling != np; 1556fcdeb7feSGrant Likely prevsib = prevsib->sibling) 1557fcdeb7feSGrant Likely ; 1558fcdeb7feSGrant Likely prevsib->sibling = np->sibling; 1559fcdeb7feSGrant Likely } 1560fcdeb7feSGrant Likely 1561fcdeb7feSGrant Likely of_node_set_flag(np, OF_DETACHED); 1562d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1563e81b3295SNathan Fontenot 1564e81b3295SNathan Fontenot of_remove_proc_dt_entry(np); 15651cf3d8b3SNathan Fontenot return rc; 1566fcdeb7feSGrant Likely } 1567fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */ 1568fcdeb7feSGrant Likely 1569611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1570611cad72SShawn Guo int id, const char *stem, int stem_len) 1571611cad72SShawn Guo { 1572611cad72SShawn Guo ap->np = np; 1573611cad72SShawn Guo ap->id = id; 1574611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1575611cad72SShawn Guo ap->stem[stem_len] = 0; 1576611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1577611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 157874a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 1579611cad72SShawn Guo } 1580611cad72SShawn Guo 1581611cad72SShawn Guo /** 1582611cad72SShawn Guo * of_alias_scan - Scan all properties of 'aliases' node 1583611cad72SShawn Guo * 1584611cad72SShawn Guo * The function scans all the properties of 'aliases' node and populate 1585611cad72SShawn Guo * the the global lookup table with the properties. It returns the 1586611cad72SShawn Guo * number of alias_prop found, or error code in error case. 1587611cad72SShawn Guo * 1588611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 1589611cad72SShawn Guo * for the resulting tree 1590611cad72SShawn Guo */ 1591611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1592611cad72SShawn Guo { 1593611cad72SShawn Guo struct property *pp; 1594611cad72SShawn Guo 1595611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1596611cad72SShawn Guo if (of_chosen == NULL) 1597611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 1598611cad72SShawn Guo of_aliases = of_find_node_by_path("/aliases"); 1599611cad72SShawn Guo if (!of_aliases) 1600611cad72SShawn Guo return; 1601611cad72SShawn Guo 16028af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1603611cad72SShawn Guo const char *start = pp->name; 1604611cad72SShawn Guo const char *end = start + strlen(start); 1605611cad72SShawn Guo struct device_node *np; 1606611cad72SShawn Guo struct alias_prop *ap; 1607611cad72SShawn Guo int id, len; 1608611cad72SShawn Guo 1609611cad72SShawn Guo /* Skip those we do not want to proceed */ 1610611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1611611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1612611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1613611cad72SShawn Guo continue; 1614611cad72SShawn Guo 1615611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1616611cad72SShawn Guo if (!np) 1617611cad72SShawn Guo continue; 1618611cad72SShawn Guo 1619611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1620611cad72SShawn Guo * the 'stem' string */ 1621611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1622611cad72SShawn Guo end--; 1623611cad72SShawn Guo len = end - start; 1624611cad72SShawn Guo 1625611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1626611cad72SShawn Guo continue; 1627611cad72SShawn Guo 1628611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1629611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1630611cad72SShawn Guo if (!ap) 1631611cad72SShawn Guo continue; 16320640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1633611cad72SShawn Guo ap->alias = start; 1634611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1635611cad72SShawn Guo } 1636611cad72SShawn Guo } 1637611cad72SShawn Guo 1638611cad72SShawn Guo /** 1639611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1640611cad72SShawn Guo * @np: Pointer to the given device_node 1641611cad72SShawn Guo * @stem: Alias stem of the given device_node 1642611cad72SShawn Guo * 1643611cad72SShawn Guo * The function travels the lookup table to get alias id for the given 1644611cad72SShawn Guo * device_node and alias stem. It returns the alias id if find it. 1645611cad72SShawn Guo */ 1646611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1647611cad72SShawn Guo { 1648611cad72SShawn Guo struct alias_prop *app; 1649611cad72SShawn Guo int id = -ENODEV; 1650611cad72SShawn Guo 1651611cad72SShawn Guo mutex_lock(&of_aliases_mutex); 1652611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1653611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1654611cad72SShawn Guo continue; 1655611cad72SShawn Guo 1656611cad72SShawn Guo if (np == app->np) { 1657611cad72SShawn Guo id = app->id; 1658611cad72SShawn Guo break; 1659611cad72SShawn Guo } 1660611cad72SShawn Guo } 1661611cad72SShawn Guo mutex_unlock(&of_aliases_mutex); 1662611cad72SShawn Guo 1663611cad72SShawn Guo return id; 1664611cad72SShawn Guo } 1665611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1666c541adc6SStephen Warren 1667c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 1668c541adc6SStephen Warren u32 *pu) 1669c541adc6SStephen Warren { 1670c541adc6SStephen Warren const void *curv = cur; 1671c541adc6SStephen Warren 1672c541adc6SStephen Warren if (!prop) 1673c541adc6SStephen Warren return NULL; 1674c541adc6SStephen Warren 1675c541adc6SStephen Warren if (!cur) { 1676c541adc6SStephen Warren curv = prop->value; 1677c541adc6SStephen Warren goto out_val; 1678c541adc6SStephen Warren } 1679c541adc6SStephen Warren 1680c541adc6SStephen Warren curv += sizeof(*cur); 1681c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1682c541adc6SStephen Warren return NULL; 1683c541adc6SStephen Warren 1684c541adc6SStephen Warren out_val: 1685c541adc6SStephen Warren *pu = be32_to_cpup(curv); 1686c541adc6SStephen Warren return curv; 1687c541adc6SStephen Warren } 1688c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 1689c541adc6SStephen Warren 1690c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 1691c541adc6SStephen Warren { 1692c541adc6SStephen Warren const void *curv = cur; 1693c541adc6SStephen Warren 1694c541adc6SStephen Warren if (!prop) 1695c541adc6SStephen Warren return NULL; 1696c541adc6SStephen Warren 1697c541adc6SStephen Warren if (!cur) 1698c541adc6SStephen Warren return prop->value; 1699c541adc6SStephen Warren 1700c541adc6SStephen Warren curv += strlen(cur) + 1; 1701c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1702c541adc6SStephen Warren return NULL; 1703c541adc6SStephen Warren 1704c541adc6SStephen Warren return curv; 1705c541adc6SStephen Warren } 1706c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 1707