197e873e5SStephen Rothwell /* 297e873e5SStephen Rothwell * Procedures for creating, accessing and interpreting the device tree. 397e873e5SStephen Rothwell * 497e873e5SStephen Rothwell * Paul Mackerras August 1996. 597e873e5SStephen Rothwell * Copyright (C) 1996-2005 Paul Mackerras. 697e873e5SStephen Rothwell * 797e873e5SStephen Rothwell * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 897e873e5SStephen Rothwell * {engebret|bergner}@us.ibm.com 997e873e5SStephen Rothwell * 1097e873e5SStephen Rothwell * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 1197e873e5SStephen Rothwell * 12e91edcf5SGrant Likely * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 13e91edcf5SGrant Likely * Grant Likely. 1497e873e5SStephen Rothwell * 1597e873e5SStephen Rothwell * This program is free software; you can redistribute it and/or 1697e873e5SStephen Rothwell * modify it under the terms of the GNU General Public License 1797e873e5SStephen Rothwell * as published by the Free Software Foundation; either version 1897e873e5SStephen Rothwell * 2 of the License, or (at your option) any later version. 1997e873e5SStephen Rothwell */ 20606ad42aSRob Herring 21606ad42aSRob Herring #define pr_fmt(fmt) "OF: " fmt 22606ad42aSRob Herring 233482f2c5SGrant Likely #include <linux/console.h> 24611cad72SShawn Guo #include <linux/ctype.h> 25183912d3SSudeep KarkadaNagesha #include <linux/cpu.h> 2697e873e5SStephen Rothwell #include <linux/module.h> 2797e873e5SStephen Rothwell #include <linux/of.h> 285fa23530SSudeep Holla #include <linux/of_device.h> 29fd9fdb78SPhilipp Zabel #include <linux/of_graph.h> 30581b605aSStephen Rothwell #include <linux/spinlock.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 3275b57ecfSGrant Likely #include <linux/string.h> 33a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 34581b605aSStephen Rothwell 35ced4eec9SStepan Moskovchenko #include "of_private.h" 36611cad72SShawn Guo 37ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 38611cad72SShawn Guo 395063e25aSGrant Likely struct device_node *of_root; 405063e25aSGrant Likely EXPORT_SYMBOL(of_root); 41fc0bdae4SGrant Likely struct device_node *of_chosen; 42611cad72SShawn Guo struct device_node *of_aliases; 43a752ee56SGrant Likely struct device_node *of_stdout; 447914a7c5SLeif Lindholm static const char *of_stdout_options; 45611cad72SShawn Guo 468a2b22a2SGrant Likely struct kset *of_kset; 4775b57ecfSGrant Likely 4875b57ecfSGrant Likely /* 498a2b22a2SGrant Likely * Used to protect the of_aliases, to hold off addition of nodes to sysfs. 508a2b22a2SGrant Likely * This mutex must be held whenever modifications are being made to the 518a2b22a2SGrant Likely * device tree. The of_{attach,detach}_node() and 528a2b22a2SGrant Likely * of_{add,remove,update}_property() helpers make sure this happens. 5375b57ecfSGrant Likely */ 54c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex); 551ef4d424SStephen Rothwell 565063e25aSGrant Likely /* use when traversing tree through the child, sibling, 57581b605aSStephen Rothwell * or parent members of struct device_node. 58581b605aSStephen Rothwell */ 59d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 6097e873e5SStephen Rothwell 6197e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 6297e873e5SStephen Rothwell { 63a9fadeefSJeremy Kerr const __be32 *ip; 6497e873e5SStephen Rothwell 6597e873e5SStephen Rothwell do { 6697e873e5SStephen Rothwell if (np->parent) 6797e873e5SStephen Rothwell np = np->parent; 6897e873e5SStephen Rothwell ip = of_get_property(np, "#address-cells", NULL); 6997e873e5SStephen Rothwell if (ip) 7033714881SJeremy Kerr return be32_to_cpup(ip); 7197e873e5SStephen Rothwell } while (np->parent); 7297e873e5SStephen Rothwell /* No #address-cells property for the root node */ 7397e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 7497e873e5SStephen Rothwell } 7597e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 7697e873e5SStephen Rothwell 7797e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 7897e873e5SStephen Rothwell { 79a9fadeefSJeremy Kerr const __be32 *ip; 8097e873e5SStephen Rothwell 8197e873e5SStephen Rothwell do { 8297e873e5SStephen Rothwell if (np->parent) 8397e873e5SStephen Rothwell np = np->parent; 8497e873e5SStephen Rothwell ip = of_get_property(np, "#size-cells", NULL); 8597e873e5SStephen Rothwell if (ip) 8633714881SJeremy Kerr return be32_to_cpup(ip); 8797e873e5SStephen Rothwell } while (np->parent); 8897e873e5SStephen Rothwell /* No #size-cells property for the root node */ 8997e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 9097e873e5SStephen Rothwell } 9197e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 9297e873e5SStephen Rothwell 930c3f061cSRob Herring #ifdef CONFIG_NUMA 940c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np) 950c3f061cSRob Herring { 96c8fff7bcSKonstantin Khlebnikov return NUMA_NO_NODE; 970c3f061cSRob Herring } 980c3f061cSRob Herring #endif 990c3f061cSRob Herring 1006afc0dc3SGrant Likely #ifndef CONFIG_OF_DYNAMIC 10175b57ecfSGrant Likely static void of_node_release(struct kobject *kobj) 10275b57ecfSGrant Likely { 10375b57ecfSGrant Likely /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ 10475b57ecfSGrant Likely } 1050f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */ 106923f7e30SGrant Likely 10775b57ecfSGrant Likely struct kobj_type of_node_ktype = { 10875b57ecfSGrant Likely .release = of_node_release, 10975b57ecfSGrant Likely }; 11075b57ecfSGrant Likely 11175b57ecfSGrant Likely static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, 11275b57ecfSGrant Likely struct bin_attribute *bin_attr, char *buf, 11375b57ecfSGrant Likely loff_t offset, size_t count) 11475b57ecfSGrant Likely { 11575b57ecfSGrant Likely struct property *pp = container_of(bin_attr, struct property, attr); 11675b57ecfSGrant Likely return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); 11775b57ecfSGrant Likely } 11875b57ecfSGrant Likely 119d9fc8807SFrank Rowand /* always return newly allocated name, caller must free after use */ 12075b57ecfSGrant Likely static const char *safe_name(struct kobject *kobj, const char *orig_name) 12175b57ecfSGrant Likely { 12275b57ecfSGrant Likely const char *name = orig_name; 12375b57ecfSGrant Likely struct kernfs_node *kn; 12475b57ecfSGrant Likely int i = 0; 12575b57ecfSGrant Likely 12675b57ecfSGrant Likely /* don't be a hero. After 16 tries give up */ 12775b57ecfSGrant Likely while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { 12875b57ecfSGrant Likely sysfs_put(kn); 12975b57ecfSGrant Likely if (name != orig_name) 13075b57ecfSGrant Likely kfree(name); 13175b57ecfSGrant Likely name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); 13275b57ecfSGrant Likely } 13375b57ecfSGrant Likely 134d9fc8807SFrank Rowand if (name == orig_name) { 135d9fc8807SFrank Rowand name = kstrdup(orig_name, GFP_KERNEL); 136d9fc8807SFrank Rowand } else { 137606ad42aSRob Herring pr_warn("Duplicate name in %s, renamed to \"%s\"\n", 13875b57ecfSGrant Likely kobject_name(kobj), name); 139d9fc8807SFrank Rowand } 14075b57ecfSGrant Likely return name; 14175b57ecfSGrant Likely } 14275b57ecfSGrant Likely 1438a2b22a2SGrant Likely int __of_add_property_sysfs(struct device_node *np, struct property *pp) 14475b57ecfSGrant Likely { 14575b57ecfSGrant Likely int rc; 14675b57ecfSGrant Likely 14775b57ecfSGrant Likely /* Important: Don't leak passwords */ 14875b57ecfSGrant Likely bool secure = strncmp(pp->name, "security-", 9) == 0; 14975b57ecfSGrant Likely 150ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 151ef69d740SGaurav Minocha return 0; 152ef69d740SGaurav Minocha 1538a2b22a2SGrant Likely if (!of_kset || !of_node_is_attached(np)) 1548a2b22a2SGrant Likely return 0; 1558a2b22a2SGrant Likely 15675b57ecfSGrant Likely sysfs_bin_attr_init(&pp->attr); 15775b57ecfSGrant Likely pp->attr.attr.name = safe_name(&np->kobj, pp->name); 15875b57ecfSGrant Likely pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; 15975b57ecfSGrant Likely pp->attr.size = secure ? 0 : pp->length; 16075b57ecfSGrant Likely pp->attr.read = of_node_property_read; 16175b57ecfSGrant Likely 16275b57ecfSGrant Likely rc = sysfs_create_bin_file(&np->kobj, &pp->attr); 16375b57ecfSGrant Likely WARN(rc, "error adding attribute %s to node %s\n", pp->name, np->full_name); 16475b57ecfSGrant Likely return rc; 16575b57ecfSGrant Likely } 16675b57ecfSGrant Likely 1678a2b22a2SGrant Likely int __of_attach_node_sysfs(struct device_node *np) 16875b57ecfSGrant Likely { 16975b57ecfSGrant Likely const char *name; 170d9fc8807SFrank Rowand struct kobject *parent; 17175b57ecfSGrant Likely struct property *pp; 17275b57ecfSGrant Likely int rc; 17375b57ecfSGrant Likely 174ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 175ef69d740SGaurav Minocha return 0; 176ef69d740SGaurav Minocha 1778a2b22a2SGrant Likely if (!of_kset) 1788a2b22a2SGrant Likely return 0; 1798a2b22a2SGrant Likely 18075b57ecfSGrant Likely np->kobj.kset = of_kset; 18175b57ecfSGrant Likely if (!np->parent) { 18275b57ecfSGrant Likely /* Nodes without parents are new top level trees */ 183d9fc8807SFrank Rowand name = safe_name(&of_kset->kobj, "base"); 184d9fc8807SFrank Rowand parent = NULL; 18575b57ecfSGrant Likely } else { 18675b57ecfSGrant Likely name = safe_name(&np->parent->kobj, kbasename(np->full_name)); 187d9fc8807SFrank Rowand parent = &np->parent->kobj; 18875b57ecfSGrant Likely } 189d9fc8807SFrank Rowand if (!name) 190d9fc8807SFrank Rowand return -ENOMEM; 191d9fc8807SFrank Rowand rc = kobject_add(&np->kobj, parent, "%s", name); 192d9fc8807SFrank Rowand kfree(name); 19375b57ecfSGrant Likely if (rc) 19475b57ecfSGrant Likely return rc; 19575b57ecfSGrant Likely 19675b57ecfSGrant Likely for_each_property_of_node(np, pp) 19775b57ecfSGrant Likely __of_add_property_sysfs(np, pp); 19875b57ecfSGrant Likely 19975b57ecfSGrant Likely return 0; 20075b57ecfSGrant Likely } 20175b57ecfSGrant Likely 202194ec936SSudeep Holla void __init of_core_init(void) 20375b57ecfSGrant Likely { 20475b57ecfSGrant Likely struct device_node *np; 20575b57ecfSGrant Likely 20675b57ecfSGrant Likely /* Create the kset, and register existing nodes */ 207c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 20875b57ecfSGrant Likely of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); 20975b57ecfSGrant Likely if (!of_kset) { 210c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 211606ad42aSRob Herring pr_err("failed to register existing nodes\n"); 212194ec936SSudeep Holla return; 21375b57ecfSGrant Likely } 21475b57ecfSGrant Likely for_each_of_allnodes(np) 2158a2b22a2SGrant Likely __of_attach_node_sysfs(np); 216c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 21775b57ecfSGrant Likely 2188357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */ 2195063e25aSGrant Likely if (of_root) 22075b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 22175b57ecfSGrant Likely } 22275b57ecfSGrant Likely 22328d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 22428d0e36bSThomas Gleixner const char *name, int *lenp) 225581b605aSStephen Rothwell { 226581b605aSStephen Rothwell struct property *pp; 227581b605aSStephen Rothwell 22864e4566fSTimur Tabi if (!np) 22964e4566fSTimur Tabi return NULL; 23064e4566fSTimur Tabi 231a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 232581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 233a3a7cab1SSachin Kamat if (lenp) 234581b605aSStephen Rothwell *lenp = pp->length; 235581b605aSStephen Rothwell break; 236581b605aSStephen Rothwell } 237581b605aSStephen Rothwell } 23828d0e36bSThomas Gleixner 23928d0e36bSThomas Gleixner return pp; 24028d0e36bSThomas Gleixner } 24128d0e36bSThomas Gleixner 24228d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 24328d0e36bSThomas Gleixner const char *name, 24428d0e36bSThomas Gleixner int *lenp) 24528d0e36bSThomas Gleixner { 24628d0e36bSThomas Gleixner struct property *pp; 247d6d3c4e6SThomas Gleixner unsigned long flags; 24828d0e36bSThomas Gleixner 249d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 25028d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 251d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 252581b605aSStephen Rothwell 253581b605aSStephen Rothwell return pp; 254581b605aSStephen Rothwell } 255581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 256581b605aSStephen Rothwell 2575063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev) 2585063e25aSGrant Likely { 2595063e25aSGrant Likely struct device_node *np; 2605063e25aSGrant Likely if (!prev) { 2615063e25aSGrant Likely np = of_root; 2625063e25aSGrant Likely } else if (prev->child) { 2635063e25aSGrant Likely np = prev->child; 2645063e25aSGrant Likely } else { 2655063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */ 2665063e25aSGrant Likely np = prev; 2675063e25aSGrant Likely while (np->parent && !np->sibling) 2685063e25aSGrant Likely np = np->parent; 2695063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */ 2705063e25aSGrant Likely } 2715063e25aSGrant Likely return np; 2725063e25aSGrant Likely } 2735063e25aSGrant Likely 274e91edcf5SGrant Likely /** 275e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 276e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 277e91edcf5SGrant Likely * of_node_put() will be called on it 278e91edcf5SGrant Likely * 279e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 280e91edcf5SGrant Likely * of_node_put() on it when done. 281e91edcf5SGrant Likely */ 282e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 283e91edcf5SGrant Likely { 284e91edcf5SGrant Likely struct device_node *np; 285d25d8694SBenjamin Herrenschmidt unsigned long flags; 286e91edcf5SGrant Likely 287d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 2885063e25aSGrant Likely np = __of_find_all_nodes(prev); 2895063e25aSGrant Likely of_node_get(np); 290e91edcf5SGrant Likely of_node_put(prev); 291d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 292e91edcf5SGrant Likely return np; 293e91edcf5SGrant Likely } 294e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 295e91edcf5SGrant Likely 29697e873e5SStephen Rothwell /* 29797e873e5SStephen Rothwell * Find a property with a given name for a given node 29897e873e5SStephen Rothwell * and return the value. 29997e873e5SStephen Rothwell */ 300a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np, 30128d0e36bSThomas Gleixner const char *name, int *lenp) 30228d0e36bSThomas Gleixner { 30328d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 30428d0e36bSThomas Gleixner 30528d0e36bSThomas Gleixner return pp ? pp->value : NULL; 30628d0e36bSThomas Gleixner } 30728d0e36bSThomas Gleixner 30828d0e36bSThomas Gleixner /* 30928d0e36bSThomas Gleixner * Find a property with a given name for a given node 31028d0e36bSThomas Gleixner * and return the value. 31128d0e36bSThomas Gleixner */ 31297e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 31397e873e5SStephen Rothwell int *lenp) 31497e873e5SStephen Rothwell { 31597e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 31697e873e5SStephen Rothwell 31797e873e5SStephen Rothwell return pp ? pp->value : NULL; 31897e873e5SStephen Rothwell } 31997e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 3200081cbc3SStephen Rothwell 321183912d3SSudeep KarkadaNagesha /* 322183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 323183912d3SSudeep KarkadaNagesha * 324183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 325183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 326183912d3SSudeep KarkadaNagesha * 327183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 328183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 329183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 330183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 331183912d3SSudeep KarkadaNagesha * 332183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 333183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 334183912d3SSudeep KarkadaNagesha */ 335183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 336183912d3SSudeep KarkadaNagesha { 337183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 338183912d3SSudeep KarkadaNagesha } 339183912d3SSudeep KarkadaNagesha 340183912d3SSudeep KarkadaNagesha /** 341183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 342183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 343183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 344183912d3SSudeep KarkadaNagesha */ 345183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 346183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 347183912d3SSudeep KarkadaNagesha { 348183912d3SSudeep KarkadaNagesha const __be32 *cell; 349183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 350183912d3SSudeep KarkadaNagesha u64 hwid; 351183912d3SSudeep KarkadaNagesha 352183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 353183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 354f3cea45aSGrant Likely if (!cell || !ac) 355183912d3SSudeep KarkadaNagesha return false; 356f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 357183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 358183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 359183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 360183912d3SSudeep KarkadaNagesha if (thread) 361183912d3SSudeep KarkadaNagesha *thread = tid; 362183912d3SSudeep KarkadaNagesha return true; 363183912d3SSudeep KarkadaNagesha } 364183912d3SSudeep KarkadaNagesha cell += ac; 365183912d3SSudeep KarkadaNagesha } 366183912d3SSudeep KarkadaNagesha return false; 367183912d3SSudeep KarkadaNagesha } 368183912d3SSudeep KarkadaNagesha 369d1cb9d1aSDavid Miller /* 370d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 371d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 372d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 373d1cb9d1aSDavid Miller * core is returned in it. 374d1cb9d1aSDavid Miller */ 375d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 376d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 377d1cb9d1aSDavid Miller { 378d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 379d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 380d1cb9d1aSDavid Miller * standard "reg" property. 381d1cb9d1aSDavid Miller */ 382d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 383d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 384d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 385d1cb9d1aSDavid Miller cpu, thread)) 386d1cb9d1aSDavid Miller return true; 387d1cb9d1aSDavid Miller 388510bd068SMasahiro Yamada return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); 389d1cb9d1aSDavid Miller } 390d1cb9d1aSDavid Miller 391183912d3SSudeep KarkadaNagesha /** 392183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 393183912d3SSudeep KarkadaNagesha * 394183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 395183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 396183912d3SSudeep KarkadaNagesha * returned 397183912d3SSudeep KarkadaNagesha * 398183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 399183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 400183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 401183912d3SSudeep KarkadaNagesha * references can use that instead. 402183912d3SSudeep KarkadaNagesha * 403183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 404183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 405183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 406183912d3SSudeep KarkadaNagesha * 4071c986e36SMasahiro Yamada * Returns a node pointer for the logical cpu with refcount incremented, use 4081c986e36SMasahiro Yamada * of_node_put() on it when done. Returns NULL if not found. 409183912d3SSudeep KarkadaNagesha */ 410183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 411183912d3SSudeep KarkadaNagesha { 412d1cb9d1aSDavid Miller struct device_node *cpun; 413183912d3SSudeep KarkadaNagesha 414d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 415d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 416183912d3SSudeep KarkadaNagesha return cpun; 417183912d3SSudeep KarkadaNagesha } 418183912d3SSudeep KarkadaNagesha return NULL; 419183912d3SSudeep KarkadaNagesha } 420183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 421183912d3SSudeep KarkadaNagesha 422215a14cfSKevin Hao /** 423215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints 424215a14cfSKevin Hao * @device: pointer to node 425215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match 426215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match 427215a14cfSKevin Hao * @name: required node name, NULL or "" for any match 428215a14cfSKevin Hao * 429215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the 430215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by 431215a14cfSKevin Hao * passing NULL or an empty string as the constraint. 432215a14cfSKevin Hao * 433215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return 434215a14cfSKevin Hao * value is a relative score with larger values indicating better 435215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value 436215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching 437215a14cfSKevin Hao * name. Practically speaking, this results in the following priority 438215a14cfSKevin Hao * order for matches: 439215a14cfSKevin Hao * 440215a14cfSKevin Hao * 1. specific compatible && type && name 441215a14cfSKevin Hao * 2. specific compatible && type 442215a14cfSKevin Hao * 3. specific compatible && name 443215a14cfSKevin Hao * 4. specific compatible 444215a14cfSKevin Hao * 5. general compatible && type && name 445215a14cfSKevin Hao * 6. general compatible && type 446215a14cfSKevin Hao * 7. general compatible && name 447215a14cfSKevin Hao * 8. general compatible 448215a14cfSKevin Hao * 9. type && name 449215a14cfSKevin Hao * 10. type 450215a14cfSKevin Hao * 11. name 4510081cbc3SStephen Rothwell */ 45228d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 453215a14cfSKevin Hao const char *compat, const char *type, const char *name) 4540081cbc3SStephen Rothwell { 455215a14cfSKevin Hao struct property *prop; 4560081cbc3SStephen Rothwell const char *cp; 457215a14cfSKevin Hao int index = 0, score = 0; 4580081cbc3SStephen Rothwell 459215a14cfSKevin Hao /* Compatible match has highest priority */ 460215a14cfSKevin Hao if (compat && compat[0]) { 461215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL); 462215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp; 463215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) { 464215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 465215a14cfSKevin Hao score = INT_MAX/2 - (index << 2); 466215a14cfSKevin Hao break; 467215a14cfSKevin Hao } 468215a14cfSKevin Hao } 469215a14cfSKevin Hao if (!score) 4700081cbc3SStephen Rothwell return 0; 4710081cbc3SStephen Rothwell } 4720081cbc3SStephen Rothwell 473215a14cfSKevin Hao /* Matching type is better than matching name */ 474215a14cfSKevin Hao if (type && type[0]) { 475215a14cfSKevin Hao if (!device->type || of_node_cmp(type, device->type)) 4760081cbc3SStephen Rothwell return 0; 477215a14cfSKevin Hao score += 2; 478215a14cfSKevin Hao } 479215a14cfSKevin Hao 480215a14cfSKevin Hao /* Matching name is a bit better than not */ 481215a14cfSKevin Hao if (name && name[0]) { 482215a14cfSKevin Hao if (!device->name || of_node_cmp(name, device->name)) 483215a14cfSKevin Hao return 0; 484215a14cfSKevin Hao score++; 485215a14cfSKevin Hao } 486215a14cfSKevin Hao 487215a14cfSKevin Hao return score; 4880081cbc3SStephen Rothwell } 48928d0e36bSThomas Gleixner 49028d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 49128d0e36bSThomas Gleixner * the device's "compatible" property 49228d0e36bSThomas Gleixner */ 49328d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 49428d0e36bSThomas Gleixner const char *compat) 49528d0e36bSThomas Gleixner { 496d6d3c4e6SThomas Gleixner unsigned long flags; 49728d0e36bSThomas Gleixner int res; 49828d0e36bSThomas Gleixner 499d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 500215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL); 501d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 50228d0e36bSThomas Gleixner return res; 50328d0e36bSThomas Gleixner } 5040081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 505e679c5f4SStephen Rothwell 506b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in 507b9c13fe3SBenjamin Herrenschmidt * a NULL terminated array of strings. Returns the best match 508b9c13fe3SBenjamin Herrenschmidt * score or 0. 509b9c13fe3SBenjamin Herrenschmidt */ 510b9c13fe3SBenjamin Herrenschmidt int of_device_compatible_match(struct device_node *device, 511b9c13fe3SBenjamin Herrenschmidt const char *const *compat) 512b9c13fe3SBenjamin Herrenschmidt { 513b9c13fe3SBenjamin Herrenschmidt unsigned int tmp, score = 0; 514b9c13fe3SBenjamin Herrenschmidt 515b9c13fe3SBenjamin Herrenschmidt if (!compat) 516b9c13fe3SBenjamin Herrenschmidt return 0; 517b9c13fe3SBenjamin Herrenschmidt 518b9c13fe3SBenjamin Herrenschmidt while (*compat) { 519b9c13fe3SBenjamin Herrenschmidt tmp = of_device_is_compatible(device, *compat); 520b9c13fe3SBenjamin Herrenschmidt if (tmp > score) 521b9c13fe3SBenjamin Herrenschmidt score = tmp; 522b9c13fe3SBenjamin Herrenschmidt compat++; 523b9c13fe3SBenjamin Herrenschmidt } 524b9c13fe3SBenjamin Herrenschmidt 525b9c13fe3SBenjamin Herrenschmidt return score; 526b9c13fe3SBenjamin Herrenschmidt } 527b9c13fe3SBenjamin Herrenschmidt 528e679c5f4SStephen Rothwell /** 52971a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 5301f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 5311f43cfb9SGrant Likely * 53225c7a1deSKevin Cernekee * Returns a positive integer if the root node has the given value in its 5331f43cfb9SGrant Likely * compatible property. 5341f43cfb9SGrant Likely */ 53571a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 5361f43cfb9SGrant Likely { 5371f43cfb9SGrant Likely struct device_node *root; 5381f43cfb9SGrant Likely int rc = 0; 5391f43cfb9SGrant Likely 5401f43cfb9SGrant Likely root = of_find_node_by_path("/"); 5411f43cfb9SGrant Likely if (root) { 5421f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 5431f43cfb9SGrant Likely of_node_put(root); 5441f43cfb9SGrant Likely } 5451f43cfb9SGrant Likely return rc; 5461f43cfb9SGrant Likely } 54771a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 5481f43cfb9SGrant Likely 5491f43cfb9SGrant Likely /** 550c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 551834d97d4SJosh Boyer * 552c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 553834d97d4SJosh Boyer * 55453a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 55553a4ab96SKevin Cernekee * false otherwise 556834d97d4SJosh Boyer */ 55753a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device) 558834d97d4SJosh Boyer { 559834d97d4SJosh Boyer const char *status; 560834d97d4SJosh Boyer int statlen; 561834d97d4SJosh Boyer 56242ccd781SXiubo Li if (!device) 56353a4ab96SKevin Cernekee return false; 56442ccd781SXiubo Li 565c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 566834d97d4SJosh Boyer if (status == NULL) 56753a4ab96SKevin Cernekee return true; 568834d97d4SJosh Boyer 569834d97d4SJosh Boyer if (statlen > 0) { 570834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 57153a4ab96SKevin Cernekee return true; 572834d97d4SJosh Boyer } 573834d97d4SJosh Boyer 57453a4ab96SKevin Cernekee return false; 575834d97d4SJosh Boyer } 576c31a0c05SStephen Warren 577c31a0c05SStephen Warren /** 578c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 579c31a0c05SStephen Warren * 580c31a0c05SStephen Warren * @device: Node to check for availability 581c31a0c05SStephen Warren * 58253a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 58353a4ab96SKevin Cernekee * false otherwise 584c31a0c05SStephen Warren */ 58553a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device) 586c31a0c05SStephen Warren { 587c31a0c05SStephen Warren unsigned long flags; 58853a4ab96SKevin Cernekee bool res; 589c31a0c05SStephen Warren 590c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 591c31a0c05SStephen Warren res = __of_device_is_available(device); 592c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 593c31a0c05SStephen Warren return res; 594c31a0c05SStephen Warren 595c31a0c05SStephen Warren } 596834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 597834d97d4SJosh Boyer 598834d97d4SJosh Boyer /** 59937786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers 60037786c7fSKevin Cernekee * 60137786c7fSKevin Cernekee * @device: Node to check for endianness 60237786c7fSKevin Cernekee * 60337786c7fSKevin Cernekee * Returns true if the device has a "big-endian" property, or if the kernel 60437786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property. 60537786c7fSKevin Cernekee * Returns false otherwise. 60637786c7fSKevin Cernekee * 60737786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if 60837786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise. 60937786c7fSKevin Cernekee */ 61037786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device) 61137786c7fSKevin Cernekee { 61237786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian")) 61337786c7fSKevin Cernekee return true; 61437786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 61537786c7fSKevin Cernekee of_property_read_bool(device, "native-endian")) 61637786c7fSKevin Cernekee return true; 61737786c7fSKevin Cernekee return false; 61837786c7fSKevin Cernekee } 61937786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian); 62037786c7fSKevin Cernekee 62137786c7fSKevin Cernekee /** 622e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 623e679c5f4SStephen Rothwell * @node: Node to get parent 624e679c5f4SStephen Rothwell * 625e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 626e679c5f4SStephen Rothwell * of_node_put() on it when done. 627e679c5f4SStephen Rothwell */ 628e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 629e679c5f4SStephen Rothwell { 630e679c5f4SStephen Rothwell struct device_node *np; 631d6d3c4e6SThomas Gleixner unsigned long flags; 632e679c5f4SStephen Rothwell 633e679c5f4SStephen Rothwell if (!node) 634e679c5f4SStephen Rothwell return NULL; 635e679c5f4SStephen Rothwell 636d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 637e679c5f4SStephen Rothwell np = of_node_get(node->parent); 638d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 639e679c5f4SStephen Rothwell return np; 640e679c5f4SStephen Rothwell } 641e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 642d1cd355aSStephen Rothwell 643d1cd355aSStephen Rothwell /** 644f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 645f4eb0107SMichael Ellerman * @node: Node to get parent of 646f4eb0107SMichael Ellerman * 647f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 648f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 649f4eb0107SMichael Ellerman * through a node's parents. 650f4eb0107SMichael Ellerman * 651f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 652f4eb0107SMichael Ellerman * of_node_put() on it when done. 653f4eb0107SMichael Ellerman */ 654f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 655f4eb0107SMichael Ellerman { 656f4eb0107SMichael Ellerman struct device_node *parent; 657d6d3c4e6SThomas Gleixner unsigned long flags; 658f4eb0107SMichael Ellerman 659f4eb0107SMichael Ellerman if (!node) 660f4eb0107SMichael Ellerman return NULL; 661f4eb0107SMichael Ellerman 662d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 663f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 664f4eb0107SMichael Ellerman of_node_put(node); 665d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 666f4eb0107SMichael Ellerman return parent; 667f4eb0107SMichael Ellerman } 6686695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 669f4eb0107SMichael Ellerman 6700d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node, 6710d0e02d6SGrant Likely struct device_node *prev) 6720d0e02d6SGrant Likely { 6730d0e02d6SGrant Likely struct device_node *next; 6740d0e02d6SGrant Likely 67543cb4367SFlorian Fainelli if (!node) 67643cb4367SFlorian Fainelli return NULL; 67743cb4367SFlorian Fainelli 6780d0e02d6SGrant Likely next = prev ? prev->sibling : node->child; 6790d0e02d6SGrant Likely for (; next; next = next->sibling) 6800d0e02d6SGrant Likely if (of_node_get(next)) 6810d0e02d6SGrant Likely break; 6820d0e02d6SGrant Likely of_node_put(prev); 6830d0e02d6SGrant Likely return next; 6840d0e02d6SGrant Likely } 6850d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \ 6860d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \ 6870d0e02d6SGrant Likely child = __of_get_next_child(parent, child)) 6880d0e02d6SGrant Likely 689f4eb0107SMichael Ellerman /** 690d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 691d1cd355aSStephen Rothwell * @node: parent node 692d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 693d1cd355aSStephen Rothwell * 69464808273SBaruch Siach * Returns a node pointer with refcount incremented, use of_node_put() on 69564808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the 69664808273SBaruch Siach * refcount of prev. 697d1cd355aSStephen Rothwell */ 698d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 699d1cd355aSStephen Rothwell struct device_node *prev) 700d1cd355aSStephen Rothwell { 701d1cd355aSStephen Rothwell struct device_node *next; 702d6d3c4e6SThomas Gleixner unsigned long flags; 703d1cd355aSStephen Rothwell 704d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 7050d0e02d6SGrant Likely next = __of_get_next_child(node, prev); 706d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 707d1cd355aSStephen Rothwell return next; 708d1cd355aSStephen Rothwell } 709d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 7101ef4d424SStephen Rothwell 7111ef4d424SStephen Rothwell /** 7123296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 7133296193dSTimur Tabi * @node: parent node 7143296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 7153296193dSTimur Tabi * 7163296193dSTimur Tabi * This function is like of_get_next_child(), except that it 7173296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 7183296193dSTimur Tabi */ 7193296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 7203296193dSTimur Tabi struct device_node *prev) 7213296193dSTimur Tabi { 7223296193dSTimur Tabi struct device_node *next; 723d25d8694SBenjamin Herrenschmidt unsigned long flags; 7243296193dSTimur Tabi 72543cb4367SFlorian Fainelli if (!node) 72643cb4367SFlorian Fainelli return NULL; 72743cb4367SFlorian Fainelli 728d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 7293296193dSTimur Tabi next = prev ? prev->sibling : node->child; 7303296193dSTimur Tabi for (; next; next = next->sibling) { 731c31a0c05SStephen Warren if (!__of_device_is_available(next)) 7323296193dSTimur Tabi continue; 7333296193dSTimur Tabi if (of_node_get(next)) 7343296193dSTimur Tabi break; 7353296193dSTimur Tabi } 7363296193dSTimur Tabi of_node_put(prev); 737d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 7383296193dSTimur Tabi return next; 7393296193dSTimur Tabi } 7403296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 7413296193dSTimur Tabi 7423296193dSTimur Tabi /** 7439c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 7449c19761aSSrinivas Kandagatla * @node: parent node 7459c19761aSSrinivas Kandagatla * @name: child name to look for. 7469c19761aSSrinivas Kandagatla * 7479c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 7489c19761aSSrinivas Kandagatla * 7499c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 7509c19761aSSrinivas Kandagatla * of_node_put() on it when done. 7519c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 7529c19761aSSrinivas Kandagatla */ 7539c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 7549c19761aSSrinivas Kandagatla const char *name) 7559c19761aSSrinivas Kandagatla { 7569c19761aSSrinivas Kandagatla struct device_node *child; 7579c19761aSSrinivas Kandagatla 7589c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 7599c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 7609c19761aSSrinivas Kandagatla break; 7619c19761aSSrinivas Kandagatla return child; 7629c19761aSSrinivas Kandagatla } 7639c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 7649c19761aSSrinivas Kandagatla 765c22e650eSGrant Likely static struct device_node *__of_find_node_by_path(struct device_node *parent, 766c22e650eSGrant Likely const char *path) 767c22e650eSGrant Likely { 768c22e650eSGrant Likely struct device_node *child; 769106937e8SLeif Lindholm int len; 770c22e650eSGrant Likely 771721a09e9SBrian Norris len = strcspn(path, "/:"); 772c22e650eSGrant Likely if (!len) 773c22e650eSGrant Likely return NULL; 774c22e650eSGrant Likely 775c22e650eSGrant Likely __for_each_child_of_node(parent, child) { 776c22e650eSGrant Likely const char *name = strrchr(child->full_name, '/'); 777c22e650eSGrant Likely if (WARN(!name, "malformed device_node %s\n", child->full_name)) 778c22e650eSGrant Likely continue; 779c22e650eSGrant Likely name++; 780c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 781c22e650eSGrant Likely return child; 782c22e650eSGrant Likely } 783c22e650eSGrant Likely return NULL; 784c22e650eSGrant Likely } 785c22e650eSGrant Likely 7869c19761aSSrinivas Kandagatla /** 78775c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path 788c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not 789c22e650eSGrant Likely * start with '/', the name of a property of the /aliases 790c22e650eSGrant Likely * node (an alias). In the case of an alias, the node 791c22e650eSGrant Likely * matching the alias' value will be returned. 79275c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of 79375c28c09SLeif Lindholm * an options string appended to the end of the path with 79475c28c09SLeif Lindholm * a ':' separator. 795c22e650eSGrant Likely * 796c22e650eSGrant Likely * Valid paths: 797c22e650eSGrant Likely * /foo/bar Full path 798c22e650eSGrant Likely * foo Valid alias 799c22e650eSGrant Likely * foo/bar Valid alias + relative path 8001ef4d424SStephen Rothwell * 8011ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8021ef4d424SStephen Rothwell * of_node_put() on it when done. 8031ef4d424SStephen Rothwell */ 80475c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) 8051ef4d424SStephen Rothwell { 806c22e650eSGrant Likely struct device_node *np = NULL; 807c22e650eSGrant Likely struct property *pp; 808d6d3c4e6SThomas Gleixner unsigned long flags; 80975c28c09SLeif Lindholm const char *separator = strchr(path, ':'); 81075c28c09SLeif Lindholm 81175c28c09SLeif Lindholm if (opts) 81275c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL; 8131ef4d424SStephen Rothwell 814c22e650eSGrant Likely if (strcmp(path, "/") == 0) 8155063e25aSGrant Likely return of_node_get(of_root); 816c22e650eSGrant Likely 817c22e650eSGrant Likely /* The path could begin with an alias */ 818c22e650eSGrant Likely if (*path != '/') { 819106937e8SLeif Lindholm int len; 820106937e8SLeif Lindholm const char *p = separator; 821106937e8SLeif Lindholm 822106937e8SLeif Lindholm if (!p) 823106937e8SLeif Lindholm p = strchrnul(path, '/'); 824106937e8SLeif Lindholm len = p - path; 825c22e650eSGrant Likely 826c22e650eSGrant Likely /* of_aliases must not be NULL */ 827c22e650eSGrant Likely if (!of_aliases) 828c22e650eSGrant Likely return NULL; 829c22e650eSGrant Likely 830c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) { 831c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { 832c22e650eSGrant Likely np = of_find_node_by_path(pp->value); 8331ef4d424SStephen Rothwell break; 8341ef4d424SStephen Rothwell } 835c22e650eSGrant Likely } 836c22e650eSGrant Likely if (!np) 837c22e650eSGrant Likely return NULL; 838c22e650eSGrant Likely path = p; 839c22e650eSGrant Likely } 840c22e650eSGrant Likely 841c22e650eSGrant Likely /* Step down the tree matching path components */ 842c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags); 843c22e650eSGrant Likely if (!np) 8445063e25aSGrant Likely np = of_node_get(of_root); 845c22e650eSGrant Likely while (np && *path == '/') { 846c22e650eSGrant Likely path++; /* Increment past '/' delimiter */ 847c22e650eSGrant Likely np = __of_find_node_by_path(np, path); 848c22e650eSGrant Likely path = strchrnul(path, '/'); 849106937e8SLeif Lindholm if (separator && separator < path) 850106937e8SLeif Lindholm break; 851c22e650eSGrant Likely } 852d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8531ef4d424SStephen Rothwell return np; 8541ef4d424SStephen Rothwell } 85575c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path); 8561ef4d424SStephen Rothwell 8571ef4d424SStephen Rothwell /** 8581ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 8591ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8601ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8611ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8621ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8631ef4d424SStephen Rothwell * @name: The name string to match against 8641ef4d424SStephen Rothwell * 8651ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8661ef4d424SStephen Rothwell * of_node_put() on it when done. 8671ef4d424SStephen Rothwell */ 8681ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 8691ef4d424SStephen Rothwell const char *name) 8701ef4d424SStephen Rothwell { 8711ef4d424SStephen Rothwell struct device_node *np; 872d6d3c4e6SThomas Gleixner unsigned long flags; 8731ef4d424SStephen Rothwell 874d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8755063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8761ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 8771ef4d424SStephen Rothwell && of_node_get(np)) 8781ef4d424SStephen Rothwell break; 8791ef4d424SStephen Rothwell of_node_put(from); 880d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8811ef4d424SStephen Rothwell return np; 8821ef4d424SStephen Rothwell } 8831ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 8841ef4d424SStephen Rothwell 8851ef4d424SStephen Rothwell /** 8861ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 8871ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 8881ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 8891ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 8901ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 8911ef4d424SStephen Rothwell * called on from for you. 8921ef4d424SStephen Rothwell * @type: The type string to match against 8931ef4d424SStephen Rothwell * 8941ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8951ef4d424SStephen Rothwell * of_node_put() on it when done. 8961ef4d424SStephen Rothwell */ 8971ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 8981ef4d424SStephen Rothwell const char *type) 8991ef4d424SStephen Rothwell { 9001ef4d424SStephen Rothwell struct device_node *np; 901d6d3c4e6SThomas Gleixner unsigned long flags; 9021ef4d424SStephen Rothwell 903d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9045063e25aSGrant Likely for_each_of_allnodes_from(from, np) 9051ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 9061ef4d424SStephen Rothwell && of_node_get(np)) 9071ef4d424SStephen Rothwell break; 9081ef4d424SStephen Rothwell of_node_put(from); 909d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9101ef4d424SStephen Rothwell return np; 9111ef4d424SStephen Rothwell } 9121ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 9131ef4d424SStephen Rothwell 9141ef4d424SStephen Rothwell /** 9151ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 9161ef4d424SStephen Rothwell * tokens in its "compatible" property 9171ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 9181ef4d424SStephen Rothwell * you pass will not be searched, only the next one 9191ef4d424SStephen Rothwell * will; typically, you pass what the previous call 9201ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 9211ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 9221ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 9231ef4d424SStephen Rothwell * "compatible" list. 9241ef4d424SStephen Rothwell * 9251ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 9261ef4d424SStephen Rothwell * of_node_put() on it when done. 9271ef4d424SStephen Rothwell */ 9281ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 9291ef4d424SStephen Rothwell const char *type, const char *compatible) 9301ef4d424SStephen Rothwell { 9311ef4d424SStephen Rothwell struct device_node *np; 932d6d3c4e6SThomas Gleixner unsigned long flags; 9331ef4d424SStephen Rothwell 934d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9355063e25aSGrant Likely for_each_of_allnodes_from(from, np) 936215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) && 93728d0e36bSThomas Gleixner of_node_get(np)) 9381ef4d424SStephen Rothwell break; 9391ef4d424SStephen Rothwell of_node_put(from); 940d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9411ef4d424SStephen Rothwell return np; 9421ef4d424SStephen Rothwell } 9431ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 944283029d1SGrant Likely 945283029d1SGrant Likely /** 9461e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 9471e291b14SMichael Ellerman * the given name. 9481e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 9491e291b14SMichael Ellerman * you pass will not be searched, only the next one 9501e291b14SMichael Ellerman * will; typically, you pass what the previous call 9511e291b14SMichael Ellerman * returned. of_node_put() will be called on it 9521e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 9531e291b14SMichael Ellerman * 9541e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 9551e291b14SMichael Ellerman * of_node_put() on it when done. 9561e291b14SMichael Ellerman */ 9571e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 9581e291b14SMichael Ellerman const char *prop_name) 9591e291b14SMichael Ellerman { 9601e291b14SMichael Ellerman struct device_node *np; 9611e291b14SMichael Ellerman struct property *pp; 962d6d3c4e6SThomas Gleixner unsigned long flags; 9631e291b14SMichael Ellerman 964d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9655063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 966a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 9671e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 9681e291b14SMichael Ellerman of_node_get(np); 9691e291b14SMichael Ellerman goto out; 9701e291b14SMichael Ellerman } 9711e291b14SMichael Ellerman } 9721e291b14SMichael Ellerman } 9731e291b14SMichael Ellerman out: 9741e291b14SMichael Ellerman of_node_put(from); 975d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 9761e291b14SMichael Ellerman return np; 9771e291b14SMichael Ellerman } 9781e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 9791e291b14SMichael Ellerman 98028d0e36bSThomas Gleixner static 98128d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 982283029d1SGrant Likely const struct device_node *node) 983283029d1SGrant Likely { 984215a14cfSKevin Hao const struct of_device_id *best_match = NULL; 985215a14cfSKevin Hao int score, best_score = 0; 986215a14cfSKevin Hao 987a52f07ecSGrant Likely if (!matches) 988a52f07ecSGrant Likely return NULL; 989a52f07ecSGrant Likely 990215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { 991215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible, 992215a14cfSKevin Hao matches->type, matches->name); 993215a14cfSKevin Hao if (score > best_score) { 994215a14cfSKevin Hao best_match = matches; 995215a14cfSKevin Hao best_score = score; 996283029d1SGrant Likely } 997215a14cfSKevin Hao } 998215a14cfSKevin Hao 999215a14cfSKevin Hao return best_match; 1000283029d1SGrant Likely } 100128d0e36bSThomas Gleixner 100228d0e36bSThomas Gleixner /** 1003c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure 100428d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 100528d0e36bSThomas Gleixner * @node: the of device structure to match against 100628d0e36bSThomas Gleixner * 100771c5498eSKevin Hao * Low level utility function used by device matching. 100828d0e36bSThomas Gleixner */ 100928d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 101028d0e36bSThomas Gleixner const struct device_node *node) 101128d0e36bSThomas Gleixner { 101228d0e36bSThomas Gleixner const struct of_device_id *match; 1013d6d3c4e6SThomas Gleixner unsigned long flags; 101428d0e36bSThomas Gleixner 1015d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 101628d0e36bSThomas Gleixner match = __of_match_node(matches, node); 1017d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 101828d0e36bSThomas Gleixner return match; 101928d0e36bSThomas Gleixner } 1020283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 1021283029d1SGrant Likely 1022283029d1SGrant Likely /** 102350c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 102450c8af4cSStephen Warren * match table. 1025283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 1026283029d1SGrant Likely * you pass will not be searched, only the next one 1027283029d1SGrant Likely * will; typically, you pass what the previous call 1028283029d1SGrant Likely * returned. of_node_put() will be called on it 1029283029d1SGrant Likely * @matches: array of of device match structures to search in 103050c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 1031283029d1SGrant Likely * 1032283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 1033283029d1SGrant Likely * of_node_put() on it when done. 1034283029d1SGrant Likely */ 103550c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 103650c8af4cSStephen Warren const struct of_device_id *matches, 103750c8af4cSStephen Warren const struct of_device_id **match) 1038283029d1SGrant Likely { 1039283029d1SGrant Likely struct device_node *np; 1040dc71bcf1SThomas Abraham const struct of_device_id *m; 1041d6d3c4e6SThomas Gleixner unsigned long flags; 1042283029d1SGrant Likely 104350c8af4cSStephen Warren if (match) 104450c8af4cSStephen Warren *match = NULL; 104550c8af4cSStephen Warren 1046d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 10475063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 104828d0e36bSThomas Gleixner m = __of_match_node(matches, np); 1049dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 105050c8af4cSStephen Warren if (match) 1051dc71bcf1SThomas Abraham *match = m; 1052283029d1SGrant Likely break; 1053283029d1SGrant Likely } 105450c8af4cSStephen Warren } 1055283029d1SGrant Likely of_node_put(from); 1056d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1057283029d1SGrant Likely return np; 1058283029d1SGrant Likely } 105980c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 10603f07af49SGrant Likely 10613f07af49SGrant Likely /** 10623f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 10633f07af49SGrant Likely * @node: pointer to a device tree node 10643f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 10653f07af49SGrant Likely * @len: Length of modalias value 10663f07af49SGrant Likely * 10672ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 10682ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 10692ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 10702ffe8c5fSGrant Likely * from the first entry in the compatible list property. 10713f07af49SGrant Likely * 10722ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 10733f07af49SGrant Likely */ 10743f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 10753f07af49SGrant Likely { 10762ffe8c5fSGrant Likely const char *compatible, *p; 10772ffe8c5fSGrant Likely int cplen; 10783f07af49SGrant Likely 10793f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 10802ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 10813f07af49SGrant Likely return -ENODEV; 10823f07af49SGrant Likely p = strchr(compatible, ','); 10832ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 10843f07af49SGrant Likely return 0; 10853f07af49SGrant Likely } 10863f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 10873f07af49SGrant Likely 108864b60e09SAnton Vorontsov /** 108989751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 109089751a7cSJeremy Kerr * @handle: phandle of the node to find 109189751a7cSJeremy Kerr * 109289751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 109389751a7cSJeremy Kerr * of_node_put() on it when done. 109489751a7cSJeremy Kerr */ 109589751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 109689751a7cSJeremy Kerr { 109789751a7cSJeremy Kerr struct device_node *np; 1098d25d8694SBenjamin Herrenschmidt unsigned long flags; 109989751a7cSJeremy Kerr 1100fc59b447SGrant Likely if (!handle) 1101fc59b447SGrant Likely return NULL; 1102fc59b447SGrant Likely 1103d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 11045063e25aSGrant Likely for_each_of_allnodes(np) 110589751a7cSJeremy Kerr if (np->phandle == handle) 110689751a7cSJeremy Kerr break; 110789751a7cSJeremy Kerr of_node_get(np); 1108d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 110989751a7cSJeremy Kerr return np; 111089751a7cSJeremy Kerr } 111189751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 111289751a7cSJeremy Kerr 111389751a7cSJeremy Kerr /** 1114ad54a0cfSHeiko Stuebner * of_property_count_elems_of_size - Count the number of elements in a property 1115ad54a0cfSHeiko Stuebner * 1116ad54a0cfSHeiko Stuebner * @np: device node from which the property value is to be read. 1117ad54a0cfSHeiko Stuebner * @propname: name of the property to be searched. 1118ad54a0cfSHeiko Stuebner * @elem_size: size of the individual element 1119ad54a0cfSHeiko Stuebner * 1120ad54a0cfSHeiko Stuebner * Search for a property in a device node and count the number of elements of 1121ad54a0cfSHeiko Stuebner * size elem_size in it. Returns number of elements on sucess, -EINVAL if the 1122ad54a0cfSHeiko Stuebner * property does not exist or its length does not match a multiple of elem_size 1123ad54a0cfSHeiko Stuebner * and -ENODATA if the property does not have a value. 1124ad54a0cfSHeiko Stuebner */ 1125ad54a0cfSHeiko Stuebner int of_property_count_elems_of_size(const struct device_node *np, 1126ad54a0cfSHeiko Stuebner const char *propname, int elem_size) 1127ad54a0cfSHeiko Stuebner { 1128ad54a0cfSHeiko Stuebner struct property *prop = of_find_property(np, propname, NULL); 1129ad54a0cfSHeiko Stuebner 1130ad54a0cfSHeiko Stuebner if (!prop) 1131ad54a0cfSHeiko Stuebner return -EINVAL; 1132ad54a0cfSHeiko Stuebner if (!prop->value) 1133ad54a0cfSHeiko Stuebner return -ENODATA; 1134ad54a0cfSHeiko Stuebner 1135ad54a0cfSHeiko Stuebner if (prop->length % elem_size != 0) { 1136ad54a0cfSHeiko Stuebner pr_err("size of %s in node %s is not a multiple of %d\n", 1137ad54a0cfSHeiko Stuebner propname, np->full_name, elem_size); 1138ad54a0cfSHeiko Stuebner return -EINVAL; 1139ad54a0cfSHeiko Stuebner } 1140ad54a0cfSHeiko Stuebner 1141ad54a0cfSHeiko Stuebner return prop->length / elem_size; 1142ad54a0cfSHeiko Stuebner } 1143ad54a0cfSHeiko Stuebner EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); 1144ad54a0cfSHeiko Stuebner 1145ad54a0cfSHeiko Stuebner /** 1146daeec1f0STony Prisk * of_find_property_value_of_size 1147daeec1f0STony Prisk * 1148daeec1f0STony Prisk * @np: device node from which the property value is to be read. 1149daeec1f0STony Prisk * @propname: name of the property to be searched. 115079ac5d31SRichard Fitzgerald * @min: minimum allowed length of property value 115179ac5d31SRichard Fitzgerald * @max: maximum allowed length of property value (0 means unlimited) 115279ac5d31SRichard Fitzgerald * @len: if !=NULL, actual length is written to here 1153daeec1f0STony Prisk * 1154daeec1f0STony Prisk * Search for a property in a device node and valid the requested size. 1155daeec1f0STony Prisk * Returns the property value on success, -EINVAL if the property does not 1156daeec1f0STony Prisk * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the 115779ac5d31SRichard Fitzgerald * property data is too small or too large. 1158daeec1f0STony Prisk * 1159daeec1f0STony Prisk */ 1160daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np, 116179ac5d31SRichard Fitzgerald const char *propname, u32 min, u32 max, size_t *len) 1162daeec1f0STony Prisk { 1163daeec1f0STony Prisk struct property *prop = of_find_property(np, propname, NULL); 1164daeec1f0STony Prisk 1165daeec1f0STony Prisk if (!prop) 1166daeec1f0STony Prisk return ERR_PTR(-EINVAL); 1167daeec1f0STony Prisk if (!prop->value) 1168daeec1f0STony Prisk return ERR_PTR(-ENODATA); 116979ac5d31SRichard Fitzgerald if (prop->length < min) 1170daeec1f0STony Prisk return ERR_PTR(-EOVERFLOW); 117179ac5d31SRichard Fitzgerald if (max && prop->length > max) 117279ac5d31SRichard Fitzgerald return ERR_PTR(-EOVERFLOW); 117379ac5d31SRichard Fitzgerald 117479ac5d31SRichard Fitzgerald if (len) 117579ac5d31SRichard Fitzgerald *len = prop->length; 1176daeec1f0STony Prisk 1177daeec1f0STony Prisk return prop->value; 1178daeec1f0STony Prisk } 1179daeec1f0STony Prisk 1180daeec1f0STony Prisk /** 11813daf3726STony Prisk * of_property_read_u32_index - Find and read a u32 from a multi-value property. 11823daf3726STony Prisk * 11833daf3726STony Prisk * @np: device node from which the property value is to be read. 11843daf3726STony Prisk * @propname: name of the property to be searched. 11853daf3726STony Prisk * @index: index of the u32 in the list of values 11863daf3726STony Prisk * @out_value: pointer to return value, modified only if no error. 11873daf3726STony Prisk * 11883daf3726STony Prisk * Search for a property in a device node and read nth 32-bit value from 11893daf3726STony Prisk * it. Returns 0 on success, -EINVAL if the property does not exist, 11903daf3726STony Prisk * -ENODATA if property does not have a value, and -EOVERFLOW if the 11913daf3726STony Prisk * property data isn't large enough. 11923daf3726STony Prisk * 11933daf3726STony Prisk * The out_value is modified only if a valid u32 value can be decoded. 11943daf3726STony Prisk */ 11953daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np, 11963daf3726STony Prisk const char *propname, 11973daf3726STony Prisk u32 index, u32 *out_value) 11983daf3726STony Prisk { 1199daeec1f0STony Prisk const u32 *val = of_find_property_value_of_size(np, propname, 120079ac5d31SRichard Fitzgerald ((index + 1) * sizeof(*out_value)), 120179ac5d31SRichard Fitzgerald 0, 120279ac5d31SRichard Fitzgerald NULL); 12033daf3726STony Prisk 1204daeec1f0STony Prisk if (IS_ERR(val)) 1205daeec1f0STony Prisk return PTR_ERR(val); 12063daf3726STony Prisk 1207daeec1f0STony Prisk *out_value = be32_to_cpup(((__be32 *)val) + index); 12083daf3726STony Prisk return 0; 12093daf3726STony Prisk } 12103daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index); 12113daf3726STony Prisk 12123daf3726STony Prisk /** 1213a67e9472SRichard Fitzgerald * of_property_read_variable_u8_array - Find and read an array of u8 from a 1214a67e9472SRichard Fitzgerald * property, with bounds on the minimum and maximum array size. 1215be193249SViresh Kumar * 1216be193249SViresh Kumar * @np: device node from which the property value is to be read. 1217be193249SViresh Kumar * @propname: name of the property to be searched. 1218792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1219a67e9472SRichard Fitzgerald * @sz_min: minimum number of array elements to read 1220a67e9472SRichard Fitzgerald * @sz_max: maximum number of array elements to read, if zero there is no 1221a67e9472SRichard Fitzgerald * upper limit on the number of elements in the dts entry but only 1222a67e9472SRichard Fitzgerald * sz_min will be read. 1223be193249SViresh Kumar * 1224be193249SViresh Kumar * Search for a property in a device node and read 8-bit value(s) from 1225a67e9472SRichard Fitzgerald * it. Returns number of elements read on success, -EINVAL if the property 1226a67e9472SRichard Fitzgerald * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW 1227a67e9472SRichard Fitzgerald * if the property data is smaller than sz_min or longer than sz_max. 1228be193249SViresh Kumar * 1229be193249SViresh Kumar * dts entry of array should be like: 1230be193249SViresh Kumar * property = /bits/ 8 <0x50 0x60 0x70>; 1231be193249SViresh Kumar * 1232792efb84SLad, Prabhakar * The out_values is modified only if a valid u8 value can be decoded. 1233be193249SViresh Kumar */ 1234a67e9472SRichard Fitzgerald int of_property_read_variable_u8_array(const struct device_node *np, 1235a67e9472SRichard Fitzgerald const char *propname, u8 *out_values, 1236a67e9472SRichard Fitzgerald size_t sz_min, size_t sz_max) 1237be193249SViresh Kumar { 1238a67e9472SRichard Fitzgerald size_t sz, count; 1239daeec1f0STony Prisk const u8 *val = of_find_property_value_of_size(np, propname, 1240a67e9472SRichard Fitzgerald (sz_min * sizeof(*out_values)), 1241a67e9472SRichard Fitzgerald (sz_max * sizeof(*out_values)), 1242a67e9472SRichard Fitzgerald &sz); 1243be193249SViresh Kumar 1244daeec1f0STony Prisk if (IS_ERR(val)) 1245daeec1f0STony Prisk return PTR_ERR(val); 1246be193249SViresh Kumar 1247a67e9472SRichard Fitzgerald if (!sz_max) 1248a67e9472SRichard Fitzgerald sz = sz_min; 1249a67e9472SRichard Fitzgerald else 1250a67e9472SRichard Fitzgerald sz /= sizeof(*out_values); 1251a67e9472SRichard Fitzgerald 1252a67e9472SRichard Fitzgerald count = sz; 1253a67e9472SRichard Fitzgerald while (count--) 1254be193249SViresh Kumar *out_values++ = *val++; 1255a67e9472SRichard Fitzgerald 1256a67e9472SRichard Fitzgerald return sz; 1257be193249SViresh Kumar } 1258a67e9472SRichard Fitzgerald EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array); 1259be193249SViresh Kumar 1260be193249SViresh Kumar /** 1261a67e9472SRichard Fitzgerald * of_property_read_variable_u16_array - Find and read an array of u16 from a 1262a67e9472SRichard Fitzgerald * property, with bounds on the minimum and maximum array size. 1263be193249SViresh Kumar * 1264be193249SViresh Kumar * @np: device node from which the property value is to be read. 1265be193249SViresh Kumar * @propname: name of the property to be searched. 1266792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1267a67e9472SRichard Fitzgerald * @sz_min: minimum number of array elements to read 1268a67e9472SRichard Fitzgerald * @sz_max: maximum number of array elements to read, if zero there is no 1269a67e9472SRichard Fitzgerald * upper limit on the number of elements in the dts entry but only 1270a67e9472SRichard Fitzgerald * sz_min will be read. 1271be193249SViresh Kumar * 1272be193249SViresh Kumar * Search for a property in a device node and read 16-bit value(s) from 1273a67e9472SRichard Fitzgerald * it. Returns number of elements read on success, -EINVAL if the property 1274a67e9472SRichard Fitzgerald * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW 1275a67e9472SRichard Fitzgerald * if the property data is smaller than sz_min or longer than sz_max. 1276be193249SViresh Kumar * 1277be193249SViresh Kumar * dts entry of array should be like: 1278be193249SViresh Kumar * property = /bits/ 16 <0x5000 0x6000 0x7000>; 1279be193249SViresh Kumar * 1280792efb84SLad, Prabhakar * The out_values is modified only if a valid u16 value can be decoded. 1281be193249SViresh Kumar */ 1282a67e9472SRichard Fitzgerald int of_property_read_variable_u16_array(const struct device_node *np, 1283a67e9472SRichard Fitzgerald const char *propname, u16 *out_values, 1284a67e9472SRichard Fitzgerald size_t sz_min, size_t sz_max) 1285be193249SViresh Kumar { 1286a67e9472SRichard Fitzgerald size_t sz, count; 1287daeec1f0STony Prisk const __be16 *val = of_find_property_value_of_size(np, propname, 1288a67e9472SRichard Fitzgerald (sz_min * sizeof(*out_values)), 1289a67e9472SRichard Fitzgerald (sz_max * sizeof(*out_values)), 1290a67e9472SRichard Fitzgerald &sz); 1291be193249SViresh Kumar 1292daeec1f0STony Prisk if (IS_ERR(val)) 1293daeec1f0STony Prisk return PTR_ERR(val); 1294be193249SViresh Kumar 1295a67e9472SRichard Fitzgerald if (!sz_max) 1296a67e9472SRichard Fitzgerald sz = sz_min; 1297a67e9472SRichard Fitzgerald else 1298a67e9472SRichard Fitzgerald sz /= sizeof(*out_values); 1299a67e9472SRichard Fitzgerald 1300a67e9472SRichard Fitzgerald count = sz; 1301a67e9472SRichard Fitzgerald while (count--) 1302be193249SViresh Kumar *out_values++ = be16_to_cpup(val++); 1303a67e9472SRichard Fitzgerald 1304a67e9472SRichard Fitzgerald return sz; 1305be193249SViresh Kumar } 1306a67e9472SRichard Fitzgerald EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array); 1307be193249SViresh Kumar 1308be193249SViresh Kumar /** 1309a67e9472SRichard Fitzgerald * of_property_read_variable_u32_array - Find and read an array of 32 bit 1310a67e9472SRichard Fitzgerald * integers from a property, with bounds on the minimum and maximum array size. 13110e373639SRob Herring * 1312a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1313a3b85363SThomas Abraham * @propname: name of the property to be searched. 1314792efb84SLad, Prabhakar * @out_values: pointer to return value, modified only if return value is 0. 1315a67e9472SRichard Fitzgerald * @sz_min: minimum number of array elements to read 1316a67e9472SRichard Fitzgerald * @sz_max: maximum number of array elements to read, if zero there is no 1317a67e9472SRichard Fitzgerald * upper limit on the number of elements in the dts entry but only 1318a67e9472SRichard Fitzgerald * sz_min will be read. 1319a3b85363SThomas Abraham * 13200e373639SRob Herring * Search for a property in a device node and read 32-bit value(s) from 1321a67e9472SRichard Fitzgerald * it. Returns number of elements read on success, -EINVAL if the property 1322a67e9472SRichard Fitzgerald * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW 1323a67e9472SRichard Fitzgerald * if the property data is smaller than sz_min or longer than sz_max. 1324a3b85363SThomas Abraham * 1325792efb84SLad, Prabhakar * The out_values is modified only if a valid u32 value can be decoded. 1326a3b85363SThomas Abraham */ 1327a67e9472SRichard Fitzgerald int of_property_read_variable_u32_array(const struct device_node *np, 1328aac285c6SJamie Iles const char *propname, u32 *out_values, 1329a67e9472SRichard Fitzgerald size_t sz_min, size_t sz_max) 1330a3b85363SThomas Abraham { 1331a67e9472SRichard Fitzgerald size_t sz, count; 1332daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 1333a67e9472SRichard Fitzgerald (sz_min * sizeof(*out_values)), 1334a67e9472SRichard Fitzgerald (sz_max * sizeof(*out_values)), 1335a67e9472SRichard Fitzgerald &sz); 1336a3b85363SThomas Abraham 1337daeec1f0STony Prisk if (IS_ERR(val)) 1338daeec1f0STony Prisk return PTR_ERR(val); 13390e373639SRob Herring 1340a67e9472SRichard Fitzgerald if (!sz_max) 1341a67e9472SRichard Fitzgerald sz = sz_min; 1342a67e9472SRichard Fitzgerald else 1343a67e9472SRichard Fitzgerald sz /= sizeof(*out_values); 1344a67e9472SRichard Fitzgerald 1345a67e9472SRichard Fitzgerald count = sz; 1346a67e9472SRichard Fitzgerald while (count--) 13470e373639SRob Herring *out_values++ = be32_to_cpup(val++); 1348a67e9472SRichard Fitzgerald 1349a67e9472SRichard Fitzgerald return sz; 1350a3b85363SThomas Abraham } 1351a67e9472SRichard Fitzgerald EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array); 1352a3b85363SThomas Abraham 1353a3b85363SThomas Abraham /** 13544cd7f7a3SJamie Iles * of_property_read_u64 - Find and read a 64 bit integer from a property 13554cd7f7a3SJamie Iles * @np: device node from which the property value is to be read. 13564cd7f7a3SJamie Iles * @propname: name of the property to be searched. 13574cd7f7a3SJamie Iles * @out_value: pointer to return value, modified only if return value is 0. 13584cd7f7a3SJamie Iles * 13594cd7f7a3SJamie Iles * Search for a property in a device node and read a 64-bit value from 13604cd7f7a3SJamie Iles * it. Returns 0 on success, -EINVAL if the property does not exist, 13614cd7f7a3SJamie Iles * -ENODATA if property does not have a value, and -EOVERFLOW if the 13624cd7f7a3SJamie Iles * property data isn't large enough. 13634cd7f7a3SJamie Iles * 13644cd7f7a3SJamie Iles * The out_value is modified only if a valid u64 value can be decoded. 13654cd7f7a3SJamie Iles */ 13664cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname, 13674cd7f7a3SJamie Iles u64 *out_value) 13684cd7f7a3SJamie Iles { 1369daeec1f0STony Prisk const __be32 *val = of_find_property_value_of_size(np, propname, 137079ac5d31SRichard Fitzgerald sizeof(*out_value), 137179ac5d31SRichard Fitzgerald 0, 137279ac5d31SRichard Fitzgerald NULL); 13734cd7f7a3SJamie Iles 1374daeec1f0STony Prisk if (IS_ERR(val)) 1375daeec1f0STony Prisk return PTR_ERR(val); 1376daeec1f0STony Prisk 1377daeec1f0STony Prisk *out_value = of_read_number(val, 2); 13784cd7f7a3SJamie Iles return 0; 13794cd7f7a3SJamie Iles } 13804cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64); 13814cd7f7a3SJamie Iles 13824cd7f7a3SJamie Iles /** 1383a67e9472SRichard Fitzgerald * of_property_read_variable_u64_array - Find and read an array of 64 bit 1384a67e9472SRichard Fitzgerald * integers from a property, with bounds on the minimum and maximum array size. 1385b31384faSRafael J. Wysocki * 1386b31384faSRafael J. Wysocki * @np: device node from which the property value is to be read. 1387b31384faSRafael J. Wysocki * @propname: name of the property to be searched. 1388b31384faSRafael J. Wysocki * @out_values: pointer to return value, modified only if return value is 0. 1389a67e9472SRichard Fitzgerald * @sz_min: minimum number of array elements to read 1390a67e9472SRichard Fitzgerald * @sz_max: maximum number of array elements to read, if zero there is no 1391a67e9472SRichard Fitzgerald * upper limit on the number of elements in the dts entry but only 1392a67e9472SRichard Fitzgerald * sz_min will be read. 1393b31384faSRafael J. Wysocki * 1394b31384faSRafael J. Wysocki * Search for a property in a device node and read 64-bit value(s) from 1395a67e9472SRichard Fitzgerald * it. Returns number of elements read on success, -EINVAL if the property 1396a67e9472SRichard Fitzgerald * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW 1397a67e9472SRichard Fitzgerald * if the property data is smaller than sz_min or longer than sz_max. 1398b31384faSRafael J. Wysocki * 1399b31384faSRafael J. Wysocki * The out_values is modified only if a valid u64 value can be decoded. 1400b31384faSRafael J. Wysocki */ 1401a67e9472SRichard Fitzgerald int of_property_read_variable_u64_array(const struct device_node *np, 1402b31384faSRafael J. Wysocki const char *propname, u64 *out_values, 1403a67e9472SRichard Fitzgerald size_t sz_min, size_t sz_max) 1404b31384faSRafael J. Wysocki { 1405a67e9472SRichard Fitzgerald size_t sz, count; 1406b31384faSRafael J. Wysocki const __be32 *val = of_find_property_value_of_size(np, propname, 1407a67e9472SRichard Fitzgerald (sz_min * sizeof(*out_values)), 1408a67e9472SRichard Fitzgerald (sz_max * sizeof(*out_values)), 1409a67e9472SRichard Fitzgerald &sz); 1410b31384faSRafael J. Wysocki 1411b31384faSRafael J. Wysocki if (IS_ERR(val)) 1412b31384faSRafael J. Wysocki return PTR_ERR(val); 1413b31384faSRafael J. Wysocki 1414a67e9472SRichard Fitzgerald if (!sz_max) 1415a67e9472SRichard Fitzgerald sz = sz_min; 1416a67e9472SRichard Fitzgerald else 1417a67e9472SRichard Fitzgerald sz /= sizeof(*out_values); 1418a67e9472SRichard Fitzgerald 1419a67e9472SRichard Fitzgerald count = sz; 1420a67e9472SRichard Fitzgerald while (count--) { 1421b31384faSRafael J. Wysocki *out_values++ = of_read_number(val, 2); 1422b31384faSRafael J. Wysocki val += 2; 1423b31384faSRafael J. Wysocki } 1424a67e9472SRichard Fitzgerald 1425a67e9472SRichard Fitzgerald return sz; 1426b31384faSRafael J. Wysocki } 1427a67e9472SRichard Fitzgerald EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array); 1428b31384faSRafael J. Wysocki 1429b31384faSRafael J. Wysocki /** 1430a3b85363SThomas Abraham * of_property_read_string - Find and read a string from a property 1431a3b85363SThomas Abraham * @np: device node from which the property value is to be read. 1432a3b85363SThomas Abraham * @propname: name of the property to be searched. 1433a3b85363SThomas Abraham * @out_string: pointer to null terminated return string, modified only if 1434a3b85363SThomas Abraham * return value is 0. 1435a3b85363SThomas Abraham * 1436a3b85363SThomas Abraham * Search for a property in a device tree node and retrieve a null 1437a3b85363SThomas Abraham * terminated string value (pointer to data, not a copy). Returns 0 on 1438a3b85363SThomas Abraham * success, -EINVAL if the property does not exist, -ENODATA if property 1439a3b85363SThomas Abraham * does not have a value, and -EILSEQ if the string is not null-terminated 1440a3b85363SThomas Abraham * within the length of the property data. 1441a3b85363SThomas Abraham * 1442a3b85363SThomas Abraham * The out_string pointer is modified only if a valid string can be decoded. 1443a3b85363SThomas Abraham */ 1444fe99c707SDavid Rivshin int of_property_read_string(const struct device_node *np, const char *propname, 1445f09bc831SShawn Guo const char **out_string) 1446a3b85363SThomas Abraham { 1447fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 1448a3b85363SThomas Abraham if (!prop) 1449a3b85363SThomas Abraham return -EINVAL; 1450a3b85363SThomas Abraham if (!prop->value) 1451a3b85363SThomas Abraham return -ENODATA; 1452a3b85363SThomas Abraham if (strnlen(prop->value, prop->length) >= prop->length) 1453a3b85363SThomas Abraham return -EILSEQ; 1454a3b85363SThomas Abraham *out_string = prop->value; 1455a3b85363SThomas Abraham return 0; 1456a3b85363SThomas Abraham } 1457a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string); 1458a3b85363SThomas Abraham 1459a3b85363SThomas Abraham /** 14607aff0fe3SGrant Likely * of_property_match_string() - Find string in a list and return index 14617aff0fe3SGrant Likely * @np: pointer to node containing string list property 14627aff0fe3SGrant Likely * @propname: string list property name 14637aff0fe3SGrant Likely * @string: pointer to string to search for in string list 14647aff0fe3SGrant Likely * 14657aff0fe3SGrant Likely * This function searches a string list property and returns the index 14667aff0fe3SGrant Likely * of a specific string value. 14677aff0fe3SGrant Likely */ 1468fe99c707SDavid Rivshin int of_property_match_string(const struct device_node *np, const char *propname, 14697aff0fe3SGrant Likely const char *string) 14707aff0fe3SGrant Likely { 1471fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 14727aff0fe3SGrant Likely size_t l; 14737aff0fe3SGrant Likely int i; 14747aff0fe3SGrant Likely const char *p, *end; 14757aff0fe3SGrant Likely 14767aff0fe3SGrant Likely if (!prop) 14777aff0fe3SGrant Likely return -EINVAL; 14787aff0fe3SGrant Likely if (!prop->value) 14797aff0fe3SGrant Likely return -ENODATA; 14807aff0fe3SGrant Likely 14817aff0fe3SGrant Likely p = prop->value; 14827aff0fe3SGrant Likely end = p + prop->length; 14837aff0fe3SGrant Likely 14847aff0fe3SGrant Likely for (i = 0; p < end; i++, p += l) { 1485a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 14867aff0fe3SGrant Likely if (p + l > end) 14877aff0fe3SGrant Likely return -EILSEQ; 14887aff0fe3SGrant Likely pr_debug("comparing %s with %s\n", string, p); 14897aff0fe3SGrant Likely if (strcmp(string, p) == 0) 14907aff0fe3SGrant Likely return i; /* Found it; return index */ 14917aff0fe3SGrant Likely } 14927aff0fe3SGrant Likely return -ENODATA; 14937aff0fe3SGrant Likely } 14947aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string); 14954fcd15a0SBenoit Cousson 14964fcd15a0SBenoit Cousson /** 1497e99010edSJiri Slaby * of_property_read_string_helper() - Utility helper for parsing string properties 14984fcd15a0SBenoit Cousson * @np: device node from which the property value is to be read. 14994fcd15a0SBenoit Cousson * @propname: name of the property to be searched. 1500a87fa1d8SGrant Likely * @out_strs: output array of string pointers. 1501a87fa1d8SGrant Likely * @sz: number of array elements to read. 1502a87fa1d8SGrant Likely * @skip: Number of strings to skip over at beginning of list. 15034fcd15a0SBenoit Cousson * 1504a87fa1d8SGrant Likely * Don't call this function directly. It is a utility helper for the 1505a87fa1d8SGrant Likely * of_property_read_string*() family of functions. 15064fcd15a0SBenoit Cousson */ 1507fe99c707SDavid Rivshin int of_property_read_string_helper(const struct device_node *np, 1508fe99c707SDavid Rivshin const char *propname, const char **out_strs, 1509fe99c707SDavid Rivshin size_t sz, int skip) 15104fcd15a0SBenoit Cousson { 1511fe99c707SDavid Rivshin const struct property *prop = of_find_property(np, propname, NULL); 1512a87fa1d8SGrant Likely int l = 0, i = 0; 1513a87fa1d8SGrant Likely const char *p, *end; 15144fcd15a0SBenoit Cousson 15154fcd15a0SBenoit Cousson if (!prop) 15164fcd15a0SBenoit Cousson return -EINVAL; 15174fcd15a0SBenoit Cousson if (!prop->value) 15184fcd15a0SBenoit Cousson return -ENODATA; 15194fcd15a0SBenoit Cousson p = prop->value; 1520a87fa1d8SGrant Likely end = p + prop->length; 15214fcd15a0SBenoit Cousson 1522a87fa1d8SGrant Likely for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 1523a87fa1d8SGrant Likely l = strnlen(p, end - p) + 1; 1524a87fa1d8SGrant Likely if (p + l > end) 1525a87fa1d8SGrant Likely return -EILSEQ; 1526a87fa1d8SGrant Likely if (out_strs && i >= skip) 1527a87fa1d8SGrant Likely *out_strs++ = p; 15284fcd15a0SBenoit Cousson } 1529a87fa1d8SGrant Likely i -= skip; 1530a87fa1d8SGrant Likely return i <= 0 ? -ENODATA : i; 1531a87fa1d8SGrant Likely } 1532a87fa1d8SGrant Likely EXPORT_SYMBOL_GPL(of_property_read_string_helper); 15334fcd15a0SBenoit Cousson 1534624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1535624cfca5SGrant Likely { 1536624cfca5SGrant Likely int i; 1537624cfca5SGrant Likely printk("%s %s", msg, of_node_full_name(args->np)); 15384aa66344SMarcin Nowakowski for (i = 0; i < args->args_count; i++) { 15394aa66344SMarcin Nowakowski const char delim = i ? ',' : ':'; 15404aa66344SMarcin Nowakowski 15414aa66344SMarcin Nowakowski pr_cont("%c%08x", delim, args->args[i]); 15424aa66344SMarcin Nowakowski } 15434aa66344SMarcin Nowakowski pr_cont("\n"); 1544624cfca5SGrant Likely } 1545624cfca5SGrant Likely 154674e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it, 154774e1fbb1SJoerg Roedel const struct device_node *np, 154874e1fbb1SJoerg Roedel const char *list_name, 154974e1fbb1SJoerg Roedel const char *cells_name, 155074e1fbb1SJoerg Roedel int cell_count) 155174e1fbb1SJoerg Roedel { 155274e1fbb1SJoerg Roedel const __be32 *list; 155374e1fbb1SJoerg Roedel int size; 155474e1fbb1SJoerg Roedel 155574e1fbb1SJoerg Roedel memset(it, 0, sizeof(*it)); 155674e1fbb1SJoerg Roedel 155774e1fbb1SJoerg Roedel list = of_get_property(np, list_name, &size); 155874e1fbb1SJoerg Roedel if (!list) 155974e1fbb1SJoerg Roedel return -ENOENT; 156074e1fbb1SJoerg Roedel 156174e1fbb1SJoerg Roedel it->cells_name = cells_name; 156274e1fbb1SJoerg Roedel it->cell_count = cell_count; 156374e1fbb1SJoerg Roedel it->parent = np; 156474e1fbb1SJoerg Roedel it->list_end = list + size / sizeof(*list); 156574e1fbb1SJoerg Roedel it->phandle_end = list; 156674e1fbb1SJoerg Roedel it->cur = list; 156774e1fbb1SJoerg Roedel 156874e1fbb1SJoerg Roedel return 0; 156974e1fbb1SJoerg Roedel } 157074e1fbb1SJoerg Roedel 1571cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it) 1572cd209b41SJoerg Roedel { 1573cd209b41SJoerg Roedel uint32_t count = 0; 1574cd209b41SJoerg Roedel 1575cd209b41SJoerg Roedel if (it->node) { 1576cd209b41SJoerg Roedel of_node_put(it->node); 1577cd209b41SJoerg Roedel it->node = NULL; 1578cd209b41SJoerg Roedel } 1579cd209b41SJoerg Roedel 1580cd209b41SJoerg Roedel if (!it->cur || it->phandle_end >= it->list_end) 1581cd209b41SJoerg Roedel return -ENOENT; 1582cd209b41SJoerg Roedel 1583cd209b41SJoerg Roedel it->cur = it->phandle_end; 1584cd209b41SJoerg Roedel 1585cd209b41SJoerg Roedel /* If phandle is 0, then it is an empty entry with no arguments. */ 1586cd209b41SJoerg Roedel it->phandle = be32_to_cpup(it->cur++); 1587cd209b41SJoerg Roedel 1588cd209b41SJoerg Roedel if (it->phandle) { 1589cd209b41SJoerg Roedel 1590cd209b41SJoerg Roedel /* 1591cd209b41SJoerg Roedel * Find the provider node and parse the #*-cells property to 1592cd209b41SJoerg Roedel * determine the argument length. 1593cd209b41SJoerg Roedel */ 1594cd209b41SJoerg Roedel it->node = of_find_node_by_phandle(it->phandle); 1595cd209b41SJoerg Roedel 1596cd209b41SJoerg Roedel if (it->cells_name) { 1597cd209b41SJoerg Roedel if (!it->node) { 1598cd209b41SJoerg Roedel pr_err("%s: could not find phandle\n", 1599cd209b41SJoerg Roedel it->parent->full_name); 1600cd209b41SJoerg Roedel goto err; 1601cd209b41SJoerg Roedel } 1602cd209b41SJoerg Roedel 1603cd209b41SJoerg Roedel if (of_property_read_u32(it->node, it->cells_name, 1604cd209b41SJoerg Roedel &count)) { 1605cd209b41SJoerg Roedel pr_err("%s: could not get %s for %s\n", 1606cd209b41SJoerg Roedel it->parent->full_name, 1607cd209b41SJoerg Roedel it->cells_name, 1608cd209b41SJoerg Roedel it->node->full_name); 1609cd209b41SJoerg Roedel goto err; 1610cd209b41SJoerg Roedel } 1611cd209b41SJoerg Roedel } else { 1612cd209b41SJoerg Roedel count = it->cell_count; 1613cd209b41SJoerg Roedel } 1614cd209b41SJoerg Roedel 1615cd209b41SJoerg Roedel /* 1616cd209b41SJoerg Roedel * Make sure that the arguments actually fit in the remaining 1617cd209b41SJoerg Roedel * property data length 1618cd209b41SJoerg Roedel */ 1619cd209b41SJoerg Roedel if (it->cur + count > it->list_end) { 1620cd209b41SJoerg Roedel pr_err("%s: arguments longer than property\n", 1621cd209b41SJoerg Roedel it->parent->full_name); 1622cd209b41SJoerg Roedel goto err; 1623cd209b41SJoerg Roedel } 1624cd209b41SJoerg Roedel } 1625cd209b41SJoerg Roedel 1626cd209b41SJoerg Roedel it->phandle_end = it->cur + count; 1627cd209b41SJoerg Roedel it->cur_count = count; 1628cd209b41SJoerg Roedel 1629cd209b41SJoerg Roedel return 0; 1630cd209b41SJoerg Roedel 1631cd209b41SJoerg Roedel err: 1632cd209b41SJoerg Roedel if (it->node) { 1633cd209b41SJoerg Roedel of_node_put(it->node); 1634cd209b41SJoerg Roedel it->node = NULL; 1635cd209b41SJoerg Roedel } 1636cd209b41SJoerg Roedel 1637cd209b41SJoerg Roedel return -EINVAL; 1638cd209b41SJoerg Roedel } 1639cd209b41SJoerg Roedel 1640abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it, 1641abdaa77bSJoerg Roedel uint32_t *args, 1642abdaa77bSJoerg Roedel int size) 1643abdaa77bSJoerg Roedel { 1644abdaa77bSJoerg Roedel int i, count; 1645abdaa77bSJoerg Roedel 1646abdaa77bSJoerg Roedel count = it->cur_count; 1647abdaa77bSJoerg Roedel 1648abdaa77bSJoerg Roedel if (WARN_ON(size < count)) 1649abdaa77bSJoerg Roedel count = size; 1650abdaa77bSJoerg Roedel 1651abdaa77bSJoerg Roedel for (i = 0; i < count; i++) 1652abdaa77bSJoerg Roedel args[i] = be32_to_cpup(it->cur++); 1653abdaa77bSJoerg Roedel 1654abdaa77bSJoerg Roedel return count; 1655abdaa77bSJoerg Roedel } 1656abdaa77bSJoerg Roedel 1657bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1658bd69f73fSGrant Likely const char *list_name, 1659035fd948SStephen Warren const char *cells_name, 1660035fd948SStephen Warren int cell_count, int index, 166115c9a0acSGrant Likely struct of_phandle_args *out_args) 166264b60e09SAnton Vorontsov { 166374e1fbb1SJoerg Roedel struct of_phandle_iterator it; 166474e1fbb1SJoerg Roedel int rc, cur_index = 0; 166515c9a0acSGrant Likely 166615c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 1667f623ce95SJoerg Roedel of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) { 166815c9a0acSGrant Likely /* 1669cd209b41SJoerg Roedel * All of the error cases bail out of the loop, so at 167015c9a0acSGrant Likely * this point, the parsing is successful. If the requested 167115c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 167215c9a0acSGrant Likely * or return -ENOENT for an empty entry. 167315c9a0acSGrant Likely */ 167423ce04c0SGrant Likely rc = -ENOENT; 167515c9a0acSGrant Likely if (cur_index == index) { 167674e1fbb1SJoerg Roedel if (!it.phandle) 167723ce04c0SGrant Likely goto err; 167815c9a0acSGrant Likely 167915c9a0acSGrant Likely if (out_args) { 1680abdaa77bSJoerg Roedel int c; 1681abdaa77bSJoerg Roedel 1682abdaa77bSJoerg Roedel c = of_phandle_iterator_args(&it, 1683abdaa77bSJoerg Roedel out_args->args, 1684abdaa77bSJoerg Roedel MAX_PHANDLE_ARGS); 168574e1fbb1SJoerg Roedel out_args->np = it.node; 1686abdaa77bSJoerg Roedel out_args->args_count = c; 1687b855f16bSTang Yuantian } else { 168874e1fbb1SJoerg Roedel of_node_put(it.node); 168915c9a0acSGrant Likely } 169023ce04c0SGrant Likely 169123ce04c0SGrant Likely /* Found it! return success */ 169215c9a0acSGrant Likely return 0; 169315c9a0acSGrant Likely } 169464b60e09SAnton Vorontsov 169564b60e09SAnton Vorontsov cur_index++; 169664b60e09SAnton Vorontsov } 169764b60e09SAnton Vorontsov 169823ce04c0SGrant Likely /* 169923ce04c0SGrant Likely * Unlock node before returning result; will be one of: 170023ce04c0SGrant Likely * -ENOENT : index is for empty phandle 170123ce04c0SGrant Likely * -EINVAL : parsing error on data 170223ce04c0SGrant Likely */ 1703cd209b41SJoerg Roedel 170423ce04c0SGrant Likely err: 170574e1fbb1SJoerg Roedel of_node_put(it.node); 170623ce04c0SGrant Likely return rc; 170764b60e09SAnton Vorontsov } 1708bd69f73fSGrant Likely 1709eded9dd4SStephen Warren /** 17105fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 17115fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 17125fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 17135fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 17145fba49e3SStephen Warren * the table 17155fba49e3SStephen Warren * 17165fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 17175fba49e3SStephen Warren * of_node_put() on it when done. 17185fba49e3SStephen Warren */ 17195fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 17205fba49e3SStephen Warren const char *phandle_name, int index) 17215fba49e3SStephen Warren { 172291d9942cSStephen Warren struct of_phandle_args args; 17235fba49e3SStephen Warren 172491d9942cSStephen Warren if (index < 0) 17255fba49e3SStephen Warren return NULL; 17265fba49e3SStephen Warren 172791d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 172891d9942cSStephen Warren index, &args)) 172991d9942cSStephen Warren return NULL; 173091d9942cSStephen Warren 173191d9942cSStephen Warren return args.np; 17325fba49e3SStephen Warren } 17335fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 17345fba49e3SStephen Warren 17355fba49e3SStephen Warren /** 1736eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1737eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1738eded9dd4SStephen Warren * @list_name: property name that contains a list 1739eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1740eded9dd4SStephen Warren * @index: index of a phandle to parse out 1741eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1742eded9dd4SStephen Warren * 1743eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1744eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1745eded9dd4SStephen Warren * errno value. 1746eded9dd4SStephen Warren * 1747d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1748eded9dd4SStephen Warren * pointer. 1749eded9dd4SStephen Warren * 1750eded9dd4SStephen Warren * Example: 1751eded9dd4SStephen Warren * 1752eded9dd4SStephen Warren * phandle1: node1 { 1753eded9dd4SStephen Warren * #list-cells = <2>; 1754eded9dd4SStephen Warren * } 1755eded9dd4SStephen Warren * 1756eded9dd4SStephen Warren * phandle2: node2 { 1757eded9dd4SStephen Warren * #list-cells = <1>; 1758eded9dd4SStephen Warren * } 1759eded9dd4SStephen Warren * 1760eded9dd4SStephen Warren * node3 { 1761eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1762eded9dd4SStephen Warren * } 1763eded9dd4SStephen Warren * 1764eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1765eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1766eded9dd4SStephen Warren */ 1767bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1768bd69f73fSGrant Likely const char *cells_name, int index, 1769bd69f73fSGrant Likely struct of_phandle_args *out_args) 1770bd69f73fSGrant Likely { 1771bd69f73fSGrant Likely if (index < 0) 1772bd69f73fSGrant Likely return -EINVAL; 1773035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1774035fd948SStephen Warren index, out_args); 1775bd69f73fSGrant Likely } 177615c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 177702af11b0SGrant Likely 1778bd69f73fSGrant Likely /** 1779035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1780035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1781035fd948SStephen Warren * @list_name: property name that contains a list 1782035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1783035fd948SStephen Warren * @index: index of a phandle to parse out 1784035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1785035fd948SStephen Warren * 1786035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1787035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1788035fd948SStephen Warren * errno value. 1789035fd948SStephen Warren * 1790d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1791035fd948SStephen Warren * pointer. 1792035fd948SStephen Warren * 1793035fd948SStephen Warren * Example: 1794035fd948SStephen Warren * 1795035fd948SStephen Warren * phandle1: node1 { 1796035fd948SStephen Warren * } 1797035fd948SStephen Warren * 1798035fd948SStephen Warren * phandle2: node2 { 1799035fd948SStephen Warren * } 1800035fd948SStephen Warren * 1801035fd948SStephen Warren * node3 { 1802035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1803035fd948SStephen Warren * } 1804035fd948SStephen Warren * 1805035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1806035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1807035fd948SStephen Warren */ 1808035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1809035fd948SStephen Warren const char *list_name, int cell_count, 1810035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1811035fd948SStephen Warren { 1812035fd948SStephen Warren if (index < 0) 1813035fd948SStephen Warren return -EINVAL; 1814035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1815035fd948SStephen Warren index, out_args); 1816035fd948SStephen Warren } 1817035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1818035fd948SStephen Warren 1819035fd948SStephen Warren /** 1820bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1821bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1822bd69f73fSGrant Likely * @list_name: property name that contains a list 1823bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1824bd69f73fSGrant Likely * 1825bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1826bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1827bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1828bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1829bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1830bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1831bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1832bd69f73fSGrant Likely * phandle. 1833bd69f73fSGrant Likely */ 1834bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1835bd69f73fSGrant Likely const char *cells_name) 1836bd69f73fSGrant Likely { 18372021bd01SJoerg Roedel struct of_phandle_iterator it; 18382021bd01SJoerg Roedel int rc, cur_index = 0; 18392021bd01SJoerg Roedel 18402021bd01SJoerg Roedel rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0); 18412021bd01SJoerg Roedel if (rc) 18422021bd01SJoerg Roedel return rc; 18432021bd01SJoerg Roedel 18442021bd01SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0) 18452021bd01SJoerg Roedel cur_index += 1; 18462021bd01SJoerg Roedel 18472021bd01SJoerg Roedel if (rc != -ENOENT) 18482021bd01SJoerg Roedel return rc; 18492021bd01SJoerg Roedel 18502021bd01SJoerg Roedel return cur_index; 1851bd69f73fSGrant Likely } 1852bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1853bd69f73fSGrant Likely 185402af11b0SGrant Likely /** 185562664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 185662664f67SXiubo Li */ 1857d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop) 185862664f67SXiubo Li { 185962664f67SXiubo Li struct property **next; 186062664f67SXiubo Li 186162664f67SXiubo Li prop->next = NULL; 186262664f67SXiubo Li next = &np->properties; 186362664f67SXiubo Li while (*next) { 186462664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 186562664f67SXiubo Li /* duplicate ! don't insert it */ 186662664f67SXiubo Li return -EEXIST; 186762664f67SXiubo Li 186862664f67SXiubo Li next = &(*next)->next; 186962664f67SXiubo Li } 187062664f67SXiubo Li *next = prop; 187162664f67SXiubo Li 187262664f67SXiubo Li return 0; 187362664f67SXiubo Li } 187462664f67SXiubo Li 187562664f67SXiubo Li /** 187679d1c712SNathan Fontenot * of_add_property - Add a property to a node 187702af11b0SGrant Likely */ 187879d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 187902af11b0SGrant Likely { 188002af11b0SGrant Likely unsigned long flags; 18811cf3d8b3SNathan Fontenot int rc; 18821cf3d8b3SNathan Fontenot 18838a2b22a2SGrant Likely mutex_lock(&of_mutex); 188402af11b0SGrant Likely 1885d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 188662664f67SXiubo Li rc = __of_add_property(np, prop); 1887d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 188802af11b0SGrant Likely 18898a2b22a2SGrant Likely if (!rc) 189075b57ecfSGrant Likely __of_add_property_sysfs(np, prop); 189102af11b0SGrant Likely 18928a2b22a2SGrant Likely mutex_unlock(&of_mutex); 18938a2b22a2SGrant Likely 1894259092a3SGrant Likely if (!rc) 1895259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1896259092a3SGrant Likely 189762664f67SXiubo Li return rc; 189802af11b0SGrant Likely } 189902af11b0SGrant Likely 1900d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop) 1901d8c50088SPantelis Antoniou { 1902d8c50088SPantelis Antoniou struct property **next; 1903d8c50088SPantelis Antoniou 1904d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1905d8c50088SPantelis Antoniou if (*next == prop) 1906d8c50088SPantelis Antoniou break; 1907d8c50088SPantelis Antoniou } 1908d8c50088SPantelis Antoniou if (*next == NULL) 1909d8c50088SPantelis Antoniou return -ENODEV; 1910d8c50088SPantelis Antoniou 1911d8c50088SPantelis Antoniou /* found the node */ 1912d8c50088SPantelis Antoniou *next = prop->next; 1913d8c50088SPantelis Antoniou prop->next = np->deadprops; 1914d8c50088SPantelis Antoniou np->deadprops = prop; 1915d8c50088SPantelis Antoniou 1916d8c50088SPantelis Antoniou return 0; 1917d8c50088SPantelis Antoniou } 1918d8c50088SPantelis Antoniou 1919d9fc8807SFrank Rowand void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop) 1920d9fc8807SFrank Rowand { 1921d9fc8807SFrank Rowand sysfs_remove_bin_file(&np->kobj, &prop->attr); 1922d9fc8807SFrank Rowand kfree(prop->attr.attr.name); 1923d9fc8807SFrank Rowand } 1924d9fc8807SFrank Rowand 19258a2b22a2SGrant Likely void __of_remove_property_sysfs(struct device_node *np, struct property *prop) 19268a2b22a2SGrant Likely { 1927ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1928ef69d740SGaurav Minocha return; 1929ef69d740SGaurav Minocha 19308a2b22a2SGrant Likely /* at early boot, bail here and defer setup to of_init() */ 19318a2b22a2SGrant Likely if (of_kset && of_node_is_attached(np)) 1932d9fc8807SFrank Rowand __of_sysfs_remove_bin_file(np, prop); 19338a2b22a2SGrant Likely } 19348a2b22a2SGrant Likely 193502af11b0SGrant Likely /** 193679d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 193702af11b0SGrant Likely * 193802af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 193902af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 194002af11b0SGrant Likely * Instead we just move the property to the "dead properties" 194102af11b0SGrant Likely * list, so it won't be found any more. 194202af11b0SGrant Likely */ 194379d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 194402af11b0SGrant Likely { 194502af11b0SGrant Likely unsigned long flags; 19461cf3d8b3SNathan Fontenot int rc; 19471cf3d8b3SNathan Fontenot 1948201b3fe5SSuraj Jitindar Singh if (!prop) 1949201b3fe5SSuraj Jitindar Singh return -ENODEV; 1950201b3fe5SSuraj Jitindar Singh 19518a2b22a2SGrant Likely mutex_lock(&of_mutex); 195202af11b0SGrant Likely 1953d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1954d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop); 1955d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 195602af11b0SGrant Likely 19578a2b22a2SGrant Likely if (!rc) 19588a2b22a2SGrant Likely __of_remove_property_sysfs(np, prop); 195902af11b0SGrant Likely 19608a2b22a2SGrant Likely mutex_unlock(&of_mutex); 19618a2b22a2SGrant Likely 1962259092a3SGrant Likely if (!rc) 1963259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1964259092a3SGrant Likely 1965d8c50088SPantelis Antoniou return rc; 196602af11b0SGrant Likely } 196702af11b0SGrant Likely 1968d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop, 1969d8c50088SPantelis Antoniou struct property **oldpropp) 1970d8c50088SPantelis Antoniou { 1971d8c50088SPantelis Antoniou struct property **next, *oldprop; 1972d8c50088SPantelis Antoniou 1973d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1974d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0) 1975d8c50088SPantelis Antoniou break; 1976d8c50088SPantelis Antoniou } 1977d8c50088SPantelis Antoniou *oldpropp = oldprop = *next; 1978d8c50088SPantelis Antoniou 1979d8c50088SPantelis Antoniou if (oldprop) { 1980d8c50088SPantelis Antoniou /* replace the node */ 1981d8c50088SPantelis Antoniou newprop->next = oldprop->next; 1982d8c50088SPantelis Antoniou *next = newprop; 1983d8c50088SPantelis Antoniou oldprop->next = np->deadprops; 1984d8c50088SPantelis Antoniou np->deadprops = oldprop; 1985d8c50088SPantelis Antoniou } else { 1986d8c50088SPantelis Antoniou /* new node */ 1987d8c50088SPantelis Antoniou newprop->next = NULL; 1988d8c50088SPantelis Antoniou *next = newprop; 1989d8c50088SPantelis Antoniou } 1990d8c50088SPantelis Antoniou 1991d8c50088SPantelis Antoniou return 0; 1992d8c50088SPantelis Antoniou } 1993d8c50088SPantelis Antoniou 19948a2b22a2SGrant Likely void __of_update_property_sysfs(struct device_node *np, struct property *newprop, 19958a2b22a2SGrant Likely struct property *oldprop) 19968a2b22a2SGrant Likely { 1997ef69d740SGaurav Minocha if (!IS_ENABLED(CONFIG_SYSFS)) 1998ef69d740SGaurav Minocha return; 1999ef69d740SGaurav Minocha 20008a2b22a2SGrant Likely /* At early boot, bail out and defer setup to of_init() */ 200102af11b0SGrant Likely if (!of_kset) 20028a2b22a2SGrant Likely return; 200302af11b0SGrant Likely 20048a2b22a2SGrant Likely if (oldprop) 2005d9fc8807SFrank Rowand __of_sysfs_remove_bin_file(np, oldprop); 20068a2b22a2SGrant Likely __of_add_property_sysfs(np, newprop); 200702af11b0SGrant Likely } 200802af11b0SGrant Likely 200902af11b0SGrant Likely /* 201079d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 2011475d0094SDong Aisheng * not exist, add it. 201202af11b0SGrant Likely * 201302af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 201402af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 201502af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 201602af11b0SGrant Likely * and add the new property to the property list 201702af11b0SGrant Likely */ 201879d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 201902af11b0SGrant Likely { 2020d8c50088SPantelis Antoniou struct property *oldprop; 202102af11b0SGrant Likely unsigned long flags; 2022947fdaadSXiubo Li int rc; 20231cf3d8b3SNathan Fontenot 2024475d0094SDong Aisheng if (!newprop->name) 2025475d0094SDong Aisheng return -EINVAL; 2026475d0094SDong Aisheng 20278a2b22a2SGrant Likely mutex_lock(&of_mutex); 2028fcdeb7feSGrant Likely 2029d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 2030d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop); 2031d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 2032e81b3295SNathan Fontenot 20338a2b22a2SGrant Likely if (!rc) 20348a2b22a2SGrant Likely __of_update_property_sysfs(np, newprop, oldprop); 2035fcdeb7feSGrant Likely 20368a2b22a2SGrant Likely mutex_unlock(&of_mutex); 20371cf3d8b3SNathan Fontenot 2038259092a3SGrant Likely if (!rc) 2039259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 2040fcdeb7feSGrant Likely 20411cf3d8b3SNathan Fontenot return rc; 2042e81b3295SNathan Fontenot } 2043e81b3295SNathan Fontenot 2044611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 2045611cad72SShawn Guo int id, const char *stem, int stem_len) 2046611cad72SShawn Guo { 2047611cad72SShawn Guo ap->np = np; 2048611cad72SShawn Guo ap->id = id; 2049611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 2050611cad72SShawn Guo ap->stem[stem_len] = 0; 2051611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 2052611cad72SShawn Guo pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 205374a7f084SGrant Likely ap->alias, ap->stem, ap->id, of_node_full_name(np)); 2054611cad72SShawn Guo } 2055611cad72SShawn Guo 2056611cad72SShawn Guo /** 20571821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node 2058611cad72SShawn Guo * 20591821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates 20601821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the 20611821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure. 2062611cad72SShawn Guo * 2063611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 20641821dda4SGeert Uytterhoeven * for storing the resulting tree 2065611cad72SShawn Guo */ 2066611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 2067611cad72SShawn Guo { 2068611cad72SShawn Guo struct property *pp; 2069611cad72SShawn Guo 20707dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases"); 2071611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 2072611cad72SShawn Guo if (of_chosen == NULL) 2073611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 20745c19e952SSascha Hauer 20755c19e952SSascha Hauer if (of_chosen) { 2076a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ 2077676e1b2fSGrant Likely const char *name = of_get_property(of_chosen, "stdout-path", NULL); 2078676e1b2fSGrant Likely if (!name) 20795c19e952SSascha Hauer name = of_get_property(of_chosen, "linux,stdout-path", NULL); 2080a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name) 2081a752ee56SGrant Likely name = of_get_property(of_aliases, "stdout", NULL); 2082f64255b5SPeter Hurley if (name) 20837914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); 20845c19e952SSascha Hauer } 20855c19e952SSascha Hauer 2086611cad72SShawn Guo if (!of_aliases) 2087611cad72SShawn Guo return; 2088611cad72SShawn Guo 20898af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 2090611cad72SShawn Guo const char *start = pp->name; 2091611cad72SShawn Guo const char *end = start + strlen(start); 2092611cad72SShawn Guo struct device_node *np; 2093611cad72SShawn Guo struct alias_prop *ap; 2094611cad72SShawn Guo int id, len; 2095611cad72SShawn Guo 2096611cad72SShawn Guo /* Skip those we do not want to proceed */ 2097611cad72SShawn Guo if (!strcmp(pp->name, "name") || 2098611cad72SShawn Guo !strcmp(pp->name, "phandle") || 2099611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 2100611cad72SShawn Guo continue; 2101611cad72SShawn Guo 2102611cad72SShawn Guo np = of_find_node_by_path(pp->value); 2103611cad72SShawn Guo if (!np) 2104611cad72SShawn Guo continue; 2105611cad72SShawn Guo 2106611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 2107611cad72SShawn Guo * the 'stem' string */ 2108611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 2109611cad72SShawn Guo end--; 2110611cad72SShawn Guo len = end - start; 2111611cad72SShawn Guo 2112611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 2113611cad72SShawn Guo continue; 2114611cad72SShawn Guo 2115611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 2116611cad72SShawn Guo ap = dt_alloc(sizeof(*ap) + len + 1, 4); 2117611cad72SShawn Guo if (!ap) 2118611cad72SShawn Guo continue; 21190640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 2120611cad72SShawn Guo ap->alias = start; 2121611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 2122611cad72SShawn Guo } 2123611cad72SShawn Guo } 2124611cad72SShawn Guo 2125611cad72SShawn Guo /** 2126611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 2127611cad72SShawn Guo * @np: Pointer to the given device_node 2128611cad72SShawn Guo * @stem: Alias stem of the given device_node 2129611cad72SShawn Guo * 21305a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given 21315a53a07fSGeert Uytterhoeven * device_node and alias stem. It returns the alias id if found. 2132611cad72SShawn Guo */ 2133611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 2134611cad72SShawn Guo { 2135611cad72SShawn Guo struct alias_prop *app; 2136611cad72SShawn Guo int id = -ENODEV; 2137611cad72SShawn Guo 2138c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 2139611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 2140611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 2141611cad72SShawn Guo continue; 2142611cad72SShawn Guo 2143611cad72SShawn Guo if (np == app->np) { 2144611cad72SShawn Guo id = app->id; 2145611cad72SShawn Guo break; 2146611cad72SShawn Guo } 2147611cad72SShawn Guo } 2148c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 2149611cad72SShawn Guo 2150611cad72SShawn Guo return id; 2151611cad72SShawn Guo } 2152611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 2153c541adc6SStephen Warren 2154351d224fSWolfram Sang /** 2155351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem 2156351d224fSWolfram Sang * @stem: Alias stem to be examined 2157351d224fSWolfram Sang * 2158351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the 2159351d224fSWolfram Sang * given alias stem. It returns the alias id if found. 2160351d224fSWolfram Sang */ 2161351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem) 2162351d224fSWolfram Sang { 2163351d224fSWolfram Sang struct alias_prop *app; 2164351d224fSWolfram Sang int id = -ENODEV; 2165351d224fSWolfram Sang 2166351d224fSWolfram Sang mutex_lock(&of_mutex); 2167351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) { 2168351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0) 2169351d224fSWolfram Sang continue; 2170351d224fSWolfram Sang 2171351d224fSWolfram Sang if (app->id > id) 2172351d224fSWolfram Sang id = app->id; 2173351d224fSWolfram Sang } 2174351d224fSWolfram Sang mutex_unlock(&of_mutex); 2175351d224fSWolfram Sang 2176351d224fSWolfram Sang return id; 2177351d224fSWolfram Sang } 2178351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id); 2179351d224fSWolfram Sang 2180c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, 2181c541adc6SStephen Warren u32 *pu) 2182c541adc6SStephen Warren { 2183c541adc6SStephen Warren const void *curv = cur; 2184c541adc6SStephen Warren 2185c541adc6SStephen Warren if (!prop) 2186c541adc6SStephen Warren return NULL; 2187c541adc6SStephen Warren 2188c541adc6SStephen Warren if (!cur) { 2189c541adc6SStephen Warren curv = prop->value; 2190c541adc6SStephen Warren goto out_val; 2191c541adc6SStephen Warren } 2192c541adc6SStephen Warren 2193c541adc6SStephen Warren curv += sizeof(*cur); 2194c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2195c541adc6SStephen Warren return NULL; 2196c541adc6SStephen Warren 2197c541adc6SStephen Warren out_val: 2198c541adc6SStephen Warren *pu = be32_to_cpup(curv); 2199c541adc6SStephen Warren return curv; 2200c541adc6SStephen Warren } 2201c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32); 2202c541adc6SStephen Warren 2203c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur) 2204c541adc6SStephen Warren { 2205c541adc6SStephen Warren const void *curv = cur; 2206c541adc6SStephen Warren 2207c541adc6SStephen Warren if (!prop) 2208c541adc6SStephen Warren return NULL; 2209c541adc6SStephen Warren 2210c541adc6SStephen Warren if (!cur) 2211c541adc6SStephen Warren return prop->value; 2212c541adc6SStephen Warren 2213c541adc6SStephen Warren curv += strlen(cur) + 1; 2214c541adc6SStephen Warren if (curv >= prop->value + prop->length) 2215c541adc6SStephen Warren return NULL; 2216c541adc6SStephen Warren 2217c541adc6SStephen Warren return curv; 2218c541adc6SStephen Warren } 2219c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string); 22205c19e952SSascha Hauer 22215c19e952SSascha Hauer /** 22223482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup 22233482f2c5SGrant Likely * @dn - Pointer to device node 22243482f2c5SGrant Likely * @name - Name to use for preferred console without index. ex. "ttyS" 22253482f2c5SGrant Likely * @index - Index to use for preferred console. 22265c19e952SSascha Hauer * 22273482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the 22283482f2c5SGrant Likely * /chosen node. If it does then register it as the preferred console and return 22293482f2c5SGrant Likely * TRUE. Otherwise return FALSE. 22305c19e952SSascha Hauer */ 22313482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index) 22325c19e952SSascha Hauer { 22333482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline) 22345c19e952SSascha Hauer return false; 22357914a7c5SLeif Lindholm return !add_preferred_console(name, index, 22367914a7c5SLeif Lindholm kstrdup(of_stdout_options, GFP_KERNEL)); 22375c19e952SSascha Hauer } 22383482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check); 2239a3e31b45SSudeep KarkadaNagesha 2240a3e31b45SSudeep KarkadaNagesha /** 2241a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 2242a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 2243a3e31b45SSudeep KarkadaNagesha * 2244a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 2245a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 2246a3e31b45SSudeep KarkadaNagesha * to np. 2247a3e31b45SSudeep KarkadaNagesha */ 2248a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 2249a3e31b45SSudeep KarkadaNagesha { 2250a3e31b45SSudeep KarkadaNagesha struct device_node *child; 2251a3e31b45SSudeep KarkadaNagesha const phandle *handle; 2252a3e31b45SSudeep KarkadaNagesha 2253a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "l2-cache", NULL); 2254a3e31b45SSudeep KarkadaNagesha if (!handle) 2255a3e31b45SSudeep KarkadaNagesha handle = of_get_property(np, "next-level-cache", NULL); 2256a3e31b45SSudeep KarkadaNagesha 2257a3e31b45SSudeep KarkadaNagesha if (handle) 2258a3e31b45SSudeep KarkadaNagesha return of_find_node_by_phandle(be32_to_cpup(handle)); 2259a3e31b45SSudeep KarkadaNagesha 2260a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 2261a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 2262a3e31b45SSudeep KarkadaNagesha */ 2263a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 2264a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 2265a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 2266a3e31b45SSudeep KarkadaNagesha return child; 2267a3e31b45SSudeep KarkadaNagesha 2268a3e31b45SSudeep KarkadaNagesha return NULL; 2269a3e31b45SSudeep KarkadaNagesha } 2270fd9fdb78SPhilipp Zabel 2271fd9fdb78SPhilipp Zabel /** 22725fa23530SSudeep Holla * of_find_last_cache_level - Find the level at which the last cache is 22735fa23530SSudeep Holla * present for the given logical cpu 22745fa23530SSudeep Holla * 22755fa23530SSudeep Holla * @cpu: cpu number(logical index) for which the last cache level is needed 22765fa23530SSudeep Holla * 22775fa23530SSudeep Holla * Returns the the level at which the last cache is present. It is exactly 22785fa23530SSudeep Holla * same as the total number of cache levels for the given logical cpu. 22795fa23530SSudeep Holla */ 22805fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu) 22815fa23530SSudeep Holla { 22825fa23530SSudeep Holla u32 cache_level = 0; 22835fa23530SSudeep Holla struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu); 22845fa23530SSudeep Holla 22855fa23530SSudeep Holla while (np) { 22865fa23530SSudeep Holla prev = np; 22875fa23530SSudeep Holla of_node_put(np); 22885fa23530SSudeep Holla np = of_find_next_cache_node(np); 22895fa23530SSudeep Holla } 22905fa23530SSudeep Holla 22915fa23530SSudeep Holla of_property_read_u32(prev, "cache-level", &cache_level); 22925fa23530SSudeep Holla 22935fa23530SSudeep Holla return cache_level; 22945fa23530SSudeep Holla } 22955fa23530SSudeep Holla 22965fa23530SSudeep Holla /** 2297f2a575f6SPhilipp Zabel * of_graph_parse_endpoint() - parse common endpoint node properties 2298f2a575f6SPhilipp Zabel * @node: pointer to endpoint device_node 2299f2a575f6SPhilipp Zabel * @endpoint: pointer to the OF endpoint data structure 2300f2a575f6SPhilipp Zabel * 2301f2a575f6SPhilipp Zabel * The caller should hold a reference to @node. 2302f2a575f6SPhilipp Zabel */ 2303f2a575f6SPhilipp Zabel int of_graph_parse_endpoint(const struct device_node *node, 2304f2a575f6SPhilipp Zabel struct of_endpoint *endpoint) 2305f2a575f6SPhilipp Zabel { 2306f2a575f6SPhilipp Zabel struct device_node *port_node = of_get_parent(node); 2307f2a575f6SPhilipp Zabel 2308d484700aSPhilipp Zabel WARN_ONCE(!port_node, "%s(): endpoint %s has no parent node\n", 2309d484700aSPhilipp Zabel __func__, node->full_name); 2310d484700aSPhilipp Zabel 2311f2a575f6SPhilipp Zabel memset(endpoint, 0, sizeof(*endpoint)); 2312f2a575f6SPhilipp Zabel 2313f2a575f6SPhilipp Zabel endpoint->local_node = node; 2314f2a575f6SPhilipp Zabel /* 2315f2a575f6SPhilipp Zabel * It doesn't matter whether the two calls below succeed. 2316f2a575f6SPhilipp Zabel * If they don't then the default value 0 is used. 2317f2a575f6SPhilipp Zabel */ 2318f2a575f6SPhilipp Zabel of_property_read_u32(port_node, "reg", &endpoint->port); 2319f2a575f6SPhilipp Zabel of_property_read_u32(node, "reg", &endpoint->id); 2320f2a575f6SPhilipp Zabel 2321f2a575f6SPhilipp Zabel of_node_put(port_node); 2322f2a575f6SPhilipp Zabel 2323f2a575f6SPhilipp Zabel return 0; 2324f2a575f6SPhilipp Zabel } 2325f2a575f6SPhilipp Zabel EXPORT_SYMBOL(of_graph_parse_endpoint); 2326f2a575f6SPhilipp Zabel 2327f2a575f6SPhilipp Zabel /** 2328bfe446e3SPhilipp Zabel * of_graph_get_port_by_id() - get the port matching a given id 2329bfe446e3SPhilipp Zabel * @parent: pointer to the parent device node 2330bfe446e3SPhilipp Zabel * @id: id of the port 2331bfe446e3SPhilipp Zabel * 2332bfe446e3SPhilipp Zabel * Return: A 'port' node pointer with refcount incremented. The caller 2333bfe446e3SPhilipp Zabel * has to use of_node_put() on it when done. 2334bfe446e3SPhilipp Zabel */ 2335bfe446e3SPhilipp Zabel struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id) 2336bfe446e3SPhilipp Zabel { 2337bfe446e3SPhilipp Zabel struct device_node *node, *port; 2338bfe446e3SPhilipp Zabel 2339bfe446e3SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2340bfe446e3SPhilipp Zabel if (node) 2341bfe446e3SPhilipp Zabel parent = node; 2342bfe446e3SPhilipp Zabel 2343bfe446e3SPhilipp Zabel for_each_child_of_node(parent, port) { 2344bfe446e3SPhilipp Zabel u32 port_id = 0; 2345bfe446e3SPhilipp Zabel 2346bfe446e3SPhilipp Zabel if (of_node_cmp(port->name, "port") != 0) 2347bfe446e3SPhilipp Zabel continue; 2348bfe446e3SPhilipp Zabel of_property_read_u32(port, "reg", &port_id); 2349bfe446e3SPhilipp Zabel if (id == port_id) 2350bfe446e3SPhilipp Zabel break; 2351bfe446e3SPhilipp Zabel } 2352bfe446e3SPhilipp Zabel 2353bfe446e3SPhilipp Zabel of_node_put(node); 2354bfe446e3SPhilipp Zabel 2355bfe446e3SPhilipp Zabel return port; 2356bfe446e3SPhilipp Zabel } 2357bfe446e3SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_port_by_id); 2358bfe446e3SPhilipp Zabel 2359bfe446e3SPhilipp Zabel /** 2360fd9fdb78SPhilipp Zabel * of_graph_get_next_endpoint() - get next endpoint node 2361fd9fdb78SPhilipp Zabel * @parent: pointer to the parent device node 2362fd9fdb78SPhilipp Zabel * @prev: previous endpoint node, or NULL to get first 2363fd9fdb78SPhilipp Zabel * 2364fd9fdb78SPhilipp Zabel * Return: An 'endpoint' node pointer with refcount incremented. Refcount 2365f033c0bcSPhilipp Zabel * of the passed @prev node is decremented. 2366fd9fdb78SPhilipp Zabel */ 2367fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_next_endpoint(const struct device_node *parent, 2368fd9fdb78SPhilipp Zabel struct device_node *prev) 2369fd9fdb78SPhilipp Zabel { 2370fd9fdb78SPhilipp Zabel struct device_node *endpoint; 23713c83e61eSLinus Torvalds struct device_node *port; 2372fd9fdb78SPhilipp Zabel 2373fd9fdb78SPhilipp Zabel if (!parent) 2374fd9fdb78SPhilipp Zabel return NULL; 2375fd9fdb78SPhilipp Zabel 23763c83e61eSLinus Torvalds /* 23773c83e61eSLinus Torvalds * Start by locating the port node. If no previous endpoint is specified 23783c83e61eSLinus Torvalds * search for the first port node, otherwise get the previous endpoint 23793c83e61eSLinus Torvalds * parent port node. 23803c83e61eSLinus Torvalds */ 2381fd9fdb78SPhilipp Zabel if (!prev) { 2382fd9fdb78SPhilipp Zabel struct device_node *node; 23833c83e61eSLinus Torvalds 2384fd9fdb78SPhilipp Zabel node = of_get_child_by_name(parent, "ports"); 2385fd9fdb78SPhilipp Zabel if (node) 2386fd9fdb78SPhilipp Zabel parent = node; 2387fd9fdb78SPhilipp Zabel 2388fd9fdb78SPhilipp Zabel port = of_get_child_by_name(parent, "port"); 2389fd9fdb78SPhilipp Zabel of_node_put(node); 23904329b93bSPhilipp Zabel 23913c83e61eSLinus Torvalds if (!port) { 2392606ad42aSRob Herring pr_err("graph: no port node found in %s\n", 2393606ad42aSRob Herring parent->full_name); 23943c83e61eSLinus Torvalds return NULL; 23954329b93bSPhilipp Zabel } 23963c83e61eSLinus Torvalds } else { 2397fd9fdb78SPhilipp Zabel port = of_get_parent(prev); 23986ff60d39SPhilipp Zabel if (WARN_ONCE(!port, "%s(): endpoint %s has no parent node\n", 23996ff60d39SPhilipp Zabel __func__, prev->full_name)) 2400fd9fdb78SPhilipp Zabel return NULL; 24013c83e61eSLinus Torvalds } 24023c83e61eSLinus Torvalds 24033c83e61eSLinus Torvalds while (1) { 24043c83e61eSLinus Torvalds /* 24053c83e61eSLinus Torvalds * Now that we have a port node, get the next endpoint by 24063c83e61eSLinus Torvalds * getting the next child. If the previous endpoint is NULL this 24073c83e61eSLinus Torvalds * will return the first child. 24083c83e61eSLinus Torvalds */ 2409fd9fdb78SPhilipp Zabel endpoint = of_get_next_child(port, prev); 2410fd9fdb78SPhilipp Zabel if (endpoint) { 2411fd9fdb78SPhilipp Zabel of_node_put(port); 2412fd9fdb78SPhilipp Zabel return endpoint; 2413fd9fdb78SPhilipp Zabel } 2414fd9fdb78SPhilipp Zabel 2415fd9fdb78SPhilipp Zabel /* No more endpoints under this port, try the next one. */ 24163c83e61eSLinus Torvalds prev = NULL; 24173c83e61eSLinus Torvalds 2418fd9fdb78SPhilipp Zabel do { 2419fd9fdb78SPhilipp Zabel port = of_get_next_child(parent, port); 2420fd9fdb78SPhilipp Zabel if (!port) 2421fd9fdb78SPhilipp Zabel return NULL; 2422fd9fdb78SPhilipp Zabel } while (of_node_cmp(port->name, "port")); 24233c83e61eSLinus Torvalds } 2424fd9fdb78SPhilipp Zabel } 2425fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_next_endpoint); 2426fd9fdb78SPhilipp Zabel 2427fd9fdb78SPhilipp Zabel /** 24288ccd0d0cSHyungwon Hwang * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers 24298ccd0d0cSHyungwon Hwang * @parent: pointer to the parent device node 24308ccd0d0cSHyungwon Hwang * @port_reg: identifier (value of reg property) of the parent port node 24318ccd0d0cSHyungwon Hwang * @reg: identifier (value of reg property) of the endpoint node 24328ccd0d0cSHyungwon Hwang * 24338ccd0d0cSHyungwon Hwang * Return: An 'endpoint' node pointer which is identified by reg and at the same 24348ccd0d0cSHyungwon Hwang * is the child of a port node identified by port_reg. reg and port_reg are 24358ccd0d0cSHyungwon Hwang * ignored when they are -1. 24368ccd0d0cSHyungwon Hwang */ 24378ccd0d0cSHyungwon Hwang struct device_node *of_graph_get_endpoint_by_regs( 24388ccd0d0cSHyungwon Hwang const struct device_node *parent, int port_reg, int reg) 24398ccd0d0cSHyungwon Hwang { 24408ccd0d0cSHyungwon Hwang struct of_endpoint endpoint; 244134276bb0SLucas Stach struct device_node *node = NULL; 24428ccd0d0cSHyungwon Hwang 244334276bb0SLucas Stach for_each_endpoint_of_node(parent, node) { 24448ccd0d0cSHyungwon Hwang of_graph_parse_endpoint(node, &endpoint); 24458ccd0d0cSHyungwon Hwang if (((port_reg == -1) || (endpoint.port == port_reg)) && 24468ccd0d0cSHyungwon Hwang ((reg == -1) || (endpoint.id == reg))) 24478ccd0d0cSHyungwon Hwang return node; 24488ccd0d0cSHyungwon Hwang } 24498ccd0d0cSHyungwon Hwang 24508ccd0d0cSHyungwon Hwang return NULL; 24518ccd0d0cSHyungwon Hwang } 24528ffaa903SDave Airlie EXPORT_SYMBOL(of_graph_get_endpoint_by_regs); 24538ccd0d0cSHyungwon Hwang 24548ccd0d0cSHyungwon Hwang /** 2455fd9fdb78SPhilipp Zabel * of_graph_get_remote_port_parent() - get remote port's parent node 2456fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2457fd9fdb78SPhilipp Zabel * 2458fd9fdb78SPhilipp Zabel * Return: Remote device node associated with remote endpoint node linked 2459fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2460fd9fdb78SPhilipp Zabel */ 2461fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port_parent( 2462fd9fdb78SPhilipp Zabel const struct device_node *node) 2463fd9fdb78SPhilipp Zabel { 2464fd9fdb78SPhilipp Zabel struct device_node *np; 2465fd9fdb78SPhilipp Zabel unsigned int depth; 2466fd9fdb78SPhilipp Zabel 2467fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2468fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2469fd9fdb78SPhilipp Zabel 2470fd9fdb78SPhilipp Zabel /* Walk 3 levels up only if there is 'ports' node. */ 2471fd9fdb78SPhilipp Zabel for (depth = 3; depth && np; depth--) { 2472fd9fdb78SPhilipp Zabel np = of_get_next_parent(np); 2473fd9fdb78SPhilipp Zabel if (depth == 2 && of_node_cmp(np->name, "ports")) 2474fd9fdb78SPhilipp Zabel break; 2475fd9fdb78SPhilipp Zabel } 2476fd9fdb78SPhilipp Zabel return np; 2477fd9fdb78SPhilipp Zabel } 2478fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port_parent); 2479fd9fdb78SPhilipp Zabel 2480fd9fdb78SPhilipp Zabel /** 2481fd9fdb78SPhilipp Zabel * of_graph_get_remote_port() - get remote port node 2482fd9fdb78SPhilipp Zabel * @node: pointer to a local endpoint device_node 2483fd9fdb78SPhilipp Zabel * 2484fd9fdb78SPhilipp Zabel * Return: Remote port node associated with remote endpoint node linked 2485fd9fdb78SPhilipp Zabel * to @node. Use of_node_put() on it when done. 2486fd9fdb78SPhilipp Zabel */ 2487fd9fdb78SPhilipp Zabel struct device_node *of_graph_get_remote_port(const struct device_node *node) 2488fd9fdb78SPhilipp Zabel { 2489fd9fdb78SPhilipp Zabel struct device_node *np; 2490fd9fdb78SPhilipp Zabel 2491fd9fdb78SPhilipp Zabel /* Get remote endpoint node. */ 2492fd9fdb78SPhilipp Zabel np = of_parse_phandle(node, "remote-endpoint", 0); 2493fd9fdb78SPhilipp Zabel if (!np) 2494fd9fdb78SPhilipp Zabel return NULL; 2495fd9fdb78SPhilipp Zabel return of_get_next_parent(np); 2496fd9fdb78SPhilipp Zabel } 2497fd9fdb78SPhilipp Zabel EXPORT_SYMBOL(of_graph_get_remote_port); 2498