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> 21183912d3SSudeep KarkadaNagesha #include <linux/cpu.h> 2297e873e5SStephen Rothwell #include <linux/module.h> 2397e873e5SStephen Rothwell #include <linux/of.h> 24581b605aSStephen Rothwell #include <linux/spinlock.h> 255a0e3ad6STejun Heo #include <linux/slab.h> 26a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 27581b605aSStephen Rothwell 28ced4eec9SStepan Moskovchenko #include "of_private.h" 29611cad72SShawn Guo 30ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 31611cad72SShawn Guo 32465aac6dSRandy Dunlap struct device_node *of_allnodes; 33465aac6dSRandy Dunlap EXPORT_SYMBOL(of_allnodes); 34fc0bdae4SGrant Likely struct device_node *of_chosen; 35611cad72SShawn Guo struct device_node *of_aliases; 365c19e952SSascha Hauer static struct device_node *of_stdout; 37611cad72SShawn Guo 38ced4eec9SStepan Moskovchenko DEFINE_MUTEX(of_aliases_mutex); 391ef4d424SStephen Rothwell 40581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling, 41581b605aSStephen Rothwell * or parent members of struct device_node. 42581b605aSStephen Rothwell */ 43d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 4497e873e5SStephen Rothwell 4597e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 4697e873e5SStephen Rothwell { 47a9fadeefSJeremy Kerr const __be32 *ip; 4897e873e5SStephen Rothwell 4997e873e5SStephen Rothwell do { 5097e873e5SStephen Rothwell if (np->parent) 5197e873e5SStephen Rothwell np = np->parent; 5297e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 5397e873e5SStephen Rothwell if (ip) 5433714881SJeremy Kerr return be32_to_cpup(ip); 5597e873e5SStephen Rothwell } while (np->parent); 5697e873e5SStephen Rothwell /* No #address-cells property for the root node */ 5797e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 5897e873e5SStephen Rothwell } 5997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 6097e873e5SStephen Rothwell 6197e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 6297e873e5SStephen Rothwell { 63a9fadeefSJeremy Kerr const __be32 *ip; 6497e873e5SStephen Rothwell 6597e873e5SStephen Rothwell do { 6697e873e5SStephen Rothwell if (np->parent) 6797e873e5SStephen Rothwell np = np->parent; 6897e873e5SStephen Rothwell ip = of_get_property(np, "#size-cells", NULL); 6997e873e5SStephen Rothwell if (ip) 7033714881SJeremy Kerr return be32_to_cpup(ip); 7197e873e5SStephen Rothwell } while (np->parent); 7297e873e5SStephen Rothwell /* No #size-cells property for the root node */ 7397e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 7497e873e5SStephen Rothwell } 7597e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 7697e873e5SStephen Rothwell 770c3f061cSRob Herring #ifdef CONFIG_NUMA 780c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np) 790c3f061cSRob Herring { 800c3f061cSRob Herring return numa_node_id(); 810c3f061cSRob Herring } 820c3f061cSRob Herring #endif 830c3f061cSRob Herring 840f22dd39SGrant Likely #if defined(CONFIG_OF_DYNAMIC) 85923f7e30SGrant Likely /** 86923f7e30SGrant Likely * of_node_get - Increment refcount of a node 87923f7e30SGrant Likely * @node: Node to inc refcount, NULL is supported to 88923f7e30SGrant Likely * simplify writing of callers 89923f7e30SGrant Likely * 90923f7e30SGrant Likely * Returns node. 91923f7e30SGrant Likely */ 92923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node) 93923f7e30SGrant Likely { 94923f7e30SGrant Likely if (node) 95923f7e30SGrant Likely kref_get(&node->kref); 96923f7e30SGrant Likely return node; 97923f7e30SGrant Likely } 98923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get); 99923f7e30SGrant Likely 100923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref) 101923f7e30SGrant Likely { 102923f7e30SGrant Likely return container_of(kref, struct device_node, kref); 103923f7e30SGrant Likely } 104923f7e30SGrant Likely 105923f7e30SGrant Likely /** 106923f7e30SGrant Likely * of_node_release - release a dynamically allocated node 107923f7e30SGrant Likely * @kref: kref element of the node to be released 108923f7e30SGrant Likely * 109923f7e30SGrant Likely * In of_node_put() this function is passed to kref_put() 110923f7e30SGrant Likely * as the destructor. 111923f7e30SGrant Likely */ 112923f7e30SGrant Likely static void of_node_release(struct kref *kref) 113923f7e30SGrant Likely { 114923f7e30SGrant Likely struct device_node *node = kref_to_device_node(kref); 115923f7e30SGrant Likely struct property *prop = node->properties; 116923f7e30SGrant Likely 117923f7e30SGrant Likely /* We should never be releasing nodes that haven't been detached. */ 118923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DETACHED)) { 119923f7e30SGrant Likely pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); 120923f7e30SGrant Likely dump_stack(); 121923f7e30SGrant Likely kref_init(&node->kref); 122923f7e30SGrant Likely return; 123923f7e30SGrant Likely } 124923f7e30SGrant Likely 125923f7e30SGrant Likely if (!of_node_check_flag(node, OF_DYNAMIC)) 126923f7e30SGrant Likely return; 127923f7e30SGrant Likely 128923f7e30SGrant Likely while (prop) { 129923f7e30SGrant Likely struct property *next = prop->next; 130923f7e30SGrant Likely kfree(prop->name); 131923f7e30SGrant Likely kfree(prop->value); 132923f7e30SGrant Likely kfree(prop); 133923f7e30SGrant Likely prop = next; 134923f7e30SGrant Likely 135923f7e30SGrant Likely if (!prop) { 136923f7e30SGrant Likely prop = node->deadprops; 137923f7e30SGrant Likely node->deadprops = NULL; 138923f7e30SGrant Likely } 139923f7e30SGrant Likely } 140923f7e30SGrant Likely kfree(node->full_name); 141923f7e30SGrant Likely kfree(node->data); 142923f7e30SGrant Likely kfree(node); 143923f7e30SGrant Likely } 144923f7e30SGrant Likely 145923f7e30SGrant Likely /** 146923f7e30SGrant Likely * of_node_put - Decrement refcount of a node 147923f7e30SGrant Likely * @node: Node to dec refcount, NULL is supported to 148923f7e30SGrant Likely * simplify writing of callers 149923f7e30SGrant Likely * 150923f7e30SGrant Likely */ 151923f7e30SGrant Likely void of_node_put(struct device_node *node) 152923f7e30SGrant Likely { 153923f7e30SGrant Likely if (node) 154923f7e30SGrant Likely kref_put(&node->kref, of_node_release); 155923f7e30SGrant Likely } 156923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put); 1570f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 158923f7e30SGrant Likely 15928d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 16028d0e36bSThomas Gleixner const char *name, int *lenp) 161581b605aSStephen Rothwell { 162581b605aSStephen Rothwell struct property *pp; 163581b605aSStephen Rothwell 16464e4566fSTimur Tabi if (!np) 16564e4566fSTimur Tabi return NULL; 16664e4566fSTimur Tabi 167a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 168581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 169a3a7cab1SSachin Kamat if (lenp) 170581b605aSStephen Rothwell *lenp = pp->length; 171581b605aSStephen Rothwell break; 172581b605aSStephen Rothwell } 173581b605aSStephen Rothwell } 17428d0e36bSThomas Gleixner 17528d0e36bSThomas Gleixner return pp; 17628d0e36bSThomas Gleixner } 17728d0e36bSThomas Gleixner 17828d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 17928d0e36bSThomas Gleixner const char *name, 18028d0e36bSThomas Gleixner int *lenp) 18128d0e36bSThomas Gleixner { 18228d0e36bSThomas Gleixner struct property *pp; 183d6d3c4e6SThomas Gleixner unsigned long flags; 18428d0e36bSThomas Gleixner 185d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 18628d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 187d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 188581b605aSStephen Rothwell 189581b605aSStephen Rothwell return pp; 190581b605aSStephen Rothwell } 191581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 192581b605aSStephen Rothwell 193e91edcf5SGrant Likely /** 194e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 195e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 196e91edcf5SGrant Likely * of_node_put() will be called on it 197e91edcf5SGrant Likely * 198e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 199e91edcf5SGrant Likely * of_node_put() on it when done. 200e91edcf5SGrant Likely */ 201e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 202e91edcf5SGrant Likely { 203e91edcf5SGrant Likely struct device_node *np; 204d25d8694SBenjamin Herrenschmidt unsigned long flags; 205e91edcf5SGrant Likely 206d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 207465aac6dSRandy Dunlap np = prev ? prev->allnext : of_allnodes; 208e91edcf5SGrant Likely for (; np != NULL; np = np->allnext) 209e91edcf5SGrant Likely if (of_node_get(np)) 210e91edcf5SGrant Likely break; 211e91edcf5SGrant Likely of_node_put(prev); 212d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 213e91edcf5SGrant Likely return np; 214e91edcf5SGrant Likely } 215e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 216e91edcf5SGrant Likely 21797e873e5SStephen Rothwell /* 21897e873e5SStephen Rothwell * Find a property with a given name for a given node 21997e873e5SStephen Rothwell * and return the value. 22097e873e5SStephen Rothwell */ 22128d0e36bSThomas Gleixner static const void *__of_get_property(const struct device_node *np, 22228d0e36bSThomas Gleixner const char *name, int *lenp) 22328d0e36bSThomas Gleixner { 22428d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 22528d0e36bSThomas Gleixner 22628d0e36bSThomas Gleixner return pp ? pp->value : NULL; 22728d0e36bSThomas Gleixner } 22828d0e36bSThomas Gleixner 22928d0e36bSThomas Gleixner /* 23028d0e36bSThomas Gleixner * Find a property with a given name for a given node 23128d0e36bSThomas Gleixner * and return the value. 23228d0e36bSThomas Gleixner */ 23397e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 23497e873e5SStephen Rothwell int *lenp) 23597e873e5SStephen Rothwell { 23697e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 23797e873e5SStephen Rothwell 23897e873e5SStephen Rothwell return pp ? pp->value : NULL; 23997e873e5SStephen Rothwell } 24097e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 2410081cbc3SStephen Rothwell 242183912d3SSudeep KarkadaNagesha /* 243183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 244183912d3SSudeep KarkadaNagesha * 245183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 246183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 247183912d3SSudeep KarkadaNagesha * 248183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 249183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 250183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 251183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 252183912d3SSudeep KarkadaNagesha * 253183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 254183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 255183912d3SSudeep KarkadaNagesha */ 256183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 257183912d3SSudeep KarkadaNagesha { 258183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 259183912d3SSudeep KarkadaNagesha } 260183912d3SSudeep KarkadaNagesha 261183912d3SSudeep KarkadaNagesha /** 262183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 263183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 264183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 265183912d3SSudeep KarkadaNagesha */ 266183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 267183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 268183912d3SSudeep KarkadaNagesha { 269183912d3SSudeep KarkadaNagesha const __be32 *cell; 270183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 271183912d3SSudeep KarkadaNagesha u64 hwid; 272183912d3SSudeep KarkadaNagesha 273183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 274183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 275f3cea45aSGrant Likely if (!cell || !ac) 276183912d3SSudeep KarkadaNagesha return false; 277f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 278183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 279183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 280183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 281183912d3SSudeep KarkadaNagesha if (thread) 282183912d3SSudeep KarkadaNagesha *thread = tid; 283183912d3SSudeep KarkadaNagesha return true; 284183912d3SSudeep KarkadaNagesha } 285183912d3SSudeep KarkadaNagesha cell += ac; 286183912d3SSudeep KarkadaNagesha } 287183912d3SSudeep KarkadaNagesha return false; 288183912d3SSudeep KarkadaNagesha } 289183912d3SSudeep KarkadaNagesha 290d1cb9d1aSDavid Miller /* 291d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 292d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 293d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 294d1cb9d1aSDavid Miller * core is returned in it. 295d1cb9d1aSDavid Miller */ 296d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 297d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 298d1cb9d1aSDavid Miller { 299d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 300d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 301d1cb9d1aSDavid Miller * standard "reg" property. 302d1cb9d1aSDavid Miller */ 303d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 304d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 305d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 306d1cb9d1aSDavid Miller cpu, thread)) 307d1cb9d1aSDavid Miller return true; 308d1cb9d1aSDavid Miller 309d1cb9d1aSDavid Miller if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) 310d1cb9d1aSDavid Miller return true; 311d1cb9d1aSDavid Miller 312d1cb9d1aSDavid Miller return false; 313d1cb9d1aSDavid Miller } 314d1cb9d1aSDavid Miller 315183912d3SSudeep KarkadaNagesha /** 316183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 317183912d3SSudeep KarkadaNagesha * 318183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 319183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 320183912d3SSudeep KarkadaNagesha * returned 321183912d3SSudeep KarkadaNagesha * 322183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 323183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 324183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 325183912d3SSudeep KarkadaNagesha * references can use that instead. 326183912d3SSudeep KarkadaNagesha * 327183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 328183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 329183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 330183912d3SSudeep KarkadaNagesha * 331183912d3SSudeep KarkadaNagesha * Returns a node pointer for the logical cpu if found, else NULL. 332183912d3SSudeep KarkadaNagesha */ 333183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 334183912d3SSudeep KarkadaNagesha { 335d1cb9d1aSDavid Miller struct device_node *cpun; 336183912d3SSudeep KarkadaNagesha 337d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 338d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 339183912d3SSudeep KarkadaNagesha return cpun; 340183912d3SSudeep KarkadaNagesha } 341183912d3SSudeep KarkadaNagesha return NULL; 342183912d3SSudeep KarkadaNagesha } 343183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 344183912d3SSudeep KarkadaNagesha 3450081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in 3460081cbc3SStephen Rothwell * the device's "compatible" property 3470081cbc3SStephen Rothwell */ 34828d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 3490081cbc3SStephen Rothwell const char *compat) 3500081cbc3SStephen Rothwell { 3510081cbc3SStephen Rothwell const char* cp; 3520081cbc3SStephen Rothwell int cplen, l; 3530081cbc3SStephen Rothwell 35428d0e36bSThomas Gleixner cp = __of_get_property(device, "compatible", &cplen); 3550081cbc3SStephen Rothwell if (cp == NULL) 3560081cbc3SStephen Rothwell return 0; 3570081cbc3SStephen Rothwell while (cplen > 0) { 3580081cbc3SStephen Rothwell if (of_compat_cmp(cp, compat, strlen(compat)) == 0) 3590081cbc3SStephen Rothwell return 1; 3600081cbc3SStephen Rothwell l = strlen(cp) + 1; 3610081cbc3SStephen Rothwell cp += l; 3620081cbc3SStephen Rothwell cplen -= l; 3630081cbc3SStephen Rothwell } 3640081cbc3SStephen Rothwell 3650081cbc3SStephen Rothwell return 0; 3660081cbc3SStephen Rothwell } 36728d0e36bSThomas Gleixner 36828d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 36928d0e36bSThomas Gleixner * the device's "compatible" property 37028d0e36bSThomas Gleixner */ 37128d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 37228d0e36bSThomas Gleixner const char *compat) 37328d0e36bSThomas Gleixner { 374d6d3c4e6SThomas Gleixner unsigned long flags; 37528d0e36bSThomas Gleixner int res; 37628d0e36bSThomas Gleixner 377d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 37828d0e36bSThomas Gleixner res = __of_device_is_compatible(device, compat); 379d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 38028d0e36bSThomas Gleixner return res; 38128d0e36bSThomas Gleixner } 3820081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 383e679c5f4SStephen Rothwell 384e679c5f4SStephen Rothwell /** 38571a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 3861f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 3871f43cfb9SGrant Likely * 3881f43cfb9SGrant Likely * Returns true if the root node has the given value in its 3891f43cfb9SGrant Likely * compatible property. 3901f43cfb9SGrant Likely */ 39171a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 3921f43cfb9SGrant Likely { 3931f43cfb9SGrant Likely struct device_node *root; 3941f43cfb9SGrant Likely int rc = 0; 3951f43cfb9SGrant Likely 3961f43cfb9SGrant Likely root = of_find_node_by_path("/"); 3971f43cfb9SGrant Likely if (root) { 3981f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 3991f43cfb9SGrant Likely of_node_put(root); 4001f43cfb9SGrant Likely } 4011f43cfb9SGrant Likely return rc; 4021f43cfb9SGrant Likely } 40371a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 4041f43cfb9SGrant Likely 4051f43cfb9SGrant Likely /** 406c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 407834d97d4SJosh Boyer * 408c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 409834d97d4SJosh Boyer * 410834d97d4SJosh Boyer * Returns 1 if the status property is absent or set to "okay" or "ok", 411834d97d4SJosh Boyer * 0 otherwise 412834d97d4SJosh Boyer */ 413c31a0c05SStephen Warren static int __of_device_is_available(const struct device_node *device) 414834d97d4SJosh Boyer { 415834d97d4SJosh Boyer const char *status; 416834d97d4SJosh Boyer int statlen; 417834d97d4SJosh Boyer 41842ccd781SXiubo Li if (!device) 41942ccd781SXiubo Li return 0; 42042ccd781SXiubo Li 421c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 422834d97d4SJosh Boyer if (status == NULL) 423834d97d4SJosh Boyer return 1; 424834d97d4SJosh Boyer 425834d97d4SJosh Boyer if (statlen > 0) { 426834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 427834d97d4SJosh Boyer return 1; 428834d97d4SJosh Boyer } 429834d97d4SJosh Boyer 430834d97d4SJosh Boyer return 0; 431834d97d4SJosh Boyer } 432c31a0c05SStephen Warren 433c31a0c05SStephen Warren /** 434c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 435c31a0c05SStephen Warren * 436c31a0c05SStephen Warren * @device: Node to check for availability 437c31a0c05SStephen Warren * 438c31a0c05SStephen Warren * Returns 1 if the status property is absent or set to "okay" or "ok", 439c31a0c05SStephen Warren * 0 otherwise 440c31a0c05SStephen Warren */ 441c31a0c05SStephen Warren int of_device_is_available(const struct device_node *device) 442c31a0c05SStephen Warren { 443c31a0c05SStephen Warren unsigned long flags; 444c31a0c05SStephen Warren int res; 445c31a0c05SStephen Warren 446c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 447c31a0c05SStephen Warren res = __of_device_is_available(device); 448c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 449c31a0c05SStephen Warren return res; 450c31a0c05SStephen Warren 451c31a0c05SStephen Warren } 452834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 453834d97d4SJosh Boyer 454834d97d4SJosh Boyer /** 455e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 456e679c5f4SStephen Rothwell * @node: Node to get parent 457e679c5f4SStephen Rothwell * 458e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 459e679c5f4SStephen Rothwell * of_node_put() on it when done. 460e679c5f4SStephen Rothwell */ 461e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 462e679c5f4SStephen Rothwell { 463e679c5f4SStephen Rothwell struct device_node *np; 464d6d3c4e6SThomas Gleixner unsigned long flags; 465e679c5f4SStephen Rothwell 466e679c5f4SStephen Rothwell if (!node) 467e679c5f4SStephen Rothwell return NULL; 468e679c5f4SStephen Rothwell 469d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 470e679c5f4SStephen Rothwell np = of_node_get(node->parent); 471d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 472e679c5f4SStephen Rothwell return np; 473e679c5f4SStephen Rothwell } 474e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 475d1cd355aSStephen Rothwell 476d1cd355aSStephen Rothwell /** 477f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 478f4eb0107SMichael Ellerman * @node: Node to get parent of 479f4eb0107SMichael Ellerman * 480f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 481f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 482f4eb0107SMichael Ellerman * through a node's parents. 483f4eb0107SMichael Ellerman * 484f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 485f4eb0107SMichael Ellerman * of_node_put() on it when done. 486f4eb0107SMichael Ellerman */ 487f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 488f4eb0107SMichael Ellerman { 489f4eb0107SMichael Ellerman struct device_node *parent; 490d6d3c4e6SThomas Gleixner unsigned long flags; 491f4eb0107SMichael Ellerman 492f4eb0107SMichael Ellerman if (!node) 493f4eb0107SMichael Ellerman return NULL; 494f4eb0107SMichael Ellerman 495d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 496f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 497f4eb0107SMichael Ellerman of_node_put(node); 498d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 499f4eb0107SMichael Ellerman return parent; 500f4eb0107SMichael Ellerman } 5016695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 502f4eb0107SMichael Ellerman 503f4eb0107SMichael Ellerman /** 504d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 505d1cd355aSStephen Rothwell * @node: parent node 506d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 507d1cd355aSStephen Rothwell * 508d1cd355aSStephen Rothwell * Returns a node pointer with refcount incremented, use 509d1cd355aSStephen Rothwell * of_node_put() on it when done. 510d1cd355aSStephen Rothwell */ 511d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 512d1cd355aSStephen Rothwell struct device_node *prev) 513d1cd355aSStephen Rothwell { 514d1cd355aSStephen Rothwell struct device_node *next; 515d6d3c4e6SThomas Gleixner unsigned long flags; 516d1cd355aSStephen Rothwell 517d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 518d1cd355aSStephen Rothwell next = prev ? prev->sibling : node->child; 519d1cd355aSStephen Rothwell for (; next; next = next->sibling) 520d1cd355aSStephen Rothwell if (of_node_get(next)) 521d1cd355aSStephen Rothwell break; 522d1cd355aSStephen Rothwell of_node_put(prev); 523d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 524d1cd355aSStephen Rothwell return next; 525d1cd355aSStephen Rothwell } 526d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 5271ef4d424SStephen Rothwell 5281ef4d424SStephen Rothwell /** 5293296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 5303296193dSTimur Tabi * @node: parent node 5313296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 5323296193dSTimur Tabi * 5333296193dSTimur Tabi * This function is like of_get_next_child(), except that it 5343296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 5353296193dSTimur Tabi */ 5363296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 5373296193dSTimur Tabi struct device_node *prev) 5383296193dSTimur Tabi { 5393296193dSTimur Tabi struct device_node *next; 540d25d8694SBenjamin Herrenschmidt unsigned long flags; 5413296193dSTimur Tabi 542d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 5433296193dSTimur Tabi next = prev ? prev->sibling : node->child; 5443296193dSTimur Tabi for (; next; next = next->sibling) { 545c31a0c05SStephen Warren if (!__of_device_is_available(next)) 5463296193dSTimur Tabi continue; 5473296193dSTimur Tabi if (of_node_get(next)) 5483296193dSTimur Tabi break; 5493296193dSTimur Tabi } 5503296193dSTimur Tabi of_node_put(prev); 551d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 5523296193dSTimur Tabi return next; 5533296193dSTimur Tabi } 5543296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 5553296193dSTimur Tabi 5563296193dSTimur Tabi /** 5579c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 5589c19761aSSrinivas Kandagatla * @node: parent node 5599c19761aSSrinivas Kandagatla * @name: child name to look for. 5609c19761aSSrinivas Kandagatla * 5619c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 5629c19761aSSrinivas Kandagatla * 5639c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 5649c19761aSSrinivas Kandagatla * of_node_put() on it when done. 5659c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 5669c19761aSSrinivas Kandagatla */ 5679c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 5689c19761aSSrinivas Kandagatla const char *name) 5699c19761aSSrinivas Kandagatla { 5709c19761aSSrinivas Kandagatla struct device_node *child; 5719c19761aSSrinivas Kandagatla 5729c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 5739c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 5749c19761aSSrinivas Kandagatla break; 5759c19761aSSrinivas Kandagatla return child; 5769c19761aSSrinivas Kandagatla } 5779c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 5789c19761aSSrinivas Kandagatla 5799c19761aSSrinivas Kandagatla /** 5801ef4d424SStephen Rothwell * of_find_node_by_path - Find a node matching a full OF path 5811ef4d424SStephen Rothwell * @path: The full path to match 5821ef4d424SStephen Rothwell * 5831ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 5841ef4d424SStephen Rothwell * of_node_put() on it when done. 5851ef4d424SStephen Rothwell */ 5861ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path) 5871ef4d424SStephen Rothwell { 588465aac6dSRandy Dunlap struct device_node *np = of_allnodes; 589d6d3c4e6SThomas Gleixner unsigned long flags; 5901ef4d424SStephen Rothwell 591d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 5921ef4d424SStephen Rothwell for (; np; np = np->allnext) { 5931ef4d424SStephen Rothwell if (np->full_name && (of_node_cmp(np->full_name, path) == 0) 5941ef4d424SStephen Rothwell && of_node_get(np)) 5951ef4d424SStephen Rothwell break; 5961ef4d424SStephen Rothwell } 597d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 5981ef4d424SStephen Rothwell return np; 5991ef4d424SStephen Rothwell } 6001ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path); 6011ef4d424SStephen Rothwell 6021ef4d424SStephen Rothwell /** 6031ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 6041ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 6051ef4d424SStephen Rothwell * you pass will not be searched, only the next one 6061ef4d424SStephen Rothwell * will; typically, you pass what the previous call 6071ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 6081ef4d424SStephen Rothwell * @name: The name string to match against 6091ef4d424SStephen Rothwell * 6101ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 6111ef4d424SStephen Rothwell * of_node_put() on it when done. 6121ef4d424SStephen Rothwell */ 6131ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 6141ef4d424SStephen Rothwell const char *name) 6151ef4d424SStephen Rothwell { 6161ef4d424SStephen Rothwell struct device_node *np; 617d6d3c4e6SThomas Gleixner unsigned long flags; 6181ef4d424SStephen Rothwell 619d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 620465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 6211ef4d424SStephen Rothwell for (; np; np = np->allnext) 6221ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 6231ef4d424SStephen Rothwell && of_node_get(np)) 6241ef4d424SStephen Rothwell break; 6251ef4d424SStephen Rothwell of_node_put(from); 626d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 6271ef4d424SStephen Rothwell return np; 6281ef4d424SStephen Rothwell } 6291ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 6301ef4d424SStephen Rothwell 6311ef4d424SStephen Rothwell /** 6321ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 6331ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 6341ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 6351ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 6361ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 6371ef4d424SStephen Rothwell * called on from for you. 6381ef4d424SStephen Rothwell * @type: The type string to match against 6391ef4d424SStephen Rothwell * 6401ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 6411ef4d424SStephen Rothwell * of_node_put() on it when done. 6421ef4d424SStephen Rothwell */ 6431ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 6441ef4d424SStephen Rothwell const char *type) 6451ef4d424SStephen Rothwell { 6461ef4d424SStephen Rothwell struct device_node *np; 647d6d3c4e6SThomas Gleixner unsigned long flags; 6481ef4d424SStephen Rothwell 649d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 650465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 6511ef4d424SStephen Rothwell for (; np; np = np->allnext) 6521ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 6531ef4d424SStephen Rothwell && of_node_get(np)) 6541ef4d424SStephen Rothwell break; 6551ef4d424SStephen Rothwell of_node_put(from); 656d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 6571ef4d424SStephen Rothwell return np; 6581ef4d424SStephen Rothwell } 6591ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 6601ef4d424SStephen Rothwell 6611ef4d424SStephen Rothwell /** 6621ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 6631ef4d424SStephen Rothwell * tokens in its "compatible" property 6641ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 6651ef4d424SStephen Rothwell * you pass will not be searched, only the next one 6661ef4d424SStephen Rothwell * will; typically, you pass what the previous call 6671ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 6681ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 6691ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 6701ef4d424SStephen Rothwell * "compatible" list. 6711ef4d424SStephen Rothwell * 6721ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 6731ef4d424SStephen Rothwell * of_node_put() on it when done. 6741ef4d424SStephen Rothwell */ 6751ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 6761ef4d424SStephen Rothwell const char *type, const char *compatible) 6771ef4d424SStephen Rothwell { 6781ef4d424SStephen Rothwell struct device_node *np; 679d6d3c4e6SThomas Gleixner unsigned long flags; 6801ef4d424SStephen Rothwell 681d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 682465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 6831ef4d424SStephen Rothwell for (; np; np = np->allnext) { 6841ef4d424SStephen Rothwell if (type 6851ef4d424SStephen Rothwell && !(np->type && (of_node_cmp(np->type, type) == 0))) 6861ef4d424SStephen Rothwell continue; 68728d0e36bSThomas Gleixner if (__of_device_is_compatible(np, compatible) && 68828d0e36bSThomas Gleixner of_node_get(np)) 6891ef4d424SStephen Rothwell break; 6901ef4d424SStephen Rothwell } 6911ef4d424SStephen Rothwell of_node_put(from); 692d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 6931ef4d424SStephen Rothwell return np; 6941ef4d424SStephen Rothwell } 6951ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 696283029d1SGrant Likely 697283029d1SGrant Likely /** 6981e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 6991e291b14SMichael Ellerman * the given name. 7001e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 7011e291b14SMichael Ellerman * you pass will not be searched, only the next one 7021e291b14SMichael Ellerman * will; typically, you pass what the previous call 7031e291b14SMichael Ellerman * returned. of_node_put() will be called on it 7041e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 7051e291b14SMichael Ellerman * 7061e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 7071e291b14SMichael Ellerman * of_node_put() on it when done. 7081e291b14SMichael Ellerman */ 7091e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 7101e291b14SMichael Ellerman const char *prop_name) 7111e291b14SMichael Ellerman { 7121e291b14SMichael Ellerman struct device_node *np; 7131e291b14SMichael Ellerman struct property *pp; 714d6d3c4e6SThomas Gleixner unsigned long flags; 7151e291b14SMichael Ellerman 716d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 717465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 7181e291b14SMichael Ellerman for (; np; np = np->allnext) { 719a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 7201e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 7211e291b14SMichael Ellerman of_node_get(np); 7221e291b14SMichael Ellerman goto out; 7231e291b14SMichael Ellerman } 7241e291b14SMichael Ellerman } 7251e291b14SMichael Ellerman } 7261e291b14SMichael Ellerman out: 7271e291b14SMichael Ellerman of_node_put(from); 728d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 7291e291b14SMichael Ellerman return np; 7301e291b14SMichael Ellerman } 7311e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 7321e291b14SMichael Ellerman 73328d0e36bSThomas Gleixner static 73428d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 735283029d1SGrant Likely const struct device_node *node) 736283029d1SGrant Likely { 73710535314SSebastian Hesselbarth const char *cp; 73810535314SSebastian Hesselbarth int cplen, l; 73910535314SSebastian Hesselbarth 740a52f07ecSGrant Likely if (!matches) 741a52f07ecSGrant Likely return NULL; 742a52f07ecSGrant Likely 74310535314SSebastian Hesselbarth cp = __of_get_property(node, "compatible", &cplen); 74410535314SSebastian Hesselbarth do { 74510535314SSebastian Hesselbarth const struct of_device_id *m = matches; 74610535314SSebastian Hesselbarth 74710535314SSebastian Hesselbarth /* Check against matches with current compatible string */ 74810535314SSebastian Hesselbarth while (m->name[0] || m->type[0] || m->compatible[0]) { 749283029d1SGrant Likely int match = 1; 75010535314SSebastian Hesselbarth if (m->name[0]) 751283029d1SGrant Likely match &= node->name 75210535314SSebastian Hesselbarth && !strcmp(m->name, node->name); 75310535314SSebastian Hesselbarth if (m->type[0]) 754283029d1SGrant Likely match &= node->type 75510535314SSebastian Hesselbarth && !strcmp(m->type, node->type); 75610535314SSebastian Hesselbarth if (m->compatible[0]) 75710535314SSebastian Hesselbarth match &= cp 75810535314SSebastian Hesselbarth && !of_compat_cmp(m->compatible, cp, 75910535314SSebastian Hesselbarth strlen(m->compatible)); 760bc51b0c2SLinus Torvalds if (match) 76110535314SSebastian Hesselbarth return m; 76210535314SSebastian Hesselbarth m++; 763283029d1SGrant Likely } 76410535314SSebastian Hesselbarth 76510535314SSebastian Hesselbarth /* Get node's next compatible string */ 76610535314SSebastian Hesselbarth if (cp) { 76710535314SSebastian Hesselbarth l = strlen(cp) + 1; 76810535314SSebastian Hesselbarth cp += l; 76910535314SSebastian Hesselbarth cplen -= l; 77010535314SSebastian Hesselbarth } 77110535314SSebastian Hesselbarth } while (cp && (cplen > 0)); 77210535314SSebastian Hesselbarth 773283029d1SGrant Likely return NULL; 774283029d1SGrant Likely } 77528d0e36bSThomas Gleixner 77628d0e36bSThomas Gleixner /** 77728d0e36bSThomas Gleixner * of_match_node - Tell if an device_node has a matching of_match structure 77828d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 77928d0e36bSThomas Gleixner * @node: the of device structure to match against 78028d0e36bSThomas Gleixner * 78110535314SSebastian Hesselbarth * Low level utility function used by device matching. Matching order 78210535314SSebastian Hesselbarth * is to compare each of the node's compatibles with all given matches 78310535314SSebastian Hesselbarth * first. This implies node's compatible is sorted from specific to 78410535314SSebastian Hesselbarth * generic while matches can be in any order. 78528d0e36bSThomas Gleixner */ 78628d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 78728d0e36bSThomas Gleixner const struct device_node *node) 78828d0e36bSThomas Gleixner { 78928d0e36bSThomas Gleixner const struct of_device_id *match; 790d6d3c4e6SThomas Gleixner unsigned long flags; 79128d0e36bSThomas Gleixner 792d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 79328d0e36bSThomas Gleixner match = __of_match_node(matches, node); 794d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 79528d0e36bSThomas Gleixner return match; 79628d0e36bSThomas Gleixner } 797283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 798283029d1SGrant Likely 799283029d1SGrant Likely /** 80050c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 80150c8af4cSStephen Warren * match table. 802283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 803283029d1SGrant Likely * you pass will not be searched, only the next one 804283029d1SGrant Likely * will; typically, you pass what the previous call 805283029d1SGrant Likely * returned. of_node_put() will be called on it 806283029d1SGrant Likely * @matches: array of of device match structures to search in 80750c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 808283029d1SGrant Likely * 809283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 810283029d1SGrant Likely * of_node_put() on it when done. 811283029d1SGrant Likely */ 81250c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 81350c8af4cSStephen Warren const struct of_device_id *matches, 81450c8af4cSStephen Warren const struct of_device_id **match) 815283029d1SGrant Likely { 816283029d1SGrant Likely struct device_node *np; 817dc71bcf1SThomas Abraham const struct of_device_id *m; 818d6d3c4e6SThomas Gleixner unsigned long flags; 819283029d1SGrant Likely 82050c8af4cSStephen Warren if (match) 82150c8af4cSStephen Warren *match = NULL; 82250c8af4cSStephen Warren 823d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 824465aac6dSRandy Dunlap np = from ? from->allnext : of_allnodes; 825283029d1SGrant Likely for (; np; np = np->allnext) { 82628d0e36bSThomas Gleixner m = __of_match_node(matches, np); 827dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 82850c8af4cSStephen Warren if (match) 829dc71bcf1SThomas Abraham *match = m; 830283029d1SGrant Likely break; 831283029d1SGrant Likely } 83250c8af4cSStephen Warren } 833283029d1SGrant Likely of_node_put(from); 834d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 835283029d1SGrant Likely return np; 836283029d1SGrant Likely } 83780c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 8383f07af49SGrant Likely 8393f07af49SGrant Likely /** 8403f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 8413f07af49SGrant Likely * @node: pointer to a device tree node 8423f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 8433f07af49SGrant Likely * @len: Length of modalias value 8443f07af49SGrant Likely * 8452ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 8462ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 8472ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 8482ffe8c5fSGrant Likely * from the first entry in the compatible list property. 8493f07af49SGrant Likely * 8502ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 8513f07af49SGrant Likely */ 8523f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 8533f07af49SGrant Likely { 8542ffe8c5fSGrant Likely const char *compatible, *p; 8552ffe8c5fSGrant Likely int cplen; 8563f07af49SGrant Likely 8573f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 8582ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 8593f07af49SGrant Likely return -ENODEV; 8603f07af49SGrant Likely p = strchr(compatible, ','); 8612ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 8623f07af49SGrant Likely return 0; 8633f07af49SGrant Likely } 8643f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 8653f07af49SGrant Likely 86664b60e09SAnton Vorontsov /** 86789751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 86889751a7cSJeremy Kerr * @handle: phandle of the node to find 86989751a7cSJeremy Kerr * 87089751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 87189751a7cSJeremy Kerr * of_node_put() on it when done. 87289751a7cSJeremy Kerr */ 87389751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 87489751a7cSJeremy Kerr { 87589751a7cSJeremy Kerr struct device_node *np; 876d25d8694SBenjamin Herrenschmidt unsigned long flags; 87789751a7cSJeremy Kerr 878d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 879465aac6dSRandy Dunlap for (np = of_allnodes; np; np = np->allnext) 88089751a7cSJeremy Kerr if (np->phandle == handle) 88189751a7cSJeremy Kerr break; 88289751a7cSJeremy Kerr of_node_get(np); 883d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 88489751a7cSJeremy Kerr return np; 88589751a7cSJeremy Kerr } 88689751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 88789751a7cSJeremy Kerr 88889751a7cSJeremy Kerr /** 889daeec1f0STony Prisk * of_find_property_value_of_size 890daeec1f0STony Prisk * 891daeec1f0STony Prisk * @np: device node from which the property value is to be read. 892daeec1f0STony Prisk * @propname: name of the property to be searched. 893daeec1f0STony Prisk * @len: requested length of property value 894daeec1f0STony Prisk * 895daeec1f0STony Prisk * Search for a property in a device node and valid the requested size. 896daeec1f0STony Prisk * Returns the property value on success, -EINVAL if the property does not 897daeec1f0STony Prisk * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 898daeec1f0STony Prisk * property data isn't large enough. 899daeec1f0STony Prisk * 900daeec1f0STony Prisk */ 901daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np, 902daeec1f0STony Prisk const char *propname, u32 len) 903daeec1f0STony Prisk { 904daeec1f0STony Prisk struct property *prop = of_find_property(np, propname, NULL); 905daeec1f0STony Prisk 906daeec1f0STony Prisk if (!prop) 907daeec1f0STony Prisk return ERR_PTR(-EINVAL); 908daeec1f0STony Prisk if (!prop->value) 909daeec1f0STony Prisk return ERR_PTR(-ENODATA); 910daeec1f0STony Prisk if (len > prop->length) 911daeec1f0STony Prisk return ERR_PTR(-EOVERFLOW); 912daeec1f0STony Prisk 913daeec1f0STony Prisk return prop->value; 914daeec1f0STony Prisk } 915daeec1f0STony Prisk 916daeec1f0STony Prisk /** 9173daf3726STony Prisk * of_property_read_u32_index - Find and read a u32 from a multi-value property. 9183daf3726STony Prisk * 9193daf3726STony Prisk * @np: device node from which the property value is to be read. 9203daf3726STony Prisk * @propname: name of the property to be searched. 9213daf3726STony Prisk * @index: index of the u32 in the list of values 9223daf3726STony Prisk * @out_value: pointer to return value, modified only if no error. 9233daf3726STony Prisk * 9243daf3726STony Prisk * Search for a property in a device node and read nth 32-bit value from 9253daf3726STony Prisk * it. Returns 0 on success, -EINVAL if the property does not exist, 9263daf3726STony Prisk * -ENODATA if property does not have a value, and -EOVERFLOW if the 9273daf3726STony Prisk * property data isn't large enough. 9283daf3726STony Prisk * 9293daf3726STony Prisk * The out_value is modified only if a valid u32 value can be decoded. 9303daf3726STony Prisk */ 9313daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np, 9323daf3726STony Prisk const char *propname, 9333daf3726STony Prisk u32 index, u32 *out_value) 9343daf3726STony Prisk { 935daeec1f0STony Prisk const u32 *val = of_find_property_value_of_size(np, propname, 936daeec1f0STony Prisk ((index + 1) * sizeof(*out_value))); 9373daf3726STony Prisk 938daeec1f0STony Prisk if (IS_ERR(val)) 939daeec1f0STony Prisk return PTR_ERR(val); 9403daf3726STony Prisk 941daeec1f0STony Prisk *out_value = be32_to_cpup(((__be32 *)val) + index); 9423daf3726STony Prisk return 0; 9433daf3726STony Prisk } 9443daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index); 9453daf3726STony Prisk 9463daf3726STony Prisk /** 947be193249SViresh Kumar * of_property_read_u8_array - Find and read an array of u8 from a property. 948be193249SViresh Kumar * 949be193249SViresh Kumar * @np: device node from which the property value is to be read. 950be193249SViresh Kumar * @propname: name of the property to be searched. 951792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 952be193249SViresh Kumar * @sz: number of array elements to read 953be193249SViresh Kumar * 954be193249SViresh Kumar * Search for a property in a device node and read 8-bit value(s) from 955be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 956be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 957be193249SViresh Kumar * property data isn't large enough. 958be193249SViresh Kumar * 959be193249SViresh Kumar * dts entry of array should be like: 960be193249SViresh Kumar * property = /bits/ 8 <0x50 0x60 0x70>; 961be193249SViresh Kumar * 962792efb84SLad, Prabhakar * The out_values is modified only if a valid u8 value can be decoded. 963be193249SViresh Kumar */ 964be193249SViresh Kumar int of_property_read_u8_array(const struct device_node *np, 965be193249SViresh Kumar const char *propname, u8 *out_values, size_t sz) 966be193249SViresh Kumar { 967daeec1f0STony Prisk const u8 *val = of_find_property_value_of_size(np, propname, 968daeec1f0STony Prisk (sz * sizeof(*out_values))); 969be193249SViresh Kumar 970daeec1f0STony Prisk if (IS_ERR(val)) 971daeec1f0STony Prisk return PTR_ERR(val); 972be193249SViresh Kumar 973be193249SViresh Kumar while (sz--) 974be193249SViresh Kumar *out_values++ = *val++; 975be193249SViresh Kumar return 0; 976be193249SViresh Kumar } 977be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u8_array); 978be193249SViresh Kumar 979be193249SViresh Kumar /** 980be193249SViresh Kumar * of_property_read_u16_array - Find and read an array of u16 from a property. 981be193249SViresh Kumar * 982be193249SViresh Kumar * @np: device node from which the property value is to be read. 983be193249SViresh Kumar * @propname: name of the property to be searched. 984792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 985be193249SViresh Kumar * @sz: number of array elements to read 986be193249SViresh Kumar * 987be193249SViresh Kumar * Search for a property in a device node and read 16-bit value(s) from 988be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 989be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 990be193249SViresh Kumar * property data isn't large enough. 991be193249SViresh Kumar * 992be193249SViresh Kumar * dts entry of array should be like: 993be193249SViresh Kumar * property = /bits/ 16 <0x5000 0x6000 0x7000>; 994be193249SViresh Kumar * 995792efb84SLad, Prabhakar * The out_values is modified only if a valid u16 value can be decoded. 996be193249SViresh Kumar */ 997be193249SViresh Kumar int of_property_read_u16_array(const struct device_node *np, 998be193249SViresh Kumar const char *propname, u16 *out_values, size_t sz) 999be193249SViresh Kumar { 1000daeec1f0STony Prisk const __be16 *val = of_find_property_value_of_size(np, propname, 1001daeec1f0STony Prisk (sz * sizeof(*out_values))); 1002be193249SViresh Kumar 1003daeec1f0STony Prisk if (IS_ERR(val)) 1004daeec1f0STony Prisk return PTR_ERR(val); 1005be193249SViresh Kumar 1006be193249SViresh Kumar while (sz--) 1007be193249SViresh Kumar *out_values++ = be16_to_cpup(val++); 1008be193249SViresh Kumar return 0; 1009be193249SViresh Kumar } 1010be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u16_array); 1011be193249SViresh Kumar 1012be193249SViresh Kumar /** 10130e373639SRob Herring * of_property_read_u32_array - Find and read an array of 32 bit integers 10140e373639SRob Herring * from a property. 10150e373639SRob Herring * 1016a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1017a3b85363SThomas Abraham * @propname: name of the property to be searched. 1018792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1019be193249SViresh Kumar * @sz: number of array elements to read 1020a3b85363SThomas Abraham * 10210e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 1022a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 1023a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 1024a3b85363SThomas Abraham * property data isn't large enough. 1025a3b85363SThomas Abraham * 1026792efb84SLad, Prabhakar * The out_values is modified only if a valid u32 value can be decoded. 1027a3b85363SThomas Abraham */ 1028aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np, 1029aac285c6SJamie Iles const char *propname, u32 *out_values, 1030aac285c6SJamie Iles size_t sz) 1031a3b85363SThomas Abraham { 1032daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1033daeec1f0STony Prisk (sz * sizeof(*out_values))); 1034a3b85363SThomas Abraham 1035daeec1f0STony Prisk if (IS_ERR(val)) 1036daeec1f0STony Prisk return PTR_ERR(val); 10370e373639SRob Herring 10380e373639SRob Herring while (sz--) 10390e373639SRob Herring *out_values++ = be32_to_cpup(val++); 1040a3b85363SThomas Abraham return 0; 1041a3b85363SThomas Abraham } 10420e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array); 1043a3b85363SThomas Abraham 1044a3b85363SThomas Abraham /** 10454cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 10464cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 10474cd7f7a3SJamie Iles * @propname: name of the property to be searched. 10484cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 10494cd7f7a3SJamie Iles * 10504cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 10514cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 10524cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 10534cd7f7a3SJamie Iles * property data isn't large enough. 10544cd7f7a3SJamie Iles * 10554cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 10564cd7f7a3SJamie Iles */ 10574cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 10584cd7f7a3SJamie Iles u64 *out_value) 10594cd7f7a3SJamie Iles { 1060daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1061daeec1f0STony Prisk sizeof(*out_value)); 10624cd7f7a3SJamie Iles 1063daeec1f0STony Prisk if (IS_ERR(val)) 1064daeec1f0STony Prisk return PTR_ERR(val); 1065daeec1f0STony Prisk 1066daeec1f0STony Prisk *out_value = of_read_number(val, 2); 10674cd7f7a3SJamie Iles return 0; 10684cd7f7a3SJamie Iles } 10694cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 10704cd7f7a3SJamie Iles 10714cd7f7a3SJamie Iles /** 1072a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 1073a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1074a3b85363SThomas Abraham * @propname: name of the property to be searched. 1075a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 1076a3b85363SThomas Abraham * return value is 0. 1077a3b85363SThomas Abraham * 1078a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 1079a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 1080a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 1081a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 1082a3b85363SThomas Abraham * within the length of the property data. 1083a3b85363SThomas Abraham * 1084a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 1085a3b85363SThomas Abraham */ 1086aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname, 1087f09bc831SShawn Guo const char **out_string) 1088a3b85363SThomas Abraham { 1089a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 1090a3b85363SThomas Abraham if (!prop) 1091a3b85363SThomas Abraham return -EINVAL; 1092a3b85363SThomas Abraham if (!prop->value) 1093a3b85363SThomas Abraham return -ENODATA; 1094a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 1095a3b85363SThomas Abraham return -EILSEQ; 1096a3b85363SThomas Abraham *out_string = prop->value; 1097a3b85363SThomas Abraham return 0; 1098a3b85363SThomas Abraham } 1099a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 1100a3b85363SThomas Abraham 1101a3b85363SThomas Abraham /** 11024fcd15a0SBenoit Cousson * of_property_read_string_index - Find and read a string from a multiple 11034fcd15a0SBenoit Cousson * strings property. 11044fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 11054fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 11064fcd15a0SBenoit Cousson * @index: index of the string in the list of strings 11074fcd15a0SBenoit Cousson * @out_string: pointer to null terminated return string, modified only if 11084fcd15a0SBenoit Cousson * return value is 0. 11094fcd15a0SBenoit Cousson * 11104fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve a null 11114fcd15a0SBenoit Cousson * terminated string value (pointer to data, not a copy) in the list of strings 11124fcd15a0SBenoit Cousson * contained in that property. 11134fcd15a0SBenoit Cousson * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if 11144fcd15a0SBenoit Cousson * property does not have a value, and -EILSEQ if the string is not 11154fcd15a0SBenoit Cousson * null-terminated within the length of the property data. 11164fcd15a0SBenoit Cousson * 11174fcd15a0SBenoit Cousson * The out_string pointer is modified only if a valid string can be decoded. 11184fcd15a0SBenoit Cousson */ 11194fcd15a0SBenoit Cousson int of_property_read_string_index(struct device_node *np, const char *propname, 11204fcd15a0SBenoit Cousson int index, const char **output) 11214fcd15a0SBenoit Cousson { 11224fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 11234fcd15a0SBenoit Cousson int i = 0; 11244fcd15a0SBenoit Cousson size_t l = 0, total = 0; 11254fcd15a0SBenoit Cousson const char *p; 11264fcd15a0SBenoit Cousson 11274fcd15a0SBenoit Cousson if (!prop) 11284fcd15a0SBenoit Cousson return -EINVAL; 11294fcd15a0SBenoit Cousson if (!prop->value) 11304fcd15a0SBenoit Cousson return -ENODATA; 11314fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 11324fcd15a0SBenoit Cousson return -EILSEQ; 11334fcd15a0SBenoit Cousson 11344fcd15a0SBenoit Cousson p = prop->value; 11354fcd15a0SBenoit Cousson 11364fcd15a0SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l) { 11374fcd15a0SBenoit Cousson l = strlen(p) + 1; 113888af7f58SBenoit Cousson if (i++ == index) { 11394fcd15a0SBenoit Cousson *output = p; 11404fcd15a0SBenoit Cousson return 0; 11414fcd15a0SBenoit Cousson } 11424fcd15a0SBenoit Cousson } 11434fcd15a0SBenoit Cousson return -ENODATA; 11444fcd15a0SBenoit Cousson } 11454fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_read_string_index); 11464fcd15a0SBenoit Cousson 11477aff0fe3SGrant Likely /** 11487aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 11497aff0fe3SGrant Likely * @np: pointer to node containing string list property 11507aff0fe3SGrant Likely * @propname: string list property name 11517aff0fe3SGrant Likely * @string: pointer to string to search for in string list 11527aff0fe3SGrant Likely * 11537aff0fe3SGrant Likely * This function searches a string list property and returns the index 11547aff0fe3SGrant Likely * of a specific string value. 11557aff0fe3SGrant Likely */ 11567aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname, 11577aff0fe3SGrant Likely const char *string) 11587aff0fe3SGrant Likely { 11597aff0fe3SGrant Likely struct property *prop = of_find_property(np, propname, NULL); 11607aff0fe3SGrant Likely size_t l; 11617aff0fe3SGrant Likely int i; 11627aff0fe3SGrant Likely const char *p, *end; 11637aff0fe3SGrant Likely 11647aff0fe3SGrant Likely if (!prop) 11657aff0fe3SGrant Likely return -EINVAL; 11667aff0fe3SGrant Likely if (!prop->value) 11677aff0fe3SGrant Likely return -ENODATA; 11687aff0fe3SGrant Likely 11697aff0fe3SGrant Likely p = prop->value; 11707aff0fe3SGrant Likely end = p + prop->length; 11717aff0fe3SGrant Likely 11727aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 11737aff0fe3SGrant Likely l = strlen(p) + 1; 11747aff0fe3SGrant Likely if (p + l > end) 11757aff0fe3SGrant Likely return -EILSEQ; 11767aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 11777aff0fe3SGrant Likely if (strcmp(string, p) == 0) 11787aff0fe3SGrant Likely return i; /* Found it; return index */ 11797aff0fe3SGrant Likely } 11807aff0fe3SGrant Likely return -ENODATA; 11817aff0fe3SGrant Likely } 11827aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 11834fcd15a0SBenoit Cousson 11844fcd15a0SBenoit Cousson /** 11854fcd15a0SBenoit Cousson * of_property_count_strings - Find and return the number of strings from a 11864fcd15a0SBenoit Cousson * multiple strings property. 11874fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 11884fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 11894fcd15a0SBenoit Cousson * 11904fcd15a0SBenoit Cousson * Search for a property in a device tree node and retrieve the number of null 11914fcd15a0SBenoit Cousson * terminated string contain in it. Returns the number of strings on 11924fcd15a0SBenoit Cousson * success, -EINVAL if the property does not exist, -ENODATA if property 11934fcd15a0SBenoit Cousson * does not have a value, and -EILSEQ if the string is not null-terminated 11944fcd15a0SBenoit Cousson * within the length of the property data. 11954fcd15a0SBenoit Cousson */ 11964fcd15a0SBenoit Cousson int of_property_count_strings(struct device_node *np, const char *propname) 11974fcd15a0SBenoit Cousson { 11984fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 11994fcd15a0SBenoit Cousson int i = 0; 12004fcd15a0SBenoit Cousson size_t l = 0, total = 0; 12014fcd15a0SBenoit Cousson const char *p; 12024fcd15a0SBenoit Cousson 12034fcd15a0SBenoit Cousson if (!prop) 12044fcd15a0SBenoit Cousson return -EINVAL; 12054fcd15a0SBenoit Cousson if (!prop->value) 12064fcd15a0SBenoit Cousson return -ENODATA; 12074fcd15a0SBenoit Cousson if (strnlen(prop->value, prop->length) >= prop->length) 12084fcd15a0SBenoit Cousson return -EILSEQ; 12094fcd15a0SBenoit Cousson 12104fcd15a0SBenoit Cousson p = prop->value; 12114fcd15a0SBenoit Cousson 121288af7f58SBenoit Cousson for (i = 0; total < prop->length; total += l, p += l, i++) 12134fcd15a0SBenoit Cousson l = strlen(p) + 1; 121488af7f58SBenoit Cousson 12154fcd15a0SBenoit Cousson return i; 12164fcd15a0SBenoit Cousson } 12174fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_count_strings); 12184fcd15a0SBenoit Cousson 1219624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1220624cfca5SGrant Likely { 1221624cfca5SGrant Likely int i; 1222624cfca5SGrant Likely printk("%s %s", msg, of_node_full_name(args->np)); 1223624cfca5SGrant Likely for (i = 0; i < args->args_count; i++) 1224624cfca5SGrant Likely printk(i ? ",%08x" : ":%08x", args->args[i]); 1225624cfca5SGrant Likely printk("\n"); 1226624cfca5SGrant Likely } 1227624cfca5SGrant Likely 1228bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1229bd69f73fSGrant Likely const char *list_name, 1230035fd948SStephen Warren const char *cells_name, 1231035fd948SStephen Warren int cell_count, int index, 123215c9a0acSGrant Likely struct of_phandle_args *out_args) 123364b60e09SAnton Vorontsov { 123415c9a0acSGrant Likely const __be32 *list, *list_end; 123523ce04c0SGrant Likely int rc = 0, size, cur_index = 0; 123615c9a0acSGrant Likely uint32_t count = 0; 123764b60e09SAnton Vorontsov struct device_node *node = NULL; 12389a6b2e58SGrant Likely phandle phandle; 123964b60e09SAnton Vorontsov 124015c9a0acSGrant Likely /* Retrieve the phandle list property */ 124115c9a0acSGrant Likely list = of_get_property(np, list_name, &size); 124215c9a0acSGrant Likely if (!list) 12431af4c7f1SAlexandre Courbot return -ENOENT; 124415c9a0acSGrant Likely list_end = list + size / sizeof(*list); 124515c9a0acSGrant Likely 124615c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 124715c9a0acSGrant Likely while (list < list_end) { 124823ce04c0SGrant Likely rc = -EINVAL; 124915c9a0acSGrant Likely count = 0; 125015c9a0acSGrant Likely 125115c9a0acSGrant Likely /* 125215c9a0acSGrant Likely * If phandle is 0, then it is an empty entry with no 125315c9a0acSGrant Likely * arguments. Skip forward to the next entry. 125415c9a0acSGrant Likely */ 12559a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 125615c9a0acSGrant Likely if (phandle) { 125715c9a0acSGrant Likely /* 125815c9a0acSGrant Likely * Find the provider node and parse the #*-cells 125991d9942cSStephen Warren * property to determine the argument length. 126091d9942cSStephen Warren * 126191d9942cSStephen Warren * This is not needed if the cell count is hard-coded 126291d9942cSStephen Warren * (i.e. cells_name not set, but cell_count is set), 126391d9942cSStephen Warren * except when we're going to return the found node 126491d9942cSStephen Warren * below. 126515c9a0acSGrant Likely */ 126691d9942cSStephen Warren if (cells_name || cur_index == index) { 12679a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 126864b60e09SAnton Vorontsov if (!node) { 126915c9a0acSGrant Likely pr_err("%s: could not find phandle\n", 127064b60e09SAnton Vorontsov np->full_name); 127123ce04c0SGrant Likely goto err; 127215c9a0acSGrant Likely } 127391d9942cSStephen Warren } 1274035fd948SStephen Warren 1275035fd948SStephen Warren if (cells_name) { 1276035fd948SStephen Warren if (of_property_read_u32(node, cells_name, 1277035fd948SStephen Warren &count)) { 127815c9a0acSGrant Likely pr_err("%s: could not get %s for %s\n", 127915c9a0acSGrant Likely np->full_name, cells_name, 128015c9a0acSGrant Likely node->full_name); 128123ce04c0SGrant Likely goto err; 128215c9a0acSGrant Likely } 1283035fd948SStephen Warren } else { 1284035fd948SStephen Warren count = cell_count; 1285035fd948SStephen Warren } 128615c9a0acSGrant Likely 128715c9a0acSGrant Likely /* 128815c9a0acSGrant Likely * Make sure that the arguments actually fit in the 128915c9a0acSGrant Likely * remaining property data length 129015c9a0acSGrant Likely */ 129115c9a0acSGrant Likely if (list + count > list_end) { 129215c9a0acSGrant Likely pr_err("%s: arguments longer than property\n", 129315c9a0acSGrant Likely np->full_name); 129423ce04c0SGrant Likely goto err; 129515c9a0acSGrant Likely } 129615c9a0acSGrant Likely } 129715c9a0acSGrant Likely 129815c9a0acSGrant Likely /* 129915c9a0acSGrant Likely * All of the error cases above bail out of the loop, so at 130015c9a0acSGrant Likely * this point, the parsing is successful. If the requested 130115c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 130215c9a0acSGrant Likely * or return -ENOENT for an empty entry. 130315c9a0acSGrant Likely */ 130423ce04c0SGrant Likely rc = -ENOENT; 130515c9a0acSGrant Likely if (cur_index == index) { 130615c9a0acSGrant Likely if (!phandle) 130723ce04c0SGrant Likely goto err; 130815c9a0acSGrant Likely 130915c9a0acSGrant Likely if (out_args) { 131015c9a0acSGrant Likely int i; 131115c9a0acSGrant Likely if (WARN_ON(count > MAX_PHANDLE_ARGS)) 131215c9a0acSGrant Likely count = MAX_PHANDLE_ARGS; 131315c9a0acSGrant Likely out_args->np = node; 131415c9a0acSGrant Likely out_args->args_count = count; 131515c9a0acSGrant Likely for (i = 0; i < count; i++) 131615c9a0acSGrant Likely out_args->args[i] = be32_to_cpup(list++); 1317b855f16bSTang Yuantian } else { 1318b855f16bSTang Yuantian of_node_put(node); 131915c9a0acSGrant Likely } 132023ce04c0SGrant Likely 132123ce04c0SGrant Likely /* Found it! return success */ 132215c9a0acSGrant Likely return 0; 132315c9a0acSGrant Likely } 132464b60e09SAnton Vorontsov 132564b60e09SAnton Vorontsov of_node_put(node); 132664b60e09SAnton Vorontsov node = NULL; 132715c9a0acSGrant Likely list += count; 132864b60e09SAnton Vorontsov cur_index++; 132964b60e09SAnton Vorontsov } 133064b60e09SAnton Vorontsov 133123ce04c0SGrant Likely /* 133223ce04c0SGrant Likely * Unlock node before returning result; will be one of: 133323ce04c0SGrant Likely * -ENOENT : index is for empty phandle 133423ce04c0SGrant Likely * -EINVAL : parsing error on data 1335bd69f73fSGrant Likely * [1..n] : Number of phandle (count mode; when index = -1) 133623ce04c0SGrant Likely */ 1337bd69f73fSGrant Likely rc = index < 0 ? cur_index : -ENOENT; 133823ce04c0SGrant Likely err: 133915c9a0acSGrant Likely if (node) 134064b60e09SAnton Vorontsov of_node_put(node); 134123ce04c0SGrant Likely return rc; 134264b60e09SAnton Vorontsov } 1343bd69f73fSGrant Likely 1344eded9dd4SStephen Warren /** 13455fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 13465fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 13475fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 13485fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 13495fba49e3SStephen Warren * the table 13505fba49e3SStephen Warren * 13515fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 13525fba49e3SStephen Warren * of_node_put() on it when done. 13535fba49e3SStephen Warren */ 13545fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 13555fba49e3SStephen Warren const char *phandle_name, int index) 13565fba49e3SStephen Warren { 135791d9942cSStephen Warren struct of_phandle_args args; 13585fba49e3SStephen Warren 135991d9942cSStephen Warren if (index < 0) 13605fba49e3SStephen Warren return NULL; 13615fba49e3SStephen Warren 136291d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 136391d9942cSStephen Warren index, &args)) 136491d9942cSStephen Warren return NULL; 136591d9942cSStephen Warren 136691d9942cSStephen Warren return args.np; 13675fba49e3SStephen Warren } 13685fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 13695fba49e3SStephen Warren 13705fba49e3SStephen Warren /** 1371eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1372eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1373eded9dd4SStephen Warren * @list_name: property name that contains a list 1374eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1375eded9dd4SStephen Warren * @index: index of a phandle to parse out 1376eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1377eded9dd4SStephen Warren * 1378eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1379eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1380eded9dd4SStephen Warren * errno value. 1381eded9dd4SStephen Warren * 1382eded9dd4SStephen Warren * Caller is responsible to call of_node_put() on the returned out_args->node 1383eded9dd4SStephen Warren * pointer. 1384eded9dd4SStephen Warren * 1385eded9dd4SStephen Warren * Example: 1386eded9dd4SStephen Warren * 1387eded9dd4SStephen Warren * phandle1: node1 { 1388eded9dd4SStephen Warren * #list-cells = <2>; 1389eded9dd4SStephen Warren * } 1390eded9dd4SStephen Warren * 1391eded9dd4SStephen Warren * phandle2: node2 { 1392eded9dd4SStephen Warren * #list-cells = <1>; 1393eded9dd4SStephen Warren * } 1394eded9dd4SStephen Warren * 1395eded9dd4SStephen Warren * node3 { 1396eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1397eded9dd4SStephen Warren * } 1398eded9dd4SStephen Warren * 1399eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1400eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1401eded9dd4SStephen Warren */ 1402bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1403bd69f73fSGrant Likely const char *cells_name, int index, 1404bd69f73fSGrant Likely struct of_phandle_args *out_args) 1405bd69f73fSGrant Likely { 1406bd69f73fSGrant Likely if (index < 0) 1407bd69f73fSGrant Likely return -EINVAL; 1408035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1409035fd948SStephen Warren index, out_args); 1410bd69f73fSGrant Likely } 141115c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 141202af11b0SGrant Likely 1413bd69f73fSGrant Likely /** 1414035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1415035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1416035fd948SStephen Warren * @list_name: property name that contains a list 1417035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1418035fd948SStephen Warren * @index: index of a phandle to parse out 1419035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1420035fd948SStephen Warren * 1421035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1422035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1423035fd948SStephen Warren * errno value. 1424035fd948SStephen Warren * 1425035fd948SStephen Warren * Caller is responsible to call of_node_put() on the returned out_args->node 1426035fd948SStephen Warren * pointer. 1427035fd948SStephen Warren * 1428035fd948SStephen Warren * Example: 1429035fd948SStephen Warren * 1430035fd948SStephen Warren * phandle1: node1 { 1431035fd948SStephen Warren * } 1432035fd948SStephen Warren * 1433035fd948SStephen Warren * phandle2: node2 { 1434035fd948SStephen Warren * } 1435035fd948SStephen Warren * 1436035fd948SStephen Warren * node3 { 1437035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1438035fd948SStephen Warren * } 1439035fd948SStephen Warren * 1440035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1441035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1442035fd948SStephen Warren */ 1443035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1444035fd948SStephen Warren const char *list_name, int cell_count, 1445035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1446035fd948SStephen Warren { 1447035fd948SStephen Warren if (index < 0) 1448035fd948SStephen Warren return -EINVAL; 1449035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1450035fd948SStephen Warren index, out_args); 1451035fd948SStephen Warren } 1452035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1453035fd948SStephen Warren 1454035fd948SStephen Warren /** 1455bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1456bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1457bd69f73fSGrant Likely * @list_name: property name that contains a list 1458bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1459bd69f73fSGrant Likely * 1460bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1461bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1462bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1463bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1464bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1465bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1466bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1467bd69f73fSGrant Likely * phandle. 1468bd69f73fSGrant Likely */ 1469bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1470bd69f73fSGrant Likely const char *cells_name) 1471bd69f73fSGrant Likely { 1472035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1, 1473035fd948SStephen Warren NULL); 1474bd69f73fSGrant Likely } 1475bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1476bd69f73fSGrant Likely 14771cf3d8b3SNathan Fontenot #if defined(CONFIG_OF_DYNAMIC) 14781cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np, 14791cf3d8b3SNathan Fontenot struct property *prop) 14801cf3d8b3SNathan Fontenot { 14811cf3d8b3SNathan Fontenot struct of_prop_reconfig pr; 14821cf3d8b3SNathan Fontenot 14831cf3d8b3SNathan Fontenot pr.dn = np; 14841cf3d8b3SNathan Fontenot pr.prop = prop; 14851cf3d8b3SNathan Fontenot return of_reconfig_notify(action, &pr); 14861cf3d8b3SNathan Fontenot } 14871cf3d8b3SNathan Fontenot #else 14881cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np, 14891cf3d8b3SNathan Fontenot struct property *prop) 14901cf3d8b3SNathan Fontenot { 14911cf3d8b3SNathan Fontenot return 0; 14921cf3d8b3SNathan Fontenot } 14931cf3d8b3SNathan Fontenot #endif 14941cf3d8b3SNathan Fontenot 149502af11b0SGrant Likely /** 149662664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 149762664f67SXiubo Li */ 149862664f67SXiubo Li static int __of_add_property(struct device_node *np, struct property *prop) 149962664f67SXiubo Li { 150062664f67SXiubo Li struct property **next; 150162664f67SXiubo Li 150262664f67SXiubo Li prop->next = NULL; 150362664f67SXiubo Li next = &np->properties; 150462664f67SXiubo Li while (*next) { 150562664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 150662664f67SXiubo Li /* duplicate ! don't insert it */ 150762664f67SXiubo Li return -EEXIST; 150862664f67SXiubo Li 150962664f67SXiubo Li next = &(*next)->next; 151062664f67SXiubo Li } 151162664f67SXiubo Li *next = prop; 151262664f67SXiubo Li 151362664f67SXiubo Li return 0; 151462664f67SXiubo Li } 151562664f67SXiubo Li 151662664f67SXiubo Li /** 151779d1c712SNathan Fontenot * of_add_property - Add a property to a node 151802af11b0SGrant Likely */ 151979d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 152002af11b0SGrant Likely { 152102af11b0SGrant Likely unsigned long flags; 15221cf3d8b3SNathan Fontenot int rc; 15231cf3d8b3SNathan Fontenot 15241cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); 15251cf3d8b3SNathan Fontenot if (rc) 15261cf3d8b3SNathan Fontenot return rc; 152702af11b0SGrant Likely 1528d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 152962664f67SXiubo Li rc = __of_add_property(np, prop); 1530d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 153102af11b0SGrant Likely 153202af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 153302af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 153462664f67SXiubo Li if (!rc && np->pde) 153502af11b0SGrant Likely proc_device_tree_add_prop(np->pde, prop); 153602af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 153702af11b0SGrant Likely 153862664f67SXiubo Li return rc; 153902af11b0SGrant Likely } 154002af11b0SGrant Likely 154102af11b0SGrant Likely /** 154279d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 154302af11b0SGrant Likely * 154402af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 154502af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 154602af11b0SGrant Likely * Instead we just move the property to the "dead properties" 154702af11b0SGrant Likely * list, so it won't be found any more. 154802af11b0SGrant Likely */ 154979d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 155002af11b0SGrant Likely { 155102af11b0SGrant Likely struct property **next; 155202af11b0SGrant Likely unsigned long flags; 155302af11b0SGrant Likely int found = 0; 15541cf3d8b3SNathan Fontenot int rc; 15551cf3d8b3SNathan Fontenot 15561cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); 15571cf3d8b3SNathan Fontenot if (rc) 15581cf3d8b3SNathan Fontenot return rc; 155902af11b0SGrant Likely 1560d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 156102af11b0SGrant Likely next = &np->properties; 156202af11b0SGrant Likely while (*next) { 156302af11b0SGrant Likely if (*next == prop) { 156402af11b0SGrant Likely /* found the node */ 156502af11b0SGrant Likely *next = prop->next; 156602af11b0SGrant Likely prop->next = np->deadprops; 156702af11b0SGrant Likely np->deadprops = prop; 156802af11b0SGrant Likely found = 1; 156902af11b0SGrant Likely break; 157002af11b0SGrant Likely } 157102af11b0SGrant Likely next = &(*next)->next; 157202af11b0SGrant Likely } 1573d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 157402af11b0SGrant Likely 157502af11b0SGrant Likely if (!found) 157602af11b0SGrant Likely return -ENODEV; 157702af11b0SGrant Likely 157802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 157902af11b0SGrant Likely /* try to remove the proc node as well */ 158002af11b0SGrant Likely if (np->pde) 158102af11b0SGrant Likely proc_device_tree_remove_prop(np->pde, prop); 158202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 158302af11b0SGrant Likely 158402af11b0SGrant Likely return 0; 158502af11b0SGrant Likely } 158602af11b0SGrant Likely 158702af11b0SGrant Likely /* 158879d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1589475d0094SDong Aisheng * not exist, add it. 159002af11b0SGrant Likely * 159102af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 159202af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 159302af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 159402af11b0SGrant Likely * and add the new property to the property list 159502af11b0SGrant Likely */ 159679d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 159702af11b0SGrant Likely { 1598475d0094SDong Aisheng struct property **next, *oldprop; 159902af11b0SGrant Likely unsigned long flags; 16001cf3d8b3SNathan Fontenot int rc, found = 0; 16011cf3d8b3SNathan Fontenot 16021cf3d8b3SNathan Fontenot rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); 16031cf3d8b3SNathan Fontenot if (rc) 16041cf3d8b3SNathan Fontenot return rc; 160502af11b0SGrant Likely 1606475d0094SDong Aisheng if (!newprop->name) 1607475d0094SDong Aisheng return -EINVAL; 1608475d0094SDong Aisheng 1609475d0094SDong Aisheng oldprop = of_find_property(np, newprop->name, NULL); 1610475d0094SDong Aisheng if (!oldprop) 161179d1c712SNathan Fontenot return of_add_property(np, newprop); 1612475d0094SDong Aisheng 1613d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 161402af11b0SGrant Likely next = &np->properties; 161502af11b0SGrant Likely while (*next) { 161602af11b0SGrant Likely if (*next == oldprop) { 161702af11b0SGrant Likely /* found the node */ 161802af11b0SGrant Likely newprop->next = oldprop->next; 161902af11b0SGrant Likely *next = newprop; 162002af11b0SGrant Likely oldprop->next = np->deadprops; 162102af11b0SGrant Likely np->deadprops = oldprop; 162202af11b0SGrant Likely found = 1; 162302af11b0SGrant Likely break; 162402af11b0SGrant Likely } 162502af11b0SGrant Likely next = &(*next)->next; 162602af11b0SGrant Likely } 1627d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 162802af11b0SGrant Likely 162902af11b0SGrant Likely if (!found) 163002af11b0SGrant Likely return -ENODEV; 163102af11b0SGrant Likely 163202af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE 163302af11b0SGrant Likely /* try to add to proc as well if it was initialized */ 163402af11b0SGrant Likely if (np->pde) 163502af11b0SGrant Likely proc_device_tree_update_prop(np->pde, newprop, oldprop); 163602af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */ 163702af11b0SGrant Likely 163802af11b0SGrant Likely return 0; 163902af11b0SGrant Likely } 1640fcdeb7feSGrant Likely 1641fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC) 1642fcdeb7feSGrant Likely /* 1643fcdeb7feSGrant Likely * Support for dynamic device trees. 1644fcdeb7feSGrant Likely * 1645fcdeb7feSGrant Likely * On some platforms, the device tree can be manipulated at runtime. 1646fcdeb7feSGrant Likely * The routines in this section support adding, removing and changing 1647fcdeb7feSGrant Likely * device tree nodes. 1648fcdeb7feSGrant Likely */ 1649fcdeb7feSGrant Likely 16501cf3d8b3SNathan Fontenot static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain); 16511cf3d8b3SNathan Fontenot 16521cf3d8b3SNathan Fontenot int of_reconfig_notifier_register(struct notifier_block *nb) 16531cf3d8b3SNathan Fontenot { 16541cf3d8b3SNathan Fontenot return blocking_notifier_chain_register(&of_reconfig_chain, nb); 16551cf3d8b3SNathan Fontenot } 16561a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_register); 16571cf3d8b3SNathan Fontenot 16581cf3d8b3SNathan Fontenot int of_reconfig_notifier_unregister(struct notifier_block *nb) 16591cf3d8b3SNathan Fontenot { 16601cf3d8b3SNathan Fontenot return blocking_notifier_chain_unregister(&of_reconfig_chain, nb); 16611cf3d8b3SNathan Fontenot } 16621a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister); 16631cf3d8b3SNathan Fontenot 16641cf3d8b3SNathan Fontenot int of_reconfig_notify(unsigned long action, void *p) 16651cf3d8b3SNathan Fontenot { 16661cf3d8b3SNathan Fontenot int rc; 16671cf3d8b3SNathan Fontenot 16681cf3d8b3SNathan Fontenot rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p); 16691cf3d8b3SNathan Fontenot return notifier_to_errno(rc); 16701cf3d8b3SNathan Fontenot } 16711cf3d8b3SNathan Fontenot 1672e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE 1673e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn) 1674e81b3295SNathan Fontenot { 1675e81b3295SNathan Fontenot struct proc_dir_entry *ent; 1676e81b3295SNathan Fontenot 1677e81b3295SNathan Fontenot ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); 1678e81b3295SNathan Fontenot if (ent) 1679e81b3295SNathan Fontenot proc_device_tree_add_node(dn, ent); 1680e81b3295SNathan Fontenot } 1681e81b3295SNathan Fontenot #else 1682e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn) 1683e81b3295SNathan Fontenot { 1684e81b3295SNathan Fontenot return; 1685e81b3295SNathan Fontenot } 1686e81b3295SNathan Fontenot #endif 1687e81b3295SNathan Fontenot 1688fcdeb7feSGrant Likely /** 1689fcdeb7feSGrant Likely * of_attach_node - Plug a device node into the tree and global list. 1690fcdeb7feSGrant Likely */ 16911cf3d8b3SNathan Fontenot int of_attach_node(struct device_node *np) 1692fcdeb7feSGrant Likely { 1693fcdeb7feSGrant Likely unsigned long flags; 16941cf3d8b3SNathan Fontenot int rc; 16951cf3d8b3SNathan Fontenot 16961cf3d8b3SNathan Fontenot rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); 16971cf3d8b3SNathan Fontenot if (rc) 16981cf3d8b3SNathan Fontenot return rc; 1699fcdeb7feSGrant Likely 1700d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1701fcdeb7feSGrant Likely np->sibling = np->parent->child; 1702465aac6dSRandy Dunlap np->allnext = of_allnodes; 1703fcdeb7feSGrant Likely np->parent->child = np; 1704465aac6dSRandy Dunlap of_allnodes = np; 1705e3963fd6SPantelis Antoniou of_node_clear_flag(np, OF_DETACHED); 1706d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1707e81b3295SNathan Fontenot 1708e81b3295SNathan Fontenot of_add_proc_dt_entry(np); 17091cf3d8b3SNathan Fontenot return 0; 1710fcdeb7feSGrant Likely } 1711fcdeb7feSGrant Likely 1712e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE 1713e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn) 1714e81b3295SNathan Fontenot { 1715a8ca16eaSDavid Howells proc_remove(dn->pde); 1716e81b3295SNathan Fontenot } 1717e81b3295SNathan Fontenot #else 1718e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn) 1719e81b3295SNathan Fontenot { 1720e81b3295SNathan Fontenot return; 1721e81b3295SNathan Fontenot } 1722e81b3295SNathan Fontenot #endif 1723e81b3295SNathan Fontenot 1724fcdeb7feSGrant Likely /** 1725fcdeb7feSGrant Likely * of_detach_node - "Unplug" a node from the device tree. 1726fcdeb7feSGrant Likely * 1727fcdeb7feSGrant Likely * The caller must hold a reference to the node. The memory associated with 1728fcdeb7feSGrant Likely * the node is not freed until its refcount goes to zero. 1729fcdeb7feSGrant Likely */ 17301cf3d8b3SNathan Fontenot int of_detach_node(struct device_node *np) 1731fcdeb7feSGrant Likely { 1732fcdeb7feSGrant Likely struct device_node *parent; 1733fcdeb7feSGrant Likely unsigned long flags; 17341cf3d8b3SNathan Fontenot int rc = 0; 17351cf3d8b3SNathan Fontenot 17361cf3d8b3SNathan Fontenot rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); 17371cf3d8b3SNathan Fontenot if (rc) 17381cf3d8b3SNathan Fontenot return rc; 1739fcdeb7feSGrant Likely 1740d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1741fcdeb7feSGrant Likely 1742e81b3295SNathan Fontenot if (of_node_check_flag(np, OF_DETACHED)) { 1743e81b3295SNathan Fontenot /* someone already detached it */ 1744d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 17451cf3d8b3SNathan Fontenot return rc; 1746e81b3295SNathan Fontenot } 1747e81b3295SNathan Fontenot 1748fcdeb7feSGrant Likely parent = np->parent; 1749e81b3295SNathan Fontenot if (!parent) { 1750d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 17511cf3d8b3SNathan Fontenot return rc; 1752e81b3295SNathan Fontenot } 1753fcdeb7feSGrant Likely 1754465aac6dSRandy Dunlap if (of_allnodes == np) 1755465aac6dSRandy Dunlap of_allnodes = np->allnext; 1756fcdeb7feSGrant Likely else { 1757fcdeb7feSGrant Likely struct device_node *prev; 1758465aac6dSRandy Dunlap for (prev = of_allnodes; 1759fcdeb7feSGrant Likely prev->allnext != np; 1760fcdeb7feSGrant Likely prev = prev->allnext) 1761fcdeb7feSGrant Likely ; 1762fcdeb7feSGrant Likely prev->allnext = np->allnext; 1763fcdeb7feSGrant Likely } 1764fcdeb7feSGrant Likely 1765fcdeb7feSGrant Likely if (parent->child == np) 1766fcdeb7feSGrant Likely parent->child = np->sibling; 1767fcdeb7feSGrant Likely else { 1768fcdeb7feSGrant Likely struct device_node *prevsib; 1769fcdeb7feSGrant Likely for (prevsib = np->parent->child; 1770fcdeb7feSGrant Likely prevsib->sibling != np; 1771fcdeb7feSGrant Likely prevsib = prevsib->sibling) 1772fcdeb7feSGrant Likely ; 1773fcdeb7feSGrant Likely prevsib->sibling = np->sibling; 1774fcdeb7feSGrant Likely } 1775fcdeb7feSGrant Likely 1776fcdeb7feSGrant Likely of_node_set_flag(np, OF_DETACHED); 1777d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1778e81b3295SNathan Fontenot 1779e81b3295SNathan Fontenot of_remove_proc_dt_entry(np); 17801cf3d8b3SNathan Fontenot return rc; 1781fcdeb7feSGrant Likely } 1782fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */ 1783fcdeb7feSGrant Likely 1784611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1785611cad72SShawn Guo int id, const char *stem, int stem_len) 1786611cad72SShawn Guo { 1787611cad72SShawn Guo ap->np = np; 1788611cad72SShawn Guo ap->id = id; 1789611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1790611cad72SShawn Guo ap->stem[stem_len] = 0; 1791611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1792611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 179374a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 1794611cad72SShawn Guo } 1795611cad72SShawn Guo 1796611cad72SShawn Guo /** 1797611cad72SShawn Guo * of_alias_scan - Scan all properties of 'aliases' node 1798611cad72SShawn Guo * 1799611cad72SShawn Guo * The function scans all the properties of 'aliases' node and populate 1800611cad72SShawn Guo * the the global lookup table with the properties. It returns the 1801611cad72SShawn Guo * number of alias_prop found, or error code in error case. 1802611cad72SShawn Guo * 1803611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 1804611cad72SShawn Guo * for the resulting tree 1805611cad72SShawn Guo */ 1806611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1807611cad72SShawn Guo { 1808611cad72SShawn Guo struct property *pp; 1809611cad72SShawn Guo 1810611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1811611cad72SShawn Guo if (of_chosen == NULL) 1812611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 18135c19e952SSascha Hauer 18145c19e952SSascha Hauer if (of_chosen) { 18155c19e952SSascha Hauer const char *name; 18165c19e952SSascha Hauer 18175c19e952SSascha Hauer name = of_get_property(of_chosen, "linux,stdout-path", NULL); 18185c19e952SSascha Hauer if (name) 18195c19e952SSascha Hauer of_stdout = of_find_node_by_path(name); 18205c19e952SSascha Hauer } 18215c19e952SSascha Hauer 1822611cad72SShawn Guo of_aliases = of_find_node_by_path("/aliases"); 1823611cad72SShawn Guo if (!of_aliases) 1824611cad72SShawn Guo return; 1825611cad72SShawn Guo 18268af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1827611cad72SShawn Guo const char *start = pp->name; 1828611cad72SShawn Guo const char *end = start + strlen(start); 1829611cad72SShawn Guo struct device_node *np; 1830611cad72SShawn Guo struct alias_prop *ap; 1831611cad72SShawn Guo int id, len; 1832611cad72SShawn Guo 1833611cad72SShawn Guo /* Skip those we do not want to proceed */ 1834611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1835611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1836611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1837611cad72SShawn Guo continue; 1838611cad72SShawn Guo 1839611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1840611cad72SShawn Guo if (!np) 1841611cad72SShawn Guo continue; 1842611cad72SShawn Guo 1843611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1844611cad72SShawn Guo * the 'stem' string */ 1845611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1846611cad72SShawn Guo end--; 1847611cad72SShawn Guo len = end - start; 1848611cad72SShawn Guo 1849611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1850611cad72SShawn Guo continue; 1851611cad72SShawn Guo 1852611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1853611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1854611cad72SShawn Guo if (!ap) 1855611cad72SShawn Guo continue; 18560640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1857611cad72SShawn Guo ap->alias = start; 1858611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1859611cad72SShawn Guo } 1860611cad72SShawn Guo } 1861611cad72SShawn Guo 1862611cad72SShawn Guo /** 1863611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1864611cad72SShawn Guo * @np: Pointer to the given device_node 1865611cad72SShawn Guo * @stem: Alias stem of the given device_node 1866611cad72SShawn Guo * 1867611cad72SShawn Guo * The function travels the lookup table to get alias id for the given 1868611cad72SShawn Guo * device_node and alias stem. It returns the alias id if find it. 1869611cad72SShawn Guo */ 1870611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1871611cad72SShawn Guo { 1872611cad72SShawn Guo struct alias_prop *app; 1873611cad72SShawn Guo int id = -ENODEV; 1874611cad72SShawn Guo 1875611cad72SShawn Guo mutex_lock(&of_aliases_mutex); 1876611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1877611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1878611cad72SShawn Guo continue; 1879611cad72SShawn Guo 1880611cad72SShawn Guo if (np == app->np) { 1881611cad72SShawn Guo id = app->id; 1882611cad72SShawn Guo break; 1883611cad72SShawn Guo } 1884611cad72SShawn Guo } 1885611cad72SShawn Guo mutex_unlock(&of_aliases_mutex); 1886611cad72SShawn Guo 1887611cad72SShawn Guo return id; 1888611cad72SShawn Guo } 1889611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1890c541adc6SStephen Warren 1891c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 1892c541adc6SStephen Warren u32 *pu) 1893c541adc6SStephen Warren { 1894c541adc6SStephen Warren const void *curv = cur; 1895c541adc6SStephen Warren 1896c541adc6SStephen Warren if (!prop) 1897c541adc6SStephen Warren return NULL; 1898c541adc6SStephen Warren 1899c541adc6SStephen Warren if (!cur) { 1900c541adc6SStephen Warren curv = prop->value; 1901c541adc6SStephen Warren goto out_val; 1902c541adc6SStephen Warren } 1903c541adc6SStephen Warren 1904c541adc6SStephen Warren curv += sizeof(*cur); 1905c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1906c541adc6SStephen Warren return NULL; 1907c541adc6SStephen Warren 1908c541adc6SStephen Warren out_val: 1909c541adc6SStephen Warren *pu = be32_to_cpup(curv); 1910c541adc6SStephen Warren return curv; 1911c541adc6SStephen Warren } 1912c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 1913c541adc6SStephen Warren 1914c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 1915c541adc6SStephen Warren { 1916c541adc6SStephen Warren const void *curv = cur; 1917c541adc6SStephen Warren 1918c541adc6SStephen Warren if (!prop) 1919c541adc6SStephen Warren return NULL; 1920c541adc6SStephen Warren 1921c541adc6SStephen Warren if (!cur) 1922c541adc6SStephen Warren return prop->value; 1923c541adc6SStephen Warren 1924c541adc6SStephen Warren curv += strlen(cur) + 1; 1925c541adc6SStephen Warren if (curv >= prop->value + prop->length) 1926c541adc6SStephen Warren return NULL; 1927c541adc6SStephen Warren 1928c541adc6SStephen Warren return curv; 1929c541adc6SStephen Warren } 1930c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 19315c19e952SSascha Hauer 19325c19e952SSascha Hauer /** 19335c19e952SSascha Hauer * of_device_is_stdout_path - check if a device node matches the 19345c19e952SSascha Hauer * linux,stdout-path property 19355c19e952SSascha Hauer * 19365c19e952SSascha Hauer * Check if this device node matches the linux,stdout-path property 19375c19e952SSascha Hauer * in the chosen node. return true if yes, false otherwise. 19385c19e952SSascha Hauer */ 19395c19e952SSascha Hauer int of_device_is_stdout_path(struct device_node *dn) 19405c19e952SSascha Hauer { 19415c19e952SSascha Hauer if (!of_stdout) 19425c19e952SSascha Hauer return false; 19435c19e952SSascha Hauer 19445c19e952SSascha Hauer return of_stdout == dn; 19455c19e952SSascha Hauer } 19465c19e952SSascha Hauer EXPORT_SYMBOL_GPL(of_device_is_stdout_path); 1947a3e31b45SSudeep KarkadaNagesha 1948a3e31b45SSudeep KarkadaNagesha /** 1949a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 1950a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 1951a3e31b45SSudeep KarkadaNagesha * 1952a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 1953a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 1954a3e31b45SSudeep KarkadaNagesha * to np. 1955a3e31b45SSudeep KarkadaNagesha */ 1956a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 1957a3e31b45SSudeep KarkadaNagesha { 1958a3e31b45SSudeep KarkadaNagesha struct device_node *child; 1959a3e31b45SSudeep KarkadaNagesha const phandle *handle; 1960a3e31b45SSudeep KarkadaNagesha 1961a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "l2-cache", NULL); 1962a3e31b45SSudeep KarkadaNagesha if (!handle) 1963a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "next-level-cache", NULL); 1964a3e31b45SSudeep KarkadaNagesha 1965a3e31b45SSudeep KarkadaNagesha if (handle) 1966a3e31b45SSudeep KarkadaNagesha return of_find_node_by_phandle(be32_to_cpup(handle)); 1967a3e31b45SSudeep KarkadaNagesha 1968a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 1969a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 1970a3e31b45SSudeep KarkadaNagesha */ 1971a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 1972a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 1973a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 1974a3e31b45SSudeep KarkadaNagesha return child; 1975a3e31b45SSudeep KarkadaNagesha 1976a3e31b45SSudeep KarkadaNagesha return NULL; 1977a3e31b45SSudeep KarkadaNagesha } 1978