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 */ 20606ad42aSRob Herring 21606ad42aSRob Herring #define pr_fmt(fmt) "OF: " fmt 22606ad42aSRob Herring 233482f2c5SGrant Likely #include <linux/console.h> 24611cad72SShawn Guo #include <linux/ctype.h> 25183912d3SSudeep KarkadaNagesha #include <linux/cpu.h> 2697e873e5SStephen Rothwell #include <linux/module.h> 2797e873e5SStephen Rothwell #include <linux/of.h> 285fa23530SSudeep Holla #include <linux/of_device.h> 29fd9fdb78SPhilipp Zabel #include <linux/of_graph.h> 30581b605aSStephen Rothwell #include <linux/spinlock.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 3275b57ecfSGrant Likely #include <linux/string.h> 33a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 34581b605aSStephen Rothwell 35ced4eec9SStepan Moskovchenko #include "of_private.h" 36611cad72SShawn Guo 37ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 38611cad72SShawn Guo 395063e25aSGrant Likely struct device_node *of_root; 405063e25aSGrant Likely EXPORT_SYMBOL(of_root); 41fc0bdae4SGrant Likely struct device_node *of_chosen; 42611cad72SShawn Guo struct device_node *of_aliases; 43a752ee56SGrant Likely struct device_node *of_stdout; 447914a7c5SLeif Lindholm static const char *of_stdout_options; 45611cad72SShawn Guo 468a2b22a2SGrant Likely struct kset *of_kset; 4775b57ecfSGrant Likely 4875b57ecfSGrant Likely /* 498a2b22a2SGrant Likely * Used to protect the of_aliases, to hold off addition of nodes to sysfs. 508a2b22a2SGrant Likely * This mutex must be held whenever modifications are being made to the 518a2b22a2SGrant Likely * device tree. The of_{attach,detach}_node() and 528a2b22a2SGrant Likely * of_{add,remove,update}_property() helpers make sure this happens. 5375b57ecfSGrant Likely */ 54c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex); 551ef4d424SStephen Rothwell 565063e25aSGrant Likely /* use when traversing tree through the child, sibling, 57581b605aSStephen Rothwell * or parent members of struct device_node. 58581b605aSStephen Rothwell */ 59d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 6097e873e5SStephen Rothwell 6197e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 6297e873e5SStephen Rothwell { 638832963dSSergei Shtylyov u32 cells; 6497e873e5SStephen Rothwell 6597e873e5SStephen Rothwell do { 6697e873e5SStephen Rothwell if (np->parent) 6797e873e5SStephen Rothwell np = np->parent; 688832963dSSergei Shtylyov if (!of_property_read_u32(np, "#address-cells", &cells)) 698832963dSSergei Shtylyov return cells; 7097e873e5SStephen Rothwell } while (np->parent); 7197e873e5SStephen Rothwell /* No #address-cells property for the root node */ 7297e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 7397e873e5SStephen Rothwell } 7497e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 7597e873e5SStephen Rothwell 7697e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 7797e873e5SStephen Rothwell { 788832963dSSergei Shtylyov u32 cells; 7997e873e5SStephen Rothwell 8097e873e5SStephen Rothwell do { 8197e873e5SStephen Rothwell if (np->parent) 8297e873e5SStephen Rothwell np = np->parent; 838832963dSSergei Shtylyov if (!of_property_read_u32(np, "#size-cells", &cells)) 848832963dSSergei Shtylyov return cells; 8597e873e5SStephen Rothwell } while (np->parent); 8697e873e5SStephen Rothwell /* No #size-cells property for the root node */ 8797e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 8897e873e5SStephen Rothwell } 8997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 9097e873e5SStephen Rothwell 910c3f061cSRob Herring #ifdef CONFIG_NUMA 920c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np) 930c3f061cSRob Herring { 94c8fff7bcSKonstantin Khlebnikov return NUMA_NO_NODE; 950c3f061cSRob Herring } 960c3f061cSRob Herring #endif 970c3f061cSRob Herring 986afc0dc3SGrant Likely #ifndef CONFIG_OF_DYNAMIC 9975b57ecfSGrant Likely static void of_node_release(struct kobject *kobj) 10075b57ecfSGrant Likely { 10175b57ecfSGrant Likely /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ 10275b57ecfSGrant Likely } 1030f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 104923f7e30SGrant Likely 10575b57ecfSGrant Likely struct kobj_type of_node_ktype = { 10675b57ecfSGrant Likely .release = of_node_release, 10775b57ecfSGrant Likely }; 10875b57ecfSGrant Likely 10975b57ecfSGrant Likely static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, 11075b57ecfSGrant Likely struct bin_attribute *bin_attr, char *buf, 11175b57ecfSGrant Likely loff_t offset, size_t count) 11275b57ecfSGrant Likely { 11375b57ecfSGrant Likely struct property *pp = container_of(bin_attr, struct property, attr); 11475b57ecfSGrant Likely return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); 11575b57ecfSGrant Likely } 11675b57ecfSGrant Likely 117d9fc8807SFrank Rowand /* always return newly allocated name, caller must free after use */ 11875b57ecfSGrant Likely static const char *safe_name(struct kobject *kobj, const char *orig_name) 11975b57ecfSGrant Likely { 12075b57ecfSGrant Likely const char *name = orig_name; 12175b57ecfSGrant Likely struct kernfs_node *kn; 12275b57ecfSGrant Likely int i = 0; 12375b57ecfSGrant Likely 12475b57ecfSGrant Likely /* don't be a hero. After 16 tries give up */ 12575b57ecfSGrant Likely while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { 12675b57ecfSGrant Likely sysfs_put(kn); 12775b57ecfSGrant Likely if (name != orig_name) 12875b57ecfSGrant Likely kfree(name); 12975b57ecfSGrant Likely name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); 13075b57ecfSGrant Likely } 13175b57ecfSGrant Likely 132d9fc8807SFrank Rowand if (name == orig_name) { 133d9fc8807SFrank Rowand name = kstrdup(orig_name, GFP_KERNEL); 134d9fc8807SFrank Rowand } else { 135606ad42aSRob Herring pr_warn("Duplicate name in %s, renamed to \"%s\"\n", 13675b57ecfSGrant Likely kobject_name(kobj), name); 137d9fc8807SFrank Rowand } 13875b57ecfSGrant Likely return name; 13975b57ecfSGrant Likely } 14075b57ecfSGrant Likely 1418a2b22a2SGrant Likely int __of_add_property_sysfs(struct device_node *np, struct property *pp) 14275b57ecfSGrant Likely { 14375b57ecfSGrant Likely int rc; 14475b57ecfSGrant Likely 14575b57ecfSGrant Likely /* Important: Don't leak passwords */ 14675b57ecfSGrant Likely bool secure = strncmp(pp->name, "security-", 9) == 0; 14775b57ecfSGrant Likely 148ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 149ef69d740SGaurav Minocha return 0; 150ef69d740SGaurav Minocha 1518a2b22a2SGrant Likely if (!of_kset || !of_node_is_attached(np)) 1528a2b22a2SGrant Likely return 0; 1538a2b22a2SGrant Likely 15475b57ecfSGrant Likely sysfs_bin_attr_init(&pp->attr); 15575b57ecfSGrant Likely pp->attr.attr.name = safe_name(&np->kobj, pp->name); 1567ace5f48SFrank Rowand pp->attr.attr.mode = secure ? 0400 : 0444; 15775b57ecfSGrant Likely pp->attr.size = secure ? 0 : pp->length; 15875b57ecfSGrant Likely pp->attr.read = of_node_property_read; 15975b57ecfSGrant Likely 16075b57ecfSGrant Likely rc = sysfs_create_bin_file(&np->kobj, &pp->attr); 1610d638a07SRob Herring WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np); 16275b57ecfSGrant Likely return rc; 16375b57ecfSGrant Likely } 16475b57ecfSGrant Likely 1658a2b22a2SGrant Likely int __of_attach_node_sysfs(struct device_node *np) 16675b57ecfSGrant Likely { 16775b57ecfSGrant Likely const char *name; 168d9fc8807SFrank Rowand struct kobject *parent; 16975b57ecfSGrant Likely struct property *pp; 17075b57ecfSGrant Likely int rc; 17175b57ecfSGrant Likely 172ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 173ef69d740SGaurav Minocha return 0; 174ef69d740SGaurav Minocha 1758a2b22a2SGrant Likely if (!of_kset) 1768a2b22a2SGrant Likely return 0; 1778a2b22a2SGrant Likely 17875b57ecfSGrant Likely np->kobj.kset = of_kset; 17975b57ecfSGrant Likely if (!np->parent) { 18075b57ecfSGrant Likely /* Nodes without parents are new top level trees */ 181d9fc8807SFrank Rowand name = safe_name(&of_kset->kobj, "base"); 182d9fc8807SFrank Rowand parent = NULL; 18375b57ecfSGrant Likely } else { 18475b57ecfSGrant Likely name = safe_name(&np->parent->kobj, kbasename(np->full_name)); 185d9fc8807SFrank Rowand parent = &np->parent->kobj; 18675b57ecfSGrant Likely } 187d9fc8807SFrank Rowand if (!name) 188d9fc8807SFrank Rowand return -ENOMEM; 189d9fc8807SFrank Rowand rc = kobject_add(&np->kobj, parent, "%s", name); 190d9fc8807SFrank Rowand kfree(name); 19175b57ecfSGrant Likely if (rc) 19275b57ecfSGrant Likely return rc; 19375b57ecfSGrant Likely 19475b57ecfSGrant Likely for_each_property_of_node(np, pp) 19575b57ecfSGrant Likely __of_add_property_sysfs(np, pp); 19675b57ecfSGrant Likely 19775b57ecfSGrant Likely return 0; 19875b57ecfSGrant Likely } 19975b57ecfSGrant Likely 200194ec936SSudeep Holla void __init of_core_init(void) 20175b57ecfSGrant Likely { 20275b57ecfSGrant Likely struct device_node *np; 20375b57ecfSGrant Likely 20475b57ecfSGrant Likely /* Create the kset, and register existing nodes */ 205c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 20675b57ecfSGrant Likely of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); 20775b57ecfSGrant Likely if (!of_kset) { 208c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 209606ad42aSRob Herring pr_err("failed to register existing nodes\n"); 210194ec936SSudeep Holla return; 21175b57ecfSGrant Likely } 21275b57ecfSGrant Likely for_each_of_allnodes(np) 2138a2b22a2SGrant Likely __of_attach_node_sysfs(np); 214c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 21575b57ecfSGrant Likely 2168357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */ 2175063e25aSGrant Likely if (of_root) 21875b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 21975b57ecfSGrant Likely } 22075b57ecfSGrant Likely 22128d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 22228d0e36bSThomas Gleixner const char *name, int *lenp) 223581b605aSStephen Rothwell { 224581b605aSStephen Rothwell struct property *pp; 225581b605aSStephen Rothwell 22664e4566fSTimur Tabi if (!np) 22764e4566fSTimur Tabi return NULL; 22864e4566fSTimur Tabi 229a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 230581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 231a3a7cab1SSachin Kamat if (lenp) 232581b605aSStephen Rothwell *lenp = pp->length; 233581b605aSStephen Rothwell break; 234581b605aSStephen Rothwell } 235581b605aSStephen Rothwell } 23628d0e36bSThomas Gleixner 23728d0e36bSThomas Gleixner return pp; 23828d0e36bSThomas Gleixner } 23928d0e36bSThomas Gleixner 24028d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 24128d0e36bSThomas Gleixner const char *name, 24228d0e36bSThomas Gleixner int *lenp) 24328d0e36bSThomas Gleixner { 24428d0e36bSThomas Gleixner struct property *pp; 245d6d3c4e6SThomas Gleixner unsigned long flags; 24628d0e36bSThomas Gleixner 247d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 24828d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 249d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 250581b605aSStephen Rothwell 251581b605aSStephen Rothwell return pp; 252581b605aSStephen Rothwell } 253581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 254581b605aSStephen Rothwell 2555063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev) 2565063e25aSGrant Likely { 2575063e25aSGrant Likely struct device_node *np; 2585063e25aSGrant Likely if (!prev) { 2595063e25aSGrant Likely np = of_root; 2605063e25aSGrant Likely } else if (prev->child) { 2615063e25aSGrant Likely np = prev->child; 2625063e25aSGrant Likely } else { 2635063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */ 2645063e25aSGrant Likely np = prev; 2655063e25aSGrant Likely while (np->parent && !np->sibling) 2665063e25aSGrant Likely np = np->parent; 2675063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */ 2685063e25aSGrant Likely } 2695063e25aSGrant Likely return np; 2705063e25aSGrant Likely } 2715063e25aSGrant Likely 272e91edcf5SGrant Likely /** 273e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 274e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 275e91edcf5SGrant Likely * of_node_put() will be called on it 276e91edcf5SGrant Likely * 277e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 278e91edcf5SGrant Likely * of_node_put() on it when done. 279e91edcf5SGrant Likely */ 280e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 281e91edcf5SGrant Likely { 282e91edcf5SGrant Likely struct device_node *np; 283d25d8694SBenjamin Herrenschmidt unsigned long flags; 284e91edcf5SGrant Likely 285d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 2865063e25aSGrant Likely np = __of_find_all_nodes(prev); 2875063e25aSGrant Likely of_node_get(np); 288e91edcf5SGrant Likely of_node_put(prev); 289d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 290e91edcf5SGrant Likely return np; 291e91edcf5SGrant Likely } 292e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 293e91edcf5SGrant Likely 29497e873e5SStephen Rothwell /* 29597e873e5SStephen Rothwell * Find a property with a given name for a given node 29697e873e5SStephen Rothwell * and return the value. 29797e873e5SStephen Rothwell */ 298a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np, 29928d0e36bSThomas Gleixner const char *name, int *lenp) 30028d0e36bSThomas Gleixner { 30128d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 30228d0e36bSThomas Gleixner 30328d0e36bSThomas Gleixner return pp ? pp->value : NULL; 30428d0e36bSThomas Gleixner } 30528d0e36bSThomas Gleixner 30628d0e36bSThomas Gleixner /* 30728d0e36bSThomas Gleixner * Find a property with a given name for a given node 30828d0e36bSThomas Gleixner * and return the value. 30928d0e36bSThomas Gleixner */ 31097e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 31197e873e5SStephen Rothwell int *lenp) 31297e873e5SStephen Rothwell { 31397e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 31497e873e5SStephen Rothwell 31597e873e5SStephen Rothwell return pp ? pp->value : NULL; 31697e873e5SStephen Rothwell } 31797e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 3180081cbc3SStephen Rothwell 319183912d3SSudeep KarkadaNagesha /* 320183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 321183912d3SSudeep KarkadaNagesha * 322183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 323183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 324183912d3SSudeep KarkadaNagesha * 325183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 326183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 327183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 328183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 329183912d3SSudeep KarkadaNagesha * 330183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 331183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 332183912d3SSudeep KarkadaNagesha */ 333183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 334183912d3SSudeep KarkadaNagesha { 335183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 336183912d3SSudeep KarkadaNagesha } 337183912d3SSudeep KarkadaNagesha 338183912d3SSudeep KarkadaNagesha /** 339183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 340183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 341183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 342183912d3SSudeep KarkadaNagesha */ 343183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 344183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 345183912d3SSudeep KarkadaNagesha { 346183912d3SSudeep KarkadaNagesha const __be32 *cell; 347183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 348183912d3SSudeep KarkadaNagesha u64 hwid; 349183912d3SSudeep KarkadaNagesha 350183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 351183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 352f3cea45aSGrant Likely if (!cell || !ac) 353183912d3SSudeep KarkadaNagesha return false; 354f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 355183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 356183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 357183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 358183912d3SSudeep KarkadaNagesha if (thread) 359183912d3SSudeep KarkadaNagesha *thread = tid; 360183912d3SSudeep KarkadaNagesha return true; 361183912d3SSudeep KarkadaNagesha } 362183912d3SSudeep KarkadaNagesha cell += ac; 363183912d3SSudeep KarkadaNagesha } 364183912d3SSudeep KarkadaNagesha return false; 365183912d3SSudeep KarkadaNagesha } 366183912d3SSudeep KarkadaNagesha 367d1cb9d1aSDavid Miller /* 368d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 369d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 370d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 371d1cb9d1aSDavid Miller * core is returned in it. 372d1cb9d1aSDavid Miller */ 373d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 374d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 375d1cb9d1aSDavid Miller { 376d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 377d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 378d1cb9d1aSDavid Miller * standard "reg" property. 379d1cb9d1aSDavid Miller */ 380d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 381d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 382d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 383d1cb9d1aSDavid Miller cpu, thread)) 384d1cb9d1aSDavid Miller return true; 385d1cb9d1aSDavid Miller 386510bd068SMasahiro Yamada return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); 387d1cb9d1aSDavid Miller } 388d1cb9d1aSDavid Miller 389183912d3SSudeep KarkadaNagesha /** 390183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 391183912d3SSudeep KarkadaNagesha * 392183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 393183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 394183912d3SSudeep KarkadaNagesha * returned 395183912d3SSudeep KarkadaNagesha * 396183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 397183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 398183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 399183912d3SSudeep KarkadaNagesha * references can use that instead. 400183912d3SSudeep KarkadaNagesha * 401183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 402183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 403183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 404183912d3SSudeep KarkadaNagesha * 4051c986e36SMasahiro Yamada * Returns a node pointer for the logical cpu with refcount incremented, use 4061c986e36SMasahiro Yamada * of_node_put() on it when done. Returns NULL if not found. 407183912d3SSudeep KarkadaNagesha */ 408183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 409183912d3SSudeep KarkadaNagesha { 410d1cb9d1aSDavid Miller struct device_node *cpun; 411183912d3SSudeep KarkadaNagesha 412d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 413d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 414183912d3SSudeep KarkadaNagesha return cpun; 415183912d3SSudeep KarkadaNagesha } 416183912d3SSudeep KarkadaNagesha return NULL; 417183912d3SSudeep KarkadaNagesha } 418183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 419183912d3SSudeep KarkadaNagesha 420215a14cfSKevin Hao /** 421215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints 422215a14cfSKevin Hao * @device: pointer to node 423215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match 424215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match 425215a14cfSKevin Hao * @name: required node name, NULL or "" for any match 426215a14cfSKevin Hao * 427215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the 428215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by 429215a14cfSKevin Hao * passing NULL or an empty string as the constraint. 430215a14cfSKevin Hao * 431215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return 432215a14cfSKevin Hao * value is a relative score with larger values indicating better 433215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value 434215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching 435215a14cfSKevin Hao * name. Practically speaking, this results in the following priority 436215a14cfSKevin Hao * order for matches: 437215a14cfSKevin Hao * 438215a14cfSKevin Hao * 1. specific compatible && type && name 439215a14cfSKevin Hao * 2. specific compatible && type 440215a14cfSKevin Hao * 3. specific compatible && name 441215a14cfSKevin Hao * 4. specific compatible 442215a14cfSKevin Hao * 5. general compatible && type && name 443215a14cfSKevin Hao * 6. general compatible && type 444215a14cfSKevin Hao * 7. general compatible && name 445215a14cfSKevin Hao * 8. general compatible 446215a14cfSKevin Hao * 9. type && name 447215a14cfSKevin Hao * 10. type 448215a14cfSKevin Hao * 11. name 4490081cbc3SStephen Rothwell */ 45028d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 451215a14cfSKevin Hao const char *compat, const char *type, const char *name) 4520081cbc3SStephen Rothwell { 453215a14cfSKevin Hao struct property *prop; 4540081cbc3SStephen Rothwell const char *cp; 455215a14cfSKevin Hao int index = 0, score = 0; 4560081cbc3SStephen Rothwell 457215a14cfSKevin Hao /* Compatible match has highest priority */ 458215a14cfSKevin Hao if (compat && compat[0]) { 459215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL); 460215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp; 461215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) { 462215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 463215a14cfSKevin Hao score = INT_MAX/2 - (index << 2); 464215a14cfSKevin Hao break; 465215a14cfSKevin Hao } 466215a14cfSKevin Hao } 467215a14cfSKevin Hao if (!score) 4680081cbc3SStephen Rothwell return 0; 4690081cbc3SStephen Rothwell } 4700081cbc3SStephen Rothwell 471215a14cfSKevin Hao /* Matching type is better than matching name */ 472215a14cfSKevin Hao if (type && type[0]) { 473215a14cfSKevin Hao if (!device->type || of_node_cmp(type, device->type)) 4740081cbc3SStephen Rothwell return 0; 475215a14cfSKevin Hao score += 2; 476215a14cfSKevin Hao } 477215a14cfSKevin Hao 478215a14cfSKevin Hao /* Matching name is a bit better than not */ 479215a14cfSKevin Hao if (name && name[0]) { 480215a14cfSKevin Hao if (!device->name || of_node_cmp(name, device->name)) 481215a14cfSKevin Hao return 0; 482215a14cfSKevin Hao score++; 483215a14cfSKevin Hao } 484215a14cfSKevin Hao 485215a14cfSKevin Hao return score; 4860081cbc3SStephen Rothwell } 48728d0e36bSThomas Gleixner 48828d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 48928d0e36bSThomas Gleixner * the device's "compatible" property 49028d0e36bSThomas Gleixner */ 49128d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 49228d0e36bSThomas Gleixner const char *compat) 49328d0e36bSThomas Gleixner { 494d6d3c4e6SThomas Gleixner unsigned long flags; 49528d0e36bSThomas Gleixner int res; 49628d0e36bSThomas Gleixner 497d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 498215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL); 499d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 50028d0e36bSThomas Gleixner return res; 50128d0e36bSThomas Gleixner } 5020081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 503e679c5f4SStephen Rothwell 504b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in 505b9c13fe3SBenjamin Herrenschmidt * a NULL terminated array of strings. Returns the best match 506b9c13fe3SBenjamin Herrenschmidt * score or 0. 507b9c13fe3SBenjamin Herrenschmidt */ 508b9c13fe3SBenjamin Herrenschmidt int of_device_compatible_match(struct device_node *device, 509b9c13fe3SBenjamin Herrenschmidt const char *const *compat) 510b9c13fe3SBenjamin Herrenschmidt { 511b9c13fe3SBenjamin Herrenschmidt unsigned int tmp, score = 0; 512b9c13fe3SBenjamin Herrenschmidt 513b9c13fe3SBenjamin Herrenschmidt if (!compat) 514b9c13fe3SBenjamin Herrenschmidt return 0; 515b9c13fe3SBenjamin Herrenschmidt 516b9c13fe3SBenjamin Herrenschmidt while (*compat) { 517b9c13fe3SBenjamin Herrenschmidt tmp = of_device_is_compatible(device, *compat); 518b9c13fe3SBenjamin Herrenschmidt if (tmp > score) 519b9c13fe3SBenjamin Herrenschmidt score = tmp; 520b9c13fe3SBenjamin Herrenschmidt compat++; 521b9c13fe3SBenjamin Herrenschmidt } 522b9c13fe3SBenjamin Herrenschmidt 523b9c13fe3SBenjamin Herrenschmidt return score; 524b9c13fe3SBenjamin Herrenschmidt } 525b9c13fe3SBenjamin Herrenschmidt 526e679c5f4SStephen Rothwell /** 52771a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 5281f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 5291f43cfb9SGrant Likely * 53025c7a1deSKevin Cernekee * Returns a positive integer if the root node has the given value in its 5311f43cfb9SGrant Likely * compatible property. 5321f43cfb9SGrant Likely */ 53371a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 5341f43cfb9SGrant Likely { 5351f43cfb9SGrant Likely struct device_node *root; 5361f43cfb9SGrant Likely int rc = 0; 5371f43cfb9SGrant Likely 5381f43cfb9SGrant Likely root = of_find_node_by_path("/"); 5391f43cfb9SGrant Likely if (root) { 5401f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 5411f43cfb9SGrant Likely of_node_put(root); 5421f43cfb9SGrant Likely } 5431f43cfb9SGrant Likely return rc; 5441f43cfb9SGrant Likely } 54571a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 5461f43cfb9SGrant Likely 5471f43cfb9SGrant Likely /** 548c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 549834d97d4SJosh Boyer * 550c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 551834d97d4SJosh Boyer * 55253a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 55353a4ab96SKevin Cernekee * false otherwise 554834d97d4SJosh Boyer */ 55553a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device) 556834d97d4SJosh Boyer { 557834d97d4SJosh Boyer const char *status; 558834d97d4SJosh Boyer int statlen; 559834d97d4SJosh Boyer 56042ccd781SXiubo Li if (!device) 56153a4ab96SKevin Cernekee return false; 56242ccd781SXiubo Li 563c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 564834d97d4SJosh Boyer if (status == NULL) 56553a4ab96SKevin Cernekee return true; 566834d97d4SJosh Boyer 567834d97d4SJosh Boyer if (statlen > 0) { 568834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 56953a4ab96SKevin Cernekee return true; 570834d97d4SJosh Boyer } 571834d97d4SJosh Boyer 57253a4ab96SKevin Cernekee return false; 573834d97d4SJosh Boyer } 574c31a0c05SStephen Warren 575c31a0c05SStephen Warren /** 576c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 577c31a0c05SStephen Warren * 578c31a0c05SStephen Warren * @device: Node to check for availability 579c31a0c05SStephen Warren * 58053a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 58153a4ab96SKevin Cernekee * false otherwise 582c31a0c05SStephen Warren */ 58353a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device) 584c31a0c05SStephen Warren { 585c31a0c05SStephen Warren unsigned long flags; 58653a4ab96SKevin Cernekee bool res; 587c31a0c05SStephen Warren 588c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 589c31a0c05SStephen Warren res = __of_device_is_available(device); 590c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 591c31a0c05SStephen Warren return res; 592c31a0c05SStephen Warren 593c31a0c05SStephen Warren } 594834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 595834d97d4SJosh Boyer 596834d97d4SJosh Boyer /** 59737786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers 59837786c7fSKevin Cernekee * 59937786c7fSKevin Cernekee * @device: Node to check for endianness 60037786c7fSKevin Cernekee * 60137786c7fSKevin Cernekee * Returns true if the device has a "big-endian" property, or if the kernel 60237786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property. 60337786c7fSKevin Cernekee * Returns false otherwise. 60437786c7fSKevin Cernekee * 60537786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if 60637786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise. 60737786c7fSKevin Cernekee */ 60837786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device) 60937786c7fSKevin Cernekee { 61037786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian")) 61137786c7fSKevin Cernekee return true; 61237786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 61337786c7fSKevin Cernekee of_property_read_bool(device, "native-endian")) 61437786c7fSKevin Cernekee return true; 61537786c7fSKevin Cernekee return false; 61637786c7fSKevin Cernekee } 61737786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian); 61837786c7fSKevin Cernekee 61937786c7fSKevin Cernekee /** 620e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 621e679c5f4SStephen Rothwell * @node: Node to get parent 622e679c5f4SStephen Rothwell * 623e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 624e679c5f4SStephen Rothwell * of_node_put() on it when done. 625e679c5f4SStephen Rothwell */ 626e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 627e679c5f4SStephen Rothwell { 628e679c5f4SStephen Rothwell struct device_node *np; 629d6d3c4e6SThomas Gleixner unsigned long flags; 630e679c5f4SStephen Rothwell 631e679c5f4SStephen Rothwell if (!node) 632e679c5f4SStephen Rothwell return NULL; 633e679c5f4SStephen Rothwell 634d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 635e679c5f4SStephen Rothwell np = of_node_get(node->parent); 636d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 637e679c5f4SStephen Rothwell return np; 638e679c5f4SStephen Rothwell } 639e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 640d1cd355aSStephen Rothwell 641d1cd355aSStephen Rothwell /** 642f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 643f4eb0107SMichael Ellerman * @node: Node to get parent of 644f4eb0107SMichael Ellerman * 645f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 646f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 647f4eb0107SMichael Ellerman * through a node's parents. 648f4eb0107SMichael Ellerman * 649f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 650f4eb0107SMichael Ellerman * of_node_put() on it when done. 651f4eb0107SMichael Ellerman */ 652f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 653f4eb0107SMichael Ellerman { 654f4eb0107SMichael Ellerman struct device_node *parent; 655d6d3c4e6SThomas Gleixner unsigned long flags; 656f4eb0107SMichael Ellerman 657f4eb0107SMichael Ellerman if (!node) 658f4eb0107SMichael Ellerman return NULL; 659f4eb0107SMichael Ellerman 660d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 661f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 662f4eb0107SMichael Ellerman of_node_put(node); 663d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 664f4eb0107SMichael Ellerman return parent; 665f4eb0107SMichael Ellerman } 6666695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 667f4eb0107SMichael Ellerman 6680d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node, 6690d0e02d6SGrant Likely struct device_node *prev) 6700d0e02d6SGrant Likely { 6710d0e02d6SGrant Likely struct device_node *next; 6720d0e02d6SGrant Likely 67343cb4367SFlorian Fainelli if (!node) 67443cb4367SFlorian Fainelli return NULL; 67543cb4367SFlorian Fainelli 6760d0e02d6SGrant Likely next = prev ? prev->sibling : node->child; 6770d0e02d6SGrant Likely for (; next; next = next->sibling) 6780d0e02d6SGrant Likely if (of_node_get(next)) 6790d0e02d6SGrant Likely break; 6800d0e02d6SGrant Likely of_node_put(prev); 6810d0e02d6SGrant Likely return next; 6820d0e02d6SGrant Likely } 6830d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \ 6840d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \ 6850d0e02d6SGrant Likely child = __of_get_next_child(parent, child)) 6860d0e02d6SGrant Likely 687f4eb0107SMichael Ellerman /** 688d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 689d1cd355aSStephen Rothwell * @node: parent node 690d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 691d1cd355aSStephen Rothwell * 69264808273SBaruch Siach * Returns a node pointer with refcount incremented, use of_node_put() on 69364808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the 69464808273SBaruch Siach * refcount of prev. 695d1cd355aSStephen Rothwell */ 696d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 697d1cd355aSStephen Rothwell struct device_node *prev) 698d1cd355aSStephen Rothwell { 699d1cd355aSStephen Rothwell struct device_node *next; 700d6d3c4e6SThomas Gleixner unsigned long flags; 701d1cd355aSStephen Rothwell 702d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 7030d0e02d6SGrant Likely next = __of_get_next_child(node, prev); 704d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 705d1cd355aSStephen Rothwell return next; 706d1cd355aSStephen Rothwell } 707d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 7081ef4d424SStephen Rothwell 7091ef4d424SStephen Rothwell /** 7103296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 7113296193dSTimur Tabi * @node: parent node 7123296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 7133296193dSTimur Tabi * 7143296193dSTimur Tabi * This function is like of_get_next_child(), except that it 7153296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 7163296193dSTimur Tabi */ 7173296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 7183296193dSTimur Tabi struct device_node *prev) 7193296193dSTimur Tabi { 7203296193dSTimur Tabi struct device_node *next; 721d25d8694SBenjamin Herrenschmidt unsigned long flags; 7223296193dSTimur Tabi 72343cb4367SFlorian Fainelli if (!node) 72443cb4367SFlorian Fainelli return NULL; 72543cb4367SFlorian Fainelli 726d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 7273296193dSTimur Tabi next = prev ? prev->sibling : node->child; 7283296193dSTimur Tabi for (; next; next = next->sibling) { 729c31a0c05SStephen Warren if (!__of_device_is_available(next)) 7303296193dSTimur Tabi continue; 7313296193dSTimur Tabi if (of_node_get(next)) 7323296193dSTimur Tabi break; 7333296193dSTimur Tabi } 7343296193dSTimur Tabi of_node_put(prev); 735d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 7363296193dSTimur Tabi return next; 7373296193dSTimur Tabi } 7383296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 7393296193dSTimur Tabi 7403296193dSTimur Tabi /** 7419c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 7429c19761aSSrinivas Kandagatla * @node: parent node 7439c19761aSSrinivas Kandagatla * @name: child name to look for. 7449c19761aSSrinivas Kandagatla * 7459c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 7469c19761aSSrinivas Kandagatla * 7479c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 7489c19761aSSrinivas Kandagatla * of_node_put() on it when done. 7499c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 7509c19761aSSrinivas Kandagatla */ 7519c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 7529c19761aSSrinivas Kandagatla const char *name) 7539c19761aSSrinivas Kandagatla { 7549c19761aSSrinivas Kandagatla struct device_node *child; 7559c19761aSSrinivas Kandagatla 7569c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 7579c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 7589c19761aSSrinivas Kandagatla break; 7599c19761aSSrinivas Kandagatla return child; 7609c19761aSSrinivas Kandagatla } 7619c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 7629c19761aSSrinivas Kandagatla 763c22e650eSGrant Likely static struct device_node *__of_find_node_by_path(struct device_node *parent, 764c22e650eSGrant Likely const char *path) 765c22e650eSGrant Likely { 766c22e650eSGrant Likely struct device_node *child; 767106937e8SLeif Lindholm int len; 768c22e650eSGrant Likely 769721a09e9SBrian Norris len = strcspn(path, "/:"); 770c22e650eSGrant Likely if (!len) 771c22e650eSGrant Likely return NULL; 772c22e650eSGrant Likely 773c22e650eSGrant Likely __for_each_child_of_node(parent, child) { 77495e6b1faSRob Herring const char *name = kbasename(child->full_name); 775c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 776c22e650eSGrant Likely return child; 777c22e650eSGrant Likely } 778c22e650eSGrant Likely return NULL; 779c22e650eSGrant Likely } 780c22e650eSGrant Likely 78127497e11SRob Herring struct device_node *__of_find_node_by_full_path(struct device_node *node, 78227497e11SRob Herring const char *path) 78327497e11SRob Herring { 78427497e11SRob Herring const char *separator = strchr(path, ':'); 78527497e11SRob Herring 78627497e11SRob Herring while (node && *path == '/') { 78727497e11SRob Herring struct device_node *tmp = node; 78827497e11SRob Herring 78927497e11SRob Herring path++; /* Increment past '/' delimiter */ 79027497e11SRob Herring node = __of_find_node_by_path(node, path); 79127497e11SRob Herring of_node_put(tmp); 79227497e11SRob Herring path = strchrnul(path, '/'); 79327497e11SRob Herring if (separator && separator < path) 79427497e11SRob Herring break; 79527497e11SRob Herring } 79627497e11SRob Herring return node; 79727497e11SRob Herring } 79827497e11SRob Herring 7999c19761aSSrinivas Kandagatla /** 80075c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path 801c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not 802c22e650eSGrant Likely * start with '/', the name of a property of the /aliases 803c22e650eSGrant Likely * node (an alias). In the case of an alias, the node 804c22e650eSGrant Likely * matching the alias' value will be returned. 80575c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of 80675c28c09SLeif Lindholm * an options string appended to the end of the path with 80775c28c09SLeif Lindholm * a ':' separator. 808c22e650eSGrant Likely * 809c22e650eSGrant Likely * Valid paths: 810c22e650eSGrant Likely * /foo/bar Full path 811c22e650eSGrant Likely * foo Valid alias 812c22e650eSGrant Likely * foo/bar Valid alias + relative path 8131ef4d424SStephen Rothwell * 8141ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8151ef4d424SStephen Rothwell * of_node_put() on it when done. 8161ef4d424SStephen Rothwell */ 81775c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) 8181ef4d424SStephen Rothwell { 819c22e650eSGrant Likely struct device_node *np = NULL; 820c22e650eSGrant Likely struct property *pp; 821d6d3c4e6SThomas Gleixner unsigned long flags; 82275c28c09SLeif Lindholm const char *separator = strchr(path, ':'); 82375c28c09SLeif Lindholm 82475c28c09SLeif Lindholm if (opts) 82575c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL; 8261ef4d424SStephen Rothwell 827c22e650eSGrant Likely if (strcmp(path, "/") == 0) 8285063e25aSGrant Likely return of_node_get(of_root); 829c22e650eSGrant Likely 830c22e650eSGrant Likely /* The path could begin with an alias */ 831c22e650eSGrant Likely if (*path != '/') { 832106937e8SLeif Lindholm int len; 833106937e8SLeif Lindholm const char *p = separator; 834106937e8SLeif Lindholm 835106937e8SLeif Lindholm if (!p) 836106937e8SLeif Lindholm p = strchrnul(path, '/'); 837106937e8SLeif Lindholm len = p - path; 838c22e650eSGrant Likely 839c22e650eSGrant Likely /* of_aliases must not be NULL */ 840c22e650eSGrant Likely if (!of_aliases) 841c22e650eSGrant Likely return NULL; 842c22e650eSGrant Likely 843c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) { 844c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { 845c22e650eSGrant Likely np = of_find_node_by_path(pp->value); 8461ef4d424SStephen Rothwell break; 8471ef4d424SStephen Rothwell } 848c22e650eSGrant Likely } 849c22e650eSGrant Likely if (!np) 850c22e650eSGrant Likely return NULL; 851c22e650eSGrant Likely path = p; 852c22e650eSGrant Likely } 853c22e650eSGrant Likely 854c22e650eSGrant Likely /* Step down the tree matching path components */ 855c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags); 856c22e650eSGrant Likely if (!np) 8575063e25aSGrant Likely np = of_node_get(of_root); 85827497e11SRob Herring np = __of_find_node_by_full_path(np, path); 859d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8601ef4d424SStephen Rothwell return np; 8611ef4d424SStephen Rothwell } 86275c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path); 8631ef4d424SStephen Rothwell 8641ef4d424SStephen Rothwell /** 8651ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 8661ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8671ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8681ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8691ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8701ef4d424SStephen Rothwell * @name: The name string to match against 8711ef4d424SStephen Rothwell * 8721ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8731ef4d424SStephen Rothwell * of_node_put() on it when done. 8741ef4d424SStephen Rothwell */ 8751ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 8761ef4d424SStephen Rothwell const char *name) 8771ef4d424SStephen Rothwell { 8781ef4d424SStephen Rothwell struct device_node *np; 879d6d3c4e6SThomas Gleixner unsigned long flags; 8801ef4d424SStephen Rothwell 881d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8825063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8831ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 8841ef4d424SStephen Rothwell && of_node_get(np)) 8851ef4d424SStephen Rothwell break; 8861ef4d424SStephen Rothwell of_node_put(from); 887d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8881ef4d424SStephen Rothwell return np; 8891ef4d424SStephen Rothwell } 8901ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 8911ef4d424SStephen Rothwell 8921ef4d424SStephen Rothwell /** 8931ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 8941ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 8951ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 8961ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 8971ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 8981ef4d424SStephen Rothwell * called on from for you. 8991ef4d424SStephen Rothwell * @type: The type string to match against 9001ef4d424SStephen Rothwell * 9011ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 9021ef4d424SStephen Rothwell * of_node_put() on it when done. 9031ef4d424SStephen Rothwell */ 9041ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 9051ef4d424SStephen Rothwell const char *type) 9061ef4d424SStephen Rothwell { 9071ef4d424SStephen Rothwell struct device_node *np; 908d6d3c4e6SThomas Gleixner unsigned long flags; 9091ef4d424SStephen Rothwell 910d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9115063e25aSGrant Likely for_each_of_allnodes_from(from, np) 9121ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 9131ef4d424SStephen Rothwell && of_node_get(np)) 9141ef4d424SStephen Rothwell break; 9151ef4d424SStephen Rothwell of_node_put(from); 916d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9171ef4d424SStephen Rothwell return np; 9181ef4d424SStephen Rothwell } 9191ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 9201ef4d424SStephen Rothwell 9211ef4d424SStephen Rothwell /** 9221ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 9231ef4d424SStephen Rothwell * tokens in its "compatible" property 9241ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 9251ef4d424SStephen Rothwell * you pass will not be searched, only the next one 9261ef4d424SStephen Rothwell * will; typically, you pass what the previous call 9271ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 9281ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 9291ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 9301ef4d424SStephen Rothwell * "compatible" list. 9311ef4d424SStephen Rothwell * 9321ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 9331ef4d424SStephen Rothwell * of_node_put() on it when done. 9341ef4d424SStephen Rothwell */ 9351ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 9361ef4d424SStephen Rothwell const char *type, const char *compatible) 9371ef4d424SStephen Rothwell { 9381ef4d424SStephen Rothwell struct device_node *np; 939d6d3c4e6SThomas Gleixner unsigned long flags; 9401ef4d424SStephen Rothwell 941d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9425063e25aSGrant Likely for_each_of_allnodes_from(from, np) 943215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) && 94428d0e36bSThomas Gleixner of_node_get(np)) 9451ef4d424SStephen Rothwell break; 9461ef4d424SStephen Rothwell of_node_put(from); 947d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9481ef4d424SStephen Rothwell return np; 9491ef4d424SStephen Rothwell } 9501ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 951283029d1SGrant Likely 952283029d1SGrant Likely /** 9531e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 9541e291b14SMichael Ellerman * the given name. 9551e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 9561e291b14SMichael Ellerman * you pass will not be searched, only the next one 9571e291b14SMichael Ellerman * will; typically, you pass what the previous call 9581e291b14SMichael Ellerman * returned. of_node_put() will be called on it 9591e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 9601e291b14SMichael Ellerman * 9611e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 9621e291b14SMichael Ellerman * of_node_put() on it when done. 9631e291b14SMichael Ellerman */ 9641e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 9651e291b14SMichael Ellerman const char *prop_name) 9661e291b14SMichael Ellerman { 9671e291b14SMichael Ellerman struct device_node *np; 9681e291b14SMichael Ellerman struct property *pp; 969d6d3c4e6SThomas Gleixner unsigned long flags; 9701e291b14SMichael Ellerman 971d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9725063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 973a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 9741e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 9751e291b14SMichael Ellerman of_node_get(np); 9761e291b14SMichael Ellerman goto out; 9771e291b14SMichael Ellerman } 9781e291b14SMichael Ellerman } 9791e291b14SMichael Ellerman } 9801e291b14SMichael Ellerman out: 9811e291b14SMichael Ellerman of_node_put(from); 982d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9831e291b14SMichael Ellerman return np; 9841e291b14SMichael Ellerman } 9851e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 9861e291b14SMichael Ellerman 98728d0e36bSThomas Gleixner static 98828d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 989283029d1SGrant Likely const struct device_node *node) 990283029d1SGrant Likely { 991215a14cfSKevin Hao const struct of_device_id *best_match = NULL; 992215a14cfSKevin Hao int score, best_score = 0; 993215a14cfSKevin Hao 994a52f07ecSGrant Likely if (!matches) 995a52f07ecSGrant Likely return NULL; 996a52f07ecSGrant Likely 997215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { 998215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible, 999215a14cfSKevin Hao matches->type, matches->name); 1000215a14cfSKevin Hao if (score > best_score) { 1001215a14cfSKevin Hao best_match = matches; 1002215a14cfSKevin Hao best_score = score; 1003283029d1SGrant Likely } 1004215a14cfSKevin Hao } 1005215a14cfSKevin Hao 1006215a14cfSKevin Hao return best_match; 1007283029d1SGrant Likely } 100828d0e36bSThomas Gleixner 100928d0e36bSThomas Gleixner /** 1010c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure 101128d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 101228d0e36bSThomas Gleixner * @node: the of device structure to match against 101328d0e36bSThomas Gleixner * 101471c5498eSKevin Hao * Low level utility function used by device matching. 101528d0e36bSThomas Gleixner */ 101628d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 101728d0e36bSThomas Gleixner const struct device_node *node) 101828d0e36bSThomas Gleixner { 101928d0e36bSThomas Gleixner const struct of_device_id *match; 1020d6d3c4e6SThomas Gleixner unsigned long flags; 102128d0e36bSThomas Gleixner 1022d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 102328d0e36bSThomas Gleixner match = __of_match_node(matches, node); 1024d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 102528d0e36bSThomas Gleixner return match; 102628d0e36bSThomas Gleixner } 1027283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 1028283029d1SGrant Likely 1029283029d1SGrant Likely /** 103050c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 103150c8af4cSStephen Warren * match table. 1032283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 1033283029d1SGrant Likely * you pass will not be searched, only the next one 1034283029d1SGrant Likely * will; typically, you pass what the previous call 1035283029d1SGrant Likely * returned. of_node_put() will be called on it 1036283029d1SGrant Likely * @matches: array of of device match structures to search in 103750c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 1038283029d1SGrant Likely * 1039283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 1040283029d1SGrant Likely * of_node_put() on it when done. 1041283029d1SGrant Likely */ 104250c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 104350c8af4cSStephen Warren const struct of_device_id *matches, 104450c8af4cSStephen Warren const struct of_device_id **match) 1045283029d1SGrant Likely { 1046283029d1SGrant Likely struct device_node *np; 1047dc71bcf1SThomas Abraham const struct of_device_id *m; 1048d6d3c4e6SThomas Gleixner unsigned long flags; 1049283029d1SGrant Likely 105050c8af4cSStephen Warren if (match) 105150c8af4cSStephen Warren *match = NULL; 105250c8af4cSStephen Warren 1053d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 10545063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 105528d0e36bSThomas Gleixner m = __of_match_node(matches, np); 1056dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 105750c8af4cSStephen Warren if (match) 1058dc71bcf1SThomas Abraham *match = m; 1059283029d1SGrant Likely break; 1060283029d1SGrant Likely } 106150c8af4cSStephen Warren } 1062283029d1SGrant Likely of_node_put(from); 1063d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1064283029d1SGrant Likely return np; 1065283029d1SGrant Likely } 106680c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 10673f07af49SGrant Likely 10683f07af49SGrant Likely /** 10693f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 10703f07af49SGrant Likely * @node: pointer to a device tree node 10713f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 10723f07af49SGrant Likely * @len: Length of modalias value 10733f07af49SGrant Likely * 10742ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 10752ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 10762ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 10772ffe8c5fSGrant Likely * from the first entry in the compatible list property. 10783f07af49SGrant Likely * 10792ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 10803f07af49SGrant Likely */ 10813f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 10823f07af49SGrant Likely { 10832ffe8c5fSGrant Likely const char *compatible, *p; 10842ffe8c5fSGrant Likely int cplen; 10853f07af49SGrant Likely 10863f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 10872ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 10883f07af49SGrant Likely return -ENODEV; 10893f07af49SGrant Likely p = strchr(compatible, ','); 10902ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 10913f07af49SGrant Likely return 0; 10923f07af49SGrant Likely } 10933f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 10943f07af49SGrant Likely 109564b60e09SAnton Vorontsov /** 109689751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 109789751a7cSJeremy Kerr * @handle: phandle of the node to find 109889751a7cSJeremy Kerr * 109989751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 110089751a7cSJeremy Kerr * of_node_put() on it when done. 110189751a7cSJeremy Kerr */ 110289751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 110389751a7cSJeremy Kerr { 110489751a7cSJeremy Kerr struct device_node *np; 1105d25d8694SBenjamin Herrenschmidt unsigned long flags; 110689751a7cSJeremy Kerr 1107fc59b447SGrant Likely if (!handle) 1108fc59b447SGrant Likely return NULL; 1109fc59b447SGrant Likely 1110d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 11115063e25aSGrant Likely for_each_of_allnodes(np) 111289751a7cSJeremy Kerr if (np->phandle == handle) 111389751a7cSJeremy Kerr break; 111489751a7cSJeremy Kerr of_node_get(np); 1115d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 111689751a7cSJeremy Kerr return np; 111789751a7cSJeremy Kerr } 111889751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 111989751a7cSJeremy Kerr 1120624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1121624cfca5SGrant Likely { 1122624cfca5SGrant Likely int i; 11230d638a07SRob Herring printk("%s %pOF", msg, args->np); 11244aa66344SMarcin Nowakowski for (i = 0; i < args->args_count; i++) { 11254aa66344SMarcin Nowakowski const char delim = i ? ',' : ':'; 11264aa66344SMarcin Nowakowski 11274aa66344SMarcin Nowakowski pr_cont("%c%08x", delim, args->args[i]); 11284aa66344SMarcin Nowakowski } 11294aa66344SMarcin Nowakowski pr_cont("\n"); 1130624cfca5SGrant Likely } 1131624cfca5SGrant Likely 113274e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it, 113374e1fbb1SJoerg Roedel const struct device_node *np, 113474e1fbb1SJoerg Roedel const char *list_name, 113574e1fbb1SJoerg Roedel const char *cells_name, 113674e1fbb1SJoerg Roedel int cell_count) 113774e1fbb1SJoerg Roedel { 113874e1fbb1SJoerg Roedel const __be32 *list; 113974e1fbb1SJoerg Roedel int size; 114074e1fbb1SJoerg Roedel 114174e1fbb1SJoerg Roedel memset(it, 0, sizeof(*it)); 114274e1fbb1SJoerg Roedel 114374e1fbb1SJoerg Roedel list = of_get_property(np, list_name, &size); 114474e1fbb1SJoerg Roedel if (!list) 114574e1fbb1SJoerg Roedel return -ENOENT; 114674e1fbb1SJoerg Roedel 114774e1fbb1SJoerg Roedel it->cells_name = cells_name; 114874e1fbb1SJoerg Roedel it->cell_count = cell_count; 114974e1fbb1SJoerg Roedel it->parent = np; 115074e1fbb1SJoerg Roedel it->list_end = list + size / sizeof(*list); 115174e1fbb1SJoerg Roedel it->phandle_end = list; 115274e1fbb1SJoerg Roedel it->cur = list; 115374e1fbb1SJoerg Roedel 115474e1fbb1SJoerg Roedel return 0; 115574e1fbb1SJoerg Roedel } 115600bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_init); 115774e1fbb1SJoerg Roedel 1158cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it) 1159cd209b41SJoerg Roedel { 1160cd209b41SJoerg Roedel uint32_t count = 0; 1161cd209b41SJoerg Roedel 1162cd209b41SJoerg Roedel if (it->node) { 1163cd209b41SJoerg Roedel of_node_put(it->node); 1164cd209b41SJoerg Roedel it->node = NULL; 1165cd209b41SJoerg Roedel } 1166cd209b41SJoerg Roedel 1167cd209b41SJoerg Roedel if (!it->cur || it->phandle_end >= it->list_end) 1168cd209b41SJoerg Roedel return -ENOENT; 1169cd209b41SJoerg Roedel 1170cd209b41SJoerg Roedel it->cur = it->phandle_end; 1171cd209b41SJoerg Roedel 1172cd209b41SJoerg Roedel /* If phandle is 0, then it is an empty entry with no arguments. */ 1173cd209b41SJoerg Roedel it->phandle = be32_to_cpup(it->cur++); 1174cd209b41SJoerg Roedel 1175cd209b41SJoerg Roedel if (it->phandle) { 1176cd209b41SJoerg Roedel 1177cd209b41SJoerg Roedel /* 1178cd209b41SJoerg Roedel * Find the provider node and parse the #*-cells property to 1179cd209b41SJoerg Roedel * determine the argument length. 1180cd209b41SJoerg Roedel */ 1181cd209b41SJoerg Roedel it->node = of_find_node_by_phandle(it->phandle); 1182cd209b41SJoerg Roedel 1183cd209b41SJoerg Roedel if (it->cells_name) { 1184cd209b41SJoerg Roedel if (!it->node) { 11850d638a07SRob Herring pr_err("%pOF: could not find phandle\n", 11860d638a07SRob Herring it->parent); 1187cd209b41SJoerg Roedel goto err; 1188cd209b41SJoerg Roedel } 1189cd209b41SJoerg Roedel 1190cd209b41SJoerg Roedel if (of_property_read_u32(it->node, it->cells_name, 1191cd209b41SJoerg Roedel &count)) { 11920d638a07SRob Herring pr_err("%pOF: could not get %s for %pOF\n", 11930d638a07SRob Herring it->parent, 1194cd209b41SJoerg Roedel it->cells_name, 11950d638a07SRob Herring it->node); 1196cd209b41SJoerg Roedel goto err; 1197cd209b41SJoerg Roedel } 1198cd209b41SJoerg Roedel } else { 1199cd209b41SJoerg Roedel count = it->cell_count; 1200cd209b41SJoerg Roedel } 1201cd209b41SJoerg Roedel 1202cd209b41SJoerg Roedel /* 1203cd209b41SJoerg Roedel * Make sure that the arguments actually fit in the remaining 1204cd209b41SJoerg Roedel * property data length 1205cd209b41SJoerg Roedel */ 1206cd209b41SJoerg Roedel if (it->cur + count > it->list_end) { 12070d638a07SRob Herring pr_err("%pOF: arguments longer than property\n", 12080d638a07SRob Herring it->parent); 1209cd209b41SJoerg Roedel goto err; 1210cd209b41SJoerg Roedel } 1211cd209b41SJoerg Roedel } 1212cd209b41SJoerg Roedel 1213cd209b41SJoerg Roedel it->phandle_end = it->cur + count; 1214cd209b41SJoerg Roedel it->cur_count = count; 1215cd209b41SJoerg Roedel 1216cd209b41SJoerg Roedel return 0; 1217cd209b41SJoerg Roedel 1218cd209b41SJoerg Roedel err: 1219cd209b41SJoerg Roedel if (it->node) { 1220cd209b41SJoerg Roedel of_node_put(it->node); 1221cd209b41SJoerg Roedel it->node = NULL; 1222cd209b41SJoerg Roedel } 1223cd209b41SJoerg Roedel 1224cd209b41SJoerg Roedel return -EINVAL; 1225cd209b41SJoerg Roedel } 122600bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_next); 1227cd209b41SJoerg Roedel 1228abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it, 1229abdaa77bSJoerg Roedel uint32_t *args, 1230abdaa77bSJoerg Roedel int size) 1231abdaa77bSJoerg Roedel { 1232abdaa77bSJoerg Roedel int i, count; 1233abdaa77bSJoerg Roedel 1234abdaa77bSJoerg Roedel count = it->cur_count; 1235abdaa77bSJoerg Roedel 1236abdaa77bSJoerg Roedel if (WARN_ON(size < count)) 1237abdaa77bSJoerg Roedel count = size; 1238abdaa77bSJoerg Roedel 1239abdaa77bSJoerg Roedel for (i = 0; i < count; i++) 1240abdaa77bSJoerg Roedel args[i] = be32_to_cpup(it->cur++); 1241abdaa77bSJoerg Roedel 1242abdaa77bSJoerg Roedel return count; 1243abdaa77bSJoerg Roedel } 1244abdaa77bSJoerg Roedel 1245bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1246bd69f73fSGrant Likely const char *list_name, 1247035fd948SStephen Warren const char *cells_name, 1248035fd948SStephen Warren int cell_count, int index, 124915c9a0acSGrant Likely struct of_phandle_args *out_args) 125064b60e09SAnton Vorontsov { 125174e1fbb1SJoerg Roedel struct of_phandle_iterator it; 125274e1fbb1SJoerg Roedel int rc, cur_index = 0; 125315c9a0acSGrant Likely 125415c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 1255f623ce95SJoerg Roedel of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) { 125615c9a0acSGrant Likely /* 1257cd209b41SJoerg Roedel * All of the error cases bail out of the loop, so at 125815c9a0acSGrant Likely * this point, the parsing is successful. If the requested 125915c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 126015c9a0acSGrant Likely * or return -ENOENT for an empty entry. 126115c9a0acSGrant Likely */ 126223ce04c0SGrant Likely rc = -ENOENT; 126315c9a0acSGrant Likely if (cur_index == index) { 126474e1fbb1SJoerg Roedel if (!it.phandle) 126523ce04c0SGrant Likely goto err; 126615c9a0acSGrant Likely 126715c9a0acSGrant Likely if (out_args) { 1268abdaa77bSJoerg Roedel int c; 1269abdaa77bSJoerg Roedel 1270abdaa77bSJoerg Roedel c = of_phandle_iterator_args(&it, 1271abdaa77bSJoerg Roedel out_args->args, 1272abdaa77bSJoerg Roedel MAX_PHANDLE_ARGS); 127374e1fbb1SJoerg Roedel out_args->np = it.node; 1274abdaa77bSJoerg Roedel out_args->args_count = c; 1275b855f16bSTang Yuantian } else { 127674e1fbb1SJoerg Roedel of_node_put(it.node); 127715c9a0acSGrant Likely } 127823ce04c0SGrant Likely 127923ce04c0SGrant Likely /* Found it! return success */ 128015c9a0acSGrant Likely return 0; 128115c9a0acSGrant Likely } 128264b60e09SAnton Vorontsov 128364b60e09SAnton Vorontsov cur_index++; 128464b60e09SAnton Vorontsov } 128564b60e09SAnton Vorontsov 128623ce04c0SGrant Likely /* 128723ce04c0SGrant Likely * Unlock node before returning result; will be one of: 128823ce04c0SGrant Likely * -ENOENT : index is for empty phandle 128923ce04c0SGrant Likely * -EINVAL : parsing error on data 129023ce04c0SGrant Likely */ 1291cd209b41SJoerg Roedel 129223ce04c0SGrant Likely err: 129374e1fbb1SJoerg Roedel of_node_put(it.node); 129423ce04c0SGrant Likely return rc; 129564b60e09SAnton Vorontsov } 1296bd69f73fSGrant Likely 1297eded9dd4SStephen Warren /** 12985fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 12995fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 13005fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 13015fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 13025fba49e3SStephen Warren * the table 13035fba49e3SStephen Warren * 13045fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 13055fba49e3SStephen Warren * of_node_put() on it when done. 13065fba49e3SStephen Warren */ 13075fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 13085fba49e3SStephen Warren const char *phandle_name, int index) 13095fba49e3SStephen Warren { 131091d9942cSStephen Warren struct of_phandle_args args; 13115fba49e3SStephen Warren 131291d9942cSStephen Warren if (index < 0) 13135fba49e3SStephen Warren return NULL; 13145fba49e3SStephen Warren 131591d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 131691d9942cSStephen Warren index, &args)) 131791d9942cSStephen Warren return NULL; 131891d9942cSStephen Warren 131991d9942cSStephen Warren return args.np; 13205fba49e3SStephen Warren } 13215fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 13225fba49e3SStephen Warren 13235fba49e3SStephen Warren /** 1324eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1325eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1326eded9dd4SStephen Warren * @list_name: property name that contains a list 1327eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1328eded9dd4SStephen Warren * @index: index of a phandle to parse out 1329eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1330eded9dd4SStephen Warren * 1331eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1332eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1333eded9dd4SStephen Warren * errno value. 1334eded9dd4SStephen Warren * 1335d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1336eded9dd4SStephen Warren * pointer. 1337eded9dd4SStephen Warren * 1338eded9dd4SStephen Warren * Example: 1339eded9dd4SStephen Warren * 1340eded9dd4SStephen Warren * phandle1: node1 { 1341eded9dd4SStephen Warren * #list-cells = <2>; 1342eded9dd4SStephen Warren * } 1343eded9dd4SStephen Warren * 1344eded9dd4SStephen Warren * phandle2: node2 { 1345eded9dd4SStephen Warren * #list-cells = <1>; 1346eded9dd4SStephen Warren * } 1347eded9dd4SStephen Warren * 1348eded9dd4SStephen Warren * node3 { 1349eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1350eded9dd4SStephen Warren * } 1351eded9dd4SStephen Warren * 1352eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1353eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1354eded9dd4SStephen Warren */ 1355bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1356bd69f73fSGrant Likely const char *cells_name, int index, 1357bd69f73fSGrant Likely struct of_phandle_args *out_args) 1358bd69f73fSGrant Likely { 1359bd69f73fSGrant Likely if (index < 0) 1360bd69f73fSGrant Likely return -EINVAL; 1361035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1362035fd948SStephen Warren index, out_args); 1363bd69f73fSGrant Likely } 136415c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 136502af11b0SGrant Likely 1366bd69f73fSGrant Likely /** 1367035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1368035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1369035fd948SStephen Warren * @list_name: property name that contains a list 1370035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1371035fd948SStephen Warren * @index: index of a phandle to parse out 1372035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1373035fd948SStephen Warren * 1374035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1375035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1376035fd948SStephen Warren * errno value. 1377035fd948SStephen Warren * 1378d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1379035fd948SStephen Warren * pointer. 1380035fd948SStephen Warren * 1381035fd948SStephen Warren * Example: 1382035fd948SStephen Warren * 1383035fd948SStephen Warren * phandle1: node1 { 1384035fd948SStephen Warren * } 1385035fd948SStephen Warren * 1386035fd948SStephen Warren * phandle2: node2 { 1387035fd948SStephen Warren * } 1388035fd948SStephen Warren * 1389035fd948SStephen Warren * node3 { 1390035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1391035fd948SStephen Warren * } 1392035fd948SStephen Warren * 1393035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1394035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1395035fd948SStephen Warren */ 1396035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1397035fd948SStephen Warren const char *list_name, int cell_count, 1398035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1399035fd948SStephen Warren { 1400035fd948SStephen Warren if (index < 0) 1401035fd948SStephen Warren return -EINVAL; 1402035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1403035fd948SStephen Warren index, out_args); 1404035fd948SStephen Warren } 1405035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1406035fd948SStephen Warren 1407035fd948SStephen Warren /** 1408bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1409bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1410bd69f73fSGrant Likely * @list_name: property name that contains a list 1411bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1412bd69f73fSGrant Likely * 1413bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1414bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1415bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1416bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1417bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1418bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1419bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1420bd69f73fSGrant Likely * phandle. 1421bd69f73fSGrant Likely */ 1422bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1423bd69f73fSGrant Likely const char *cells_name) 1424bd69f73fSGrant Likely { 14252021bd01SJoerg Roedel struct of_phandle_iterator it; 14262021bd01SJoerg Roedel int rc, cur_index = 0; 14272021bd01SJoerg Roedel 14282021bd01SJoerg Roedel rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0); 14292021bd01SJoerg Roedel if (rc) 14302021bd01SJoerg Roedel return rc; 14312021bd01SJoerg Roedel 14322021bd01SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0) 14332021bd01SJoerg Roedel cur_index += 1; 14342021bd01SJoerg Roedel 14352021bd01SJoerg Roedel if (rc != -ENOENT) 14362021bd01SJoerg Roedel return rc; 14372021bd01SJoerg Roedel 14382021bd01SJoerg Roedel return cur_index; 1439bd69f73fSGrant Likely } 1440bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1441bd69f73fSGrant Likely 144202af11b0SGrant Likely /** 144362664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 144462664f67SXiubo Li */ 1445d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop) 144662664f67SXiubo Li { 144762664f67SXiubo Li struct property **next; 144862664f67SXiubo Li 144962664f67SXiubo Li prop->next = NULL; 145062664f67SXiubo Li next = &np->properties; 145162664f67SXiubo Li while (*next) { 145262664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 145362664f67SXiubo Li /* duplicate ! don't insert it */ 145462664f67SXiubo Li return -EEXIST; 145562664f67SXiubo Li 145662664f67SXiubo Li next = &(*next)->next; 145762664f67SXiubo Li } 145862664f67SXiubo Li *next = prop; 145962664f67SXiubo Li 146062664f67SXiubo Li return 0; 146162664f67SXiubo Li } 146262664f67SXiubo Li 146362664f67SXiubo Li /** 146479d1c712SNathan Fontenot * of_add_property - Add a property to a node 146502af11b0SGrant Likely */ 146679d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 146702af11b0SGrant Likely { 146802af11b0SGrant Likely unsigned long flags; 14691cf3d8b3SNathan Fontenot int rc; 14701cf3d8b3SNathan Fontenot 14718a2b22a2SGrant Likely mutex_lock(&of_mutex); 147202af11b0SGrant Likely 1473d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 147462664f67SXiubo Li rc = __of_add_property(np, prop); 1475d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 147602af11b0SGrant Likely 14778a2b22a2SGrant Likely if (!rc) 147875b57ecfSGrant Likely __of_add_property_sysfs(np, prop); 147902af11b0SGrant Likely 14808a2b22a2SGrant Likely mutex_unlock(&of_mutex); 14818a2b22a2SGrant Likely 1482259092a3SGrant Likely if (!rc) 1483259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1484259092a3SGrant Likely 148562664f67SXiubo Li return rc; 148602af11b0SGrant Likely } 148702af11b0SGrant Likely 1488d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop) 1489d8c50088SPantelis Antoniou { 1490d8c50088SPantelis Antoniou struct property **next; 1491d8c50088SPantelis Antoniou 1492d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1493d8c50088SPantelis Antoniou if (*next == prop) 1494d8c50088SPantelis Antoniou break; 1495d8c50088SPantelis Antoniou } 1496d8c50088SPantelis Antoniou if (*next == NULL) 1497d8c50088SPantelis Antoniou return -ENODEV; 1498d8c50088SPantelis Antoniou 1499d8c50088SPantelis Antoniou /* found the node */ 1500d8c50088SPantelis Antoniou *next = prop->next; 1501d8c50088SPantelis Antoniou prop->next = np->deadprops; 1502d8c50088SPantelis Antoniou np->deadprops = prop; 1503d8c50088SPantelis Antoniou 1504d8c50088SPantelis Antoniou return 0; 1505d8c50088SPantelis Antoniou } 1506d8c50088SPantelis Antoniou 1507d9fc8807SFrank Rowand void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) 1508d9fc8807SFrank Rowand { 1509d9fc8807SFrank Rowand sysfs_remove_bin_file(&np->kobj, &prop->attr); 1510d9fc8807SFrank Rowand kfree(prop->attr.attr.name); 1511d9fc8807SFrank Rowand } 1512d9fc8807SFrank Rowand 15138a2b22a2SGrant Likely void __of_remove_property_sysfs(struct device_node *np, struct property *prop) 15148a2b22a2SGrant Likely { 1515ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1516ef69d740SGaurav Minocha return; 1517ef69d740SGaurav Minocha 15188a2b22a2SGrant Likely /* at early boot, bail here and defer setup to of_init() */ 15198a2b22a2SGrant Likely if (of_kset && of_node_is_attached(np)) 1520d9fc8807SFrank Rowand __of_sysfs_remove_bin_file(np, prop); 15218a2b22a2SGrant Likely } 15228a2b22a2SGrant Likely 152302af11b0SGrant Likely /** 152479d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 152502af11b0SGrant Likely * 152602af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 152702af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 152802af11b0SGrant Likely * Instead we just move the property to the "dead properties" 152902af11b0SGrant Likely * list, so it won't be found any more. 153002af11b0SGrant Likely */ 153179d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 153202af11b0SGrant Likely { 153302af11b0SGrant Likely unsigned long flags; 15341cf3d8b3SNathan Fontenot int rc; 15351cf3d8b3SNathan Fontenot 1536201b3fe5SSuraj Jitindar Singh if (!prop) 1537201b3fe5SSuraj Jitindar Singh return -ENODEV; 1538201b3fe5SSuraj Jitindar Singh 15398a2b22a2SGrant Likely mutex_lock(&of_mutex); 154002af11b0SGrant Likely 1541d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1542d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop); 1543d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 154402af11b0SGrant Likely 15458a2b22a2SGrant Likely if (!rc) 15468a2b22a2SGrant Likely __of_remove_property_sysfs(np, prop); 154702af11b0SGrant Likely 15488a2b22a2SGrant Likely mutex_unlock(&of_mutex); 15498a2b22a2SGrant Likely 1550259092a3SGrant Likely if (!rc) 1551259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1552259092a3SGrant Likely 1553d8c50088SPantelis Antoniou return rc; 155402af11b0SGrant Likely } 155502af11b0SGrant Likely 1556d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop, 1557d8c50088SPantelis Antoniou struct property **oldpropp) 1558d8c50088SPantelis Antoniou { 1559d8c50088SPantelis Antoniou struct property **next, *oldprop; 1560d8c50088SPantelis Antoniou 1561d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1562d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0) 1563d8c50088SPantelis Antoniou break; 1564d8c50088SPantelis Antoniou } 1565d8c50088SPantelis Antoniou *oldpropp = oldprop = *next; 1566d8c50088SPantelis Antoniou 1567d8c50088SPantelis Antoniou if (oldprop) { 1568d8c50088SPantelis Antoniou /* replace the node */ 1569d8c50088SPantelis Antoniou newprop->next = oldprop->next; 1570d8c50088SPantelis Antoniou *next = newprop; 1571d8c50088SPantelis Antoniou oldprop->next = np->deadprops; 1572d8c50088SPantelis Antoniou np->deadprops = oldprop; 1573d8c50088SPantelis Antoniou } else { 1574d8c50088SPantelis Antoniou /* new node */ 1575d8c50088SPantelis Antoniou newprop->next = NULL; 1576d8c50088SPantelis Antoniou *next = newprop; 1577d8c50088SPantelis Antoniou } 1578d8c50088SPantelis Antoniou 1579d8c50088SPantelis Antoniou return 0; 1580d8c50088SPantelis Antoniou } 1581d8c50088SPantelis Antoniou 15828a2b22a2SGrant Likely void __of_update_property_sysfs(struct device_node *np, struct property *newprop, 15838a2b22a2SGrant Likely struct property *oldprop) 15848a2b22a2SGrant Likely { 1585ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1586ef69d740SGaurav Minocha return; 1587ef69d740SGaurav Minocha 15888a2b22a2SGrant Likely /* At early boot, bail out and defer setup to of_init() */ 158902af11b0SGrant Likely if (!of_kset) 15908a2b22a2SGrant Likely return; 159102af11b0SGrant Likely 15928a2b22a2SGrant Likely if (oldprop) 1593d9fc8807SFrank Rowand __of_sysfs_remove_bin_file(np, oldprop); 15948a2b22a2SGrant Likely __of_add_property_sysfs(np, newprop); 159502af11b0SGrant Likely } 159602af11b0SGrant Likely 159702af11b0SGrant Likely /* 159879d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1599475d0094SDong Aisheng * not exist, add it. 160002af11b0SGrant Likely * 160102af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 160202af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 160302af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 160402af11b0SGrant Likely * and add the new property to the property list 160502af11b0SGrant Likely */ 160679d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 160702af11b0SGrant Likely { 1608d8c50088SPantelis Antoniou struct property *oldprop; 160902af11b0SGrant Likely unsigned long flags; 1610947fdaadSXiubo Li int rc; 16111cf3d8b3SNathan Fontenot 1612475d0094SDong Aisheng if (!newprop->name) 1613475d0094SDong Aisheng return -EINVAL; 1614475d0094SDong Aisheng 16158a2b22a2SGrant Likely mutex_lock(&of_mutex); 1616fcdeb7feSGrant Likely 1617d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1618d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop); 1619d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1620e81b3295SNathan Fontenot 16218a2b22a2SGrant Likely if (!rc) 16228a2b22a2SGrant Likely __of_update_property_sysfs(np, newprop, oldprop); 1623fcdeb7feSGrant Likely 16248a2b22a2SGrant Likely mutex_unlock(&of_mutex); 16251cf3d8b3SNathan Fontenot 1626259092a3SGrant Likely if (!rc) 1627259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 1628fcdeb7feSGrant Likely 16291cf3d8b3SNathan Fontenot return rc; 1630e81b3295SNathan Fontenot } 1631e81b3295SNathan Fontenot 1632611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1633611cad72SShawn Guo int id, const char *stem, int stem_len) 1634611cad72SShawn Guo { 1635611cad72SShawn Guo ap->np = np; 1636611cad72SShawn Guo ap->id = id; 1637611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1638611cad72SShawn Guo ap->stem[stem_len] = 0; 1639611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 16400d638a07SRob Herring pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n", 16410d638a07SRob Herring ap->alias, ap->stem, ap->id, np); 1642611cad72SShawn Guo } 1643611cad72SShawn Guo 1644611cad72SShawn Guo /** 16451821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node 1646611cad72SShawn Guo * 16471821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates 16481821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the 16491821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure. 1650611cad72SShawn Guo * 1651611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 16521821dda4SGeert Uytterhoeven * for storing the resulting tree 1653611cad72SShawn Guo */ 1654611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1655611cad72SShawn Guo { 1656611cad72SShawn Guo struct property *pp; 1657611cad72SShawn Guo 16587dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases"); 1659611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1660611cad72SShawn Guo if (of_chosen == NULL) 1661611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 16625c19e952SSascha Hauer 16635c19e952SSascha Hauer if (of_chosen) { 1664a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ 1665676e1b2fSGrant Likely const char *name = of_get_property(of_chosen, "stdout-path", NULL); 1666676e1b2fSGrant Likely if (!name) 16675c19e952SSascha Hauer name = of_get_property(of_chosen, "linux,stdout-path", NULL); 1668a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name) 1669a752ee56SGrant Likely name = of_get_property(of_aliases, "stdout", NULL); 1670f64255b5SPeter Hurley if (name) 16717914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); 16725c19e952SSascha Hauer } 16735c19e952SSascha Hauer 1674611cad72SShawn Guo if (!of_aliases) 1675611cad72SShawn Guo return; 1676611cad72SShawn Guo 16778af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1678611cad72SShawn Guo const char *start = pp->name; 1679611cad72SShawn Guo const char *end = start + strlen(start); 1680611cad72SShawn Guo struct device_node *np; 1681611cad72SShawn Guo struct alias_prop *ap; 1682611cad72SShawn Guo int id, len; 1683611cad72SShawn Guo 1684611cad72SShawn Guo /* Skip those we do not want to proceed */ 1685611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1686611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1687611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1688611cad72SShawn Guo continue; 1689611cad72SShawn Guo 1690611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1691611cad72SShawn Guo if (!np) 1692611cad72SShawn Guo continue; 1693611cad72SShawn Guo 1694611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1695611cad72SShawn Guo * the 'stem' string */ 1696611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1697611cad72SShawn Guo end--; 1698611cad72SShawn Guo len = end - start; 1699611cad72SShawn Guo 1700611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1701611cad72SShawn Guo continue; 1702611cad72SShawn Guo 1703611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1704de96ec2aSPaul Burton ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap)); 1705611cad72SShawn Guo if (!ap) 1706611cad72SShawn Guo continue; 17070640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1708611cad72SShawn Guo ap->alias = start; 1709611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1710611cad72SShawn Guo } 1711611cad72SShawn Guo } 1712611cad72SShawn Guo 1713611cad72SShawn Guo /** 1714611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1715611cad72SShawn Guo * @np: Pointer to the given device_node 1716611cad72SShawn Guo * @stem: Alias stem of the given device_node 1717611cad72SShawn Guo * 17185a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given 17195a53a07fSGeert Uytterhoeven * device_node and alias stem. It returns the alias id if found. 1720611cad72SShawn Guo */ 1721611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1722611cad72SShawn Guo { 1723611cad72SShawn Guo struct alias_prop *app; 1724611cad72SShawn Guo int id = -ENODEV; 1725611cad72SShawn Guo 1726c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 1727611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1728611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1729611cad72SShawn Guo continue; 1730611cad72SShawn Guo 1731611cad72SShawn Guo if (np == app->np) { 1732611cad72SShawn Guo id = app->id; 1733611cad72SShawn Guo break; 1734611cad72SShawn Guo } 1735611cad72SShawn Guo } 1736c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 1737611cad72SShawn Guo 1738611cad72SShawn Guo return id; 1739611cad72SShawn Guo } 1740611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1741c541adc6SStephen Warren 1742351d224fSWolfram Sang /** 1743351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem 1744351d224fSWolfram Sang * @stem: Alias stem to be examined 1745351d224fSWolfram Sang * 1746351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the 1747351d224fSWolfram Sang * given alias stem. It returns the alias id if found. 1748351d224fSWolfram Sang */ 1749351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem) 1750351d224fSWolfram Sang { 1751351d224fSWolfram Sang struct alias_prop *app; 1752351d224fSWolfram Sang int id = -ENODEV; 1753351d224fSWolfram Sang 1754351d224fSWolfram Sang mutex_lock(&of_mutex); 1755351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) { 1756351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0) 1757351d224fSWolfram Sang continue; 1758351d224fSWolfram Sang 1759351d224fSWolfram Sang if (app->id > id) 1760351d224fSWolfram Sang id = app->id; 1761351d224fSWolfram Sang } 1762351d224fSWolfram Sang mutex_unlock(&of_mutex); 1763351d224fSWolfram Sang 1764351d224fSWolfram Sang return id; 1765351d224fSWolfram Sang } 1766351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id); 1767351d224fSWolfram Sang 17685c19e952SSascha Hauer /** 17693482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup 17703482f2c5SGrant Likely * @dn - Pointer to device node 17713482f2c5SGrant Likely * @name - Name to use for preferred console without index. ex. "ttyS" 17723482f2c5SGrant Likely * @index - Index to use for preferred console. 17735c19e952SSascha Hauer * 17743482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the 17753482f2c5SGrant Likely * /chosen node. If it does then register it as the preferred console and return 17763482f2c5SGrant Likely * TRUE. Otherwise return FALSE. 17775c19e952SSascha Hauer */ 17783482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index) 17795c19e952SSascha Hauer { 17803482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline) 17815c19e952SSascha Hauer return false; 17827914a7c5SLeif Lindholm return !add_preferred_console(name, index, 17837914a7c5SLeif Lindholm kstrdup(of_stdout_options, GFP_KERNEL)); 17845c19e952SSascha Hauer } 17853482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check); 1786a3e31b45SSudeep KarkadaNagesha 1787a3e31b45SSudeep KarkadaNagesha /** 1788a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 1789a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 1790a3e31b45SSudeep KarkadaNagesha * 1791a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 1792a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 1793a3e31b45SSudeep KarkadaNagesha * to np. 1794a3e31b45SSudeep KarkadaNagesha */ 1795a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 1796a3e31b45SSudeep KarkadaNagesha { 179791d96749SRob Herring struct device_node *child, *cache_node; 1798a3e31b45SSudeep KarkadaNagesha 179991d96749SRob Herring cache_node = of_parse_phandle(np, "l2-cache", 0); 180091d96749SRob Herring if (!cache_node) 180191d96749SRob Herring cache_node = of_parse_phandle(np, "next-level-cache", 0); 1802a3e31b45SSudeep KarkadaNagesha 180391d96749SRob Herring if (cache_node) 180491d96749SRob Herring return cache_node; 1805a3e31b45SSudeep KarkadaNagesha 1806a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 1807a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 1808a3e31b45SSudeep KarkadaNagesha */ 1809a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 1810a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 1811a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 1812a3e31b45SSudeep KarkadaNagesha return child; 1813a3e31b45SSudeep KarkadaNagesha 1814a3e31b45SSudeep KarkadaNagesha return NULL; 1815a3e31b45SSudeep KarkadaNagesha } 1816fd9fdb78SPhilipp Zabel 1817fd9fdb78SPhilipp Zabel /** 18185fa23530SSudeep Holla * of_find_last_cache_level - Find the level at which the last cache is 18195fa23530SSudeep Holla * present for the given logical cpu 18205fa23530SSudeep Holla * 18215fa23530SSudeep Holla * @cpu: cpu number(logical index) for which the last cache level is needed 18225fa23530SSudeep Holla * 18235fa23530SSudeep Holla * Returns the the level at which the last cache is present. It is exactly 18245fa23530SSudeep Holla * same as the total number of cache levels for the given logical cpu. 18255fa23530SSudeep Holla */ 18265fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu) 18275fa23530SSudeep Holla { 18285fa23530SSudeep Holla u32 cache_level = 0; 18295fa23530SSudeep Holla struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu); 18305fa23530SSudeep Holla 18315fa23530SSudeep Holla while (np) { 18325fa23530SSudeep Holla prev = np; 18335fa23530SSudeep Holla of_node_put(np); 18345fa23530SSudeep Holla np = of_find_next_cache_node(np); 18355fa23530SSudeep Holla } 18365fa23530SSudeep Holla 18375fa23530SSudeep Holla of_property_read_u32(prev, "cache-level", &cache_level); 18385fa23530SSudeep Holla 18395fa23530SSudeep Holla return cache_level; 18405fa23530SSudeep Holla } 1841