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 */ 203482f2c5SGrant Likely #include <linux/console.h> 21611cad72SShawn Guo #include <linux/ctype.h> 22183912d3SSudeep KarkadaNagesha #include <linux/cpu.h> 2397e873e5SStephen Rothwell #include <linux/module.h> 2497e873e5SStephen Rothwell #include <linux/of.h> 25fd9fdb78SPhilipp Zabel #include <linux/of_graph.h> 26581b605aSStephen Rothwell #include <linux/spinlock.h> 275a0e3ad6STejun Heo #include <linux/slab.h> 2875b57ecfSGrant Likely #include <linux/string.h> 29a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 30581b605aSStephen Rothwell 31ced4eec9SStepan Moskovchenko #include "of_private.h" 32611cad72SShawn Guo 33ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 34611cad72SShawn Guo 355063e25aSGrant Likely struct device_node *of_root; 365063e25aSGrant Likely EXPORT_SYMBOL(of_root); 37fc0bdae4SGrant Likely struct device_node *of_chosen; 38611cad72SShawn Guo struct device_node *of_aliases; 39a752ee56SGrant Likely struct device_node *of_stdout; 407914a7c5SLeif Lindholm static const char *of_stdout_options; 41611cad72SShawn Guo 428a2b22a2SGrant Likely struct kset *of_kset; 4375b57ecfSGrant Likely 4475b57ecfSGrant Likely /* 458a2b22a2SGrant Likely * Used to protect the of_aliases, to hold off addition of nodes to sysfs. 468a2b22a2SGrant Likely * This mutex must be held whenever modifications are being made to the 478a2b22a2SGrant Likely * device tree. The of_{attach,detach}_node() and 488a2b22a2SGrant Likely * of_{add,remove,update}_property() helpers make sure this happens. 4975b57ecfSGrant Likely */ 50c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex); 511ef4d424SStephen Rothwell 525063e25aSGrant Likely /* use when traversing tree through the child, sibling, 53581b605aSStephen Rothwell * or parent members of struct device_node. 54581b605aSStephen Rothwell */ 55d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 5697e873e5SStephen Rothwell 5797e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 5897e873e5SStephen Rothwell { 59a9fadeefSJeremy Kerr const __be32 *ip; 6097e873e5SStephen Rothwell 6197e873e5SStephen Rothwell do { 6297e873e5SStephen Rothwell if (np->parent) 6397e873e5SStephen Rothwell np = np->parent; 6497e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 6597e873e5SStephen Rothwell if (ip) 6633714881SJeremy Kerr return be32_to_cpup(ip); 6797e873e5SStephen Rothwell } while (np->parent); 6897e873e5SStephen Rothwell /* No #address-cells property for the root node */ 6997e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 7097e873e5SStephen Rothwell } 7197e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 7297e873e5SStephen Rothwell 7397e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 7497e873e5SStephen Rothwell { 75a9fadeefSJeremy Kerr const __be32 *ip; 7697e873e5SStephen Rothwell 7797e873e5SStephen Rothwell do { 7897e873e5SStephen Rothwell if (np->parent) 7997e873e5SStephen Rothwell np = np->parent; 8097e873e5SStephen Rothwell ip = of_get_property(np, "#size-cells", NULL); 8197e873e5SStephen Rothwell if (ip) 8233714881SJeremy Kerr return be32_to_cpup(ip); 8397e873e5SStephen Rothwell } while (np->parent); 8497e873e5SStephen Rothwell /* No #size-cells property for the root node */ 8597e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 8697e873e5SStephen Rothwell } 8797e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 8897e873e5SStephen Rothwell 890c3f061cSRob Herring #ifdef CONFIG_NUMA 900c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np) 910c3f061cSRob Herring { 92c8fff7bcSKonstantin Khlebnikov return NUMA_NO_NODE; 930c3f061cSRob Herring } 940c3f061cSRob Herring #endif 950c3f061cSRob Herring 966afc0dc3SGrant Likely #ifndef CONFIG_OF_DYNAMIC 9775b57ecfSGrant Likely static void of_node_release(struct kobject *kobj) 9875b57ecfSGrant Likely { 9975b57ecfSGrant Likely /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ 10075b57ecfSGrant Likely } 1010f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 102923f7e30SGrant Likely 10375b57ecfSGrant Likely struct kobj_type of_node_ktype = { 10475b57ecfSGrant Likely .release = of_node_release, 10575b57ecfSGrant Likely }; 10675b57ecfSGrant Likely 10775b57ecfSGrant Likely static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, 10875b57ecfSGrant Likely struct bin_attribute *bin_attr, char *buf, 10975b57ecfSGrant Likely loff_t offset, size_t count) 11075b57ecfSGrant Likely { 11175b57ecfSGrant Likely struct property *pp = container_of(bin_attr, struct property, attr); 11275b57ecfSGrant Likely return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); 11375b57ecfSGrant Likely } 11475b57ecfSGrant Likely 11575b57ecfSGrant Likely static const char *safe_name(struct kobject *kobj, const char *orig_name) 11675b57ecfSGrant Likely { 11775b57ecfSGrant Likely const char *name = orig_name; 11875b57ecfSGrant Likely struct kernfs_node *kn; 11975b57ecfSGrant Likely int i = 0; 12075b57ecfSGrant Likely 12175b57ecfSGrant Likely /* don't be a hero. After 16 tries give up */ 12275b57ecfSGrant Likely while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { 12375b57ecfSGrant Likely sysfs_put(kn); 12475b57ecfSGrant Likely if (name != orig_name) 12575b57ecfSGrant Likely kfree(name); 12675b57ecfSGrant Likely name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); 12775b57ecfSGrant Likely } 12875b57ecfSGrant Likely 12975b57ecfSGrant Likely if (name != orig_name) 13075b57ecfSGrant Likely pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n", 13175b57ecfSGrant Likely kobject_name(kobj), name); 13275b57ecfSGrant Likely return name; 13375b57ecfSGrant Likely } 13475b57ecfSGrant Likely 1358a2b22a2SGrant Likely int __of_add_property_sysfs(struct device_node *np, struct property *pp) 13675b57ecfSGrant Likely { 13775b57ecfSGrant Likely int rc; 13875b57ecfSGrant Likely 13975b57ecfSGrant Likely /* Important: Don't leak passwords */ 14075b57ecfSGrant Likely bool secure = strncmp(pp->name, "security-", 9) == 0; 14175b57ecfSGrant Likely 142ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 143ef69d740SGaurav Minocha return 0; 144ef69d740SGaurav Minocha 1458a2b22a2SGrant Likely if (!of_kset || !of_node_is_attached(np)) 1468a2b22a2SGrant Likely return 0; 1478a2b22a2SGrant Likely 14875b57ecfSGrant Likely sysfs_bin_attr_init(&pp->attr); 14975b57ecfSGrant Likely pp->attr.attr.name = safe_name(&np->kobj, pp->name); 15075b57ecfSGrant Likely pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; 15175b57ecfSGrant Likely pp->attr.size = secure ? 0 : pp->length; 15275b57ecfSGrant Likely pp->attr.read = of_node_property_read; 15375b57ecfSGrant Likely 15475b57ecfSGrant Likely rc = sysfs_create_bin_file(&np->kobj, &pp->attr); 15575b57ecfSGrant Likely WARN(rc, "error adding attribute %s to node %s\n", pp->name, np->full_name); 15675b57ecfSGrant Likely return rc; 15775b57ecfSGrant Likely } 15875b57ecfSGrant Likely 1598a2b22a2SGrant Likely int __of_attach_node_sysfs(struct device_node *np) 16075b57ecfSGrant Likely { 16175b57ecfSGrant Likely const char *name; 16275b57ecfSGrant Likely struct property *pp; 16375b57ecfSGrant Likely int rc; 16475b57ecfSGrant Likely 165ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 166ef69d740SGaurav Minocha return 0; 167ef69d740SGaurav Minocha 1688a2b22a2SGrant Likely if (!of_kset) 1698a2b22a2SGrant Likely return 0; 1708a2b22a2SGrant Likely 17175b57ecfSGrant Likely np->kobj.kset = of_kset; 17275b57ecfSGrant Likely if (!np->parent) { 17375b57ecfSGrant Likely /* Nodes without parents are new top level trees */ 17428d3ee40SKees Cook rc = kobject_add(&np->kobj, NULL, "%s", 17528d3ee40SKees Cook safe_name(&of_kset->kobj, "base")); 17675b57ecfSGrant Likely } else { 17775b57ecfSGrant Likely name = safe_name(&np->parent->kobj, kbasename(np->full_name)); 17875b57ecfSGrant Likely if (!name || !name[0]) 17975b57ecfSGrant Likely return -EINVAL; 18075b57ecfSGrant Likely 18175b57ecfSGrant Likely rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name); 18275b57ecfSGrant Likely } 18375b57ecfSGrant Likely if (rc) 18475b57ecfSGrant Likely return rc; 18575b57ecfSGrant Likely 18675b57ecfSGrant Likely for_each_property_of_node(np, pp) 18775b57ecfSGrant Likely __of_add_property_sysfs(np, pp); 18875b57ecfSGrant Likely 18975b57ecfSGrant Likely return 0; 19075b57ecfSGrant Likely } 19175b57ecfSGrant Likely 192194ec936SSudeep Holla void __init of_core_init(void) 19375b57ecfSGrant Likely { 19475b57ecfSGrant Likely struct device_node *np; 19575b57ecfSGrant Likely 19675b57ecfSGrant Likely /* Create the kset, and register existing nodes */ 197c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 19875b57ecfSGrant Likely of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); 19975b57ecfSGrant Likely if (!of_kset) { 200c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 201194ec936SSudeep Holla pr_err("devicetree: failed to register existing nodes\n"); 202194ec936SSudeep Holla return; 20375b57ecfSGrant Likely } 20475b57ecfSGrant Likely for_each_of_allnodes(np) 2058a2b22a2SGrant Likely __of_attach_node_sysfs(np); 206c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 20775b57ecfSGrant Likely 2088357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */ 2095063e25aSGrant Likely if (of_root) 21075b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 21175b57ecfSGrant Likely } 21275b57ecfSGrant Likely 21328d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 21428d0e36bSThomas Gleixner const char *name, int *lenp) 215581b605aSStephen Rothwell { 216581b605aSStephen Rothwell struct property *pp; 217581b605aSStephen Rothwell 21864e4566fSTimur Tabi if (!np) 21964e4566fSTimur Tabi return NULL; 22064e4566fSTimur Tabi 221a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 222581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 223a3a7cab1SSachin Kamat if (lenp) 224581b605aSStephen Rothwell *lenp = pp->length; 225581b605aSStephen Rothwell break; 226581b605aSStephen Rothwell } 227581b605aSStephen Rothwell } 22828d0e36bSThomas Gleixner 22928d0e36bSThomas Gleixner return pp; 23028d0e36bSThomas Gleixner } 23128d0e36bSThomas Gleixner 23228d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 23328d0e36bSThomas Gleixner const char *name, 23428d0e36bSThomas Gleixner int *lenp) 23528d0e36bSThomas Gleixner { 23628d0e36bSThomas Gleixner struct property *pp; 237d6d3c4e6SThomas Gleixner unsigned long flags; 23828d0e36bSThomas Gleixner 239d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 24028d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 241d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 242581b605aSStephen Rothwell 243581b605aSStephen Rothwell return pp; 244581b605aSStephen Rothwell } 245581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 246581b605aSStephen Rothwell 2475063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev) 2485063e25aSGrant Likely { 2495063e25aSGrant Likely struct device_node *np; 2505063e25aSGrant Likely if (!prev) { 2515063e25aSGrant Likely np = of_root; 2525063e25aSGrant Likely } else if (prev->child) { 2535063e25aSGrant Likely np = prev->child; 2545063e25aSGrant Likely } else { 2555063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */ 2565063e25aSGrant Likely np = prev; 2575063e25aSGrant Likely while (np->parent && !np->sibling) 2585063e25aSGrant Likely np = np->parent; 2595063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */ 2605063e25aSGrant Likely } 2615063e25aSGrant Likely return np; 2625063e25aSGrant Likely } 2635063e25aSGrant Likely 264e91edcf5SGrant Likely /** 265e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 266e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 267e91edcf5SGrant Likely * of_node_put() will be called on it 268e91edcf5SGrant Likely * 269e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 270e91edcf5SGrant Likely * of_node_put() on it when done. 271e91edcf5SGrant Likely */ 272e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 273e91edcf5SGrant Likely { 274e91edcf5SGrant Likely struct device_node *np; 275d25d8694SBenjamin Herrenschmidt unsigned long flags; 276e91edcf5SGrant Likely 277d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 2785063e25aSGrant Likely np = __of_find_all_nodes(prev); 2795063e25aSGrant Likely of_node_get(np); 280e91edcf5SGrant Likely of_node_put(prev); 281d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 282e91edcf5SGrant Likely return np; 283e91edcf5SGrant Likely } 284e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 285e91edcf5SGrant Likely 28697e873e5SStephen Rothwell /* 28797e873e5SStephen Rothwell * Find a property with a given name for a given node 28897e873e5SStephen Rothwell * and return the value. 28997e873e5SStephen Rothwell */ 290a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np, 29128d0e36bSThomas Gleixner const char *name, int *lenp) 29228d0e36bSThomas Gleixner { 29328d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 29428d0e36bSThomas Gleixner 29528d0e36bSThomas Gleixner return pp ? pp->value : NULL; 29628d0e36bSThomas Gleixner } 29728d0e36bSThomas Gleixner 29828d0e36bSThomas Gleixner /* 29928d0e36bSThomas Gleixner * Find a property with a given name for a given node 30028d0e36bSThomas Gleixner * and return the value. 30128d0e36bSThomas Gleixner */ 30297e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 30397e873e5SStephen Rothwell int *lenp) 30497e873e5SStephen Rothwell { 30597e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 30697e873e5SStephen Rothwell 30797e873e5SStephen Rothwell return pp ? pp->value : NULL; 30897e873e5SStephen Rothwell } 30997e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 3100081cbc3SStephen Rothwell 311183912d3SSudeep KarkadaNagesha /* 312183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 313183912d3SSudeep KarkadaNagesha * 314183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 315183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 316183912d3SSudeep KarkadaNagesha * 317183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 318183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 319183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 320183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 321183912d3SSudeep KarkadaNagesha * 322183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 323183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 324183912d3SSudeep KarkadaNagesha */ 325183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 326183912d3SSudeep KarkadaNagesha { 327183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 328183912d3SSudeep KarkadaNagesha } 329183912d3SSudeep KarkadaNagesha 330183912d3SSudeep KarkadaNagesha /** 331183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 332183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 333183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 334183912d3SSudeep KarkadaNagesha */ 335183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 336183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 337183912d3SSudeep KarkadaNagesha { 338183912d3SSudeep KarkadaNagesha const __be32 *cell; 339183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 340183912d3SSudeep KarkadaNagesha u64 hwid; 341183912d3SSudeep KarkadaNagesha 342183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 343183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 344f3cea45aSGrant Likely if (!cell || !ac) 345183912d3SSudeep KarkadaNagesha return false; 346f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 347183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 348183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 349183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 350183912d3SSudeep KarkadaNagesha if (thread) 351183912d3SSudeep KarkadaNagesha *thread = tid; 352183912d3SSudeep KarkadaNagesha return true; 353183912d3SSudeep KarkadaNagesha } 354183912d3SSudeep KarkadaNagesha cell += ac; 355183912d3SSudeep KarkadaNagesha } 356183912d3SSudeep KarkadaNagesha return false; 357183912d3SSudeep KarkadaNagesha } 358183912d3SSudeep KarkadaNagesha 359d1cb9d1aSDavid Miller /* 360d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 361d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 362d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 363d1cb9d1aSDavid Miller * core is returned in it. 364d1cb9d1aSDavid Miller */ 365d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 366d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 367d1cb9d1aSDavid Miller { 368d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 369d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 370d1cb9d1aSDavid Miller * standard "reg" property. 371d1cb9d1aSDavid Miller */ 372d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 373d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 374d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 375d1cb9d1aSDavid Miller cpu, thread)) 376d1cb9d1aSDavid Miller return true; 377d1cb9d1aSDavid Miller 378510bd068SMasahiro Yamada return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); 379d1cb9d1aSDavid Miller } 380d1cb9d1aSDavid Miller 381183912d3SSudeep KarkadaNagesha /** 382183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 383183912d3SSudeep KarkadaNagesha * 384183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 385183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 386183912d3SSudeep KarkadaNagesha * returned 387183912d3SSudeep KarkadaNagesha * 388183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 389183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 390183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 391183912d3SSudeep KarkadaNagesha * references can use that instead. 392183912d3SSudeep KarkadaNagesha * 393183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 394183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 395183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 396183912d3SSudeep KarkadaNagesha * 397183912d3SSudeep KarkadaNagesha * Returns a node pointer for the logical cpu if found, else NULL. 398183912d3SSudeep KarkadaNagesha */ 399183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 400183912d3SSudeep KarkadaNagesha { 401d1cb9d1aSDavid Miller struct device_node *cpun; 402183912d3SSudeep KarkadaNagesha 403d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 404d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 405183912d3SSudeep KarkadaNagesha return cpun; 406183912d3SSudeep KarkadaNagesha } 407183912d3SSudeep KarkadaNagesha return NULL; 408183912d3SSudeep KarkadaNagesha } 409183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 410183912d3SSudeep KarkadaNagesha 411215a14cfSKevin Hao /** 412215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints 413215a14cfSKevin Hao * @device: pointer to node 414215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match 415215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match 416215a14cfSKevin Hao * @name: required node name, NULL or "" for any match 417215a14cfSKevin Hao * 418215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the 419215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by 420215a14cfSKevin Hao * passing NULL or an empty string as the constraint. 421215a14cfSKevin Hao * 422215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return 423215a14cfSKevin Hao * value is a relative score with larger values indicating better 424215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value 425215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching 426215a14cfSKevin Hao * name. Practically speaking, this results in the following priority 427215a14cfSKevin Hao * order for matches: 428215a14cfSKevin Hao * 429215a14cfSKevin Hao * 1. specific compatible && type && name 430215a14cfSKevin Hao * 2. specific compatible && type 431215a14cfSKevin Hao * 3. specific compatible && name 432215a14cfSKevin Hao * 4. specific compatible 433215a14cfSKevin Hao * 5. general compatible && type && name 434215a14cfSKevin Hao * 6. general compatible && type 435215a14cfSKevin Hao * 7. general compatible && name 436215a14cfSKevin Hao * 8. general compatible 437215a14cfSKevin Hao * 9. type && name 438215a14cfSKevin Hao * 10. type 439215a14cfSKevin Hao * 11. name 4400081cbc3SStephen Rothwell */ 44128d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 442215a14cfSKevin Hao const char *compat, const char *type, const char *name) 4430081cbc3SStephen Rothwell { 444215a14cfSKevin Hao struct property *prop; 4450081cbc3SStephen Rothwell const char *cp; 446215a14cfSKevin Hao int index = 0, score = 0; 4470081cbc3SStephen Rothwell 448215a14cfSKevin Hao /* Compatible match has highest priority */ 449215a14cfSKevin Hao if (compat && compat[0]) { 450215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL); 451215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp; 452215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) { 453215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 454215a14cfSKevin Hao score = INT_MAX/2 - (index << 2); 455215a14cfSKevin Hao break; 456215a14cfSKevin Hao } 457215a14cfSKevin Hao } 458215a14cfSKevin Hao if (!score) 4590081cbc3SStephen Rothwell return 0; 4600081cbc3SStephen Rothwell } 4610081cbc3SStephen Rothwell 462215a14cfSKevin Hao /* Matching type is better than matching name */ 463215a14cfSKevin Hao if (type && type[0]) { 464215a14cfSKevin Hao if (!device->type || of_node_cmp(type, device->type)) 4650081cbc3SStephen Rothwell return 0; 466215a14cfSKevin Hao score += 2; 467215a14cfSKevin Hao } 468215a14cfSKevin Hao 469215a14cfSKevin Hao /* Matching name is a bit better than not */ 470215a14cfSKevin Hao if (name && name[0]) { 471215a14cfSKevin Hao if (!device->name || of_node_cmp(name, device->name)) 472215a14cfSKevin Hao return 0; 473215a14cfSKevin Hao score++; 474215a14cfSKevin Hao } 475215a14cfSKevin Hao 476215a14cfSKevin Hao return score; 4770081cbc3SStephen Rothwell } 47828d0e36bSThomas Gleixner 47928d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 48028d0e36bSThomas Gleixner * the device's "compatible" property 48128d0e36bSThomas Gleixner */ 48228d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 48328d0e36bSThomas Gleixner const char *compat) 48428d0e36bSThomas Gleixner { 485d6d3c4e6SThomas Gleixner unsigned long flags; 48628d0e36bSThomas Gleixner int res; 48728d0e36bSThomas Gleixner 488d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 489215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL); 490d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 49128d0e36bSThomas Gleixner return res; 49228d0e36bSThomas Gleixner } 4930081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 494e679c5f4SStephen Rothwell 495e679c5f4SStephen Rothwell /** 49671a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 4971f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 4981f43cfb9SGrant Likely * 49925c7a1deSKevin Cernekee * Returns a positive integer if the root node has the given value in its 5001f43cfb9SGrant Likely * compatible property. 5011f43cfb9SGrant Likely */ 50271a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 5031f43cfb9SGrant Likely { 5041f43cfb9SGrant Likely struct device_node *root; 5051f43cfb9SGrant Likely int rc = 0; 5061f43cfb9SGrant Likely 5071f43cfb9SGrant Likely root = of_find_node_by_path("/"); 5081f43cfb9SGrant Likely if (root) { 5091f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 5101f43cfb9SGrant Likely of_node_put(root); 5111f43cfb9SGrant Likely } 5121f43cfb9SGrant Likely return rc; 5131f43cfb9SGrant Likely } 51471a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 5151f43cfb9SGrant Likely 5161f43cfb9SGrant Likely /** 517c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 518834d97d4SJosh Boyer * 519c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 520834d97d4SJosh Boyer * 52153a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 52253a4ab96SKevin Cernekee * false otherwise 523834d97d4SJosh Boyer */ 52453a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device) 525834d97d4SJosh Boyer { 526834d97d4SJosh Boyer const char *status; 527834d97d4SJosh Boyer int statlen; 528834d97d4SJosh Boyer 52942ccd781SXiubo Li if (!device) 53053a4ab96SKevin Cernekee return false; 53142ccd781SXiubo Li 532c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 533834d97d4SJosh Boyer if (status == NULL) 53453a4ab96SKevin Cernekee return true; 535834d97d4SJosh Boyer 536834d97d4SJosh Boyer if (statlen > 0) { 537834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 53853a4ab96SKevin Cernekee return true; 539834d97d4SJosh Boyer } 540834d97d4SJosh Boyer 54153a4ab96SKevin Cernekee return false; 542834d97d4SJosh Boyer } 543c31a0c05SStephen Warren 544c31a0c05SStephen Warren /** 545c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 546c31a0c05SStephen Warren * 547c31a0c05SStephen Warren * @device: Node to check for availability 548c31a0c05SStephen Warren * 54953a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 55053a4ab96SKevin Cernekee * false otherwise 551c31a0c05SStephen Warren */ 55253a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device) 553c31a0c05SStephen Warren { 554c31a0c05SStephen Warren unsigned long flags; 55553a4ab96SKevin Cernekee bool res; 556c31a0c05SStephen Warren 557c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 558c31a0c05SStephen Warren res = __of_device_is_available(device); 559c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 560c31a0c05SStephen Warren return res; 561c31a0c05SStephen Warren 562c31a0c05SStephen Warren } 563834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 564834d97d4SJosh Boyer 565834d97d4SJosh Boyer /** 56637786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers 56737786c7fSKevin Cernekee * 56837786c7fSKevin Cernekee * @device: Node to check for endianness 56937786c7fSKevin Cernekee * 57037786c7fSKevin Cernekee * Returns true if the device has a "big-endian" property, or if the kernel 57137786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property. 57237786c7fSKevin Cernekee * Returns false otherwise. 57337786c7fSKevin Cernekee * 57437786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if 57537786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise. 57637786c7fSKevin Cernekee */ 57737786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device) 57837786c7fSKevin Cernekee { 57937786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian")) 58037786c7fSKevin Cernekee return true; 58137786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 58237786c7fSKevin Cernekee of_property_read_bool(device, "native-endian")) 58337786c7fSKevin Cernekee return true; 58437786c7fSKevin Cernekee return false; 58537786c7fSKevin Cernekee } 58637786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian); 58737786c7fSKevin Cernekee 58837786c7fSKevin Cernekee /** 589e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 590e679c5f4SStephen Rothwell * @node: Node to get parent 591e679c5f4SStephen Rothwell * 592e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 593e679c5f4SStephen Rothwell * of_node_put() on it when done. 594e679c5f4SStephen Rothwell */ 595e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 596e679c5f4SStephen Rothwell { 597e679c5f4SStephen Rothwell struct device_node *np; 598d6d3c4e6SThomas Gleixner unsigned long flags; 599e679c5f4SStephen Rothwell 600e679c5f4SStephen Rothwell if (!node) 601e679c5f4SStephen Rothwell return NULL; 602e679c5f4SStephen Rothwell 603d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 604e679c5f4SStephen Rothwell np = of_node_get(node->parent); 605d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 606e679c5f4SStephen Rothwell return np; 607e679c5f4SStephen Rothwell } 608e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 609d1cd355aSStephen Rothwell 610d1cd355aSStephen Rothwell /** 611f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 612f4eb0107SMichael Ellerman * @node: Node to get parent of 613f4eb0107SMichael Ellerman * 614f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 615f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 616f4eb0107SMichael Ellerman * through a node's parents. 617f4eb0107SMichael Ellerman * 618f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 619f4eb0107SMichael Ellerman * of_node_put() on it when done. 620f4eb0107SMichael Ellerman */ 621f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 622f4eb0107SMichael Ellerman { 623f4eb0107SMichael Ellerman struct device_node *parent; 624d6d3c4e6SThomas Gleixner unsigned long flags; 625f4eb0107SMichael Ellerman 626f4eb0107SMichael Ellerman if (!node) 627f4eb0107SMichael Ellerman return NULL; 628f4eb0107SMichael Ellerman 629d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 630f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 631f4eb0107SMichael Ellerman of_node_put(node); 632d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 633f4eb0107SMichael Ellerman return parent; 634f4eb0107SMichael Ellerman } 6356695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 636f4eb0107SMichael Ellerman 6370d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node, 6380d0e02d6SGrant Likely struct device_node *prev) 6390d0e02d6SGrant Likely { 6400d0e02d6SGrant Likely struct device_node *next; 6410d0e02d6SGrant Likely 64243cb4367SFlorian Fainelli if (!node) 64343cb4367SFlorian Fainelli return NULL; 64443cb4367SFlorian Fainelli 6450d0e02d6SGrant Likely next = prev ? prev->sibling : node->child; 6460d0e02d6SGrant Likely for (; next; next = next->sibling) 6470d0e02d6SGrant Likely if (of_node_get(next)) 6480d0e02d6SGrant Likely break; 6490d0e02d6SGrant Likely of_node_put(prev); 6500d0e02d6SGrant Likely return next; 6510d0e02d6SGrant Likely } 6520d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \ 6530d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \ 6540d0e02d6SGrant Likely child = __of_get_next_child(parent, child)) 6550d0e02d6SGrant Likely 656f4eb0107SMichael Ellerman /** 657d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 658d1cd355aSStephen Rothwell * @node: parent node 659d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 660d1cd355aSStephen Rothwell * 66164808273SBaruch Siach * Returns a node pointer with refcount incremented, use of_node_put() on 66264808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the 66364808273SBaruch Siach * refcount of prev. 664d1cd355aSStephen Rothwell */ 665d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 666d1cd355aSStephen Rothwell struct device_node *prev) 667d1cd355aSStephen Rothwell { 668d1cd355aSStephen Rothwell struct device_node *next; 669d6d3c4e6SThomas Gleixner unsigned long flags; 670d1cd355aSStephen Rothwell 671d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 6720d0e02d6SGrant Likely next = __of_get_next_child(node, prev); 673d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 674d1cd355aSStephen Rothwell return next; 675d1cd355aSStephen Rothwell } 676d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 6771ef4d424SStephen Rothwell 6781ef4d424SStephen Rothwell /** 6793296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 6803296193dSTimur Tabi * @node: parent node 6813296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 6823296193dSTimur Tabi * 6833296193dSTimur Tabi * This function is like of_get_next_child(), except that it 6843296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 6853296193dSTimur Tabi */ 6863296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 6873296193dSTimur Tabi struct device_node *prev) 6883296193dSTimur Tabi { 6893296193dSTimur Tabi struct device_node *next; 690d25d8694SBenjamin Herrenschmidt unsigned long flags; 6913296193dSTimur Tabi 69243cb4367SFlorian Fainelli if (!node) 69343cb4367SFlorian Fainelli return NULL; 69443cb4367SFlorian Fainelli 695d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 6963296193dSTimur Tabi next = prev ? prev->sibling : node->child; 6973296193dSTimur Tabi for (; next; next = next->sibling) { 698c31a0c05SStephen Warren if (!__of_device_is_available(next)) 6993296193dSTimur Tabi continue; 7003296193dSTimur Tabi if (of_node_get(next)) 7013296193dSTimur Tabi break; 7023296193dSTimur Tabi } 7033296193dSTimur Tabi of_node_put(prev); 704d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 7053296193dSTimur Tabi return next; 7063296193dSTimur Tabi } 7073296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 7083296193dSTimur Tabi 7093296193dSTimur Tabi /** 7109c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 7119c19761aSSrinivas Kandagatla * @node: parent node 7129c19761aSSrinivas Kandagatla * @name: child name to look for. 7139c19761aSSrinivas Kandagatla * 7149c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 7159c19761aSSrinivas Kandagatla * 7169c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 7179c19761aSSrinivas Kandagatla * of_node_put() on it when done. 7189c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 7199c19761aSSrinivas Kandagatla */ 7209c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 7219c19761aSSrinivas Kandagatla const char *name) 7229c19761aSSrinivas Kandagatla { 7239c19761aSSrinivas Kandagatla struct device_node *child; 7249c19761aSSrinivas Kandagatla 7259c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 7269c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 7279c19761aSSrinivas Kandagatla break; 7289c19761aSSrinivas Kandagatla return child; 7299c19761aSSrinivas Kandagatla } 7309c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 7319c19761aSSrinivas Kandagatla 732c22e650eSGrant Likely static struct device_node *__of_find_node_by_path(struct device_node *parent, 733c22e650eSGrant Likely const char *path) 734c22e650eSGrant Likely { 735c22e650eSGrant Likely struct device_node *child; 736106937e8SLeif Lindholm int len; 737c22e650eSGrant Likely 738721a09e9SBrian Norris len = strcspn(path, "/:"); 739c22e650eSGrant Likely if (!len) 740c22e650eSGrant Likely return NULL; 741c22e650eSGrant Likely 742c22e650eSGrant Likely __for_each_child_of_node(parent, child) { 743c22e650eSGrant Likely const char *name = strrchr(child->full_name, '/'); 744c22e650eSGrant Likely if (WARN(!name, "malformed device_node %s\n", child->full_name)) 745c22e650eSGrant Likely continue; 746c22e650eSGrant Likely name++; 747c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 748c22e650eSGrant Likely return child; 749c22e650eSGrant Likely } 750c22e650eSGrant Likely return NULL; 751c22e650eSGrant Likely } 752c22e650eSGrant Likely 7539c19761aSSrinivas Kandagatla /** 75475c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path 755c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not 756c22e650eSGrant Likely * start with '/', the name of a property of the /aliases 757c22e650eSGrant Likely * node (an alias). In the case of an alias, the node 758c22e650eSGrant Likely * matching the alias' value will be returned. 75975c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of 76075c28c09SLeif Lindholm * an options string appended to the end of the path with 76175c28c09SLeif Lindholm * a ':' separator. 762c22e650eSGrant Likely * 763c22e650eSGrant Likely * Valid paths: 764c22e650eSGrant Likely * /foo/bar Full path 765c22e650eSGrant Likely * foo Valid alias 766c22e650eSGrant Likely * foo/bar Valid alias + relative path 7671ef4d424SStephen Rothwell * 7681ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 7691ef4d424SStephen Rothwell * of_node_put() on it when done. 7701ef4d424SStephen Rothwell */ 77175c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) 7721ef4d424SStephen Rothwell { 773c22e650eSGrant Likely struct device_node *np = NULL; 774c22e650eSGrant Likely struct property *pp; 775d6d3c4e6SThomas Gleixner unsigned long flags; 77675c28c09SLeif Lindholm const char *separator = strchr(path, ':'); 77775c28c09SLeif Lindholm 77875c28c09SLeif Lindholm if (opts) 77975c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL; 7801ef4d424SStephen Rothwell 781c22e650eSGrant Likely if (strcmp(path, "/") == 0) 7825063e25aSGrant Likely return of_node_get(of_root); 783c22e650eSGrant Likely 784c22e650eSGrant Likely /* The path could begin with an alias */ 785c22e650eSGrant Likely if (*path != '/') { 786106937e8SLeif Lindholm int len; 787106937e8SLeif Lindholm const char *p = separator; 788106937e8SLeif Lindholm 789106937e8SLeif Lindholm if (!p) 790106937e8SLeif Lindholm p = strchrnul(path, '/'); 791106937e8SLeif Lindholm len = p - path; 792c22e650eSGrant Likely 793c22e650eSGrant Likely /* of_aliases must not be NULL */ 794c22e650eSGrant Likely if (!of_aliases) 795c22e650eSGrant Likely return NULL; 796c22e650eSGrant Likely 797c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) { 798c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { 799c22e650eSGrant Likely np = of_find_node_by_path(pp->value); 8001ef4d424SStephen Rothwell break; 8011ef4d424SStephen Rothwell } 802c22e650eSGrant Likely } 803c22e650eSGrant Likely if (!np) 804c22e650eSGrant Likely return NULL; 805c22e650eSGrant Likely path = p; 806c22e650eSGrant Likely } 807c22e650eSGrant Likely 808c22e650eSGrant Likely /* Step down the tree matching path components */ 809c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags); 810c22e650eSGrant Likely if (!np) 8115063e25aSGrant Likely np = of_node_get(of_root); 812c22e650eSGrant Likely while (np && *path == '/') { 813c22e650eSGrant Likely path++; /* Increment past '/' delimiter */ 814c22e650eSGrant Likely np = __of_find_node_by_path(np, path); 815c22e650eSGrant Likely path = strchrnul(path, '/'); 816106937e8SLeif Lindholm if (separator && separator < path) 817106937e8SLeif Lindholm break; 818c22e650eSGrant Likely } 819d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8201ef4d424SStephen Rothwell return np; 8211ef4d424SStephen Rothwell } 82275c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path); 8231ef4d424SStephen Rothwell 8241ef4d424SStephen Rothwell /** 8251ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 8261ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8271ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8281ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8291ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8301ef4d424SStephen Rothwell * @name: The name string to match against 8311ef4d424SStephen Rothwell * 8321ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8331ef4d424SStephen Rothwell * of_node_put() on it when done. 8341ef4d424SStephen Rothwell */ 8351ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 8361ef4d424SStephen Rothwell const char *name) 8371ef4d424SStephen Rothwell { 8381ef4d424SStephen Rothwell struct device_node *np; 839d6d3c4e6SThomas Gleixner unsigned long flags; 8401ef4d424SStephen Rothwell 841d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8425063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8431ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 8441ef4d424SStephen Rothwell && of_node_get(np)) 8451ef4d424SStephen Rothwell break; 8461ef4d424SStephen Rothwell of_node_put(from); 847d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8481ef4d424SStephen Rothwell return np; 8491ef4d424SStephen Rothwell } 8501ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 8511ef4d424SStephen Rothwell 8521ef4d424SStephen Rothwell /** 8531ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 8541ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 8551ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 8561ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 8571ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 8581ef4d424SStephen Rothwell * called on from for you. 8591ef4d424SStephen Rothwell * @type: The type string to match against 8601ef4d424SStephen Rothwell * 8611ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8621ef4d424SStephen Rothwell * of_node_put() on it when done. 8631ef4d424SStephen Rothwell */ 8641ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 8651ef4d424SStephen Rothwell const char *type) 8661ef4d424SStephen Rothwell { 8671ef4d424SStephen Rothwell struct device_node *np; 868d6d3c4e6SThomas Gleixner unsigned long flags; 8691ef4d424SStephen Rothwell 870d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8715063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8721ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 8731ef4d424SStephen Rothwell && of_node_get(np)) 8741ef4d424SStephen Rothwell break; 8751ef4d424SStephen Rothwell of_node_put(from); 876d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8771ef4d424SStephen Rothwell return np; 8781ef4d424SStephen Rothwell } 8791ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 8801ef4d424SStephen Rothwell 8811ef4d424SStephen Rothwell /** 8821ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 8831ef4d424SStephen Rothwell * tokens in its "compatible" property 8841ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8851ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8861ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8871ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8881ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 8891ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 8901ef4d424SStephen Rothwell * "compatible" list. 8911ef4d424SStephen Rothwell * 8921ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8931ef4d424SStephen Rothwell * of_node_put() on it when done. 8941ef4d424SStephen Rothwell */ 8951ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 8961ef4d424SStephen Rothwell const char *type, const char *compatible) 8971ef4d424SStephen Rothwell { 8981ef4d424SStephen Rothwell struct device_node *np; 899d6d3c4e6SThomas Gleixner unsigned long flags; 9001ef4d424SStephen Rothwell 901d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9025063e25aSGrant Likely for_each_of_allnodes_from(from, np) 903215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) && 90428d0e36bSThomas Gleixner of_node_get(np)) 9051ef4d424SStephen Rothwell break; 9061ef4d424SStephen Rothwell of_node_put(from); 907d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9081ef4d424SStephen Rothwell return np; 9091ef4d424SStephen Rothwell } 9101ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 911283029d1SGrant Likely 912283029d1SGrant Likely /** 9131e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 9141e291b14SMichael Ellerman * the given name. 9151e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 9161e291b14SMichael Ellerman * you pass will not be searched, only the next one 9171e291b14SMichael Ellerman * will; typically, you pass what the previous call 9181e291b14SMichael Ellerman * returned. of_node_put() will be called on it 9191e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 9201e291b14SMichael Ellerman * 9211e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 9221e291b14SMichael Ellerman * of_node_put() on it when done. 9231e291b14SMichael Ellerman */ 9241e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 9251e291b14SMichael Ellerman const char *prop_name) 9261e291b14SMichael Ellerman { 9271e291b14SMichael Ellerman struct device_node *np; 9281e291b14SMichael Ellerman struct property *pp; 929d6d3c4e6SThomas Gleixner unsigned long flags; 9301e291b14SMichael Ellerman 931d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9325063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 933a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 9341e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 9351e291b14SMichael Ellerman of_node_get(np); 9361e291b14SMichael Ellerman goto out; 9371e291b14SMichael Ellerman } 9381e291b14SMichael Ellerman } 9391e291b14SMichael Ellerman } 9401e291b14SMichael Ellerman out: 9411e291b14SMichael Ellerman of_node_put(from); 942d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9431e291b14SMichael Ellerman return np; 9441e291b14SMichael Ellerman } 9451e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 9461e291b14SMichael Ellerman 94728d0e36bSThomas Gleixner static 94828d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 949283029d1SGrant Likely const struct device_node *node) 950283029d1SGrant Likely { 951215a14cfSKevin Hao const struct of_device_id *best_match = NULL; 952215a14cfSKevin Hao int score, best_score = 0; 953215a14cfSKevin Hao 954a52f07ecSGrant Likely if (!matches) 955a52f07ecSGrant Likely return NULL; 956a52f07ecSGrant Likely 957215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { 958215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible, 959215a14cfSKevin Hao matches->type, matches->name); 960215a14cfSKevin Hao if (score > best_score) { 961215a14cfSKevin Hao best_match = matches; 962215a14cfSKevin Hao best_score = score; 963283029d1SGrant Likely } 964215a14cfSKevin Hao } 965215a14cfSKevin Hao 966215a14cfSKevin Hao return best_match; 967283029d1SGrant Likely } 96828d0e36bSThomas Gleixner 96928d0e36bSThomas Gleixner /** 970c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure 97128d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 97228d0e36bSThomas Gleixner * @node: the of device structure to match against 97328d0e36bSThomas Gleixner * 97471c5498eSKevin Hao * Low level utility function used by device matching. 97528d0e36bSThomas Gleixner */ 97628d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 97728d0e36bSThomas Gleixner const struct device_node *node) 97828d0e36bSThomas Gleixner { 97928d0e36bSThomas Gleixner const struct of_device_id *match; 980d6d3c4e6SThomas Gleixner unsigned long flags; 98128d0e36bSThomas Gleixner 982d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 98328d0e36bSThomas Gleixner match = __of_match_node(matches, node); 984d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 98528d0e36bSThomas Gleixner return match; 98628d0e36bSThomas Gleixner } 987283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 988283029d1SGrant Likely 989283029d1SGrant Likely /** 99050c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 99150c8af4cSStephen Warren * match table. 992283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 993283029d1SGrant Likely * you pass will not be searched, only the next one 994283029d1SGrant Likely * will; typically, you pass what the previous call 995283029d1SGrant Likely * returned. of_node_put() will be called on it 996283029d1SGrant Likely * @matches: array of of device match structures to search in 99750c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 998283029d1SGrant Likely * 999283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 1000283029d1SGrant Likely * of_node_put() on it when done. 1001283029d1SGrant Likely */ 100250c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 100350c8af4cSStephen Warren const struct of_device_id *matches, 100450c8af4cSStephen Warren const struct of_device_id **match) 1005283029d1SGrant Likely { 1006283029d1SGrant Likely struct device_node *np; 1007dc71bcf1SThomas Abraham const struct of_device_id *m; 1008d6d3c4e6SThomas Gleixner unsigned long flags; 1009283029d1SGrant Likely 101050c8af4cSStephen Warren if (match) 101150c8af4cSStephen Warren *match = NULL; 101250c8af4cSStephen Warren 1013d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 10145063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 101528d0e36bSThomas Gleixner m = __of_match_node(matches, np); 1016dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 101750c8af4cSStephen Warren if (match) 1018dc71bcf1SThomas Abraham *match = m; 1019283029d1SGrant Likely break; 1020283029d1SGrant Likely } 102150c8af4cSStephen Warren } 1022283029d1SGrant Likely of_node_put(from); 1023d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1024283029d1SGrant Likely return np; 1025283029d1SGrant Likely } 102680c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 10273f07af49SGrant Likely 10283f07af49SGrant Likely /** 10293f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 10303f07af49SGrant Likely * @node: pointer to a device tree node 10313f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 10323f07af49SGrant Likely * @len: Length of modalias value 10333f07af49SGrant Likely * 10342ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 10352ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 10362ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 10372ffe8c5fSGrant Likely * from the first entry in the compatible list property. 10383f07af49SGrant Likely * 10392ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 10403f07af49SGrant Likely */ 10413f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 10423f07af49SGrant Likely { 10432ffe8c5fSGrant Likely const char *compatible, *p; 10442ffe8c5fSGrant Likely int cplen; 10453f07af49SGrant Likely 10463f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 10472ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 10483f07af49SGrant Likely return -ENODEV; 10493f07af49SGrant Likely p = strchr(compatible, ','); 10502ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 10513f07af49SGrant Likely return 0; 10523f07af49SGrant Likely } 10533f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 10543f07af49SGrant Likely 105564b60e09SAnton Vorontsov /** 105689751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 105789751a7cSJeremy Kerr * @handle: phandle of the node to find 105889751a7cSJeremy Kerr * 105989751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 106089751a7cSJeremy Kerr * of_node_put() on it when done. 106189751a7cSJeremy Kerr */ 106289751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 106389751a7cSJeremy Kerr { 106489751a7cSJeremy Kerr struct device_node *np; 1065d25d8694SBenjamin Herrenschmidt unsigned long flags; 106689751a7cSJeremy Kerr 1067fc59b447SGrant Likely if (!handle) 1068fc59b447SGrant Likely return NULL; 1069fc59b447SGrant Likely 1070d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 10715063e25aSGrant Likely for_each_of_allnodes(np) 107289751a7cSJeremy Kerr if (np->phandle == handle) 107389751a7cSJeremy Kerr break; 107489751a7cSJeremy Kerr of_node_get(np); 1075d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 107689751a7cSJeremy Kerr return np; 107789751a7cSJeremy Kerr } 107889751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 107989751a7cSJeremy Kerr 108089751a7cSJeremy Kerr /** 1081ad54a0cfSHeiko Stuebner * of_property_count_elems_of_size - Count the number of elements in a property 1082ad54a0cfSHeiko Stuebner * 1083ad54a0cfSHeiko Stuebner * @np: device node from which the property value is to be read. 1084ad54a0cfSHeiko Stuebner * @propname: name of the property to be searched. 1085ad54a0cfSHeiko Stuebner * @elem_size: size of the individual element 1086ad54a0cfSHeiko Stuebner * 1087ad54a0cfSHeiko Stuebner * Search for a property in a device node and count the number of elements of 1088ad54a0cfSHeiko Stuebner * size elem_size in it. Returns number of elements on sucess, -EINVAL if the 1089ad54a0cfSHeiko Stuebner * property does not exist or its length does not match a multiple of elem_size 1090ad54a0cfSHeiko Stuebner * and -ENODATA if the property does not have a value. 1091ad54a0cfSHeiko Stuebner */ 1092ad54a0cfSHeiko Stuebner int of_property_count_elems_of_size(const struct device_node *np, 1093ad54a0cfSHeiko Stuebner const char *propname, int elem_size) 1094ad54a0cfSHeiko Stuebner { 1095ad54a0cfSHeiko Stuebner struct property *prop = of_find_property(np, propname, NULL); 1096ad54a0cfSHeiko Stuebner 1097ad54a0cfSHeiko Stuebner if (!prop) 1098ad54a0cfSHeiko Stuebner return -EINVAL; 1099ad54a0cfSHeiko Stuebner if (!prop->value) 1100ad54a0cfSHeiko Stuebner return -ENODATA; 1101ad54a0cfSHeiko Stuebner 1102ad54a0cfSHeiko Stuebner if (prop->length % elem_size != 0) { 1103ad54a0cfSHeiko Stuebner pr_err("size of %s in node %s is not a multiple of %d\n", 1104ad54a0cfSHeiko Stuebner propname, np->full_name, elem_size); 1105ad54a0cfSHeiko Stuebner return -EINVAL; 1106ad54a0cfSHeiko Stuebner } 1107ad54a0cfSHeiko Stuebner 1108ad54a0cfSHeiko Stuebner return prop->length / elem_size; 1109ad54a0cfSHeiko Stuebner } 1110ad54a0cfSHeiko Stuebner EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); 1111ad54a0cfSHeiko Stuebner 1112ad54a0cfSHeiko Stuebner /** 1113daeec1f0STony Prisk * of_find_property_value_of_size 1114daeec1f0STony Prisk * 1115daeec1f0STony Prisk * @np: device node from which the property value is to be read. 1116daeec1f0STony Prisk * @propname: name of the property to be searched. 1117daeec1f0STony Prisk * @len: requested length of property value 1118daeec1f0STony Prisk * 1119daeec1f0STony Prisk * Search for a property in a device node and valid the requested size. 1120daeec1f0STony Prisk * Returns the property value on success, -EINVAL if the property does not 1121daeec1f0STony Prisk * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 1122daeec1f0STony Prisk * property data isn't large enough. 1123daeec1f0STony Prisk * 1124daeec1f0STony Prisk */ 1125daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np, 1126daeec1f0STony Prisk const char *propname, u32 len) 1127daeec1f0STony Prisk { 1128daeec1f0STony Prisk struct property *prop = of_find_property(np, propname, NULL); 1129daeec1f0STony Prisk 1130daeec1f0STony Prisk if (!prop) 1131daeec1f0STony Prisk return ERR_PTR(-EINVAL); 1132daeec1f0STony Prisk if (!prop->value) 1133daeec1f0STony Prisk return ERR_PTR(-ENODATA); 1134daeec1f0STony Prisk if (len > prop->length) 1135daeec1f0STony Prisk return ERR_PTR(-EOVERFLOW); 1136daeec1f0STony Prisk 1137daeec1f0STony Prisk return prop->value; 1138daeec1f0STony Prisk } 1139daeec1f0STony Prisk 1140daeec1f0STony Prisk /** 11413daf3726STony Prisk * of_property_read_u32_index - Find and read a u32 from a multi-value property. 11423daf3726STony Prisk * 11433daf3726STony Prisk * @np: device node from which the property value is to be read. 11443daf3726STony Prisk * @propname: name of the property to be searched. 11453daf3726STony Prisk * @index: index of the u32 in the list of values 11463daf3726STony Prisk * @out_value: pointer to return value, modified only if no error. 11473daf3726STony Prisk * 11483daf3726STony Prisk * Search for a property in a device node and read nth 32-bit value from 11493daf3726STony Prisk * it. Returns 0 on success, -EINVAL if the property does not exist, 11503daf3726STony Prisk * -ENODATA if property does not have a value, and -EOVERFLOW if the 11513daf3726STony Prisk * property data isn't large enough. 11523daf3726STony Prisk * 11533daf3726STony Prisk * The out_value is modified only if a valid u32 value can be decoded. 11543daf3726STony Prisk */ 11553daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np, 11563daf3726STony Prisk const char *propname, 11573daf3726STony Prisk u32 index, u32 *out_value) 11583daf3726STony Prisk { 1159daeec1f0STony Prisk const u32 *val = of_find_property_value_of_size(np, propname, 1160daeec1f0STony Prisk ((index + 1) * sizeof(*out_value))); 11613daf3726STony Prisk 1162daeec1f0STony Prisk if (IS_ERR(val)) 1163daeec1f0STony Prisk return PTR_ERR(val); 11643daf3726STony Prisk 1165daeec1f0STony Prisk *out_value = be32_to_cpup(((__be32 *)val) + index); 11663daf3726STony Prisk return 0; 11673daf3726STony Prisk } 11683daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index); 11693daf3726STony Prisk 11703daf3726STony Prisk /** 1171be193249SViresh Kumar * of_property_read_u8_array - Find and read an array of u8 from a property. 1172be193249SViresh Kumar * 1173be193249SViresh Kumar * @np: device node from which the property value is to be read. 1174be193249SViresh Kumar * @propname: name of the property to be searched. 1175792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1176be193249SViresh Kumar * @sz: number of array elements to read 1177be193249SViresh Kumar * 1178be193249SViresh Kumar * Search for a property in a device node and read 8-bit value(s) from 1179be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 1180be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 1181be193249SViresh Kumar * property data isn't large enough. 1182be193249SViresh Kumar * 1183be193249SViresh Kumar * dts entry of array should be like: 1184be193249SViresh Kumar * property = /bits/ 8 <0x50 0x60 0x70>; 1185be193249SViresh Kumar * 1186792efb84SLad, Prabhakar * The out_values is modified only if a valid u8 value can be decoded. 1187be193249SViresh Kumar */ 1188be193249SViresh Kumar int of_property_read_u8_array(const struct device_node *np, 1189be193249SViresh Kumar const char *propname, u8 *out_values, size_t sz) 1190be193249SViresh Kumar { 1191daeec1f0STony Prisk const u8 *val = of_find_property_value_of_size(np, propname, 1192daeec1f0STony Prisk (sz * sizeof(*out_values))); 1193be193249SViresh Kumar 1194daeec1f0STony Prisk if (IS_ERR(val)) 1195daeec1f0STony Prisk return PTR_ERR(val); 1196be193249SViresh Kumar 1197be193249SViresh Kumar while (sz--) 1198be193249SViresh Kumar *out_values++ = *val++; 1199be193249SViresh Kumar return 0; 1200be193249SViresh Kumar } 1201be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u8_array); 1202be193249SViresh Kumar 1203be193249SViresh Kumar /** 1204be193249SViresh Kumar * of_property_read_u16_array - Find and read an array of u16 from a property. 1205be193249SViresh Kumar * 1206be193249SViresh Kumar * @np: device node from which the property value is to be read. 1207be193249SViresh Kumar * @propname: name of the property to be searched. 1208792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1209be193249SViresh Kumar * @sz: number of array elements to read 1210be193249SViresh Kumar * 1211be193249SViresh Kumar * Search for a property in a device node and read 16-bit value(s) from 1212be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 1213be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 1214be193249SViresh Kumar * property data isn't large enough. 1215be193249SViresh Kumar * 1216be193249SViresh Kumar * dts entry of array should be like: 1217be193249SViresh Kumar * property = /bits/ 16 <0x5000 0x6000 0x7000>; 1218be193249SViresh Kumar * 1219792efb84SLad, Prabhakar * The out_values is modified only if a valid u16 value can be decoded. 1220be193249SViresh Kumar */ 1221be193249SViresh Kumar int of_property_read_u16_array(const struct device_node *np, 1222be193249SViresh Kumar const char *propname, u16 *out_values, size_t sz) 1223be193249SViresh Kumar { 1224daeec1f0STony Prisk const __be16 *val = of_find_property_value_of_size(np, propname, 1225daeec1f0STony Prisk (sz * sizeof(*out_values))); 1226be193249SViresh Kumar 1227daeec1f0STony Prisk if (IS_ERR(val)) 1228daeec1f0STony Prisk return PTR_ERR(val); 1229be193249SViresh Kumar 1230be193249SViresh Kumar while (sz--) 1231be193249SViresh Kumar *out_values++ = be16_to_cpup(val++); 1232be193249SViresh Kumar return 0; 1233be193249SViresh Kumar } 1234be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u16_array); 1235be193249SViresh Kumar 1236be193249SViresh Kumar /** 12370e373639SRob Herring * of_property_read_u32_array - Find and read an array of 32 bit integers 12380e373639SRob Herring * from a property. 12390e373639SRob Herring * 1240a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1241a3b85363SThomas Abraham * @propname: name of the property to be searched. 1242792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1243be193249SViresh Kumar * @sz: number of array elements to read 1244a3b85363SThomas Abraham * 12450e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 1246a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 1247a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 1248a3b85363SThomas Abraham * property data isn't large enough. 1249a3b85363SThomas Abraham * 1250792efb84SLad, Prabhakar * The out_values is modified only if a valid u32 value can be decoded. 1251a3b85363SThomas Abraham */ 1252aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np, 1253aac285c6SJamie Iles const char *propname, u32 *out_values, 1254aac285c6SJamie Iles size_t sz) 1255a3b85363SThomas Abraham { 1256daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1257daeec1f0STony Prisk (sz * sizeof(*out_values))); 1258a3b85363SThomas Abraham 1259daeec1f0STony Prisk if (IS_ERR(val)) 1260daeec1f0STony Prisk return PTR_ERR(val); 12610e373639SRob Herring 12620e373639SRob Herring while (sz--) 12630e373639SRob Herring *out_values++ = be32_to_cpup(val++); 1264a3b85363SThomas Abraham return 0; 1265a3b85363SThomas Abraham } 12660e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array); 1267a3b85363SThomas Abraham 1268a3b85363SThomas Abraham /** 12694cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 12704cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 12714cd7f7a3SJamie Iles * @propname: name of the property to be searched. 12724cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 12734cd7f7a3SJamie Iles * 12744cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 12754cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 12764cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 12774cd7f7a3SJamie Iles * property data isn't large enough. 12784cd7f7a3SJamie Iles * 12794cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 12804cd7f7a3SJamie Iles */ 12814cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 12824cd7f7a3SJamie Iles u64 *out_value) 12834cd7f7a3SJamie Iles { 1284daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1285daeec1f0STony Prisk sizeof(*out_value)); 12864cd7f7a3SJamie Iles 1287daeec1f0STony Prisk if (IS_ERR(val)) 1288daeec1f0STony Prisk return PTR_ERR(val); 1289daeec1f0STony Prisk 1290daeec1f0STony Prisk *out_value = of_read_number(val, 2); 12914cd7f7a3SJamie Iles return 0; 12924cd7f7a3SJamie Iles } 12934cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 12944cd7f7a3SJamie Iles 12954cd7f7a3SJamie Iles /** 1296b31384faSRafael J. Wysocki * of_property_read_u64_array - Find and read an array of 64 bit integers 1297b31384faSRafael J. Wysocki * from a property. 1298b31384faSRafael J. Wysocki * 1299b31384faSRafael J. Wysocki * @np: device node from which the property value is to be read. 1300b31384faSRafael J. Wysocki * @propname: name of the property to be searched. 1301b31384faSRafael J. Wysocki * @out_values: pointer to return value, modified only if return value is 0. 1302b31384faSRafael J. Wysocki * @sz: number of array elements to read 1303b31384faSRafael J. Wysocki * 1304b31384faSRafael J. Wysocki * Search for a property in a device node and read 64-bit value(s) from 1305b31384faSRafael J. Wysocki * it. Returns 0 on success, -EINVAL if the property does not exist, 1306b31384faSRafael J. Wysocki * -ENODATA if property does not have a value, and -EOVERFLOW if the 1307b31384faSRafael J. Wysocki * property data isn't large enough. 1308b31384faSRafael J. Wysocki * 1309b31384faSRafael J. Wysocki * The out_values is modified only if a valid u64 value can be decoded. 1310b31384faSRafael J. Wysocki */ 1311b31384faSRafael J. Wysocki int of_property_read_u64_array(const struct device_node *np, 1312b31384faSRafael J. Wysocki const char *propname, u64 *out_values, 1313b31384faSRafael J. Wysocki size_t sz) 1314b31384faSRafael J. Wysocki { 1315b31384faSRafael J. Wysocki const __be32 *val = of_find_property_value_of_size(np, propname, 1316b31384faSRafael J. Wysocki (sz * sizeof(*out_values))); 1317b31384faSRafael J. Wysocki 1318b31384faSRafael J. Wysocki if (IS_ERR(val)) 1319b31384faSRafael J. Wysocki return PTR_ERR(val); 1320b31384faSRafael J. Wysocki 1321b31384faSRafael J. Wysocki while (sz--) { 1322b31384faSRafael J. Wysocki *out_values++ = of_read_number(val, 2); 1323b31384faSRafael J. Wysocki val += 2; 1324b31384faSRafael J. Wysocki } 1325b31384faSRafael J. Wysocki return 0; 1326b31384faSRafael J. Wysocki } 13272d4c0aefSSakari Ailus EXPORT_SYMBOL_GPL(of_property_read_u64_array); 1328b31384faSRafael J. Wysocki 1329b31384faSRafael J. Wysocki /** 1330a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 1331a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1332a3b85363SThomas Abraham * @propname: name of the property to be searched. 1333a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 1334a3b85363SThomas Abraham * return value is 0. 1335a3b85363SThomas Abraham * 1336a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 1337a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 1338a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 1339a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 1340a3b85363SThomas Abraham * within the length of the property data. 1341a3b85363SThomas Abraham * 1342a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 1343a3b85363SThomas Abraham */ 1344fe99c707SDavid Rivshin int of_property_read_string(const struct device_node *np, const char *propname, 1345f09bc831SShawn Guo const char **out_string) 1346a3b85363SThomas Abraham { 1347fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 1348a3b85363SThomas Abraham if (!prop) 1349a3b85363SThomas Abraham return -EINVAL; 1350a3b85363SThomas Abraham if (!prop->value) 1351a3b85363SThomas Abraham return -ENODATA; 1352a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 1353a3b85363SThomas Abraham return -EILSEQ; 1354a3b85363SThomas Abraham *out_string = prop->value; 1355a3b85363SThomas Abraham return 0; 1356a3b85363SThomas Abraham } 1357a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 1358a3b85363SThomas Abraham 1359a3b85363SThomas Abraham /** 13607aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 13617aff0fe3SGrant Likely * @np: pointer to node containing string list property 13627aff0fe3SGrant Likely * @propname: string list property name 13637aff0fe3SGrant Likely * @string: pointer to string to search for in string list 13647aff0fe3SGrant Likely * 13657aff0fe3SGrant Likely * This function searches a string list property and returns the index 13667aff0fe3SGrant Likely * of a specific string value. 13677aff0fe3SGrant Likely */ 1368fe99c707SDavid Rivshin int of_property_match_string(const struct device_node *np, const char *propname, 13697aff0fe3SGrant Likely const char *string) 13707aff0fe3SGrant Likely { 1371fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 13727aff0fe3SGrant Likely size_t l; 13737aff0fe3SGrant Likely int i; 13747aff0fe3SGrant Likely const char *p, *end; 13757aff0fe3SGrant Likely 13767aff0fe3SGrant Likely if (!prop) 13777aff0fe3SGrant Likely return -EINVAL; 13787aff0fe3SGrant Likely if (!prop->value) 13797aff0fe3SGrant Likely return -ENODATA; 13807aff0fe3SGrant Likely 13817aff0fe3SGrant Likely p = prop->value; 13827aff0fe3SGrant Likely end = p + prop->length; 13837aff0fe3SGrant Likely 13847aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 1385a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 13867aff0fe3SGrant Likely if (p + l > end) 13877aff0fe3SGrant Likely return -EILSEQ; 13887aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 13897aff0fe3SGrant Likely if (strcmp(string, p) == 0) 13907aff0fe3SGrant Likely return i; /* Found it; return index */ 13917aff0fe3SGrant Likely } 13927aff0fe3SGrant Likely return -ENODATA; 13937aff0fe3SGrant Likely } 13947aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 13954fcd15a0SBenoit Cousson 13964fcd15a0SBenoit Cousson /** 1397e99010edSJiri Slaby * of_property_read_string_helper() - Utility helper for parsing string properties 13984fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 13994fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 1400a87fa1d8SGrant Likely * @out_strs: output array of string pointers. 1401a87fa1d8SGrant Likely * @sz: number of array elements to read. 1402a87fa1d8SGrant Likely * @skip: Number of strings to skip over at beginning of list. 14034fcd15a0SBenoit Cousson * 1404a87fa1d8SGrant Likely * Don't call this function directly. It is a utility helper for the 1405a87fa1d8SGrant Likely * of_property_read_string*() family of functions. 14064fcd15a0SBenoit Cousson */ 1407fe99c707SDavid Rivshin int of_property_read_string_helper(const struct device_node *np, 1408fe99c707SDavid Rivshin const char *propname, const char **out_strs, 1409fe99c707SDavid Rivshin size_t sz, int skip) 14104fcd15a0SBenoit Cousson { 1411fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 1412a87fa1d8SGrant Likely int l = 0, i = 0; 1413a87fa1d8SGrant Likely const char *p, *end; 14144fcd15a0SBenoit Cousson 14154fcd15a0SBenoit Cousson if (!prop) 14164fcd15a0SBenoit Cousson return -EINVAL; 14174fcd15a0SBenoit Cousson if (!prop->value) 14184fcd15a0SBenoit Cousson return -ENODATA; 14194fcd15a0SBenoit Cousson p = prop->value; 1420a87fa1d8SGrant Likely end = p + prop->length; 14214fcd15a0SBenoit Cousson 1422a87fa1d8SGrant Likely for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 1423a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 1424a87fa1d8SGrant Likely if (p + l > end) 1425a87fa1d8SGrant Likely return -EILSEQ; 1426a87fa1d8SGrant Likely if (out_strs && i >= skip) 1427a87fa1d8SGrant Likely *out_strs++ = p; 14284fcd15a0SBenoit Cousson } 1429a87fa1d8SGrant Likely i -= skip; 1430a87fa1d8SGrant Likely return i <= 0 ? -ENODATA : i; 1431a87fa1d8SGrant Likely } 1432a87fa1d8SGrant Likely EXPORT_SYMBOL_GPL(of_property_read_string_helper); 14334fcd15a0SBenoit Cousson 1434624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1435624cfca5SGrant Likely { 1436624cfca5SGrant Likely int i; 1437624cfca5SGrant Likely printk("%s %s", msg, of_node_full_name(args->np)); 1438624cfca5SGrant Likely for (i = 0; i < args->args_count; i++) 1439624cfca5SGrant Likely printk(i ? ",%08x" : ":%08x", args->args[i]); 1440624cfca5SGrant Likely printk("\n"); 1441624cfca5SGrant Likely } 1442624cfca5SGrant Likely 144374e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it, 144474e1fbb1SJoerg Roedel const struct device_node *np, 144574e1fbb1SJoerg Roedel const char *list_name, 144674e1fbb1SJoerg Roedel const char *cells_name, 144774e1fbb1SJoerg Roedel int cell_count) 144874e1fbb1SJoerg Roedel { 144974e1fbb1SJoerg Roedel const __be32 *list; 145074e1fbb1SJoerg Roedel int size; 145174e1fbb1SJoerg Roedel 145274e1fbb1SJoerg Roedel memset(it, 0, sizeof(*it)); 145374e1fbb1SJoerg Roedel 145474e1fbb1SJoerg Roedel list = of_get_property(np, list_name, &size); 145574e1fbb1SJoerg Roedel if (!list) 145674e1fbb1SJoerg Roedel return -ENOENT; 145774e1fbb1SJoerg Roedel 145874e1fbb1SJoerg Roedel it->cells_name = cells_name; 145974e1fbb1SJoerg Roedel it->cell_count = cell_count; 146074e1fbb1SJoerg Roedel it->parent = np; 146174e1fbb1SJoerg Roedel it->list_end = list + size / sizeof(*list); 146274e1fbb1SJoerg Roedel it->phandle_end = list; 146374e1fbb1SJoerg Roedel it->cur = list; 146474e1fbb1SJoerg Roedel 146574e1fbb1SJoerg Roedel return 0; 146674e1fbb1SJoerg Roedel } 146774e1fbb1SJoerg Roedel 1468cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it) 1469cd209b41SJoerg Roedel { 1470cd209b41SJoerg Roedel uint32_t count = 0; 1471cd209b41SJoerg Roedel 1472cd209b41SJoerg Roedel if (it->node) { 1473cd209b41SJoerg Roedel of_node_put(it->node); 1474cd209b41SJoerg Roedel it->node = NULL; 1475cd209b41SJoerg Roedel } 1476cd209b41SJoerg Roedel 1477cd209b41SJoerg Roedel if (!it->cur || it->phandle_end >= it->list_end) 1478cd209b41SJoerg Roedel return -ENOENT; 1479cd209b41SJoerg Roedel 1480cd209b41SJoerg Roedel it->cur = it->phandle_end; 1481cd209b41SJoerg Roedel 1482cd209b41SJoerg Roedel /* If phandle is 0, then it is an empty entry with no arguments. */ 1483cd209b41SJoerg Roedel it->phandle = be32_to_cpup(it->cur++); 1484cd209b41SJoerg Roedel 1485cd209b41SJoerg Roedel if (it->phandle) { 1486cd209b41SJoerg Roedel 1487cd209b41SJoerg Roedel /* 1488cd209b41SJoerg Roedel * Find the provider node and parse the #*-cells property to 1489cd209b41SJoerg Roedel * determine the argument length. 1490cd209b41SJoerg Roedel */ 1491cd209b41SJoerg Roedel it->node = of_find_node_by_phandle(it->phandle); 1492cd209b41SJoerg Roedel 1493cd209b41SJoerg Roedel if (it->cells_name) { 1494cd209b41SJoerg Roedel if (!it->node) { 1495cd209b41SJoerg Roedel pr_err("%s: could not find phandle\n", 1496cd209b41SJoerg Roedel it->parent->full_name); 1497cd209b41SJoerg Roedel goto err; 1498cd209b41SJoerg Roedel } 1499cd209b41SJoerg Roedel 1500cd209b41SJoerg Roedel if (of_property_read_u32(it->node, it->cells_name, 1501cd209b41SJoerg Roedel &count)) { 1502cd209b41SJoerg Roedel pr_err("%s: could not get %s for %s\n", 1503cd209b41SJoerg Roedel it->parent->full_name, 1504cd209b41SJoerg Roedel it->cells_name, 1505cd209b41SJoerg Roedel it->node->full_name); 1506cd209b41SJoerg Roedel goto err; 1507cd209b41SJoerg Roedel } 1508cd209b41SJoerg Roedel } else { 1509cd209b41SJoerg Roedel count = it->cell_count; 1510cd209b41SJoerg Roedel } 1511cd209b41SJoerg Roedel 1512cd209b41SJoerg Roedel /* 1513cd209b41SJoerg Roedel * Make sure that the arguments actually fit in the remaining 1514cd209b41SJoerg Roedel * property data length 1515cd209b41SJoerg Roedel */ 1516cd209b41SJoerg Roedel if (it->cur + count > it->list_end) { 1517cd209b41SJoerg Roedel pr_err("%s: arguments longer than property\n", 1518cd209b41SJoerg Roedel it->parent->full_name); 1519cd209b41SJoerg Roedel goto err; 1520cd209b41SJoerg Roedel } 1521cd209b41SJoerg Roedel } 1522cd209b41SJoerg Roedel 1523cd209b41SJoerg Roedel it->phandle_end = it->cur + count; 1524cd209b41SJoerg Roedel it->cur_count = count; 1525cd209b41SJoerg Roedel 1526cd209b41SJoerg Roedel return 0; 1527cd209b41SJoerg Roedel 1528cd209b41SJoerg Roedel err: 1529cd209b41SJoerg Roedel if (it->node) { 1530cd209b41SJoerg Roedel of_node_put(it->node); 1531cd209b41SJoerg Roedel it->node = NULL; 1532cd209b41SJoerg Roedel } 1533cd209b41SJoerg Roedel 1534cd209b41SJoerg Roedel return -EINVAL; 1535cd209b41SJoerg Roedel } 1536cd209b41SJoerg Roedel 1537bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1538bd69f73fSGrant Likely const char *list_name, 1539035fd948SStephen Warren const char *cells_name, 1540035fd948SStephen Warren int cell_count, int index, 154115c9a0acSGrant Likely struct of_phandle_args *out_args) 154264b60e09SAnton Vorontsov { 154374e1fbb1SJoerg Roedel struct of_phandle_iterator it; 154474e1fbb1SJoerg Roedel int rc, cur_index = 0; 154564b60e09SAnton Vorontsov 154674e1fbb1SJoerg Roedel rc = of_phandle_iterator_init(&it, np, list_name, 154774e1fbb1SJoerg Roedel cells_name, cell_count); 154874e1fbb1SJoerg Roedel if (rc) 154974e1fbb1SJoerg Roedel return rc; 155015c9a0acSGrant Likely 155115c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 1552cd209b41SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0) { 155315c9a0acSGrant Likely /* 1554cd209b41SJoerg Roedel * All of the error cases bail out of the loop, so at 155515c9a0acSGrant Likely * this point, the parsing is successful. If the requested 155615c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 155715c9a0acSGrant Likely * or return -ENOENT for an empty entry. 155815c9a0acSGrant Likely */ 155923ce04c0SGrant Likely rc = -ENOENT; 156015c9a0acSGrant Likely if (cur_index == index) { 156174e1fbb1SJoerg Roedel if (!it.phandle) 156223ce04c0SGrant Likely goto err; 156315c9a0acSGrant Likely 156415c9a0acSGrant Likely if (out_args) { 156515c9a0acSGrant Likely int i; 156674e1fbb1SJoerg Roedel if (WARN_ON(it.cur_count > MAX_PHANDLE_ARGS)) 156774e1fbb1SJoerg Roedel it.cur_count = MAX_PHANDLE_ARGS; 156874e1fbb1SJoerg Roedel out_args->np = it.node; 156974e1fbb1SJoerg Roedel out_args->args_count = it.cur_count; 157074e1fbb1SJoerg Roedel for (i = 0; i < it.cur_count; i++) 157174e1fbb1SJoerg Roedel out_args->args[i] = be32_to_cpup(it.cur++); 1572b855f16bSTang Yuantian } else { 157374e1fbb1SJoerg Roedel of_node_put(it.node); 157415c9a0acSGrant Likely } 157523ce04c0SGrant Likely 157623ce04c0SGrant Likely /* Found it! return success */ 157715c9a0acSGrant Likely return 0; 157815c9a0acSGrant Likely } 157964b60e09SAnton Vorontsov 158064b60e09SAnton Vorontsov cur_index++; 158164b60e09SAnton Vorontsov } 158264b60e09SAnton Vorontsov 158323ce04c0SGrant Likely /* 158423ce04c0SGrant Likely * Unlock node before returning result; will be one of: 158523ce04c0SGrant Likely * -ENOENT : index is for empty phandle 158623ce04c0SGrant Likely * -EINVAL : parsing error on data 158723ce04c0SGrant Likely */ 1588cd209b41SJoerg Roedel 158923ce04c0SGrant Likely err: 159074e1fbb1SJoerg Roedel if (it.node) 159174e1fbb1SJoerg Roedel of_node_put(it.node); 159223ce04c0SGrant Likely return rc; 159364b60e09SAnton Vorontsov } 1594bd69f73fSGrant Likely 1595eded9dd4SStephen Warren /** 15965fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 15975fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 15985fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 15995fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 16005fba49e3SStephen Warren * the table 16015fba49e3SStephen Warren * 16025fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 16035fba49e3SStephen Warren * of_node_put() on it when done. 16045fba49e3SStephen Warren */ 16055fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 16065fba49e3SStephen Warren const char *phandle_name, int index) 16075fba49e3SStephen Warren { 160891d9942cSStephen Warren struct of_phandle_args args; 16095fba49e3SStephen Warren 161091d9942cSStephen Warren if (index < 0) 16115fba49e3SStephen Warren return NULL; 16125fba49e3SStephen Warren 161391d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 161491d9942cSStephen Warren index, &args)) 161591d9942cSStephen Warren return NULL; 161691d9942cSStephen Warren 161791d9942cSStephen Warren return args.np; 16185fba49e3SStephen Warren } 16195fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 16205fba49e3SStephen Warren 16215fba49e3SStephen Warren /** 1622eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1623eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1624eded9dd4SStephen Warren * @list_name: property name that contains a list 1625eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1626eded9dd4SStephen Warren * @index: index of a phandle to parse out 1627eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1628eded9dd4SStephen Warren * 1629eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1630eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1631eded9dd4SStephen Warren * errno value. 1632eded9dd4SStephen Warren * 1633d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1634eded9dd4SStephen Warren * pointer. 1635eded9dd4SStephen Warren * 1636eded9dd4SStephen Warren * Example: 1637eded9dd4SStephen Warren * 1638eded9dd4SStephen Warren * phandle1: node1 { 1639eded9dd4SStephen Warren * #list-cells = <2>; 1640eded9dd4SStephen Warren * } 1641eded9dd4SStephen Warren * 1642eded9dd4SStephen Warren * phandle2: node2 { 1643eded9dd4SStephen Warren * #list-cells = <1>; 1644eded9dd4SStephen Warren * } 1645eded9dd4SStephen Warren * 1646eded9dd4SStephen Warren * node3 { 1647eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1648eded9dd4SStephen Warren * } 1649eded9dd4SStephen Warren * 1650eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1651eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1652eded9dd4SStephen Warren */ 1653bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1654bd69f73fSGrant Likely const char *cells_name, int index, 1655bd69f73fSGrant Likely struct of_phandle_args *out_args) 1656bd69f73fSGrant Likely { 1657bd69f73fSGrant Likely if (index < 0) 1658bd69f73fSGrant Likely return -EINVAL; 1659035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1660035fd948SStephen Warren index, out_args); 1661bd69f73fSGrant Likely } 166215c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 166302af11b0SGrant Likely 1664bd69f73fSGrant Likely /** 1665035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1666035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1667035fd948SStephen Warren * @list_name: property name that contains a list 1668035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1669035fd948SStephen Warren * @index: index of a phandle to parse out 1670035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1671035fd948SStephen Warren * 1672035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1673035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1674035fd948SStephen Warren * errno value. 1675035fd948SStephen Warren * 1676d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1677035fd948SStephen Warren * pointer. 1678035fd948SStephen Warren * 1679035fd948SStephen Warren * Example: 1680035fd948SStephen Warren * 1681035fd948SStephen Warren * phandle1: node1 { 1682035fd948SStephen Warren * } 1683035fd948SStephen Warren * 1684035fd948SStephen Warren * phandle2: node2 { 1685035fd948SStephen Warren * } 1686035fd948SStephen Warren * 1687035fd948SStephen Warren * node3 { 1688035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1689035fd948SStephen Warren * } 1690035fd948SStephen Warren * 1691035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1692035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1693035fd948SStephen Warren */ 1694035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1695035fd948SStephen Warren const char *list_name, int cell_count, 1696035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1697035fd948SStephen Warren { 1698035fd948SStephen Warren if (index < 0) 1699035fd948SStephen Warren return -EINVAL; 1700035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1701035fd948SStephen Warren index, out_args); 1702035fd948SStephen Warren } 1703035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1704035fd948SStephen Warren 1705035fd948SStephen Warren /** 1706bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1707bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1708bd69f73fSGrant Likely * @list_name: property name that contains a list 1709bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1710bd69f73fSGrant Likely * 1711bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1712bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1713bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1714bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1715bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1716bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1717bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1718bd69f73fSGrant Likely * phandle. 1719bd69f73fSGrant Likely */ 1720bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1721bd69f73fSGrant Likely const char *cells_name) 1722bd69f73fSGrant Likely { 17232021bd01SJoerg Roedel struct of_phandle_iterator it; 17242021bd01SJoerg Roedel int rc, cur_index = 0; 17252021bd01SJoerg Roedel 17262021bd01SJoerg Roedel rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0); 17272021bd01SJoerg Roedel if (rc) 17282021bd01SJoerg Roedel return rc; 17292021bd01SJoerg Roedel 17302021bd01SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0) 17312021bd01SJoerg Roedel cur_index += 1; 17322021bd01SJoerg Roedel 17332021bd01SJoerg Roedel if (rc != -ENOENT) 17342021bd01SJoerg Roedel return rc; 17352021bd01SJoerg Roedel 17362021bd01SJoerg Roedel return cur_index; 1737bd69f73fSGrant Likely } 1738bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1739bd69f73fSGrant Likely 174002af11b0SGrant Likely /** 174162664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 174262664f67SXiubo Li */ 1743d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop) 174462664f67SXiubo Li { 174562664f67SXiubo Li struct property **next; 174662664f67SXiubo Li 174762664f67SXiubo Li prop->next = NULL; 174862664f67SXiubo Li next = &np->properties; 174962664f67SXiubo Li while (*next) { 175062664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 175162664f67SXiubo Li /* duplicate ! don't insert it */ 175262664f67SXiubo Li return -EEXIST; 175362664f67SXiubo Li 175462664f67SXiubo Li next = &(*next)->next; 175562664f67SXiubo Li } 175662664f67SXiubo Li *next = prop; 175762664f67SXiubo Li 175862664f67SXiubo Li return 0; 175962664f67SXiubo Li } 176062664f67SXiubo Li 176162664f67SXiubo Li /** 176279d1c712SNathan Fontenot * of_add_property - Add a property to a node 176302af11b0SGrant Likely */ 176479d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 176502af11b0SGrant Likely { 176602af11b0SGrant Likely unsigned long flags; 17671cf3d8b3SNathan Fontenot int rc; 17681cf3d8b3SNathan Fontenot 17698a2b22a2SGrant Likely mutex_lock(&of_mutex); 177002af11b0SGrant Likely 1771d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 177262664f67SXiubo Li rc = __of_add_property(np, prop); 1773d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 177402af11b0SGrant Likely 17758a2b22a2SGrant Likely if (!rc) 177675b57ecfSGrant Likely __of_add_property_sysfs(np, prop); 177702af11b0SGrant Likely 17788a2b22a2SGrant Likely mutex_unlock(&of_mutex); 17798a2b22a2SGrant Likely 1780259092a3SGrant Likely if (!rc) 1781259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1782259092a3SGrant Likely 178362664f67SXiubo Li return rc; 178402af11b0SGrant Likely } 178502af11b0SGrant Likely 1786d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop) 1787d8c50088SPantelis Antoniou { 1788d8c50088SPantelis Antoniou struct property **next; 1789d8c50088SPantelis Antoniou 1790d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1791d8c50088SPantelis Antoniou if (*next == prop) 1792d8c50088SPantelis Antoniou break; 1793d8c50088SPantelis Antoniou } 1794d8c50088SPantelis Antoniou if (*next == NULL) 1795d8c50088SPantelis Antoniou return -ENODEV; 1796d8c50088SPantelis Antoniou 1797d8c50088SPantelis Antoniou /* found the node */ 1798d8c50088SPantelis Antoniou *next = prop->next; 1799d8c50088SPantelis Antoniou prop->next = np->deadprops; 1800d8c50088SPantelis Antoniou np->deadprops = prop; 1801d8c50088SPantelis Antoniou 1802d8c50088SPantelis Antoniou return 0; 1803d8c50088SPantelis Antoniou } 1804d8c50088SPantelis Antoniou 18058a2b22a2SGrant Likely void __of_remove_property_sysfs(struct device_node *np, struct property *prop) 18068a2b22a2SGrant Likely { 1807ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1808ef69d740SGaurav Minocha return; 1809ef69d740SGaurav Minocha 18108a2b22a2SGrant Likely /* at early boot, bail here and defer setup to of_init() */ 18118a2b22a2SGrant Likely if (of_kset && of_node_is_attached(np)) 18128a2b22a2SGrant Likely sysfs_remove_bin_file(&np->kobj, &prop->attr); 18138a2b22a2SGrant Likely } 18148a2b22a2SGrant Likely 181502af11b0SGrant Likely /** 181679d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 181702af11b0SGrant Likely * 181802af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 181902af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 182002af11b0SGrant Likely * Instead we just move the property to the "dead properties" 182102af11b0SGrant Likely * list, so it won't be found any more. 182202af11b0SGrant Likely */ 182379d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 182402af11b0SGrant Likely { 182502af11b0SGrant Likely unsigned long flags; 18261cf3d8b3SNathan Fontenot int rc; 18271cf3d8b3SNathan Fontenot 18288a2b22a2SGrant Likely mutex_lock(&of_mutex); 182902af11b0SGrant Likely 1830d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1831d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop); 1832d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 183302af11b0SGrant Likely 18348a2b22a2SGrant Likely if (!rc) 18358a2b22a2SGrant Likely __of_remove_property_sysfs(np, prop); 183602af11b0SGrant Likely 18378a2b22a2SGrant Likely mutex_unlock(&of_mutex); 18388a2b22a2SGrant Likely 1839259092a3SGrant Likely if (!rc) 1840259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1841259092a3SGrant Likely 1842d8c50088SPantelis Antoniou return rc; 184302af11b0SGrant Likely } 184402af11b0SGrant Likely 1845d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop, 1846d8c50088SPantelis Antoniou struct property **oldpropp) 1847d8c50088SPantelis Antoniou { 1848d8c50088SPantelis Antoniou struct property **next, *oldprop; 1849d8c50088SPantelis Antoniou 1850d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1851d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0) 1852d8c50088SPantelis Antoniou break; 1853d8c50088SPantelis Antoniou } 1854d8c50088SPantelis Antoniou *oldpropp = oldprop = *next; 1855d8c50088SPantelis Antoniou 1856d8c50088SPantelis Antoniou if (oldprop) { 1857d8c50088SPantelis Antoniou /* replace the node */ 1858d8c50088SPantelis Antoniou newprop->next = oldprop->next; 1859d8c50088SPantelis Antoniou *next = newprop; 1860d8c50088SPantelis Antoniou oldprop->next = np->deadprops; 1861d8c50088SPantelis Antoniou np->deadprops = oldprop; 1862d8c50088SPantelis Antoniou } else { 1863d8c50088SPantelis Antoniou /* new node */ 1864d8c50088SPantelis Antoniou newprop->next = NULL; 1865d8c50088SPantelis Antoniou *next = newprop; 1866d8c50088SPantelis Antoniou } 1867d8c50088SPantelis Antoniou 1868d8c50088SPantelis Antoniou return 0; 1869d8c50088SPantelis Antoniou } 1870d8c50088SPantelis Antoniou 18718a2b22a2SGrant Likely void __of_update_property_sysfs(struct device_node *np, struct property *newprop, 18728a2b22a2SGrant Likely struct property *oldprop) 18738a2b22a2SGrant Likely { 1874ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1875ef69d740SGaurav Minocha return; 1876ef69d740SGaurav Minocha 18778a2b22a2SGrant Likely /* At early boot, bail out and defer setup to of_init() */ 187802af11b0SGrant Likely if (!of_kset) 18798a2b22a2SGrant Likely return; 188002af11b0SGrant Likely 18818a2b22a2SGrant Likely if (oldprop) 18828a2b22a2SGrant Likely sysfs_remove_bin_file(&np->kobj, &oldprop->attr); 18838a2b22a2SGrant Likely __of_add_property_sysfs(np, newprop); 188402af11b0SGrant Likely } 188502af11b0SGrant Likely 188602af11b0SGrant Likely /* 188779d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1888475d0094SDong Aisheng * not exist, add it. 188902af11b0SGrant Likely * 189002af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 189102af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 189202af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 189302af11b0SGrant Likely * and add the new property to the property list 189402af11b0SGrant Likely */ 189579d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 189602af11b0SGrant Likely { 1897d8c50088SPantelis Antoniou struct property *oldprop; 189802af11b0SGrant Likely unsigned long flags; 1899947fdaadSXiubo Li int rc; 19001cf3d8b3SNathan Fontenot 1901475d0094SDong Aisheng if (!newprop->name) 1902475d0094SDong Aisheng return -EINVAL; 1903475d0094SDong Aisheng 19048a2b22a2SGrant Likely mutex_lock(&of_mutex); 1905fcdeb7feSGrant Likely 1906d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1907d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop); 1908d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1909e81b3295SNathan Fontenot 19108a2b22a2SGrant Likely if (!rc) 19118a2b22a2SGrant Likely __of_update_property_sysfs(np, newprop, oldprop); 1912fcdeb7feSGrant Likely 19138a2b22a2SGrant Likely mutex_unlock(&of_mutex); 19141cf3d8b3SNathan Fontenot 1915259092a3SGrant Likely if (!rc) 1916259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 1917fcdeb7feSGrant Likely 19181cf3d8b3SNathan Fontenot return rc; 1919e81b3295SNathan Fontenot } 1920e81b3295SNathan Fontenot 1921611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1922611cad72SShawn Guo int id, const char *stem, int stem_len) 1923611cad72SShawn Guo { 1924611cad72SShawn Guo ap->np = np; 1925611cad72SShawn Guo ap->id = id; 1926611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1927611cad72SShawn Guo ap->stem[stem_len] = 0; 1928611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1929611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 193074a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 1931611cad72SShawn Guo } 1932611cad72SShawn Guo 1933611cad72SShawn Guo /** 19341821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node 1935611cad72SShawn Guo * 19361821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates 19371821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the 19381821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure. 1939611cad72SShawn Guo * 1940611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 19411821dda4SGeert Uytterhoeven * for storing the resulting tree 1942611cad72SShawn Guo */ 1943611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1944611cad72SShawn Guo { 1945611cad72SShawn Guo struct property *pp; 1946611cad72SShawn Guo 19477dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases"); 1948611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1949611cad72SShawn Guo if (of_chosen == NULL) 1950611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 19515c19e952SSascha Hauer 19525c19e952SSascha Hauer if (of_chosen) { 1953a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ 1954676e1b2fSGrant Likely const char *name = of_get_property(of_chosen, "stdout-path", NULL); 1955676e1b2fSGrant Likely if (!name) 19565c19e952SSascha Hauer name = of_get_property(of_chosen, "linux,stdout-path", NULL); 1957a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name) 1958a752ee56SGrant Likely name = of_get_property(of_aliases, "stdout", NULL); 1959f64255b5SPeter Hurley if (name) 19607914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); 19615c19e952SSascha Hauer } 19625c19e952SSascha Hauer 1963611cad72SShawn Guo if (!of_aliases) 1964611cad72SShawn Guo return; 1965611cad72SShawn Guo 19668af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1967611cad72SShawn Guo const char *start = pp->name; 1968611cad72SShawn Guo const char *end = start + strlen(start); 1969611cad72SShawn Guo struct device_node *np; 1970611cad72SShawn Guo struct alias_prop *ap; 1971611cad72SShawn Guo int id, len; 1972611cad72SShawn Guo 1973611cad72SShawn Guo /* Skip those we do not want to proceed */ 1974611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1975611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1976611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1977611cad72SShawn Guo continue; 1978611cad72SShawn Guo 1979611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1980611cad72SShawn Guo if (!np) 1981611cad72SShawn Guo continue; 1982611cad72SShawn Guo 1983611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1984611cad72SShawn Guo * the 'stem' string */ 1985611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1986611cad72SShawn Guo end--; 1987611cad72SShawn Guo len = end - start; 1988611cad72SShawn Guo 1989611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1990611cad72SShawn Guo continue; 1991611cad72SShawn Guo 1992611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1993611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1994611cad72SShawn Guo if (!ap) 1995611cad72SShawn Guo continue; 19960640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1997611cad72SShawn Guo ap->alias = start; 1998611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1999611cad72SShawn Guo } 2000611cad72SShawn Guo } 2001611cad72SShawn Guo 2002611cad72SShawn Guo /** 2003611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 2004611cad72SShawn Guo * @np: Pointer to the given device_node 2005611cad72SShawn Guo * @stem: Alias stem of the given device_node 2006611cad72SShawn Guo * 20075a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given 20085a53a07fSGeert Uytterhoeven * device_node and alias stem. It returns the alias id if found. 2009611cad72SShawn Guo */ 2010611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 2011611cad72SShawn Guo { 2012611cad72SShawn Guo struct alias_prop *app; 2013611cad72SShawn Guo int id = -ENODEV; 2014611cad72SShawn Guo 2015c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 2016611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 2017611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 2018611cad72SShawn Guo continue; 2019611cad72SShawn Guo 2020611cad72SShawn Guo if (np == app->np) { 2021611cad72SShawn Guo id = app->id; 2022611cad72SShawn Guo break; 2023611cad72SShawn Guo } 2024611cad72SShawn Guo } 2025c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 2026611cad72SShawn Guo 2027611cad72SShawn Guo return id; 2028611cad72SShawn Guo } 2029611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 2030c541adc6SStephen Warren 2031351d224fSWolfram Sang /** 2032351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem 2033351d224fSWolfram Sang * @stem: Alias stem to be examined 2034351d224fSWolfram Sang * 2035351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the 2036351d224fSWolfram Sang * given alias stem. It returns the alias id if found. 2037351d224fSWolfram Sang */ 2038351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem) 2039351d224fSWolfram Sang { 2040351d224fSWolfram Sang struct alias_prop *app; 2041351d224fSWolfram Sang int id = -ENODEV; 2042351d224fSWolfram Sang 2043351d224fSWolfram Sang mutex_lock(&of_mutex); 2044351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) { 2045351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0) 2046351d224fSWolfram Sang continue; 2047351d224fSWolfram Sang 2048351d224fSWolfram Sang if (app->id > id) 2049351d224fSWolfram Sang id = app->id; 2050351d224fSWolfram Sang } 2051351d224fSWolfram Sang mutex_unlock(&of_mutex); 2052351d224fSWolfram Sang 2053351d224fSWolfram Sang return id; 2054351d224fSWolfram Sang } 2055351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id); 2056351d224fSWolfram Sang 2057c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 2058c541adc6SStephen Warren u32 *pu) 2059c541adc6SStephen Warren { 2060c541adc6SStephen Warren const void *curv = cur; 2061c541adc6SStephen Warren 2062c541adc6SStephen Warren if (!prop) 2063c541adc6SStephen Warren return NULL; 2064c541adc6SStephen Warren 2065c541adc6SStephen Warren if (!cur) { 2066c541adc6SStephen Warren curv = prop->value; 2067c541adc6SStephen Warren goto out_val; 2068c541adc6SStephen Warren } 2069c541adc6SStephen Warren 2070c541adc6SStephen Warren curv += sizeof(*cur); 2071c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2072c541adc6SStephen Warren return NULL; 2073c541adc6SStephen Warren 2074c541adc6SStephen Warren out_val: 2075c541adc6SStephen Warren *pu = be32_to_cpup(curv); 2076c541adc6SStephen Warren return curv; 2077c541adc6SStephen Warren } 2078c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 2079c541adc6SStephen Warren 2080c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 2081c541adc6SStephen Warren { 2082c541adc6SStephen Warren const void *curv = cur; 2083c541adc6SStephen Warren 2084c541adc6SStephen Warren if (!prop) 2085c541adc6SStephen Warren return NULL; 2086c541adc6SStephen Warren 2087c541adc6SStephen Warren if (!cur) 2088c541adc6SStephen Warren return prop->value; 2089c541adc6SStephen Warren 2090c541adc6SStephen Warren curv += strlen(cur) + 1; 2091c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2092c541adc6SStephen Warren return NULL; 2093c541adc6SStephen Warren 2094c541adc6SStephen Warren return curv; 2095c541adc6SStephen Warren } 2096c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 20975c19e952SSascha Hauer 20985c19e952SSascha Hauer /** 20993482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup 21003482f2c5SGrant Likely * @dn - Pointer to device node 21013482f2c5SGrant Likely * @name - Name to use for preferred console without index. ex. "ttyS" 21023482f2c5SGrant Likely * @index - Index to use for preferred console. 21035c19e952SSascha Hauer * 21043482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the 21053482f2c5SGrant Likely * /chosen node. If it does then register it as the preferred console and return 21063482f2c5SGrant Likely * TRUE. Otherwise return FALSE. 21075c19e952SSascha Hauer */ 21083482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index) 21095c19e952SSascha Hauer { 21103482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline) 21115c19e952SSascha Hauer return false; 21127914a7c5SLeif Lindholm return !add_preferred_console(name, index, 21137914a7c5SLeif Lindholm kstrdup(of_stdout_options, GFP_KERNEL)); 21145c19e952SSascha Hauer } 21153482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check); 2116a3e31b45SSudeep KarkadaNagesha 2117a3e31b45SSudeep KarkadaNagesha /** 2118a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 2119a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 2120a3e31b45SSudeep KarkadaNagesha * 2121a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 2122a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 2123a3e31b45SSudeep KarkadaNagesha * to np. 2124a3e31b45SSudeep KarkadaNagesha */ 2125a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 2126a3e31b45SSudeep KarkadaNagesha { 2127a3e31b45SSudeep KarkadaNagesha struct device_node *child; 2128a3e31b45SSudeep KarkadaNagesha const phandle *handle; 2129a3e31b45SSudeep KarkadaNagesha 2130a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "l2-cache", NULL); 2131a3e31b45SSudeep KarkadaNagesha if (!handle) 2132a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "next-level-cache", NULL); 2133a3e31b45SSudeep KarkadaNagesha 2134a3e31b45SSudeep KarkadaNagesha if (handle) 2135a3e31b45SSudeep KarkadaNagesha return of_find_node_by_phandle(be32_to_cpup(handle)); 2136a3e31b45SSudeep KarkadaNagesha 2137a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 2138a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 2139a3e31b45SSudeep KarkadaNagesha */ 2140a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 2141a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 2142a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 2143a3e31b45SSudeep KarkadaNagesha return child; 2144a3e31b45SSudeep KarkadaNagesha 2145a3e31b45SSudeep KarkadaNagesha return NULL; 2146a3e31b45SSudeep KarkadaNagesha } 2147fd9fdb78SPhilipp Zabel 2148fd9fdb78SPhilipp Zabel /** 2149f2a575f6SPhilipp Zabel * of_graph_parse_endpoint() - parse common endpoint node properties 2150f2a575f6SPhilipp Zabel * @node: pointer to endpoint device_node 2151f2a575f6SPhilipp Zabel * @endpoint: pointer to the OF endpoint data structure 2152f2a575f6SPhilipp Zabel * 2153f2a575f6SPhilipp Zabel * The caller should hold a reference to @node. 2154f2a575f6SPhilipp Zabel */ 2155f2a575f6SPhilipp Zabel int of_graph_parse_endpoint(const struct device_node *node, 2156f2a575f6SPhilipp Zabel struct of_endpoint *endpoint) 2157f2a575f6SPhilipp Zabel { 2158f2a575f6SPhilipp Zabel struct device_node *port_node = of_get_parent(node); 2159f2a575f6SPhilipp Zabel 2160d484700aSPhilipp Zabel WARN_ONCE(!port_node, "%s(): endpoint %s has no parent node\n", 2161d484700aSPhilipp Zabel __func__, node->full_name); 2162d484700aSPhilipp Zabel 2163f2a575f6SPhilipp Zabel memset(endpoint, 0, sizeof(*endpoint)); 2164f2a575f6SPhilipp Zabel 2165f2a575f6SPhilipp Zabel endpoint->local_node = node; 2166f2a575f6SPhilipp Zabel /* 2167f2a575f6SPhilipp Zabel * It doesn't matter whether the two calls below succeed. 2168f2a575f6SPhilipp Zabel * If they don't then the default value 0 is used. 2169f2a575f6SPhilipp Zabel */ 2170f2a575f6SPhilipp Zabel of_property_read_u32(port_node, "reg", &endpoint->port); 2171f2a575f6SPhilipp Zabel of_property_read_u32(node, "reg", &endpoint->id); 2172f2a575f6SPhilipp Zabel 2173f2a575f6SPhilipp Zabel of_node_put(port_node); 2174f2a575f6SPhilipp Zabel 2175f2a575f6SPhilipp Zabel return 0; 2176f2a575f6SPhilipp Zabel } 2177f2a575f6SPhilipp Zabel EXPORT_SYMBOL(of_graph_parse_endpoint); 2178f2a575f6SPhilipp Zabel 2179f2a575f6SPhilipp Zabel /** 2180bfe446e3SPhilipp Zabel * of_graph_get_port_by_id() - get the port matching a given id 2181bfe446e3SPhilipp Zabel * @parent: pointer to the parent device node 2182bfe446e3SPhilipp Zabel * @id: id of the port 2183bfe446e3SPhilipp Zabel * 2184bfe446e3SPhilipp Zabel * Return: A 'port' node pointer with refcount incremented. The caller 2185bfe446e3SPhilipp Zabel * has to use of_node_put() on it when done. 2186bfe446e3SPhilipp Zabel */ 2187bfe446e3SPhilipp Zabel struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) 2188bfe446e3SPhilipp Zabel { 2189bfe446e3SPhilipp Zabel struct device_node *node, *port; 2190bfe446e3SPhilipp Zabel 2191bfe446e3SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2192bfe446e3SPhilipp Zabel if (node) 2193bfe446e3SPhilipp Zabel parent = node; 2194bfe446e3SPhilipp Zabel 2195bfe446e3SPhilipp Zabel for_each_child_of_node(parent, port) { 2196bfe446e3SPhilipp Zabel u32 port_id = 0; 2197bfe446e3SPhilipp Zabel 2198bfe446e3SPhilipp Zabel if (of_node_cmp(port->name, "port") != 0) 2199bfe446e3SPhilipp Zabel continue; 2200bfe446e3SPhilipp Zabel of_property_read_u32(port, "reg", &port_id); 2201bfe446e3SPhilipp Zabel if (id == port_id) 2202bfe446e3SPhilipp Zabel break; 2203bfe446e3SPhilipp Zabel } 2204bfe446e3SPhilipp Zabel 2205bfe446e3SPhilipp Zabel of_node_put(node); 2206bfe446e3SPhilipp Zabel 2207bfe446e3SPhilipp Zabel return port; 2208bfe446e3SPhilipp Zabel } 2209bfe446e3SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_port_by_id); 2210bfe446e3SPhilipp Zabel 2211bfe446e3SPhilipp Zabel /** 2212fd9fdb78SPhilipp Zabel * of_graph_get_next_endpoint() - get next endpoint node 2213fd9fdb78SPhilipp Zabel * @parent: pointer to the parent device node 2214fd9fdb78SPhilipp Zabel * @prev: previous endpoint node, or NULL to get first 2215fd9fdb78SPhilipp Zabel * 2216fd9fdb78SPhilipp Zabel * Return: An 'endpoint' node pointer with refcount incremented. Refcount 2217f033c0bcSPhilipp Zabel * of the passed @prev node is decremented. 2218fd9fdb78SPhilipp Zabel */ 2219fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, 2220fd9fdb78SPhilipp Zabel struct device_node *prev) 2221fd9fdb78SPhilipp Zabel { 2222fd9fdb78SPhilipp Zabel struct device_node *endpoint; 22233c83e61eSLinus Torvalds struct device_node *port; 2224fd9fdb78SPhilipp Zabel 2225fd9fdb78SPhilipp Zabel if (!parent) 2226fd9fdb78SPhilipp Zabel return NULL; 2227fd9fdb78SPhilipp Zabel 22283c83e61eSLinus Torvalds /* 22293c83e61eSLinus Torvalds * Start by locating the port node. If no previous endpoint is specified 22303c83e61eSLinus Torvalds * search for the first port node, otherwise get the previous endpoint 22313c83e61eSLinus Torvalds * parent port node. 22323c83e61eSLinus Torvalds */ 2233fd9fdb78SPhilipp Zabel if (!prev) { 2234fd9fdb78SPhilipp Zabel struct device_node *node; 22353c83e61eSLinus Torvalds 2236fd9fdb78SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2237fd9fdb78SPhilipp Zabel if (node) 2238fd9fdb78SPhilipp Zabel parent = node; 2239fd9fdb78SPhilipp Zabel 2240fd9fdb78SPhilipp Zabel port = of_get_child_by_name(parent, "port"); 2241fd9fdb78SPhilipp Zabel of_node_put(node); 22424329b93bSPhilipp Zabel 22433c83e61eSLinus Torvalds if (!port) { 22443c83e61eSLinus Torvalds pr_err("%s(): no port node found in %s\n", 22453c83e61eSLinus Torvalds __func__, parent->full_name); 22463c83e61eSLinus Torvalds return NULL; 22474329b93bSPhilipp Zabel } 22483c83e61eSLinus Torvalds } else { 2249fd9fdb78SPhilipp Zabel port = of_get_parent(prev); 22506ff60d39SPhilipp Zabel if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", 22516ff60d39SPhilipp Zabel __func__, prev->full_name)) 2252fd9fdb78SPhilipp Zabel return NULL; 22533c83e61eSLinus Torvalds } 22543c83e61eSLinus Torvalds 22553c83e61eSLinus Torvalds while (1) { 22563c83e61eSLinus Torvalds /* 22573c83e61eSLinus Torvalds * Now that we have a port node, get the next endpoint by 22583c83e61eSLinus Torvalds * getting the next child. If the previous endpoint is NULL this 22593c83e61eSLinus Torvalds * will return the first child. 22603c83e61eSLinus Torvalds */ 2261fd9fdb78SPhilipp Zabel endpoint = of_get_next_child(port, prev); 2262fd9fdb78SPhilipp Zabel if (endpoint) { 2263fd9fdb78SPhilipp Zabel of_node_put(port); 2264fd9fdb78SPhilipp Zabel return endpoint; 2265fd9fdb78SPhilipp Zabel } 2266fd9fdb78SPhilipp Zabel 2267fd9fdb78SPhilipp Zabel /* No more endpoints under this port, try the next one. */ 22683c83e61eSLinus Torvalds prev = NULL; 22693c83e61eSLinus Torvalds 2270fd9fdb78SPhilipp Zabel do { 2271fd9fdb78SPhilipp Zabel port = of_get_next_child(parent, port); 2272fd9fdb78SPhilipp Zabel if (!port) 2273fd9fdb78SPhilipp Zabel return NULL; 2274fd9fdb78SPhilipp Zabel } while (of_node_cmp(port->name, "port")); 22753c83e61eSLinus Torvalds } 2276fd9fdb78SPhilipp Zabel } 2277fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_next_endpoint); 2278fd9fdb78SPhilipp Zabel 2279fd9fdb78SPhilipp Zabel /** 22808ccd0d0cSHyungwon Hwang * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers 22818ccd0d0cSHyungwon Hwang * @parent: pointer to the parent device node 22828ccd0d0cSHyungwon Hwang * @port_reg: identifier (value of reg property) of the parent port node 22838ccd0d0cSHyungwon Hwang * @reg: identifier (value of reg property) of the endpoint node 22848ccd0d0cSHyungwon Hwang * 22858ccd0d0cSHyungwon Hwang * Return: An 'endpoint' node pointer which is identified by reg and at the same 22868ccd0d0cSHyungwon Hwang * is the child of a port node identified by port_reg. reg and port_reg are 22878ccd0d0cSHyungwon Hwang * ignored when they are -1. 22888ccd0d0cSHyungwon Hwang */ 22898ccd0d0cSHyungwon Hwang struct device_node *of_graph_get_endpoint_by_regs( 22908ccd0d0cSHyungwon Hwang const struct device_node *parent, int port_reg, int reg) 22918ccd0d0cSHyungwon Hwang { 22928ccd0d0cSHyungwon Hwang struct of_endpoint endpoint; 22938ccd0d0cSHyungwon Hwang struct device_node *node, *prev_node = NULL; 22948ccd0d0cSHyungwon Hwang 22958ccd0d0cSHyungwon Hwang while (1) { 22968ccd0d0cSHyungwon Hwang node = of_graph_get_next_endpoint(parent, prev_node); 22978ccd0d0cSHyungwon Hwang of_node_put(prev_node); 22988ccd0d0cSHyungwon Hwang if (!node) 22998ccd0d0cSHyungwon Hwang break; 23008ccd0d0cSHyungwon Hwang 23018ccd0d0cSHyungwon Hwang of_graph_parse_endpoint(node, &endpoint); 23028ccd0d0cSHyungwon Hwang if (((port_reg == -1) || (endpoint.port == port_reg)) && 23038ccd0d0cSHyungwon Hwang ((reg == -1) || (endpoint.id == reg))) 23048ccd0d0cSHyungwon Hwang return node; 23058ccd0d0cSHyungwon Hwang 23068ccd0d0cSHyungwon Hwang prev_node = node; 23078ccd0d0cSHyungwon Hwang } 23088ccd0d0cSHyungwon Hwang 23098ccd0d0cSHyungwon Hwang return NULL; 23108ccd0d0cSHyungwon Hwang } 23118ffaa903SDave Airlie EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); 23128ccd0d0cSHyungwon Hwang 23138ccd0d0cSHyungwon Hwang /** 2314fd9fdb78SPhilipp Zabel * of_graph_get_remote_port_parent() - get remote port's parent node 2315fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2316fd9fdb78SPhilipp Zabel * 2317fd9fdb78SPhilipp Zabel * Return: Remote device node associated with remote endpoint node linked 2318fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2319fd9fdb78SPhilipp Zabel */ 2320fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port_parent( 2321fd9fdb78SPhilipp Zabel const struct device_node *node) 2322fd9fdb78SPhilipp Zabel { 2323fd9fdb78SPhilipp Zabel struct device_node *np; 2324fd9fdb78SPhilipp Zabel unsigned int depth; 2325fd9fdb78SPhilipp Zabel 2326fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2327fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2328fd9fdb78SPhilipp Zabel 2329fd9fdb78SPhilipp Zabel /* Walk 3 levels up only if there is 'ports' node. */ 2330fd9fdb78SPhilipp Zabel for (depth = 3; depth && np; depth--) { 2331fd9fdb78SPhilipp Zabel np = of_get_next_parent(np); 2332fd9fdb78SPhilipp Zabel if (depth == 2 && of_node_cmp(np->name, "ports")) 2333fd9fdb78SPhilipp Zabel break; 2334fd9fdb78SPhilipp Zabel } 2335fd9fdb78SPhilipp Zabel return np; 2336fd9fdb78SPhilipp Zabel } 2337fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port_parent); 2338fd9fdb78SPhilipp Zabel 2339fd9fdb78SPhilipp Zabel /** 2340fd9fdb78SPhilipp Zabel * of_graph_get_remote_port() - get remote port node 2341fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2342fd9fdb78SPhilipp Zabel * 2343fd9fdb78SPhilipp Zabel * Return: Remote port node associated with remote endpoint node linked 2344fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2345fd9fdb78SPhilipp Zabel */ 2346fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port(const struct device_node *node) 2347fd9fdb78SPhilipp Zabel { 2348fd9fdb78SPhilipp Zabel struct device_node *np; 2349fd9fdb78SPhilipp Zabel 2350fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2351fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2352fd9fdb78SPhilipp Zabel if (!np) 2353fd9fdb78SPhilipp Zabel return NULL; 2354fd9fdb78SPhilipp Zabel return of_get_next_parent(np); 2355fd9fdb78SPhilipp Zabel } 2356fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port); 2357