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 { 920c3f061cSRob Herring return numa_node_id(); 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 19275b57ecfSGrant Likely static int __init of_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); 20175b57ecfSGrant Likely return -ENOMEM; 20275b57ecfSGrant Likely } 20375b57ecfSGrant Likely for_each_of_allnodes(np) 2048a2b22a2SGrant Likely __of_attach_node_sysfs(np); 205c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 20675b57ecfSGrant Likely 2078357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */ 2085063e25aSGrant Likely if (of_root) 20975b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 21075b57ecfSGrant Likely 21175b57ecfSGrant Likely return 0; 21275b57ecfSGrant Likely } 21375b57ecfSGrant Likely core_initcall(of_init); 21475b57ecfSGrant Likely 21528d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 21628d0e36bSThomas Gleixner const char *name, int *lenp) 217581b605aSStephen Rothwell { 218581b605aSStephen Rothwell struct property *pp; 219581b605aSStephen Rothwell 22064e4566fSTimur Tabi if (!np) 22164e4566fSTimur Tabi return NULL; 22264e4566fSTimur Tabi 223a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 224581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 225a3a7cab1SSachin Kamat if (lenp) 226581b605aSStephen Rothwell *lenp = pp->length; 227581b605aSStephen Rothwell break; 228581b605aSStephen Rothwell } 229581b605aSStephen Rothwell } 23028d0e36bSThomas Gleixner 23128d0e36bSThomas Gleixner return pp; 23228d0e36bSThomas Gleixner } 23328d0e36bSThomas Gleixner 23428d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 23528d0e36bSThomas Gleixner const char *name, 23628d0e36bSThomas Gleixner int *lenp) 23728d0e36bSThomas Gleixner { 23828d0e36bSThomas Gleixner struct property *pp; 239d6d3c4e6SThomas Gleixner unsigned long flags; 24028d0e36bSThomas Gleixner 241d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 24228d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 243d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 244581b605aSStephen Rothwell 245581b605aSStephen Rothwell return pp; 246581b605aSStephen Rothwell } 247581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 248581b605aSStephen Rothwell 2495063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev) 2505063e25aSGrant Likely { 2515063e25aSGrant Likely struct device_node *np; 2525063e25aSGrant Likely if (!prev) { 2535063e25aSGrant Likely np = of_root; 2545063e25aSGrant Likely } else if (prev->child) { 2555063e25aSGrant Likely np = prev->child; 2565063e25aSGrant Likely } else { 2575063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */ 2585063e25aSGrant Likely np = prev; 2595063e25aSGrant Likely while (np->parent && !np->sibling) 2605063e25aSGrant Likely np = np->parent; 2615063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */ 2625063e25aSGrant Likely } 2635063e25aSGrant Likely return np; 2645063e25aSGrant Likely } 2655063e25aSGrant Likely 266e91edcf5SGrant Likely /** 267e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 268e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 269e91edcf5SGrant Likely * of_node_put() will be called on it 270e91edcf5SGrant Likely * 271e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 272e91edcf5SGrant Likely * of_node_put() on it when done. 273e91edcf5SGrant Likely */ 274e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 275e91edcf5SGrant Likely { 276e91edcf5SGrant Likely struct device_node *np; 277d25d8694SBenjamin Herrenschmidt unsigned long flags; 278e91edcf5SGrant Likely 279d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 2805063e25aSGrant Likely np = __of_find_all_nodes(prev); 2815063e25aSGrant Likely of_node_get(np); 282e91edcf5SGrant Likely of_node_put(prev); 283d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 284e91edcf5SGrant Likely return np; 285e91edcf5SGrant Likely } 286e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 287e91edcf5SGrant Likely 28897e873e5SStephen Rothwell /* 28997e873e5SStephen Rothwell * Find a property with a given name for a given node 29097e873e5SStephen Rothwell * and return the value. 29197e873e5SStephen Rothwell */ 292a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np, 29328d0e36bSThomas Gleixner const char *name, int *lenp) 29428d0e36bSThomas Gleixner { 29528d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 29628d0e36bSThomas Gleixner 29728d0e36bSThomas Gleixner return pp ? pp->value : NULL; 29828d0e36bSThomas Gleixner } 29928d0e36bSThomas Gleixner 30028d0e36bSThomas Gleixner /* 30128d0e36bSThomas Gleixner * Find a property with a given name for a given node 30228d0e36bSThomas Gleixner * and return the value. 30328d0e36bSThomas Gleixner */ 30497e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 30597e873e5SStephen Rothwell int *lenp) 30697e873e5SStephen Rothwell { 30797e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 30897e873e5SStephen Rothwell 30997e873e5SStephen Rothwell return pp ? pp->value : NULL; 31097e873e5SStephen Rothwell } 31197e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 3120081cbc3SStephen Rothwell 313183912d3SSudeep KarkadaNagesha /* 314183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 315183912d3SSudeep KarkadaNagesha * 316183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 317183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 318183912d3SSudeep KarkadaNagesha * 319183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 320183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 321183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 322183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 323183912d3SSudeep KarkadaNagesha * 324183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 325183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 326183912d3SSudeep KarkadaNagesha */ 327183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 328183912d3SSudeep KarkadaNagesha { 329183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 330183912d3SSudeep KarkadaNagesha } 331183912d3SSudeep KarkadaNagesha 332183912d3SSudeep KarkadaNagesha /** 333183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 334183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 335183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 336183912d3SSudeep KarkadaNagesha */ 337183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 338183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 339183912d3SSudeep KarkadaNagesha { 340183912d3SSudeep KarkadaNagesha const __be32 *cell; 341183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 342183912d3SSudeep KarkadaNagesha u64 hwid; 343183912d3SSudeep KarkadaNagesha 344183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 345183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 346f3cea45aSGrant Likely if (!cell || !ac) 347183912d3SSudeep KarkadaNagesha return false; 348f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 349183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 350183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 351183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 352183912d3SSudeep KarkadaNagesha if (thread) 353183912d3SSudeep KarkadaNagesha *thread = tid; 354183912d3SSudeep KarkadaNagesha return true; 355183912d3SSudeep KarkadaNagesha } 356183912d3SSudeep KarkadaNagesha cell += ac; 357183912d3SSudeep KarkadaNagesha } 358183912d3SSudeep KarkadaNagesha return false; 359183912d3SSudeep KarkadaNagesha } 360183912d3SSudeep KarkadaNagesha 361d1cb9d1aSDavid Miller /* 362d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 363d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 364d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 365d1cb9d1aSDavid Miller * core is returned in it. 366d1cb9d1aSDavid Miller */ 367d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 368d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 369d1cb9d1aSDavid Miller { 370d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 371d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 372d1cb9d1aSDavid Miller * standard "reg" property. 373d1cb9d1aSDavid Miller */ 374d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 375d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 376d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 377d1cb9d1aSDavid Miller cpu, thread)) 378d1cb9d1aSDavid Miller return true; 379d1cb9d1aSDavid Miller 380d1cb9d1aSDavid Miller if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) 381d1cb9d1aSDavid Miller return true; 382d1cb9d1aSDavid Miller 383d1cb9d1aSDavid Miller return false; 384d1cb9d1aSDavid Miller } 385d1cb9d1aSDavid Miller 386183912d3SSudeep KarkadaNagesha /** 387183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 388183912d3SSudeep KarkadaNagesha * 389183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 390183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 391183912d3SSudeep KarkadaNagesha * returned 392183912d3SSudeep KarkadaNagesha * 393183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 394183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 395183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 396183912d3SSudeep KarkadaNagesha * references can use that instead. 397183912d3SSudeep KarkadaNagesha * 398183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 399183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 400183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 401183912d3SSudeep KarkadaNagesha * 402183912d3SSudeep KarkadaNagesha * Returns a node pointer for the logical cpu if found, else NULL. 403183912d3SSudeep KarkadaNagesha */ 404183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 405183912d3SSudeep KarkadaNagesha { 406d1cb9d1aSDavid Miller struct device_node *cpun; 407183912d3SSudeep KarkadaNagesha 408d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 409d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 410183912d3SSudeep KarkadaNagesha return cpun; 411183912d3SSudeep KarkadaNagesha } 412183912d3SSudeep KarkadaNagesha return NULL; 413183912d3SSudeep KarkadaNagesha } 414183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 415183912d3SSudeep KarkadaNagesha 416215a14cfSKevin Hao /** 417215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints 418215a14cfSKevin Hao * @device: pointer to node 419215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match 420215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match 421215a14cfSKevin Hao * @name: required node name, NULL or "" for any match 422215a14cfSKevin Hao * 423215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the 424215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by 425215a14cfSKevin Hao * passing NULL or an empty string as the constraint. 426215a14cfSKevin Hao * 427215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return 428215a14cfSKevin Hao * value is a relative score with larger values indicating better 429215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value 430215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching 431215a14cfSKevin Hao * name. Practically speaking, this results in the following priority 432215a14cfSKevin Hao * order for matches: 433215a14cfSKevin Hao * 434215a14cfSKevin Hao * 1. specific compatible && type && name 435215a14cfSKevin Hao * 2. specific compatible && type 436215a14cfSKevin Hao * 3. specific compatible && name 437215a14cfSKevin Hao * 4. specific compatible 438215a14cfSKevin Hao * 5. general compatible && type && name 439215a14cfSKevin Hao * 6. general compatible && type 440215a14cfSKevin Hao * 7. general compatible && name 441215a14cfSKevin Hao * 8. general compatible 442215a14cfSKevin Hao * 9. type && name 443215a14cfSKevin Hao * 10. type 444215a14cfSKevin Hao * 11. name 4450081cbc3SStephen Rothwell */ 44628d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 447215a14cfSKevin Hao const char *compat, const char *type, const char *name) 4480081cbc3SStephen Rothwell { 449215a14cfSKevin Hao struct property *prop; 4500081cbc3SStephen Rothwell const char *cp; 451215a14cfSKevin Hao int index = 0, score = 0; 4520081cbc3SStephen Rothwell 453215a14cfSKevin Hao /* Compatible match has highest priority */ 454215a14cfSKevin Hao if (compat && compat[0]) { 455215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL); 456215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp; 457215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) { 458215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 459215a14cfSKevin Hao score = INT_MAX/2 - (index << 2); 460215a14cfSKevin Hao break; 461215a14cfSKevin Hao } 462215a14cfSKevin Hao } 463215a14cfSKevin Hao if (!score) 4640081cbc3SStephen Rothwell return 0; 4650081cbc3SStephen Rothwell } 4660081cbc3SStephen Rothwell 467215a14cfSKevin Hao /* Matching type is better than matching name */ 468215a14cfSKevin Hao if (type && type[0]) { 469215a14cfSKevin Hao if (!device->type || of_node_cmp(type, device->type)) 4700081cbc3SStephen Rothwell return 0; 471215a14cfSKevin Hao score += 2; 472215a14cfSKevin Hao } 473215a14cfSKevin Hao 474215a14cfSKevin Hao /* Matching name is a bit better than not */ 475215a14cfSKevin Hao if (name && name[0]) { 476215a14cfSKevin Hao if (!device->name || of_node_cmp(name, device->name)) 477215a14cfSKevin Hao return 0; 478215a14cfSKevin Hao score++; 479215a14cfSKevin Hao } 480215a14cfSKevin Hao 481215a14cfSKevin Hao return score; 4820081cbc3SStephen Rothwell } 48328d0e36bSThomas Gleixner 48428d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 48528d0e36bSThomas Gleixner * the device's "compatible" property 48628d0e36bSThomas Gleixner */ 48728d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 48828d0e36bSThomas Gleixner const char *compat) 48928d0e36bSThomas Gleixner { 490d6d3c4e6SThomas Gleixner unsigned long flags; 49128d0e36bSThomas Gleixner int res; 49228d0e36bSThomas Gleixner 493d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 494215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL); 495d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 49628d0e36bSThomas Gleixner return res; 49728d0e36bSThomas Gleixner } 4980081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 499e679c5f4SStephen Rothwell 500e679c5f4SStephen Rothwell /** 50171a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 5021f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 5031f43cfb9SGrant Likely * 50425c7a1deSKevin Cernekee * Returns a positive integer if the root node has the given value in its 5051f43cfb9SGrant Likely * compatible property. 5061f43cfb9SGrant Likely */ 50771a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 5081f43cfb9SGrant Likely { 5091f43cfb9SGrant Likely struct device_node *root; 5101f43cfb9SGrant Likely int rc = 0; 5111f43cfb9SGrant Likely 5121f43cfb9SGrant Likely root = of_find_node_by_path("/"); 5131f43cfb9SGrant Likely if (root) { 5141f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 5151f43cfb9SGrant Likely of_node_put(root); 5161f43cfb9SGrant Likely } 5171f43cfb9SGrant Likely return rc; 5181f43cfb9SGrant Likely } 51971a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 5201f43cfb9SGrant Likely 5211f43cfb9SGrant Likely /** 522c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 523834d97d4SJosh Boyer * 524c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 525834d97d4SJosh Boyer * 52653a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 52753a4ab96SKevin Cernekee * false otherwise 528834d97d4SJosh Boyer */ 52953a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device) 530834d97d4SJosh Boyer { 531834d97d4SJosh Boyer const char *status; 532834d97d4SJosh Boyer int statlen; 533834d97d4SJosh Boyer 53442ccd781SXiubo Li if (!device) 53553a4ab96SKevin Cernekee return false; 53642ccd781SXiubo Li 537c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 538834d97d4SJosh Boyer if (status == NULL) 53953a4ab96SKevin Cernekee return true; 540834d97d4SJosh Boyer 541834d97d4SJosh Boyer if (statlen > 0) { 542834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 54353a4ab96SKevin Cernekee return true; 544834d97d4SJosh Boyer } 545834d97d4SJosh Boyer 54653a4ab96SKevin Cernekee return false; 547834d97d4SJosh Boyer } 548c31a0c05SStephen Warren 549c31a0c05SStephen Warren /** 550c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 551c31a0c05SStephen Warren * 552c31a0c05SStephen Warren * @device: Node to check for availability 553c31a0c05SStephen Warren * 55453a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 55553a4ab96SKevin Cernekee * false otherwise 556c31a0c05SStephen Warren */ 55753a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device) 558c31a0c05SStephen Warren { 559c31a0c05SStephen Warren unsigned long flags; 56053a4ab96SKevin Cernekee bool res; 561c31a0c05SStephen Warren 562c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 563c31a0c05SStephen Warren res = __of_device_is_available(device); 564c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 565c31a0c05SStephen Warren return res; 566c31a0c05SStephen Warren 567c31a0c05SStephen Warren } 568834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 569834d97d4SJosh Boyer 570834d97d4SJosh Boyer /** 57137786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers 57237786c7fSKevin Cernekee * 57337786c7fSKevin Cernekee * @device: Node to check for endianness 57437786c7fSKevin Cernekee * 57537786c7fSKevin Cernekee * Returns true if the device has a "big-endian" property, or if the kernel 57637786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property. 57737786c7fSKevin Cernekee * Returns false otherwise. 57837786c7fSKevin Cernekee * 57937786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if 58037786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise. 58137786c7fSKevin Cernekee */ 58237786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device) 58337786c7fSKevin Cernekee { 58437786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian")) 58537786c7fSKevin Cernekee return true; 58637786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 58737786c7fSKevin Cernekee of_property_read_bool(device, "native-endian")) 58837786c7fSKevin Cernekee return true; 58937786c7fSKevin Cernekee return false; 59037786c7fSKevin Cernekee } 59137786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian); 59237786c7fSKevin Cernekee 59337786c7fSKevin Cernekee /** 594e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 595e679c5f4SStephen Rothwell * @node: Node to get parent 596e679c5f4SStephen Rothwell * 597e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 598e679c5f4SStephen Rothwell * of_node_put() on it when done. 599e679c5f4SStephen Rothwell */ 600e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 601e679c5f4SStephen Rothwell { 602e679c5f4SStephen Rothwell struct device_node *np; 603d6d3c4e6SThomas Gleixner unsigned long flags; 604e679c5f4SStephen Rothwell 605e679c5f4SStephen Rothwell if (!node) 606e679c5f4SStephen Rothwell return NULL; 607e679c5f4SStephen Rothwell 608d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 609e679c5f4SStephen Rothwell np = of_node_get(node->parent); 610d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 611e679c5f4SStephen Rothwell return np; 612e679c5f4SStephen Rothwell } 613e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 614d1cd355aSStephen Rothwell 615d1cd355aSStephen Rothwell /** 616f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 617f4eb0107SMichael Ellerman * @node: Node to get parent of 618f4eb0107SMichael Ellerman * 619f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 620f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 621f4eb0107SMichael Ellerman * through a node's parents. 622f4eb0107SMichael Ellerman * 623f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 624f4eb0107SMichael Ellerman * of_node_put() on it when done. 625f4eb0107SMichael Ellerman */ 626f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 627f4eb0107SMichael Ellerman { 628f4eb0107SMichael Ellerman struct device_node *parent; 629d6d3c4e6SThomas Gleixner unsigned long flags; 630f4eb0107SMichael Ellerman 631f4eb0107SMichael Ellerman if (!node) 632f4eb0107SMichael Ellerman return NULL; 633f4eb0107SMichael Ellerman 634d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 635f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 636f4eb0107SMichael Ellerman of_node_put(node); 637d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 638f4eb0107SMichael Ellerman return parent; 639f4eb0107SMichael Ellerman } 6406695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 641f4eb0107SMichael Ellerman 6420d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node, 6430d0e02d6SGrant Likely struct device_node *prev) 6440d0e02d6SGrant Likely { 6450d0e02d6SGrant Likely struct device_node *next; 6460d0e02d6SGrant Likely 64743cb4367SFlorian Fainelli if (!node) 64843cb4367SFlorian Fainelli return NULL; 64943cb4367SFlorian Fainelli 6500d0e02d6SGrant Likely next = prev ? prev->sibling : node->child; 6510d0e02d6SGrant Likely for (; next; next = next->sibling) 6520d0e02d6SGrant Likely if (of_node_get(next)) 6530d0e02d6SGrant Likely break; 6540d0e02d6SGrant Likely of_node_put(prev); 6550d0e02d6SGrant Likely return next; 6560d0e02d6SGrant Likely } 6570d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \ 6580d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \ 6590d0e02d6SGrant Likely child = __of_get_next_child(parent, child)) 6600d0e02d6SGrant Likely 661f4eb0107SMichael Ellerman /** 662d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 663d1cd355aSStephen Rothwell * @node: parent node 664d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 665d1cd355aSStephen Rothwell * 66664808273SBaruch Siach * Returns a node pointer with refcount incremented, use of_node_put() on 66764808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the 66864808273SBaruch Siach * refcount of prev. 669d1cd355aSStephen Rothwell */ 670d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 671d1cd355aSStephen Rothwell struct device_node *prev) 672d1cd355aSStephen Rothwell { 673d1cd355aSStephen Rothwell struct device_node *next; 674d6d3c4e6SThomas Gleixner unsigned long flags; 675d1cd355aSStephen Rothwell 676d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 6770d0e02d6SGrant Likely next = __of_get_next_child(node, prev); 678d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 679d1cd355aSStephen Rothwell return next; 680d1cd355aSStephen Rothwell } 681d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 6821ef4d424SStephen Rothwell 6831ef4d424SStephen Rothwell /** 6843296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 6853296193dSTimur Tabi * @node: parent node 6863296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 6873296193dSTimur Tabi * 6883296193dSTimur Tabi * This function is like of_get_next_child(), except that it 6893296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 6903296193dSTimur Tabi */ 6913296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 6923296193dSTimur Tabi struct device_node *prev) 6933296193dSTimur Tabi { 6943296193dSTimur Tabi struct device_node *next; 695d25d8694SBenjamin Herrenschmidt unsigned long flags; 6963296193dSTimur Tabi 69743cb4367SFlorian Fainelli if (!node) 69843cb4367SFlorian Fainelli return NULL; 69943cb4367SFlorian Fainelli 700d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 7013296193dSTimur Tabi next = prev ? prev->sibling : node->child; 7023296193dSTimur Tabi for (; next; next = next->sibling) { 703c31a0c05SStephen Warren if (!__of_device_is_available(next)) 7043296193dSTimur Tabi continue; 7053296193dSTimur Tabi if (of_node_get(next)) 7063296193dSTimur Tabi break; 7073296193dSTimur Tabi } 7083296193dSTimur Tabi of_node_put(prev); 709d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 7103296193dSTimur Tabi return next; 7113296193dSTimur Tabi } 7123296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 7133296193dSTimur Tabi 7143296193dSTimur Tabi /** 7159c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 7169c19761aSSrinivas Kandagatla * @node: parent node 7179c19761aSSrinivas Kandagatla * @name: child name to look for. 7189c19761aSSrinivas Kandagatla * 7199c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 7209c19761aSSrinivas Kandagatla * 7219c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 7229c19761aSSrinivas Kandagatla * of_node_put() on it when done. 7239c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 7249c19761aSSrinivas Kandagatla */ 7259c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 7269c19761aSSrinivas Kandagatla const char *name) 7279c19761aSSrinivas Kandagatla { 7289c19761aSSrinivas Kandagatla struct device_node *child; 7299c19761aSSrinivas Kandagatla 7309c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 7319c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 7329c19761aSSrinivas Kandagatla break; 7339c19761aSSrinivas Kandagatla return child; 7349c19761aSSrinivas Kandagatla } 7359c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 7369c19761aSSrinivas Kandagatla 737c22e650eSGrant Likely static struct device_node *__of_find_node_by_path(struct device_node *parent, 738c22e650eSGrant Likely const char *path) 739c22e650eSGrant Likely { 740c22e650eSGrant Likely struct device_node *child; 741106937e8SLeif Lindholm int len; 742c22e650eSGrant Likely 743721a09e9SBrian Norris len = strcspn(path, "/:"); 744c22e650eSGrant Likely if (!len) 745c22e650eSGrant Likely return NULL; 746c22e650eSGrant Likely 747c22e650eSGrant Likely __for_each_child_of_node(parent, child) { 748c22e650eSGrant Likely const char *name = strrchr(child->full_name, '/'); 749c22e650eSGrant Likely if (WARN(!name, "malformed device_node %s\n", child->full_name)) 750c22e650eSGrant Likely continue; 751c22e650eSGrant Likely name++; 752c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 753c22e650eSGrant Likely return child; 754c22e650eSGrant Likely } 755c22e650eSGrant Likely return NULL; 756c22e650eSGrant Likely } 757c22e650eSGrant Likely 7589c19761aSSrinivas Kandagatla /** 75975c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path 760c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not 761c22e650eSGrant Likely * start with '/', the name of a property of the /aliases 762c22e650eSGrant Likely * node (an alias). In the case of an alias, the node 763c22e650eSGrant Likely * matching the alias' value will be returned. 76475c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of 76575c28c09SLeif Lindholm * an options string appended to the end of the path with 76675c28c09SLeif Lindholm * a ':' separator. 767c22e650eSGrant Likely * 768c22e650eSGrant Likely * Valid paths: 769c22e650eSGrant Likely * /foo/bar Full path 770c22e650eSGrant Likely * foo Valid alias 771c22e650eSGrant Likely * foo/bar Valid alias + relative path 7721ef4d424SStephen Rothwell * 7731ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 7741ef4d424SStephen Rothwell * of_node_put() on it when done. 7751ef4d424SStephen Rothwell */ 77675c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) 7771ef4d424SStephen Rothwell { 778c22e650eSGrant Likely struct device_node *np = NULL; 779c22e650eSGrant Likely struct property *pp; 780d6d3c4e6SThomas Gleixner unsigned long flags; 78175c28c09SLeif Lindholm const char *separator = strchr(path, ':'); 78275c28c09SLeif Lindholm 78375c28c09SLeif Lindholm if (opts) 78475c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL; 7851ef4d424SStephen Rothwell 786c22e650eSGrant Likely if (strcmp(path, "/") == 0) 7875063e25aSGrant Likely return of_node_get(of_root); 788c22e650eSGrant Likely 789c22e650eSGrant Likely /* The path could begin with an alias */ 790c22e650eSGrant Likely if (*path != '/') { 791106937e8SLeif Lindholm int len; 792106937e8SLeif Lindholm const char *p = separator; 793106937e8SLeif Lindholm 794106937e8SLeif Lindholm if (!p) 795106937e8SLeif Lindholm p = strchrnul(path, '/'); 796106937e8SLeif Lindholm len = p - path; 797c22e650eSGrant Likely 798c22e650eSGrant Likely /* of_aliases must not be NULL */ 799c22e650eSGrant Likely if (!of_aliases) 800c22e650eSGrant Likely return NULL; 801c22e650eSGrant Likely 802c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) { 803c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { 804c22e650eSGrant Likely np = of_find_node_by_path(pp->value); 8051ef4d424SStephen Rothwell break; 8061ef4d424SStephen Rothwell } 807c22e650eSGrant Likely } 808c22e650eSGrant Likely if (!np) 809c22e650eSGrant Likely return NULL; 810c22e650eSGrant Likely path = p; 811c22e650eSGrant Likely } 812c22e650eSGrant Likely 813c22e650eSGrant Likely /* Step down the tree matching path components */ 814c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags); 815c22e650eSGrant Likely if (!np) 8165063e25aSGrant Likely np = of_node_get(of_root); 817c22e650eSGrant Likely while (np && *path == '/') { 818c22e650eSGrant Likely path++; /* Increment past '/' delimiter */ 819c22e650eSGrant Likely np = __of_find_node_by_path(np, path); 820c22e650eSGrant Likely path = strchrnul(path, '/'); 821106937e8SLeif Lindholm if (separator && separator < path) 822106937e8SLeif Lindholm break; 823c22e650eSGrant Likely } 824d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8251ef4d424SStephen Rothwell return np; 8261ef4d424SStephen Rothwell } 82775c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path); 8281ef4d424SStephen Rothwell 8291ef4d424SStephen Rothwell /** 8301ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 8311ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8321ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8331ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8341ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8351ef4d424SStephen Rothwell * @name: The name string to match against 8361ef4d424SStephen Rothwell * 8371ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8381ef4d424SStephen Rothwell * of_node_put() on it when done. 8391ef4d424SStephen Rothwell */ 8401ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 8411ef4d424SStephen Rothwell const char *name) 8421ef4d424SStephen Rothwell { 8431ef4d424SStephen Rothwell struct device_node *np; 844d6d3c4e6SThomas Gleixner unsigned long flags; 8451ef4d424SStephen Rothwell 846d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8475063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8481ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 8491ef4d424SStephen Rothwell && of_node_get(np)) 8501ef4d424SStephen Rothwell break; 8511ef4d424SStephen Rothwell of_node_put(from); 852d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8531ef4d424SStephen Rothwell return np; 8541ef4d424SStephen Rothwell } 8551ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 8561ef4d424SStephen Rothwell 8571ef4d424SStephen Rothwell /** 8581ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 8591ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 8601ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 8611ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 8621ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 8631ef4d424SStephen Rothwell * called on from for you. 8641ef4d424SStephen Rothwell * @type: The type string to match against 8651ef4d424SStephen Rothwell * 8661ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8671ef4d424SStephen Rothwell * of_node_put() on it when done. 8681ef4d424SStephen Rothwell */ 8691ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 8701ef4d424SStephen Rothwell const char *type) 8711ef4d424SStephen Rothwell { 8721ef4d424SStephen Rothwell struct device_node *np; 873d6d3c4e6SThomas Gleixner unsigned long flags; 8741ef4d424SStephen Rothwell 875d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8765063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8771ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 8781ef4d424SStephen Rothwell && of_node_get(np)) 8791ef4d424SStephen Rothwell break; 8801ef4d424SStephen Rothwell of_node_put(from); 881d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8821ef4d424SStephen Rothwell return np; 8831ef4d424SStephen Rothwell } 8841ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 8851ef4d424SStephen Rothwell 8861ef4d424SStephen Rothwell /** 8871ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 8881ef4d424SStephen Rothwell * tokens in its "compatible" property 8891ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8901ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8911ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8921ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8931ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 8941ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 8951ef4d424SStephen Rothwell * "compatible" list. 8961ef4d424SStephen Rothwell * 8971ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8981ef4d424SStephen Rothwell * of_node_put() on it when done. 8991ef4d424SStephen Rothwell */ 9001ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 9011ef4d424SStephen Rothwell const char *type, const char *compatible) 9021ef4d424SStephen Rothwell { 9031ef4d424SStephen Rothwell struct device_node *np; 904d6d3c4e6SThomas Gleixner unsigned long flags; 9051ef4d424SStephen Rothwell 906d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9075063e25aSGrant Likely for_each_of_allnodes_from(from, np) 908215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) && 90928d0e36bSThomas Gleixner of_node_get(np)) 9101ef4d424SStephen Rothwell break; 9111ef4d424SStephen Rothwell of_node_put(from); 912d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9131ef4d424SStephen Rothwell return np; 9141ef4d424SStephen Rothwell } 9151ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 916283029d1SGrant Likely 917283029d1SGrant Likely /** 9181e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 9191e291b14SMichael Ellerman * the given name. 9201e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 9211e291b14SMichael Ellerman * you pass will not be searched, only the next one 9221e291b14SMichael Ellerman * will; typically, you pass what the previous call 9231e291b14SMichael Ellerman * returned. of_node_put() will be called on it 9241e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 9251e291b14SMichael Ellerman * 9261e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 9271e291b14SMichael Ellerman * of_node_put() on it when done. 9281e291b14SMichael Ellerman */ 9291e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 9301e291b14SMichael Ellerman const char *prop_name) 9311e291b14SMichael Ellerman { 9321e291b14SMichael Ellerman struct device_node *np; 9331e291b14SMichael Ellerman struct property *pp; 934d6d3c4e6SThomas Gleixner unsigned long flags; 9351e291b14SMichael Ellerman 936d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9375063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 938a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 9391e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 9401e291b14SMichael Ellerman of_node_get(np); 9411e291b14SMichael Ellerman goto out; 9421e291b14SMichael Ellerman } 9431e291b14SMichael Ellerman } 9441e291b14SMichael Ellerman } 9451e291b14SMichael Ellerman out: 9461e291b14SMichael Ellerman of_node_put(from); 947d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9481e291b14SMichael Ellerman return np; 9491e291b14SMichael Ellerman } 9501e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 9511e291b14SMichael Ellerman 95228d0e36bSThomas Gleixner static 95328d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 954283029d1SGrant Likely const struct device_node *node) 955283029d1SGrant Likely { 956215a14cfSKevin Hao const struct of_device_id *best_match = NULL; 957215a14cfSKevin Hao int score, best_score = 0; 958215a14cfSKevin Hao 959a52f07ecSGrant Likely if (!matches) 960a52f07ecSGrant Likely return NULL; 961a52f07ecSGrant Likely 962215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { 963215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible, 964215a14cfSKevin Hao matches->type, matches->name); 965215a14cfSKevin Hao if (score > best_score) { 966215a14cfSKevin Hao best_match = matches; 967215a14cfSKevin Hao best_score = score; 968283029d1SGrant Likely } 969215a14cfSKevin Hao } 970215a14cfSKevin Hao 971215a14cfSKevin Hao return best_match; 972283029d1SGrant Likely } 97328d0e36bSThomas Gleixner 97428d0e36bSThomas Gleixner /** 975c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure 97628d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 97728d0e36bSThomas Gleixner * @node: the of device structure to match against 97828d0e36bSThomas Gleixner * 97971c5498eSKevin Hao * Low level utility function used by device matching. 98028d0e36bSThomas Gleixner */ 98128d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 98228d0e36bSThomas Gleixner const struct device_node *node) 98328d0e36bSThomas Gleixner { 98428d0e36bSThomas Gleixner const struct of_device_id *match; 985d6d3c4e6SThomas Gleixner unsigned long flags; 98628d0e36bSThomas Gleixner 987d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 98828d0e36bSThomas Gleixner match = __of_match_node(matches, node); 989d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 99028d0e36bSThomas Gleixner return match; 99128d0e36bSThomas Gleixner } 992283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 993283029d1SGrant Likely 994283029d1SGrant Likely /** 99550c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 99650c8af4cSStephen Warren * match table. 997283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 998283029d1SGrant Likely * you pass will not be searched, only the next one 999283029d1SGrant Likely * will; typically, you pass what the previous call 1000283029d1SGrant Likely * returned. of_node_put() will be called on it 1001283029d1SGrant Likely * @matches: array of of device match structures to search in 100250c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 1003283029d1SGrant Likely * 1004283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 1005283029d1SGrant Likely * of_node_put() on it when done. 1006283029d1SGrant Likely */ 100750c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 100850c8af4cSStephen Warren const struct of_device_id *matches, 100950c8af4cSStephen Warren const struct of_device_id **match) 1010283029d1SGrant Likely { 1011283029d1SGrant Likely struct device_node *np; 1012dc71bcf1SThomas Abraham const struct of_device_id *m; 1013d6d3c4e6SThomas Gleixner unsigned long flags; 1014283029d1SGrant Likely 101550c8af4cSStephen Warren if (match) 101650c8af4cSStephen Warren *match = NULL; 101750c8af4cSStephen Warren 1018d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 10195063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 102028d0e36bSThomas Gleixner m = __of_match_node(matches, np); 1021dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 102250c8af4cSStephen Warren if (match) 1023dc71bcf1SThomas Abraham *match = m; 1024283029d1SGrant Likely break; 1025283029d1SGrant Likely } 102650c8af4cSStephen Warren } 1027283029d1SGrant Likely of_node_put(from); 1028d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1029283029d1SGrant Likely return np; 1030283029d1SGrant Likely } 103180c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 10323f07af49SGrant Likely 10333f07af49SGrant Likely /** 10343f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 10353f07af49SGrant Likely * @node: pointer to a device tree node 10363f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 10373f07af49SGrant Likely * @len: Length of modalias value 10383f07af49SGrant Likely * 10392ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 10402ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 10412ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 10422ffe8c5fSGrant Likely * from the first entry in the compatible list property. 10433f07af49SGrant Likely * 10442ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 10453f07af49SGrant Likely */ 10463f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 10473f07af49SGrant Likely { 10482ffe8c5fSGrant Likely const char *compatible, *p; 10492ffe8c5fSGrant Likely int cplen; 10503f07af49SGrant Likely 10513f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 10522ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 10533f07af49SGrant Likely return -ENODEV; 10543f07af49SGrant Likely p = strchr(compatible, ','); 10552ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 10563f07af49SGrant Likely return 0; 10573f07af49SGrant Likely } 10583f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 10593f07af49SGrant Likely 106064b60e09SAnton Vorontsov /** 106189751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 106289751a7cSJeremy Kerr * @handle: phandle of the node to find 106389751a7cSJeremy Kerr * 106489751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 106589751a7cSJeremy Kerr * of_node_put() on it when done. 106689751a7cSJeremy Kerr */ 106789751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 106889751a7cSJeremy Kerr { 106989751a7cSJeremy Kerr struct device_node *np; 1070d25d8694SBenjamin Herrenschmidt unsigned long flags; 107189751a7cSJeremy Kerr 1072fc59b447SGrant Likely if (!handle) 1073fc59b447SGrant Likely return NULL; 1074fc59b447SGrant Likely 1075d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 10765063e25aSGrant Likely for_each_of_allnodes(np) 107789751a7cSJeremy Kerr if (np->phandle == handle) 107889751a7cSJeremy Kerr break; 107989751a7cSJeremy Kerr of_node_get(np); 1080d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 108189751a7cSJeremy Kerr return np; 108289751a7cSJeremy Kerr } 108389751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 108489751a7cSJeremy Kerr 108589751a7cSJeremy Kerr /** 1086ad54a0cfSHeiko Stuebner * of_property_count_elems_of_size - Count the number of elements in a property 1087ad54a0cfSHeiko Stuebner * 1088ad54a0cfSHeiko Stuebner * @np: device node from which the property value is to be read. 1089ad54a0cfSHeiko Stuebner * @propname: name of the property to be searched. 1090ad54a0cfSHeiko Stuebner * @elem_size: size of the individual element 1091ad54a0cfSHeiko Stuebner * 1092ad54a0cfSHeiko Stuebner * Search for a property in a device node and count the number of elements of 1093ad54a0cfSHeiko Stuebner * size elem_size in it. Returns number of elements on sucess, -EINVAL if the 1094ad54a0cfSHeiko Stuebner * property does not exist or its length does not match a multiple of elem_size 1095ad54a0cfSHeiko Stuebner * and -ENODATA if the property does not have a value. 1096ad54a0cfSHeiko Stuebner */ 1097ad54a0cfSHeiko Stuebner int of_property_count_elems_of_size(const struct device_node *np, 1098ad54a0cfSHeiko Stuebner const char *propname, int elem_size) 1099ad54a0cfSHeiko Stuebner { 1100ad54a0cfSHeiko Stuebner struct property *prop = of_find_property(np, propname, NULL); 1101ad54a0cfSHeiko Stuebner 1102ad54a0cfSHeiko Stuebner if (!prop) 1103ad54a0cfSHeiko Stuebner return -EINVAL; 1104ad54a0cfSHeiko Stuebner if (!prop->value) 1105ad54a0cfSHeiko Stuebner return -ENODATA; 1106ad54a0cfSHeiko Stuebner 1107ad54a0cfSHeiko Stuebner if (prop->length % elem_size != 0) { 1108ad54a0cfSHeiko Stuebner pr_err("size of %s in node %s is not a multiple of %d\n", 1109ad54a0cfSHeiko Stuebner propname, np->full_name, elem_size); 1110ad54a0cfSHeiko Stuebner return -EINVAL; 1111ad54a0cfSHeiko Stuebner } 1112ad54a0cfSHeiko Stuebner 1113ad54a0cfSHeiko Stuebner return prop->length / elem_size; 1114ad54a0cfSHeiko Stuebner } 1115ad54a0cfSHeiko Stuebner EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); 1116ad54a0cfSHeiko Stuebner 1117ad54a0cfSHeiko Stuebner /** 1118daeec1f0STony Prisk * of_find_property_value_of_size 1119daeec1f0STony Prisk * 1120daeec1f0STony Prisk * @np: device node from which the property value is to be read. 1121daeec1f0STony Prisk * @propname: name of the property to be searched. 1122daeec1f0STony Prisk * @len: requested length of property value 1123daeec1f0STony Prisk * 1124daeec1f0STony Prisk * Search for a property in a device node and valid the requested size. 1125daeec1f0STony Prisk * Returns the property value on success, -EINVAL if the property does not 1126daeec1f0STony Prisk * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 1127daeec1f0STony Prisk * property data isn't large enough. 1128daeec1f0STony Prisk * 1129daeec1f0STony Prisk */ 1130daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np, 1131daeec1f0STony Prisk const char *propname, u32 len) 1132daeec1f0STony Prisk { 1133daeec1f0STony Prisk struct property *prop = of_find_property(np, propname, NULL); 1134daeec1f0STony Prisk 1135daeec1f0STony Prisk if (!prop) 1136daeec1f0STony Prisk return ERR_PTR(-EINVAL); 1137daeec1f0STony Prisk if (!prop->value) 1138daeec1f0STony Prisk return ERR_PTR(-ENODATA); 1139daeec1f0STony Prisk if (len > prop->length) 1140daeec1f0STony Prisk return ERR_PTR(-EOVERFLOW); 1141daeec1f0STony Prisk 1142daeec1f0STony Prisk return prop->value; 1143daeec1f0STony Prisk } 1144daeec1f0STony Prisk 1145daeec1f0STony Prisk /** 11463daf3726STony Prisk * of_property_read_u32_index - Find and read a u32 from a multi-value property. 11473daf3726STony Prisk * 11483daf3726STony Prisk * @np: device node from which the property value is to be read. 11493daf3726STony Prisk * @propname: name of the property to be searched. 11503daf3726STony Prisk * @index: index of the u32 in the list of values 11513daf3726STony Prisk * @out_value: pointer to return value, modified only if no error. 11523daf3726STony Prisk * 11533daf3726STony Prisk * Search for a property in a device node and read nth 32-bit value from 11543daf3726STony Prisk * it. Returns 0 on success, -EINVAL if the property does not exist, 11553daf3726STony Prisk * -ENODATA if property does not have a value, and -EOVERFLOW if the 11563daf3726STony Prisk * property data isn't large enough. 11573daf3726STony Prisk * 11583daf3726STony Prisk * The out_value is modified only if a valid u32 value can be decoded. 11593daf3726STony Prisk */ 11603daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np, 11613daf3726STony Prisk const char *propname, 11623daf3726STony Prisk u32 index, u32 *out_value) 11633daf3726STony Prisk { 1164daeec1f0STony Prisk const u32 *val = of_find_property_value_of_size(np, propname, 1165daeec1f0STony Prisk ((index + 1) * sizeof(*out_value))); 11663daf3726STony Prisk 1167daeec1f0STony Prisk if (IS_ERR(val)) 1168daeec1f0STony Prisk return PTR_ERR(val); 11693daf3726STony Prisk 1170daeec1f0STony Prisk *out_value = be32_to_cpup(((__be32 *)val) + index); 11713daf3726STony Prisk return 0; 11723daf3726STony Prisk } 11733daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index); 11743daf3726STony Prisk 11753daf3726STony Prisk /** 1176be193249SViresh Kumar * of_property_read_u8_array - Find and read an array of u8 from a property. 1177be193249SViresh Kumar * 1178be193249SViresh Kumar * @np: device node from which the property value is to be read. 1179be193249SViresh Kumar * @propname: name of the property to be searched. 1180792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1181be193249SViresh Kumar * @sz: number of array elements to read 1182be193249SViresh Kumar * 1183be193249SViresh Kumar * Search for a property in a device node and read 8-bit value(s) from 1184be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 1185be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 1186be193249SViresh Kumar * property data isn't large enough. 1187be193249SViresh Kumar * 1188be193249SViresh Kumar * dts entry of array should be like: 1189be193249SViresh Kumar * property = /bits/ 8 <0x50 0x60 0x70>; 1190be193249SViresh Kumar * 1191792efb84SLad, Prabhakar * The out_values is modified only if a valid u8 value can be decoded. 1192be193249SViresh Kumar */ 1193be193249SViresh Kumar int of_property_read_u8_array(const struct device_node *np, 1194be193249SViresh Kumar const char *propname, u8 *out_values, size_t sz) 1195be193249SViresh Kumar { 1196daeec1f0STony Prisk const u8 *val = of_find_property_value_of_size(np, propname, 1197daeec1f0STony Prisk (sz * sizeof(*out_values))); 1198be193249SViresh Kumar 1199daeec1f0STony Prisk if (IS_ERR(val)) 1200daeec1f0STony Prisk return PTR_ERR(val); 1201be193249SViresh Kumar 1202be193249SViresh Kumar while (sz--) 1203be193249SViresh Kumar *out_values++ = *val++; 1204be193249SViresh Kumar return 0; 1205be193249SViresh Kumar } 1206be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u8_array); 1207be193249SViresh Kumar 1208be193249SViresh Kumar /** 1209be193249SViresh Kumar * of_property_read_u16_array - Find and read an array of u16 from a property. 1210be193249SViresh Kumar * 1211be193249SViresh Kumar * @np: device node from which the property value is to be read. 1212be193249SViresh Kumar * @propname: name of the property to be searched. 1213792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1214be193249SViresh Kumar * @sz: number of array elements to read 1215be193249SViresh Kumar * 1216be193249SViresh Kumar * Search for a property in a device node and read 16-bit value(s) from 1217be193249SViresh Kumar * it. Returns 0 on success, -EINVAL if the property does not exist, 1218be193249SViresh Kumar * -ENODATA if property does not have a value, and -EOVERFLOW if the 1219be193249SViresh Kumar * property data isn't large enough. 1220be193249SViresh Kumar * 1221be193249SViresh Kumar * dts entry of array should be like: 1222be193249SViresh Kumar * property = /bits/ 16 <0x5000 0x6000 0x7000>; 1223be193249SViresh Kumar * 1224792efb84SLad, Prabhakar * The out_values is modified only if a valid u16 value can be decoded. 1225be193249SViresh Kumar */ 1226be193249SViresh Kumar int of_property_read_u16_array(const struct device_node *np, 1227be193249SViresh Kumar const char *propname, u16 *out_values, size_t sz) 1228be193249SViresh Kumar { 1229daeec1f0STony Prisk const __be16 *val = of_find_property_value_of_size(np, propname, 1230daeec1f0STony Prisk (sz * sizeof(*out_values))); 1231be193249SViresh Kumar 1232daeec1f0STony Prisk if (IS_ERR(val)) 1233daeec1f0STony Prisk return PTR_ERR(val); 1234be193249SViresh Kumar 1235be193249SViresh Kumar while (sz--) 1236be193249SViresh Kumar *out_values++ = be16_to_cpup(val++); 1237be193249SViresh Kumar return 0; 1238be193249SViresh Kumar } 1239be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u16_array); 1240be193249SViresh Kumar 1241be193249SViresh Kumar /** 12420e373639SRob Herring * of_property_read_u32_array - Find and read an array of 32 bit integers 12430e373639SRob Herring * from a property. 12440e373639SRob Herring * 1245a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1246a3b85363SThomas Abraham * @propname: name of the property to be searched. 1247792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1248be193249SViresh Kumar * @sz: number of array elements to read 1249a3b85363SThomas Abraham * 12500e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 1251a3b85363SThomas Abraham * it. Returns 0 on success, -EINVAL if the property does not exist, 1252a3b85363SThomas Abraham * -ENODATA if property does not have a value, and -EOVERFLOW if the 1253a3b85363SThomas Abraham * property data isn't large enough. 1254a3b85363SThomas Abraham * 1255792efb84SLad, Prabhakar * The out_values is modified only if a valid u32 value can be decoded. 1256a3b85363SThomas Abraham */ 1257aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np, 1258aac285c6SJamie Iles const char *propname, u32 *out_values, 1259aac285c6SJamie Iles size_t sz) 1260a3b85363SThomas Abraham { 1261daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1262daeec1f0STony Prisk (sz * sizeof(*out_values))); 1263a3b85363SThomas Abraham 1264daeec1f0STony Prisk if (IS_ERR(val)) 1265daeec1f0STony Prisk return PTR_ERR(val); 12660e373639SRob Herring 12670e373639SRob Herring while (sz--) 12680e373639SRob Herring *out_values++ = be32_to_cpup(val++); 1269a3b85363SThomas Abraham return 0; 1270a3b85363SThomas Abraham } 12710e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array); 1272a3b85363SThomas Abraham 1273a3b85363SThomas Abraham /** 12744cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 12754cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 12764cd7f7a3SJamie Iles * @propname: name of the property to be searched. 12774cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 12784cd7f7a3SJamie Iles * 12794cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 12804cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 12814cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 12824cd7f7a3SJamie Iles * property data isn't large enough. 12834cd7f7a3SJamie Iles * 12844cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 12854cd7f7a3SJamie Iles */ 12864cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 12874cd7f7a3SJamie Iles u64 *out_value) 12884cd7f7a3SJamie Iles { 1289daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1290daeec1f0STony Prisk sizeof(*out_value)); 12914cd7f7a3SJamie Iles 1292daeec1f0STony Prisk if (IS_ERR(val)) 1293daeec1f0STony Prisk return PTR_ERR(val); 1294daeec1f0STony Prisk 1295daeec1f0STony Prisk *out_value = of_read_number(val, 2); 12964cd7f7a3SJamie Iles return 0; 12974cd7f7a3SJamie Iles } 12984cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 12994cd7f7a3SJamie Iles 13004cd7f7a3SJamie Iles /** 1301b31384faSRafael J. Wysocki * of_property_read_u64_array - Find and read an array of 64 bit integers 1302b31384faSRafael J. Wysocki * from a property. 1303b31384faSRafael J. Wysocki * 1304b31384faSRafael J. Wysocki * @np: device node from which the property value is to be read. 1305b31384faSRafael J. Wysocki * @propname: name of the property to be searched. 1306b31384faSRafael J. Wysocki * @out_values: pointer to return value, modified only if return value is 0. 1307b31384faSRafael J. Wysocki * @sz: number of array elements to read 1308b31384faSRafael J. Wysocki * 1309b31384faSRafael J. Wysocki * Search for a property in a device node and read 64-bit value(s) from 1310b31384faSRafael J. Wysocki * it. Returns 0 on success, -EINVAL if the property does not exist, 1311b31384faSRafael J. Wysocki * -ENODATA if property does not have a value, and -EOVERFLOW if the 1312b31384faSRafael J. Wysocki * property data isn't large enough. 1313b31384faSRafael J. Wysocki * 1314b31384faSRafael J. Wysocki * The out_values is modified only if a valid u64 value can be decoded. 1315b31384faSRafael J. Wysocki */ 1316b31384faSRafael J. Wysocki int of_property_read_u64_array(const struct device_node *np, 1317b31384faSRafael J. Wysocki const char *propname, u64 *out_values, 1318b31384faSRafael J. Wysocki size_t sz) 1319b31384faSRafael J. Wysocki { 1320b31384faSRafael J. Wysocki const __be32 *val = of_find_property_value_of_size(np, propname, 1321b31384faSRafael J. Wysocki (sz * sizeof(*out_values))); 1322b31384faSRafael J. Wysocki 1323b31384faSRafael J. Wysocki if (IS_ERR(val)) 1324b31384faSRafael J. Wysocki return PTR_ERR(val); 1325b31384faSRafael J. Wysocki 1326b31384faSRafael J. Wysocki while (sz--) { 1327b31384faSRafael J. Wysocki *out_values++ = of_read_number(val, 2); 1328b31384faSRafael J. Wysocki val += 2; 1329b31384faSRafael J. Wysocki } 1330b31384faSRafael J. Wysocki return 0; 1331b31384faSRafael J. Wysocki } 13322d4c0aefSSakari Ailus EXPORT_SYMBOL_GPL(of_property_read_u64_array); 1333b31384faSRafael J. Wysocki 1334b31384faSRafael J. Wysocki /** 1335a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 1336a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1337a3b85363SThomas Abraham * @propname: name of the property to be searched. 1338a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 1339a3b85363SThomas Abraham * return value is 0. 1340a3b85363SThomas Abraham * 1341a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 1342a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 1343a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 1344a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 1345a3b85363SThomas Abraham * within the length of the property data. 1346a3b85363SThomas Abraham * 1347a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 1348a3b85363SThomas Abraham */ 1349aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname, 1350f09bc831SShawn Guo const char **out_string) 1351a3b85363SThomas Abraham { 1352a3b85363SThomas Abraham struct property *prop = of_find_property(np, propname, NULL); 1353a3b85363SThomas Abraham if (!prop) 1354a3b85363SThomas Abraham return -EINVAL; 1355a3b85363SThomas Abraham if (!prop->value) 1356a3b85363SThomas Abraham return -ENODATA; 1357a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 1358a3b85363SThomas Abraham return -EILSEQ; 1359a3b85363SThomas Abraham *out_string = prop->value; 1360a3b85363SThomas Abraham return 0; 1361a3b85363SThomas Abraham } 1362a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 1363a3b85363SThomas Abraham 1364a3b85363SThomas Abraham /** 13657aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 13667aff0fe3SGrant Likely * @np: pointer to node containing string list property 13677aff0fe3SGrant Likely * @propname: string list property name 13687aff0fe3SGrant Likely * @string: pointer to string to search for in string list 13697aff0fe3SGrant Likely * 13707aff0fe3SGrant Likely * This function searches a string list property and returns the index 13717aff0fe3SGrant Likely * of a specific string value. 13727aff0fe3SGrant Likely */ 13737aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname, 13747aff0fe3SGrant Likely const char *string) 13757aff0fe3SGrant Likely { 13767aff0fe3SGrant Likely struct property *prop = of_find_property(np, propname, NULL); 13777aff0fe3SGrant Likely size_t l; 13787aff0fe3SGrant Likely int i; 13797aff0fe3SGrant Likely const char *p, *end; 13807aff0fe3SGrant Likely 13817aff0fe3SGrant Likely if (!prop) 13827aff0fe3SGrant Likely return -EINVAL; 13837aff0fe3SGrant Likely if (!prop->value) 13847aff0fe3SGrant Likely return -ENODATA; 13857aff0fe3SGrant Likely 13867aff0fe3SGrant Likely p = prop->value; 13877aff0fe3SGrant Likely end = p + prop->length; 13887aff0fe3SGrant Likely 13897aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 1390a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 13917aff0fe3SGrant Likely if (p + l > end) 13927aff0fe3SGrant Likely return -EILSEQ; 13937aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 13947aff0fe3SGrant Likely if (strcmp(string, p) == 0) 13957aff0fe3SGrant Likely return i; /* Found it; return index */ 13967aff0fe3SGrant Likely } 13977aff0fe3SGrant Likely return -ENODATA; 13987aff0fe3SGrant Likely } 13997aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 14004fcd15a0SBenoit Cousson 14014fcd15a0SBenoit Cousson /** 1402e99010edSJiri Slaby * of_property_read_string_helper() - Utility helper for parsing string properties 14034fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 14044fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 1405a87fa1d8SGrant Likely * @out_strs: output array of string pointers. 1406a87fa1d8SGrant Likely * @sz: number of array elements to read. 1407a87fa1d8SGrant Likely * @skip: Number of strings to skip over at beginning of list. 14084fcd15a0SBenoit Cousson * 1409a87fa1d8SGrant Likely * Don't call this function directly. It is a utility helper for the 1410a87fa1d8SGrant Likely * of_property_read_string*() family of functions. 14114fcd15a0SBenoit Cousson */ 1412a87fa1d8SGrant Likely int of_property_read_string_helper(struct device_node *np, const char *propname, 1413a87fa1d8SGrant Likely const char **out_strs, size_t sz, int skip) 14144fcd15a0SBenoit Cousson { 14154fcd15a0SBenoit Cousson struct property *prop = of_find_property(np, propname, NULL); 1416a87fa1d8SGrant Likely int l = 0, i = 0; 1417a87fa1d8SGrant Likely const char *p, *end; 14184fcd15a0SBenoit Cousson 14194fcd15a0SBenoit Cousson if (!prop) 14204fcd15a0SBenoit Cousson return -EINVAL; 14214fcd15a0SBenoit Cousson if (!prop->value) 14224fcd15a0SBenoit Cousson return -ENODATA; 14234fcd15a0SBenoit Cousson p = prop->value; 1424a87fa1d8SGrant Likely end = p + prop->length; 14254fcd15a0SBenoit Cousson 1426a87fa1d8SGrant Likely for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 1427a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 1428a87fa1d8SGrant Likely if (p + l > end) 1429a87fa1d8SGrant Likely return -EILSEQ; 1430a87fa1d8SGrant Likely if (out_strs && i >= skip) 1431a87fa1d8SGrant Likely *out_strs++ = p; 14324fcd15a0SBenoit Cousson } 1433a87fa1d8SGrant Likely i -= skip; 1434a87fa1d8SGrant Likely return i <= 0 ? -ENODATA : i; 1435a87fa1d8SGrant Likely } 1436a87fa1d8SGrant Likely EXPORT_SYMBOL_GPL(of_property_read_string_helper); 14374fcd15a0SBenoit Cousson 1438624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1439624cfca5SGrant Likely { 1440624cfca5SGrant Likely int i; 1441624cfca5SGrant Likely printk("%s %s", msg, of_node_full_name(args->np)); 1442624cfca5SGrant Likely for (i = 0; i < args->args_count; i++) 1443624cfca5SGrant Likely printk(i ? ",%08x" : ":%08x", args->args[i]); 1444624cfca5SGrant Likely printk("\n"); 1445624cfca5SGrant Likely } 1446624cfca5SGrant Likely 1447bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1448bd69f73fSGrant Likely const char *list_name, 1449035fd948SStephen Warren const char *cells_name, 1450035fd948SStephen Warren int cell_count, int index, 145115c9a0acSGrant Likely struct of_phandle_args *out_args) 145264b60e09SAnton Vorontsov { 145315c9a0acSGrant Likely const __be32 *list, *list_end; 145423ce04c0SGrant Likely int rc = 0, size, cur_index = 0; 145515c9a0acSGrant Likely uint32_t count = 0; 145664b60e09SAnton Vorontsov struct device_node *node = NULL; 14579a6b2e58SGrant Likely phandle phandle; 145864b60e09SAnton Vorontsov 145915c9a0acSGrant Likely /* Retrieve the phandle list property */ 146015c9a0acSGrant Likely list = of_get_property(np, list_name, &size); 146115c9a0acSGrant Likely if (!list) 14621af4c7f1SAlexandre Courbot return -ENOENT; 146315c9a0acSGrant Likely list_end = list + size / sizeof(*list); 146415c9a0acSGrant Likely 146515c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 146615c9a0acSGrant Likely while (list < list_end) { 146723ce04c0SGrant Likely rc = -EINVAL; 146815c9a0acSGrant Likely count = 0; 146915c9a0acSGrant Likely 147015c9a0acSGrant Likely /* 147115c9a0acSGrant Likely * If phandle is 0, then it is an empty entry with no 147215c9a0acSGrant Likely * arguments. Skip forward to the next entry. 147315c9a0acSGrant Likely */ 14749a6b2e58SGrant Likely phandle = be32_to_cpup(list++); 147515c9a0acSGrant Likely if (phandle) { 147615c9a0acSGrant Likely /* 147715c9a0acSGrant Likely * Find the provider node and parse the #*-cells 147891d9942cSStephen Warren * property to determine the argument length. 147991d9942cSStephen Warren * 148091d9942cSStephen Warren * This is not needed if the cell count is hard-coded 148191d9942cSStephen Warren * (i.e. cells_name not set, but cell_count is set), 148291d9942cSStephen Warren * except when we're going to return the found node 148391d9942cSStephen Warren * below. 148415c9a0acSGrant Likely */ 148591d9942cSStephen Warren if (cells_name || cur_index == index) { 14869a6b2e58SGrant Likely node = of_find_node_by_phandle(phandle); 148764b60e09SAnton Vorontsov if (!node) { 148815c9a0acSGrant Likely pr_err("%s: could not find phandle\n", 148964b60e09SAnton Vorontsov np->full_name); 149023ce04c0SGrant Likely goto err; 149115c9a0acSGrant Likely } 149291d9942cSStephen Warren } 1493035fd948SStephen Warren 1494035fd948SStephen Warren if (cells_name) { 1495035fd948SStephen Warren if (of_property_read_u32(node, cells_name, 1496035fd948SStephen Warren &count)) { 149715c9a0acSGrant Likely pr_err("%s: could not get %s for %s\n", 149815c9a0acSGrant Likely np->full_name, cells_name, 149915c9a0acSGrant Likely node->full_name); 150023ce04c0SGrant Likely goto err; 150115c9a0acSGrant Likely } 1502035fd948SStephen Warren } else { 1503035fd948SStephen Warren count = cell_count; 1504035fd948SStephen Warren } 150515c9a0acSGrant Likely 150615c9a0acSGrant Likely /* 150715c9a0acSGrant Likely * Make sure that the arguments actually fit in the 150815c9a0acSGrant Likely * remaining property data length 150915c9a0acSGrant Likely */ 151015c9a0acSGrant Likely if (list + count > list_end) { 151115c9a0acSGrant Likely pr_err("%s: arguments longer than property\n", 151215c9a0acSGrant Likely np->full_name); 151323ce04c0SGrant Likely goto err; 151415c9a0acSGrant Likely } 151515c9a0acSGrant Likely } 151615c9a0acSGrant Likely 151715c9a0acSGrant Likely /* 151815c9a0acSGrant Likely * All of the error cases above bail out of the loop, so at 151915c9a0acSGrant Likely * this point, the parsing is successful. If the requested 152015c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 152115c9a0acSGrant Likely * or return -ENOENT for an empty entry. 152215c9a0acSGrant Likely */ 152323ce04c0SGrant Likely rc = -ENOENT; 152415c9a0acSGrant Likely if (cur_index == index) { 152515c9a0acSGrant Likely if (!phandle) 152623ce04c0SGrant Likely goto err; 152715c9a0acSGrant Likely 152815c9a0acSGrant Likely if (out_args) { 152915c9a0acSGrant Likely int i; 153015c9a0acSGrant Likely if (WARN_ON(count > MAX_PHANDLE_ARGS)) 153115c9a0acSGrant Likely count = MAX_PHANDLE_ARGS; 153215c9a0acSGrant Likely out_args->np = node; 153315c9a0acSGrant Likely out_args->args_count = count; 153415c9a0acSGrant Likely for (i = 0; i < count; i++) 153515c9a0acSGrant Likely out_args->args[i] = be32_to_cpup(list++); 1536b855f16bSTang Yuantian } else { 1537b855f16bSTang Yuantian of_node_put(node); 153815c9a0acSGrant Likely } 153923ce04c0SGrant Likely 154023ce04c0SGrant Likely /* Found it! return success */ 154115c9a0acSGrant Likely return 0; 154215c9a0acSGrant Likely } 154364b60e09SAnton Vorontsov 154464b60e09SAnton Vorontsov of_node_put(node); 154564b60e09SAnton Vorontsov node = NULL; 154615c9a0acSGrant Likely list += count; 154764b60e09SAnton Vorontsov cur_index++; 154864b60e09SAnton Vorontsov } 154964b60e09SAnton Vorontsov 155023ce04c0SGrant Likely /* 155123ce04c0SGrant Likely * Unlock node before returning result; will be one of: 155223ce04c0SGrant Likely * -ENOENT : index is for empty phandle 155323ce04c0SGrant Likely * -EINVAL : parsing error on data 1554bd69f73fSGrant Likely * [1..n] : Number of phandle (count mode; when index = -1) 155523ce04c0SGrant Likely */ 1556bd69f73fSGrant Likely rc = index < 0 ? cur_index : -ENOENT; 155723ce04c0SGrant Likely err: 155815c9a0acSGrant Likely if (node) 155964b60e09SAnton Vorontsov of_node_put(node); 156023ce04c0SGrant Likely return rc; 156164b60e09SAnton Vorontsov } 1562bd69f73fSGrant Likely 1563eded9dd4SStephen Warren /** 15645fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 15655fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 15665fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 15675fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 15685fba49e3SStephen Warren * the table 15695fba49e3SStephen Warren * 15705fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 15715fba49e3SStephen Warren * of_node_put() on it when done. 15725fba49e3SStephen Warren */ 15735fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 15745fba49e3SStephen Warren const char *phandle_name, int index) 15755fba49e3SStephen Warren { 157691d9942cSStephen Warren struct of_phandle_args args; 15775fba49e3SStephen Warren 157891d9942cSStephen Warren if (index < 0) 15795fba49e3SStephen Warren return NULL; 15805fba49e3SStephen Warren 158191d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 158291d9942cSStephen Warren index, &args)) 158391d9942cSStephen Warren return NULL; 158491d9942cSStephen Warren 158591d9942cSStephen Warren return args.np; 15865fba49e3SStephen Warren } 15875fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 15885fba49e3SStephen Warren 15895fba49e3SStephen Warren /** 1590eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1591eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1592eded9dd4SStephen Warren * @list_name: property name that contains a list 1593eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1594eded9dd4SStephen Warren * @index: index of a phandle to parse out 1595eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1596eded9dd4SStephen Warren * 1597eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1598eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1599eded9dd4SStephen Warren * errno value. 1600eded9dd4SStephen Warren * 1601d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1602eded9dd4SStephen Warren * pointer. 1603eded9dd4SStephen Warren * 1604eded9dd4SStephen Warren * Example: 1605eded9dd4SStephen Warren * 1606eded9dd4SStephen Warren * phandle1: node1 { 1607eded9dd4SStephen Warren * #list-cells = <2>; 1608eded9dd4SStephen Warren * } 1609eded9dd4SStephen Warren * 1610eded9dd4SStephen Warren * phandle2: node2 { 1611eded9dd4SStephen Warren * #list-cells = <1>; 1612eded9dd4SStephen Warren * } 1613eded9dd4SStephen Warren * 1614eded9dd4SStephen Warren * node3 { 1615eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1616eded9dd4SStephen Warren * } 1617eded9dd4SStephen Warren * 1618eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1619eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1620eded9dd4SStephen Warren */ 1621bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1622bd69f73fSGrant Likely const char *cells_name, int index, 1623bd69f73fSGrant Likely struct of_phandle_args *out_args) 1624bd69f73fSGrant Likely { 1625bd69f73fSGrant Likely if (index < 0) 1626bd69f73fSGrant Likely return -EINVAL; 1627035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1628035fd948SStephen Warren index, out_args); 1629bd69f73fSGrant Likely } 163015c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 163102af11b0SGrant Likely 1632bd69f73fSGrant Likely /** 1633035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1634035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1635035fd948SStephen Warren * @list_name: property name that contains a list 1636035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1637035fd948SStephen Warren * @index: index of a phandle to parse out 1638035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1639035fd948SStephen Warren * 1640035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1641035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1642035fd948SStephen Warren * errno value. 1643035fd948SStephen Warren * 1644d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1645035fd948SStephen Warren * pointer. 1646035fd948SStephen Warren * 1647035fd948SStephen Warren * Example: 1648035fd948SStephen Warren * 1649035fd948SStephen Warren * phandle1: node1 { 1650035fd948SStephen Warren * } 1651035fd948SStephen Warren * 1652035fd948SStephen Warren * phandle2: node2 { 1653035fd948SStephen Warren * } 1654035fd948SStephen Warren * 1655035fd948SStephen Warren * node3 { 1656035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1657035fd948SStephen Warren * } 1658035fd948SStephen Warren * 1659035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1660035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1661035fd948SStephen Warren */ 1662035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1663035fd948SStephen Warren const char *list_name, int cell_count, 1664035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1665035fd948SStephen Warren { 1666035fd948SStephen Warren if (index < 0) 1667035fd948SStephen Warren return -EINVAL; 1668035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1669035fd948SStephen Warren index, out_args); 1670035fd948SStephen Warren } 1671035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1672035fd948SStephen Warren 1673035fd948SStephen Warren /** 1674bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1675bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1676bd69f73fSGrant Likely * @list_name: property name that contains a list 1677bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1678bd69f73fSGrant Likely * 1679bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1680bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1681bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1682bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1683bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1684bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1685bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1686bd69f73fSGrant Likely * phandle. 1687bd69f73fSGrant Likely */ 1688bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1689bd69f73fSGrant Likely const char *cells_name) 1690bd69f73fSGrant Likely { 1691035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, -1, 1692035fd948SStephen Warren NULL); 1693bd69f73fSGrant Likely } 1694bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1695bd69f73fSGrant Likely 169602af11b0SGrant Likely /** 169762664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 169862664f67SXiubo Li */ 1699d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop) 170062664f67SXiubo Li { 170162664f67SXiubo Li struct property **next; 170262664f67SXiubo Li 170362664f67SXiubo Li prop->next = NULL; 170462664f67SXiubo Li next = &np->properties; 170562664f67SXiubo Li while (*next) { 170662664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 170762664f67SXiubo Li /* duplicate ! don't insert it */ 170862664f67SXiubo Li return -EEXIST; 170962664f67SXiubo Li 171062664f67SXiubo Li next = &(*next)->next; 171162664f67SXiubo Li } 171262664f67SXiubo Li *next = prop; 171362664f67SXiubo Li 171462664f67SXiubo Li return 0; 171562664f67SXiubo Li } 171662664f67SXiubo Li 171762664f67SXiubo Li /** 171879d1c712SNathan Fontenot * of_add_property - Add a property to a node 171902af11b0SGrant Likely */ 172079d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 172102af11b0SGrant Likely { 172202af11b0SGrant Likely unsigned long flags; 17231cf3d8b3SNathan Fontenot int rc; 17241cf3d8b3SNathan Fontenot 17258a2b22a2SGrant Likely mutex_lock(&of_mutex); 172602af11b0SGrant Likely 1727d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 172862664f67SXiubo Li rc = __of_add_property(np, prop); 1729d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 173002af11b0SGrant Likely 17318a2b22a2SGrant Likely if (!rc) 173275b57ecfSGrant Likely __of_add_property_sysfs(np, prop); 173302af11b0SGrant Likely 17348a2b22a2SGrant Likely mutex_unlock(&of_mutex); 17358a2b22a2SGrant Likely 1736259092a3SGrant Likely if (!rc) 1737259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1738259092a3SGrant Likely 173962664f67SXiubo Li return rc; 174002af11b0SGrant Likely } 174102af11b0SGrant Likely 1742d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop) 1743d8c50088SPantelis Antoniou { 1744d8c50088SPantelis Antoniou struct property **next; 1745d8c50088SPantelis Antoniou 1746d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1747d8c50088SPantelis Antoniou if (*next == prop) 1748d8c50088SPantelis Antoniou break; 1749d8c50088SPantelis Antoniou } 1750d8c50088SPantelis Antoniou if (*next == NULL) 1751d8c50088SPantelis Antoniou return -ENODEV; 1752d8c50088SPantelis Antoniou 1753d8c50088SPantelis Antoniou /* found the node */ 1754d8c50088SPantelis Antoniou *next = prop->next; 1755d8c50088SPantelis Antoniou prop->next = np->deadprops; 1756d8c50088SPantelis Antoniou np->deadprops = prop; 1757d8c50088SPantelis Antoniou 1758d8c50088SPantelis Antoniou return 0; 1759d8c50088SPantelis Antoniou } 1760d8c50088SPantelis Antoniou 17618a2b22a2SGrant Likely void __of_remove_property_sysfs(struct device_node *np, struct property *prop) 17628a2b22a2SGrant Likely { 1763ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1764ef69d740SGaurav Minocha return; 1765ef69d740SGaurav Minocha 17668a2b22a2SGrant Likely /* at early boot, bail here and defer setup to of_init() */ 17678a2b22a2SGrant Likely if (of_kset && of_node_is_attached(np)) 17688a2b22a2SGrant Likely sysfs_remove_bin_file(&np->kobj, &prop->attr); 17698a2b22a2SGrant Likely } 17708a2b22a2SGrant Likely 177102af11b0SGrant Likely /** 177279d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 177302af11b0SGrant Likely * 177402af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 177502af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 177602af11b0SGrant Likely * Instead we just move the property to the "dead properties" 177702af11b0SGrant Likely * list, so it won't be found any more. 177802af11b0SGrant Likely */ 177979d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 178002af11b0SGrant Likely { 178102af11b0SGrant Likely unsigned long flags; 17821cf3d8b3SNathan Fontenot int rc; 17831cf3d8b3SNathan Fontenot 17848a2b22a2SGrant Likely mutex_lock(&of_mutex); 178502af11b0SGrant Likely 1786d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1787d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop); 1788d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 178902af11b0SGrant Likely 17908a2b22a2SGrant Likely if (!rc) 17918a2b22a2SGrant Likely __of_remove_property_sysfs(np, prop); 179202af11b0SGrant Likely 17938a2b22a2SGrant Likely mutex_unlock(&of_mutex); 17948a2b22a2SGrant Likely 1795259092a3SGrant Likely if (!rc) 1796259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1797259092a3SGrant Likely 1798d8c50088SPantelis Antoniou return rc; 179902af11b0SGrant Likely } 180002af11b0SGrant Likely 1801d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop, 1802d8c50088SPantelis Antoniou struct property **oldpropp) 1803d8c50088SPantelis Antoniou { 1804d8c50088SPantelis Antoniou struct property **next, *oldprop; 1805d8c50088SPantelis Antoniou 1806d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1807d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0) 1808d8c50088SPantelis Antoniou break; 1809d8c50088SPantelis Antoniou } 1810d8c50088SPantelis Antoniou *oldpropp = oldprop = *next; 1811d8c50088SPantelis Antoniou 1812d8c50088SPantelis Antoniou if (oldprop) { 1813d8c50088SPantelis Antoniou /* replace the node */ 1814d8c50088SPantelis Antoniou newprop->next = oldprop->next; 1815d8c50088SPantelis Antoniou *next = newprop; 1816d8c50088SPantelis Antoniou oldprop->next = np->deadprops; 1817d8c50088SPantelis Antoniou np->deadprops = oldprop; 1818d8c50088SPantelis Antoniou } else { 1819d8c50088SPantelis Antoniou /* new node */ 1820d8c50088SPantelis Antoniou newprop->next = NULL; 1821d8c50088SPantelis Antoniou *next = newprop; 1822d8c50088SPantelis Antoniou } 1823d8c50088SPantelis Antoniou 1824d8c50088SPantelis Antoniou return 0; 1825d8c50088SPantelis Antoniou } 1826d8c50088SPantelis Antoniou 18278a2b22a2SGrant Likely void __of_update_property_sysfs(struct device_node *np, struct property *newprop, 18288a2b22a2SGrant Likely struct property *oldprop) 18298a2b22a2SGrant Likely { 1830ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1831ef69d740SGaurav Minocha return; 1832ef69d740SGaurav Minocha 18338a2b22a2SGrant Likely /* At early boot, bail out and defer setup to of_init() */ 183402af11b0SGrant Likely if (!of_kset) 18358a2b22a2SGrant Likely return; 183602af11b0SGrant Likely 18378a2b22a2SGrant Likely if (oldprop) 18388a2b22a2SGrant Likely sysfs_remove_bin_file(&np->kobj, &oldprop->attr); 18398a2b22a2SGrant Likely __of_add_property_sysfs(np, newprop); 184002af11b0SGrant Likely } 184102af11b0SGrant Likely 184202af11b0SGrant Likely /* 184379d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1844475d0094SDong Aisheng * not exist, add it. 184502af11b0SGrant Likely * 184602af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 184702af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 184802af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 184902af11b0SGrant Likely * and add the new property to the property list 185002af11b0SGrant Likely */ 185179d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 185202af11b0SGrant Likely { 1853d8c50088SPantelis Antoniou struct property *oldprop; 185402af11b0SGrant Likely unsigned long flags; 1855947fdaadSXiubo Li int rc; 18561cf3d8b3SNathan Fontenot 1857475d0094SDong Aisheng if (!newprop->name) 1858475d0094SDong Aisheng return -EINVAL; 1859475d0094SDong Aisheng 18608a2b22a2SGrant Likely mutex_lock(&of_mutex); 1861fcdeb7feSGrant Likely 1862d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1863d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop); 1864d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1865e81b3295SNathan Fontenot 18668a2b22a2SGrant Likely if (!rc) 18678a2b22a2SGrant Likely __of_update_property_sysfs(np, newprop, oldprop); 1868fcdeb7feSGrant Likely 18698a2b22a2SGrant Likely mutex_unlock(&of_mutex); 18701cf3d8b3SNathan Fontenot 1871259092a3SGrant Likely if (!rc) 1872259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 1873fcdeb7feSGrant Likely 18741cf3d8b3SNathan Fontenot return rc; 1875e81b3295SNathan Fontenot } 1876e81b3295SNathan Fontenot 1877611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1878611cad72SShawn Guo int id, const char *stem, int stem_len) 1879611cad72SShawn Guo { 1880611cad72SShawn Guo ap->np = np; 1881611cad72SShawn Guo ap->id = id; 1882611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1883611cad72SShawn Guo ap->stem[stem_len] = 0; 1884611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 1885611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 188674a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 1887611cad72SShawn Guo } 1888611cad72SShawn Guo 1889611cad72SShawn Guo /** 18901821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node 1891611cad72SShawn Guo * 18921821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates 18931821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the 18941821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure. 1895611cad72SShawn Guo * 1896611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 18971821dda4SGeert Uytterhoeven * for storing the resulting tree 1898611cad72SShawn Guo */ 1899611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1900611cad72SShawn Guo { 1901611cad72SShawn Guo struct property *pp; 1902611cad72SShawn Guo 19037dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases"); 1904611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1905611cad72SShawn Guo if (of_chosen == NULL) 1906611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 19075c19e952SSascha Hauer 19085c19e952SSascha Hauer if (of_chosen) { 1909a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ 1910676e1b2fSGrant Likely const char *name = of_get_property(of_chosen, "stdout-path", NULL); 1911676e1b2fSGrant Likely if (!name) 19125c19e952SSascha Hauer name = of_get_property(of_chosen, "linux,stdout-path", NULL); 1913a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name) 1914a752ee56SGrant Likely name = of_get_property(of_aliases, "stdout", NULL); 1915f64255b5SPeter Hurley if (name) 19167914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); 19175c19e952SSascha Hauer } 19185c19e952SSascha Hauer 1919611cad72SShawn Guo if (!of_aliases) 1920611cad72SShawn Guo return; 1921611cad72SShawn Guo 19228af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1923611cad72SShawn Guo const char *start = pp->name; 1924611cad72SShawn Guo const char *end = start + strlen(start); 1925611cad72SShawn Guo struct device_node *np; 1926611cad72SShawn Guo struct alias_prop *ap; 1927611cad72SShawn Guo int id, len; 1928611cad72SShawn Guo 1929611cad72SShawn Guo /* Skip those we do not want to proceed */ 1930611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1931611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1932611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1933611cad72SShawn Guo continue; 1934611cad72SShawn Guo 1935611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1936611cad72SShawn Guo if (!np) 1937611cad72SShawn Guo continue; 1938611cad72SShawn Guo 1939611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1940611cad72SShawn Guo * the 'stem' string */ 1941611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1942611cad72SShawn Guo end--; 1943611cad72SShawn Guo len = end - start; 1944611cad72SShawn Guo 1945611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1946611cad72SShawn Guo continue; 1947611cad72SShawn Guo 1948611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1949611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 1950611cad72SShawn Guo if (!ap) 1951611cad72SShawn Guo continue; 19520640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1953611cad72SShawn Guo ap->alias = start; 1954611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1955611cad72SShawn Guo } 1956611cad72SShawn Guo } 1957611cad72SShawn Guo 1958611cad72SShawn Guo /** 1959611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1960611cad72SShawn Guo * @np: Pointer to the given device_node 1961611cad72SShawn Guo * @stem: Alias stem of the given device_node 1962611cad72SShawn Guo * 19635a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given 19645a53a07fSGeert Uytterhoeven * device_node and alias stem. It returns the alias id if found. 1965611cad72SShawn Guo */ 1966611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1967611cad72SShawn Guo { 1968611cad72SShawn Guo struct alias_prop *app; 1969611cad72SShawn Guo int id = -ENODEV; 1970611cad72SShawn Guo 1971c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 1972611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1973611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1974611cad72SShawn Guo continue; 1975611cad72SShawn Guo 1976611cad72SShawn Guo if (np == app->np) { 1977611cad72SShawn Guo id = app->id; 1978611cad72SShawn Guo break; 1979611cad72SShawn Guo } 1980611cad72SShawn Guo } 1981c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 1982611cad72SShawn Guo 1983611cad72SShawn Guo return id; 1984611cad72SShawn Guo } 1985611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1986c541adc6SStephen Warren 1987351d224fSWolfram Sang /** 1988351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem 1989351d224fSWolfram Sang * @stem: Alias stem to be examined 1990351d224fSWolfram Sang * 1991351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the 1992351d224fSWolfram Sang * given alias stem. It returns the alias id if found. 1993351d224fSWolfram Sang */ 1994351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem) 1995351d224fSWolfram Sang { 1996351d224fSWolfram Sang struct alias_prop *app; 1997351d224fSWolfram Sang int id = -ENODEV; 1998351d224fSWolfram Sang 1999351d224fSWolfram Sang mutex_lock(&of_mutex); 2000351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) { 2001351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0) 2002351d224fSWolfram Sang continue; 2003351d224fSWolfram Sang 2004351d224fSWolfram Sang if (app->id > id) 2005351d224fSWolfram Sang id = app->id; 2006351d224fSWolfram Sang } 2007351d224fSWolfram Sang mutex_unlock(&of_mutex); 2008351d224fSWolfram Sang 2009351d224fSWolfram Sang return id; 2010351d224fSWolfram Sang } 2011351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id); 2012351d224fSWolfram Sang 2013c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 2014c541adc6SStephen Warren u32 *pu) 2015c541adc6SStephen Warren { 2016c541adc6SStephen Warren const void *curv = cur; 2017c541adc6SStephen Warren 2018c541adc6SStephen Warren if (!prop) 2019c541adc6SStephen Warren return NULL; 2020c541adc6SStephen Warren 2021c541adc6SStephen Warren if (!cur) { 2022c541adc6SStephen Warren curv = prop->value; 2023c541adc6SStephen Warren goto out_val; 2024c541adc6SStephen Warren } 2025c541adc6SStephen Warren 2026c541adc6SStephen Warren curv += sizeof(*cur); 2027c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2028c541adc6SStephen Warren return NULL; 2029c541adc6SStephen Warren 2030c541adc6SStephen Warren out_val: 2031c541adc6SStephen Warren *pu = be32_to_cpup(curv); 2032c541adc6SStephen Warren return curv; 2033c541adc6SStephen Warren } 2034c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 2035c541adc6SStephen Warren 2036c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 2037c541adc6SStephen Warren { 2038c541adc6SStephen Warren const void *curv = cur; 2039c541adc6SStephen Warren 2040c541adc6SStephen Warren if (!prop) 2041c541adc6SStephen Warren return NULL; 2042c541adc6SStephen Warren 2043c541adc6SStephen Warren if (!cur) 2044c541adc6SStephen Warren return prop->value; 2045c541adc6SStephen Warren 2046c541adc6SStephen Warren curv += strlen(cur) + 1; 2047c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2048c541adc6SStephen Warren return NULL; 2049c541adc6SStephen Warren 2050c541adc6SStephen Warren return curv; 2051c541adc6SStephen Warren } 2052c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 20535c19e952SSascha Hauer 20545c19e952SSascha Hauer /** 20553482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup 20563482f2c5SGrant Likely * @dn - Pointer to device node 20573482f2c5SGrant Likely * @name - Name to use for preferred console without index. ex. "ttyS" 20583482f2c5SGrant Likely * @index - Index to use for preferred console. 20595c19e952SSascha Hauer * 20603482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the 20613482f2c5SGrant Likely * /chosen node. If it does then register it as the preferred console and return 20623482f2c5SGrant Likely * TRUE. Otherwise return FALSE. 20635c19e952SSascha Hauer */ 20643482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index) 20655c19e952SSascha Hauer { 20663482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline) 20675c19e952SSascha Hauer return false; 20687914a7c5SLeif Lindholm return !add_preferred_console(name, index, 20697914a7c5SLeif Lindholm kstrdup(of_stdout_options, GFP_KERNEL)); 20705c19e952SSascha Hauer } 20713482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check); 2072a3e31b45SSudeep KarkadaNagesha 2073a3e31b45SSudeep KarkadaNagesha /** 2074a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 2075a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 2076a3e31b45SSudeep KarkadaNagesha * 2077a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 2078a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 2079a3e31b45SSudeep KarkadaNagesha * to np. 2080a3e31b45SSudeep KarkadaNagesha */ 2081a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 2082a3e31b45SSudeep KarkadaNagesha { 2083a3e31b45SSudeep KarkadaNagesha struct device_node *child; 2084a3e31b45SSudeep KarkadaNagesha const phandle *handle; 2085a3e31b45SSudeep KarkadaNagesha 2086a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "l2-cache", NULL); 2087a3e31b45SSudeep KarkadaNagesha if (!handle) 2088a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "next-level-cache", NULL); 2089a3e31b45SSudeep KarkadaNagesha 2090a3e31b45SSudeep KarkadaNagesha if (handle) 2091a3e31b45SSudeep KarkadaNagesha return of_find_node_by_phandle(be32_to_cpup(handle)); 2092a3e31b45SSudeep KarkadaNagesha 2093a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 2094a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 2095a3e31b45SSudeep KarkadaNagesha */ 2096a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 2097a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 2098a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 2099a3e31b45SSudeep KarkadaNagesha return child; 2100a3e31b45SSudeep KarkadaNagesha 2101a3e31b45SSudeep KarkadaNagesha return NULL; 2102a3e31b45SSudeep KarkadaNagesha } 2103fd9fdb78SPhilipp Zabel 2104fd9fdb78SPhilipp Zabel /** 2105f2a575f6SPhilipp Zabel * of_graph_parse_endpoint() - parse common endpoint node properties 2106f2a575f6SPhilipp Zabel * @node: pointer to endpoint device_node 2107f2a575f6SPhilipp Zabel * @endpoint: pointer to the OF endpoint data structure 2108f2a575f6SPhilipp Zabel * 2109f2a575f6SPhilipp Zabel * The caller should hold a reference to @node. 2110f2a575f6SPhilipp Zabel */ 2111f2a575f6SPhilipp Zabel int of_graph_parse_endpoint(const struct device_node *node, 2112f2a575f6SPhilipp Zabel struct of_endpoint *endpoint) 2113f2a575f6SPhilipp Zabel { 2114f2a575f6SPhilipp Zabel struct device_node *port_node = of_get_parent(node); 2115f2a575f6SPhilipp Zabel 2116d484700aSPhilipp Zabel WARN_ONCE(!port_node, "%s(): endpoint %s has no parent node\n", 2117d484700aSPhilipp Zabel __func__, node->full_name); 2118d484700aSPhilipp Zabel 2119f2a575f6SPhilipp Zabel memset(endpoint, 0, sizeof(*endpoint)); 2120f2a575f6SPhilipp Zabel 2121f2a575f6SPhilipp Zabel endpoint->local_node = node; 2122f2a575f6SPhilipp Zabel /* 2123f2a575f6SPhilipp Zabel * It doesn't matter whether the two calls below succeed. 2124f2a575f6SPhilipp Zabel * If they don't then the default value 0 is used. 2125f2a575f6SPhilipp Zabel */ 2126f2a575f6SPhilipp Zabel of_property_read_u32(port_node, "reg", &endpoint->port); 2127f2a575f6SPhilipp Zabel of_property_read_u32(node, "reg", &endpoint->id); 2128f2a575f6SPhilipp Zabel 2129f2a575f6SPhilipp Zabel of_node_put(port_node); 2130f2a575f6SPhilipp Zabel 2131f2a575f6SPhilipp Zabel return 0; 2132f2a575f6SPhilipp Zabel } 2133f2a575f6SPhilipp Zabel EXPORT_SYMBOL(of_graph_parse_endpoint); 2134f2a575f6SPhilipp Zabel 2135f2a575f6SPhilipp Zabel /** 2136bfe446e3SPhilipp Zabel * of_graph_get_port_by_id() - get the port matching a given id 2137bfe446e3SPhilipp Zabel * @parent: pointer to the parent device node 2138bfe446e3SPhilipp Zabel * @id: id of the port 2139bfe446e3SPhilipp Zabel * 2140bfe446e3SPhilipp Zabel * Return: A 'port' node pointer with refcount incremented. The caller 2141bfe446e3SPhilipp Zabel * has to use of_node_put() on it when done. 2142bfe446e3SPhilipp Zabel */ 2143bfe446e3SPhilipp Zabel struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) 2144bfe446e3SPhilipp Zabel { 2145bfe446e3SPhilipp Zabel struct device_node *node, *port; 2146bfe446e3SPhilipp Zabel 2147bfe446e3SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2148bfe446e3SPhilipp Zabel if (node) 2149bfe446e3SPhilipp Zabel parent = node; 2150bfe446e3SPhilipp Zabel 2151bfe446e3SPhilipp Zabel for_each_child_of_node(parent, port) { 2152bfe446e3SPhilipp Zabel u32 port_id = 0; 2153bfe446e3SPhilipp Zabel 2154bfe446e3SPhilipp Zabel if (of_node_cmp(port->name, "port") != 0) 2155bfe446e3SPhilipp Zabel continue; 2156bfe446e3SPhilipp Zabel of_property_read_u32(port, "reg", &port_id); 2157bfe446e3SPhilipp Zabel if (id == port_id) 2158bfe446e3SPhilipp Zabel break; 2159bfe446e3SPhilipp Zabel } 2160bfe446e3SPhilipp Zabel 2161bfe446e3SPhilipp Zabel of_node_put(node); 2162bfe446e3SPhilipp Zabel 2163bfe446e3SPhilipp Zabel return port; 2164bfe446e3SPhilipp Zabel } 2165bfe446e3SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_port_by_id); 2166bfe446e3SPhilipp Zabel 2167bfe446e3SPhilipp Zabel /** 2168fd9fdb78SPhilipp Zabel * of_graph_get_next_endpoint() - get next endpoint node 2169fd9fdb78SPhilipp Zabel * @parent: pointer to the parent device node 2170fd9fdb78SPhilipp Zabel * @prev: previous endpoint node, or NULL to get first 2171fd9fdb78SPhilipp Zabel * 2172fd9fdb78SPhilipp Zabel * Return: An 'endpoint' node pointer with refcount incremented. Refcount 2173f033c0bcSPhilipp Zabel * of the passed @prev node is decremented. 2174fd9fdb78SPhilipp Zabel */ 2175fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, 2176fd9fdb78SPhilipp Zabel struct device_node *prev) 2177fd9fdb78SPhilipp Zabel { 2178fd9fdb78SPhilipp Zabel struct device_node *endpoint; 21793c83e61eSLinus Torvalds struct device_node *port; 2180fd9fdb78SPhilipp Zabel 2181fd9fdb78SPhilipp Zabel if (!parent) 2182fd9fdb78SPhilipp Zabel return NULL; 2183fd9fdb78SPhilipp Zabel 21843c83e61eSLinus Torvalds /* 21853c83e61eSLinus Torvalds * Start by locating the port node. If no previous endpoint is specified 21863c83e61eSLinus Torvalds * search for the first port node, otherwise get the previous endpoint 21873c83e61eSLinus Torvalds * parent port node. 21883c83e61eSLinus Torvalds */ 2189fd9fdb78SPhilipp Zabel if (!prev) { 2190fd9fdb78SPhilipp Zabel struct device_node *node; 21913c83e61eSLinus Torvalds 2192fd9fdb78SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2193fd9fdb78SPhilipp Zabel if (node) 2194fd9fdb78SPhilipp Zabel parent = node; 2195fd9fdb78SPhilipp Zabel 2196fd9fdb78SPhilipp Zabel port = of_get_child_by_name(parent, "port"); 2197fd9fdb78SPhilipp Zabel of_node_put(node); 21984329b93bSPhilipp Zabel 21993c83e61eSLinus Torvalds if (!port) { 22003c83e61eSLinus Torvalds pr_err("%s(): no port node found in %s\n", 22013c83e61eSLinus Torvalds __func__, parent->full_name); 22023c83e61eSLinus Torvalds return NULL; 22034329b93bSPhilipp Zabel } 22043c83e61eSLinus Torvalds } else { 2205fd9fdb78SPhilipp Zabel port = of_get_parent(prev); 22066ff60d39SPhilipp Zabel if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", 22076ff60d39SPhilipp Zabel __func__, prev->full_name)) 2208fd9fdb78SPhilipp Zabel return NULL; 22093c83e61eSLinus Torvalds } 22103c83e61eSLinus Torvalds 22113c83e61eSLinus Torvalds while (1) { 22123c83e61eSLinus Torvalds /* 22133c83e61eSLinus Torvalds * Now that we have a port node, get the next endpoint by 22143c83e61eSLinus Torvalds * getting the next child. If the previous endpoint is NULL this 22153c83e61eSLinus Torvalds * will return the first child. 22163c83e61eSLinus Torvalds */ 2217fd9fdb78SPhilipp Zabel endpoint = of_get_next_child(port, prev); 2218fd9fdb78SPhilipp Zabel if (endpoint) { 2219fd9fdb78SPhilipp Zabel of_node_put(port); 2220fd9fdb78SPhilipp Zabel return endpoint; 2221fd9fdb78SPhilipp Zabel } 2222fd9fdb78SPhilipp Zabel 2223fd9fdb78SPhilipp Zabel /* No more endpoints under this port, try the next one. */ 22243c83e61eSLinus Torvalds prev = NULL; 22253c83e61eSLinus Torvalds 2226fd9fdb78SPhilipp Zabel do { 2227fd9fdb78SPhilipp Zabel port = of_get_next_child(parent, port); 2228fd9fdb78SPhilipp Zabel if (!port) 2229fd9fdb78SPhilipp Zabel return NULL; 2230fd9fdb78SPhilipp Zabel } while (of_node_cmp(port->name, "port")); 22313c83e61eSLinus Torvalds } 2232fd9fdb78SPhilipp Zabel } 2233fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_next_endpoint); 2234fd9fdb78SPhilipp Zabel 2235fd9fdb78SPhilipp Zabel /** 22368ccd0d0cSHyungwon Hwang * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers 22378ccd0d0cSHyungwon Hwang * @parent: pointer to the parent device node 22388ccd0d0cSHyungwon Hwang * @port_reg: identifier (value of reg property) of the parent port node 22398ccd0d0cSHyungwon Hwang * @reg: identifier (value of reg property) of the endpoint node 22408ccd0d0cSHyungwon Hwang * 22418ccd0d0cSHyungwon Hwang * Return: An 'endpoint' node pointer which is identified by reg and at the same 22428ccd0d0cSHyungwon Hwang * is the child of a port node identified by port_reg. reg and port_reg are 22438ccd0d0cSHyungwon Hwang * ignored when they are -1. 22448ccd0d0cSHyungwon Hwang */ 22458ccd0d0cSHyungwon Hwang struct device_node *of_graph_get_endpoint_by_regs( 22468ccd0d0cSHyungwon Hwang const struct device_node *parent, int port_reg, int reg) 22478ccd0d0cSHyungwon Hwang { 22488ccd0d0cSHyungwon Hwang struct of_endpoint endpoint; 22498ccd0d0cSHyungwon Hwang struct device_node *node, *prev_node = NULL; 22508ccd0d0cSHyungwon Hwang 22518ccd0d0cSHyungwon Hwang while (1) { 22528ccd0d0cSHyungwon Hwang node = of_graph_get_next_endpoint(parent, prev_node); 22538ccd0d0cSHyungwon Hwang of_node_put(prev_node); 22548ccd0d0cSHyungwon Hwang if (!node) 22558ccd0d0cSHyungwon Hwang break; 22568ccd0d0cSHyungwon Hwang 22578ccd0d0cSHyungwon Hwang of_graph_parse_endpoint(node, &endpoint); 22588ccd0d0cSHyungwon Hwang if (((port_reg == -1) || (endpoint.port == port_reg)) && 22598ccd0d0cSHyungwon Hwang ((reg == -1) || (endpoint.id == reg))) 22608ccd0d0cSHyungwon Hwang return node; 22618ccd0d0cSHyungwon Hwang 22628ccd0d0cSHyungwon Hwang prev_node = node; 22638ccd0d0cSHyungwon Hwang } 22648ccd0d0cSHyungwon Hwang 22658ccd0d0cSHyungwon Hwang return NULL; 22668ccd0d0cSHyungwon Hwang } 22678ffaa903SDave Airlie EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); 22688ccd0d0cSHyungwon Hwang 22698ccd0d0cSHyungwon Hwang /** 2270fd9fdb78SPhilipp Zabel * of_graph_get_remote_port_parent() - get remote port's parent node 2271fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2272fd9fdb78SPhilipp Zabel * 2273fd9fdb78SPhilipp Zabel * Return: Remote device node associated with remote endpoint node linked 2274fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2275fd9fdb78SPhilipp Zabel */ 2276fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port_parent( 2277fd9fdb78SPhilipp Zabel const struct device_node *node) 2278fd9fdb78SPhilipp Zabel { 2279fd9fdb78SPhilipp Zabel struct device_node *np; 2280fd9fdb78SPhilipp Zabel unsigned int depth; 2281fd9fdb78SPhilipp Zabel 2282fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2283fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2284fd9fdb78SPhilipp Zabel 2285fd9fdb78SPhilipp Zabel /* Walk 3 levels up only if there is 'ports' node. */ 2286fd9fdb78SPhilipp Zabel for (depth = 3; depth && np; depth--) { 2287fd9fdb78SPhilipp Zabel np = of_get_next_parent(np); 2288fd9fdb78SPhilipp Zabel if (depth == 2 && of_node_cmp(np->name, "ports")) 2289fd9fdb78SPhilipp Zabel break; 2290fd9fdb78SPhilipp Zabel } 2291fd9fdb78SPhilipp Zabel return np; 2292fd9fdb78SPhilipp Zabel } 2293fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port_parent); 2294fd9fdb78SPhilipp Zabel 2295fd9fdb78SPhilipp Zabel /** 2296fd9fdb78SPhilipp Zabel * of_graph_get_remote_port() - get remote port node 2297fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2298fd9fdb78SPhilipp Zabel * 2299fd9fdb78SPhilipp Zabel * Return: Remote port node associated with remote endpoint node linked 2300fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2301fd9fdb78SPhilipp Zabel */ 2302fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port(const struct device_node *node) 2303fd9fdb78SPhilipp Zabel { 2304fd9fdb78SPhilipp Zabel struct device_node *np; 2305fd9fdb78SPhilipp Zabel 2306fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2307fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2308fd9fdb78SPhilipp Zabel if (!np) 2309fd9fdb78SPhilipp Zabel return NULL; 2310fd9fdb78SPhilipp Zabel return of_get_next_parent(np); 2311fd9fdb78SPhilipp Zabel } 2312fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port); 2313