197e873e5SStephen Rothwell /* 297e873e5SStephen Rothwell * Procedures for creating, accessing and interpreting the device tree. 397e873e5SStephen Rothwell * 497e873e5SStephen Rothwell * Paul Mackerras August 1996. 597e873e5SStephen Rothwell * Copyright (C) 1996-2005 Paul Mackerras. 697e873e5SStephen Rothwell * 797e873e5SStephen Rothwell * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 897e873e5SStephen Rothwell * {engebret|bergner}@us.ibm.com 997e873e5SStephen Rothwell * 1097e873e5SStephen Rothwell * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 1197e873e5SStephen Rothwell * 12e91edcf5SGrant Likely * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 13e91edcf5SGrant Likely * Grant Likely. 1497e873e5SStephen Rothwell * 1597e873e5SStephen Rothwell * This program is free software; you can redistribute it and/or 1697e873e5SStephen Rothwell * modify it under the terms of the GNU General Public License 1797e873e5SStephen Rothwell * as published by the Free Software Foundation; either version 1897e873e5SStephen Rothwell * 2 of the License, or (at your option) any later version. 1997e873e5SStephen Rothwell */ 20606ad42aSRob Herring 21606ad42aSRob Herring #define pr_fmt(fmt) "OF: " fmt 22606ad42aSRob Herring 233482f2c5SGrant Likely #include <linux/console.h> 24611cad72SShawn Guo #include <linux/ctype.h> 25183912d3SSudeep KarkadaNagesha #include <linux/cpu.h> 2697e873e5SStephen Rothwell #include <linux/module.h> 2797e873e5SStephen Rothwell #include <linux/of.h> 285fa23530SSudeep Holla #include <linux/of_device.h> 29fd9fdb78SPhilipp Zabel #include <linux/of_graph.h> 30581b605aSStephen Rothwell #include <linux/spinlock.h> 315a0e3ad6STejun Heo #include <linux/slab.h> 3275b57ecfSGrant Likely #include <linux/string.h> 33a9f2f63aSJeremy Kerr #include <linux/proc_fs.h> 34581b605aSStephen Rothwell 35ced4eec9SStepan Moskovchenko #include "of_private.h" 36611cad72SShawn Guo 37ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup); 38611cad72SShawn Guo 395063e25aSGrant Likely struct device_node *of_root; 405063e25aSGrant Likely EXPORT_SYMBOL(of_root); 41fc0bdae4SGrant Likely struct device_node *of_chosen; 42611cad72SShawn Guo struct device_node *of_aliases; 43a752ee56SGrant Likely struct device_node *of_stdout; 447914a7c5SLeif Lindholm static const char *of_stdout_options; 45611cad72SShawn Guo 468a2b22a2SGrant Likely struct kset *of_kset; 4775b57ecfSGrant Likely 4875b57ecfSGrant Likely /* 498a2b22a2SGrant Likely * Used to protect the of_aliases, to hold off addition of nodes to sysfs. 508a2b22a2SGrant Likely * This mutex must be held whenever modifications are being made to the 518a2b22a2SGrant Likely * device tree. The of_{attach,detach}_node() and 528a2b22a2SGrant Likely * of_{add,remove,update}_property() helpers make sure this happens. 5375b57ecfSGrant Likely */ 54c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex); 551ef4d424SStephen Rothwell 565063e25aSGrant Likely /* use when traversing tree through the child, sibling, 57581b605aSStephen Rothwell * or parent members of struct device_node. 58581b605aSStephen Rothwell */ 59d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock); 6097e873e5SStephen Rothwell 6197e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np) 6297e873e5SStephen Rothwell { 638832963dSSergei Shtylyov u32 cells; 6497e873e5SStephen Rothwell 6597e873e5SStephen Rothwell do { 6697e873e5SStephen Rothwell if (np->parent) 6797e873e5SStephen Rothwell np = np->parent; 688832963dSSergei Shtylyov if (!of_property_read_u32(np, "#address-cells", &cells)) 698832963dSSergei Shtylyov return cells; 7097e873e5SStephen Rothwell } while (np->parent); 7197e873e5SStephen Rothwell /* No #address-cells property for the root node */ 7297e873e5SStephen Rothwell return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 7397e873e5SStephen Rothwell } 7497e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells); 7597e873e5SStephen Rothwell 7697e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np) 7797e873e5SStephen Rothwell { 788832963dSSergei Shtylyov u32 cells; 7997e873e5SStephen Rothwell 8097e873e5SStephen Rothwell do { 8197e873e5SStephen Rothwell if (np->parent) 8297e873e5SStephen Rothwell np = np->parent; 838832963dSSergei Shtylyov if (!of_property_read_u32(np, "#size-cells", &cells)) 848832963dSSergei Shtylyov return cells; 8597e873e5SStephen Rothwell } while (np->parent); 8697e873e5SStephen Rothwell /* No #size-cells property for the root node */ 8797e873e5SStephen Rothwell return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 8897e873e5SStephen Rothwell } 8997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells); 9097e873e5SStephen Rothwell 910c3f061cSRob Herring #ifdef CONFIG_NUMA 920c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np) 930c3f061cSRob Herring { 94c8fff7bcSKonstantin Khlebnikov return NUMA_NO_NODE; 950c3f061cSRob Herring } 960c3f061cSRob Herring #endif 970c3f061cSRob Herring 98194ec936SSudeep Holla void __init of_core_init(void) 9975b57ecfSGrant Likely { 10075b57ecfSGrant Likely struct device_node *np; 10175b57ecfSGrant Likely 10275b57ecfSGrant Likely /* Create the kset, and register existing nodes */ 103c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 10475b57ecfSGrant Likely of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); 10575b57ecfSGrant Likely if (!of_kset) { 106c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 107606ad42aSRob Herring pr_err("failed to register existing nodes\n"); 108194ec936SSudeep Holla return; 10975b57ecfSGrant Likely } 11075b57ecfSGrant Likely for_each_of_allnodes(np) 1118a2b22a2SGrant Likely __of_attach_node_sysfs(np); 112c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 11375b57ecfSGrant Likely 1148357041aSGrant Likely /* Symlink in /proc as required by userspace ABI */ 1155063e25aSGrant Likely if (of_root) 11675b57ecfSGrant Likely proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); 11775b57ecfSGrant Likely } 11875b57ecfSGrant Likely 11928d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np, 12028d0e36bSThomas Gleixner const char *name, int *lenp) 121581b605aSStephen Rothwell { 122581b605aSStephen Rothwell struct property *pp; 123581b605aSStephen Rothwell 12464e4566fSTimur Tabi if (!np) 12564e4566fSTimur Tabi return NULL; 12664e4566fSTimur Tabi 127a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 128581b605aSStephen Rothwell if (of_prop_cmp(pp->name, name) == 0) { 129a3a7cab1SSachin Kamat if (lenp) 130581b605aSStephen Rothwell *lenp = pp->length; 131581b605aSStephen Rothwell break; 132581b605aSStephen Rothwell } 133581b605aSStephen Rothwell } 13428d0e36bSThomas Gleixner 13528d0e36bSThomas Gleixner return pp; 13628d0e36bSThomas Gleixner } 13728d0e36bSThomas Gleixner 13828d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np, 13928d0e36bSThomas Gleixner const char *name, 14028d0e36bSThomas Gleixner int *lenp) 14128d0e36bSThomas Gleixner { 14228d0e36bSThomas Gleixner struct property *pp; 143d6d3c4e6SThomas Gleixner unsigned long flags; 14428d0e36bSThomas Gleixner 145d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 14628d0e36bSThomas Gleixner pp = __of_find_property(np, name, lenp); 147d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 148581b605aSStephen Rothwell 149581b605aSStephen Rothwell return pp; 150581b605aSStephen Rothwell } 151581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property); 152581b605aSStephen Rothwell 1535063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev) 1545063e25aSGrant Likely { 1555063e25aSGrant Likely struct device_node *np; 1565063e25aSGrant Likely if (!prev) { 1575063e25aSGrant Likely np = of_root; 1585063e25aSGrant Likely } else if (prev->child) { 1595063e25aSGrant Likely np = prev->child; 1605063e25aSGrant Likely } else { 1615063e25aSGrant Likely /* Walk back up looking for a sibling, or the end of the structure */ 1625063e25aSGrant Likely np = prev; 1635063e25aSGrant Likely while (np->parent && !np->sibling) 1645063e25aSGrant Likely np = np->parent; 1655063e25aSGrant Likely np = np->sibling; /* Might be null at the end of the tree */ 1665063e25aSGrant Likely } 1675063e25aSGrant Likely return np; 1685063e25aSGrant Likely } 1695063e25aSGrant Likely 170e91edcf5SGrant Likely /** 171e91edcf5SGrant Likely * of_find_all_nodes - Get next node in global list 172e91edcf5SGrant Likely * @prev: Previous node or NULL to start iteration 173e91edcf5SGrant Likely * of_node_put() will be called on it 174e91edcf5SGrant Likely * 175e91edcf5SGrant Likely * Returns a node pointer with refcount incremented, use 176e91edcf5SGrant Likely * of_node_put() on it when done. 177e91edcf5SGrant Likely */ 178e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev) 179e91edcf5SGrant Likely { 180e91edcf5SGrant Likely struct device_node *np; 181d25d8694SBenjamin Herrenschmidt unsigned long flags; 182e91edcf5SGrant Likely 183d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 1845063e25aSGrant Likely np = __of_find_all_nodes(prev); 1855063e25aSGrant Likely of_node_get(np); 186e91edcf5SGrant Likely of_node_put(prev); 187d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 188e91edcf5SGrant Likely return np; 189e91edcf5SGrant Likely } 190e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes); 191e91edcf5SGrant Likely 19297e873e5SStephen Rothwell /* 19397e873e5SStephen Rothwell * Find a property with a given name for a given node 19497e873e5SStephen Rothwell * and return the value. 19597e873e5SStephen Rothwell */ 196a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np, 19728d0e36bSThomas Gleixner const char *name, int *lenp) 19828d0e36bSThomas Gleixner { 19928d0e36bSThomas Gleixner struct property *pp = __of_find_property(np, name, lenp); 20028d0e36bSThomas Gleixner 20128d0e36bSThomas Gleixner return pp ? pp->value : NULL; 20228d0e36bSThomas Gleixner } 20328d0e36bSThomas Gleixner 20428d0e36bSThomas Gleixner /* 20528d0e36bSThomas Gleixner * Find a property with a given name for a given node 20628d0e36bSThomas Gleixner * and return the value. 20728d0e36bSThomas Gleixner */ 20897e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name, 20997e873e5SStephen Rothwell int *lenp) 21097e873e5SStephen Rothwell { 21197e873e5SStephen Rothwell struct property *pp = of_find_property(np, name, lenp); 21297e873e5SStephen Rothwell 21397e873e5SStephen Rothwell return pp ? pp->value : NULL; 21497e873e5SStephen Rothwell } 21597e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property); 2160081cbc3SStephen Rothwell 217183912d3SSudeep KarkadaNagesha /* 218183912d3SSudeep KarkadaNagesha * arch_match_cpu_phys_id - Match the given logical CPU and physical id 219183912d3SSudeep KarkadaNagesha * 220183912d3SSudeep KarkadaNagesha * @cpu: logical cpu index of a core/thread 221183912d3SSudeep KarkadaNagesha * @phys_id: physical identifier of a core/thread 222183912d3SSudeep KarkadaNagesha * 223183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific. 224183912d3SSudeep KarkadaNagesha * However this __weak function provides a default match of physical 225183912d3SSudeep KarkadaNagesha * id to logical cpu index. phys_id provided here is usually values read 226183912d3SSudeep KarkadaNagesha * from the device tree which must match the hardware internal registers. 227183912d3SSudeep KarkadaNagesha * 228183912d3SSudeep KarkadaNagesha * Returns true if the physical identifier and the logical cpu index 229183912d3SSudeep KarkadaNagesha * correspond to the same core/thread, false otherwise. 230183912d3SSudeep KarkadaNagesha */ 231183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) 232183912d3SSudeep KarkadaNagesha { 233183912d3SSudeep KarkadaNagesha return (u32)phys_id == cpu; 234183912d3SSudeep KarkadaNagesha } 235183912d3SSudeep KarkadaNagesha 236183912d3SSudeep KarkadaNagesha /** 237183912d3SSudeep KarkadaNagesha * Checks if the given "prop_name" property holds the physical id of the 238183912d3SSudeep KarkadaNagesha * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not 239183912d3SSudeep KarkadaNagesha * NULL, local thread number within the core is returned in it. 240183912d3SSudeep KarkadaNagesha */ 241183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun, 242183912d3SSudeep KarkadaNagesha const char *prop_name, int cpu, unsigned int *thread) 243183912d3SSudeep KarkadaNagesha { 244183912d3SSudeep KarkadaNagesha const __be32 *cell; 245183912d3SSudeep KarkadaNagesha int ac, prop_len, tid; 246183912d3SSudeep KarkadaNagesha u64 hwid; 247183912d3SSudeep KarkadaNagesha 248183912d3SSudeep KarkadaNagesha ac = of_n_addr_cells(cpun); 249183912d3SSudeep KarkadaNagesha cell = of_get_property(cpun, prop_name, &prop_len); 250f3cea45aSGrant Likely if (!cell || !ac) 251183912d3SSudeep KarkadaNagesha return false; 252f3cea45aSGrant Likely prop_len /= sizeof(*cell) * ac; 253183912d3SSudeep KarkadaNagesha for (tid = 0; tid < prop_len; tid++) { 254183912d3SSudeep KarkadaNagesha hwid = of_read_number(cell, ac); 255183912d3SSudeep KarkadaNagesha if (arch_match_cpu_phys_id(cpu, hwid)) { 256183912d3SSudeep KarkadaNagesha if (thread) 257183912d3SSudeep KarkadaNagesha *thread = tid; 258183912d3SSudeep KarkadaNagesha return true; 259183912d3SSudeep KarkadaNagesha } 260183912d3SSudeep KarkadaNagesha cell += ac; 261183912d3SSudeep KarkadaNagesha } 262183912d3SSudeep KarkadaNagesha return false; 263183912d3SSudeep KarkadaNagesha } 264183912d3SSudeep KarkadaNagesha 265d1cb9d1aSDavid Miller /* 266d1cb9d1aSDavid Miller * arch_find_n_match_cpu_physical_id - See if the given device node is 267d1cb9d1aSDavid Miller * for the cpu corresponding to logical cpu 'cpu'. Return true if so, 268d1cb9d1aSDavid Miller * else false. If 'thread' is non-NULL, the local thread number within the 269d1cb9d1aSDavid Miller * core is returned in it. 270d1cb9d1aSDavid Miller */ 271d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, 272d1cb9d1aSDavid Miller int cpu, unsigned int *thread) 273d1cb9d1aSDavid Miller { 274d1cb9d1aSDavid Miller /* Check for non-standard "ibm,ppc-interrupt-server#s" property 275d1cb9d1aSDavid Miller * for thread ids on PowerPC. If it doesn't exist fallback to 276d1cb9d1aSDavid Miller * standard "reg" property. 277d1cb9d1aSDavid Miller */ 278d1cb9d1aSDavid Miller if (IS_ENABLED(CONFIG_PPC) && 279d1cb9d1aSDavid Miller __of_find_n_match_cpu_property(cpun, 280d1cb9d1aSDavid Miller "ibm,ppc-interrupt-server#s", 281d1cb9d1aSDavid Miller cpu, thread)) 282d1cb9d1aSDavid Miller return true; 283d1cb9d1aSDavid Miller 284510bd068SMasahiro Yamada return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); 285d1cb9d1aSDavid Miller } 286d1cb9d1aSDavid Miller 287183912d3SSudeep KarkadaNagesha /** 288183912d3SSudeep KarkadaNagesha * of_get_cpu_node - Get device node associated with the given logical CPU 289183912d3SSudeep KarkadaNagesha * 290183912d3SSudeep KarkadaNagesha * @cpu: CPU number(logical index) for which device node is required 291183912d3SSudeep KarkadaNagesha * @thread: if not NULL, local thread number within the physical core is 292183912d3SSudeep KarkadaNagesha * returned 293183912d3SSudeep KarkadaNagesha * 294183912d3SSudeep KarkadaNagesha * The main purpose of this function is to retrieve the device node for the 295183912d3SSudeep KarkadaNagesha * given logical CPU index. It should be used to initialize the of_node in 296183912d3SSudeep KarkadaNagesha * cpu device. Once of_node in cpu device is populated, all the further 297183912d3SSudeep KarkadaNagesha * references can use that instead. 298183912d3SSudeep KarkadaNagesha * 299183912d3SSudeep KarkadaNagesha * CPU logical to physical index mapping is architecture specific and is built 300183912d3SSudeep KarkadaNagesha * before booting secondary cores. This function uses arch_match_cpu_phys_id 301183912d3SSudeep KarkadaNagesha * which can be overridden by architecture specific implementation. 302183912d3SSudeep KarkadaNagesha * 3031c986e36SMasahiro Yamada * Returns a node pointer for the logical cpu with refcount incremented, use 3041c986e36SMasahiro Yamada * of_node_put() on it when done. Returns NULL if not found. 305183912d3SSudeep KarkadaNagesha */ 306183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) 307183912d3SSudeep KarkadaNagesha { 308d1cb9d1aSDavid Miller struct device_node *cpun; 309183912d3SSudeep KarkadaNagesha 310d1cb9d1aSDavid Miller for_each_node_by_type(cpun, "cpu") { 311d1cb9d1aSDavid Miller if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) 312183912d3SSudeep KarkadaNagesha return cpun; 313183912d3SSudeep KarkadaNagesha } 314183912d3SSudeep KarkadaNagesha return NULL; 315183912d3SSudeep KarkadaNagesha } 316183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node); 317183912d3SSudeep KarkadaNagesha 318215a14cfSKevin Hao /** 319215a14cfSKevin Hao * __of_device_is_compatible() - Check if the node matches given constraints 320215a14cfSKevin Hao * @device: pointer to node 321215a14cfSKevin Hao * @compat: required compatible string, NULL or "" for any match 322215a14cfSKevin Hao * @type: required device_type value, NULL or "" for any match 323215a14cfSKevin Hao * @name: required node name, NULL or "" for any match 324215a14cfSKevin Hao * 325215a14cfSKevin Hao * Checks if the given @compat, @type and @name strings match the 326215a14cfSKevin Hao * properties of the given @device. A constraints can be skipped by 327215a14cfSKevin Hao * passing NULL or an empty string as the constraint. 328215a14cfSKevin Hao * 329215a14cfSKevin Hao * Returns 0 for no match, and a positive integer on match. The return 330215a14cfSKevin Hao * value is a relative score with larger values indicating better 331215a14cfSKevin Hao * matches. The score is weighted for the most specific compatible value 332215a14cfSKevin Hao * to get the highest score. Matching type is next, followed by matching 333215a14cfSKevin Hao * name. Practically speaking, this results in the following priority 334215a14cfSKevin Hao * order for matches: 335215a14cfSKevin Hao * 336215a14cfSKevin Hao * 1. specific compatible && type && name 337215a14cfSKevin Hao * 2. specific compatible && type 338215a14cfSKevin Hao * 3. specific compatible && name 339215a14cfSKevin Hao * 4. specific compatible 340215a14cfSKevin Hao * 5. general compatible && type && name 341215a14cfSKevin Hao * 6. general compatible && type 342215a14cfSKevin Hao * 7. general compatible && name 343215a14cfSKevin Hao * 8. general compatible 344215a14cfSKevin Hao * 9. type && name 345215a14cfSKevin Hao * 10. type 346215a14cfSKevin Hao * 11. name 3470081cbc3SStephen Rothwell */ 34828d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device, 349215a14cfSKevin Hao const char *compat, const char *type, const char *name) 3500081cbc3SStephen Rothwell { 351215a14cfSKevin Hao struct property *prop; 3520081cbc3SStephen Rothwell const char *cp; 353215a14cfSKevin Hao int index = 0, score = 0; 3540081cbc3SStephen Rothwell 355215a14cfSKevin Hao /* Compatible match has highest priority */ 356215a14cfSKevin Hao if (compat && compat[0]) { 357215a14cfSKevin Hao prop = __of_find_property(device, "compatible", NULL); 358215a14cfSKevin Hao for (cp = of_prop_next_string(prop, NULL); cp; 359215a14cfSKevin Hao cp = of_prop_next_string(prop, cp), index++) { 360215a14cfSKevin Hao if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 361215a14cfSKevin Hao score = INT_MAX/2 - (index << 2); 362215a14cfSKevin Hao break; 363215a14cfSKevin Hao } 364215a14cfSKevin Hao } 365215a14cfSKevin Hao if (!score) 3660081cbc3SStephen Rothwell return 0; 3670081cbc3SStephen Rothwell } 3680081cbc3SStephen Rothwell 369215a14cfSKevin Hao /* Matching type is better than matching name */ 370215a14cfSKevin Hao if (type && type[0]) { 371215a14cfSKevin Hao if (!device->type || of_node_cmp(type, device->type)) 3720081cbc3SStephen Rothwell return 0; 373215a14cfSKevin Hao score += 2; 374215a14cfSKevin Hao } 375215a14cfSKevin Hao 376215a14cfSKevin Hao /* Matching name is a bit better than not */ 377215a14cfSKevin Hao if (name && name[0]) { 378215a14cfSKevin Hao if (!device->name || of_node_cmp(name, device->name)) 379215a14cfSKevin Hao return 0; 380215a14cfSKevin Hao score++; 381215a14cfSKevin Hao } 382215a14cfSKevin Hao 383215a14cfSKevin Hao return score; 3840081cbc3SStephen Rothwell } 38528d0e36bSThomas Gleixner 38628d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in 38728d0e36bSThomas Gleixner * the device's "compatible" property 38828d0e36bSThomas Gleixner */ 38928d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device, 39028d0e36bSThomas Gleixner const char *compat) 39128d0e36bSThomas Gleixner { 392d6d3c4e6SThomas Gleixner unsigned long flags; 39328d0e36bSThomas Gleixner int res; 39428d0e36bSThomas Gleixner 395d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 396215a14cfSKevin Hao res = __of_device_is_compatible(device, compat, NULL, NULL); 397d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 39828d0e36bSThomas Gleixner return res; 39928d0e36bSThomas Gleixner } 4000081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible); 401e679c5f4SStephen Rothwell 402b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in 403b9c13fe3SBenjamin Herrenschmidt * a NULL terminated array of strings. Returns the best match 404b9c13fe3SBenjamin Herrenschmidt * score or 0. 405b9c13fe3SBenjamin Herrenschmidt */ 406b9c13fe3SBenjamin Herrenschmidt int of_device_compatible_match(struct device_node *device, 407b9c13fe3SBenjamin Herrenschmidt const char *const *compat) 408b9c13fe3SBenjamin Herrenschmidt { 409b9c13fe3SBenjamin Herrenschmidt unsigned int tmp, score = 0; 410b9c13fe3SBenjamin Herrenschmidt 411b9c13fe3SBenjamin Herrenschmidt if (!compat) 412b9c13fe3SBenjamin Herrenschmidt return 0; 413b9c13fe3SBenjamin Herrenschmidt 414b9c13fe3SBenjamin Herrenschmidt while (*compat) { 415b9c13fe3SBenjamin Herrenschmidt tmp = of_device_is_compatible(device, *compat); 416b9c13fe3SBenjamin Herrenschmidt if (tmp > score) 417b9c13fe3SBenjamin Herrenschmidt score = tmp; 418b9c13fe3SBenjamin Herrenschmidt compat++; 419b9c13fe3SBenjamin Herrenschmidt } 420b9c13fe3SBenjamin Herrenschmidt 421b9c13fe3SBenjamin Herrenschmidt return score; 422b9c13fe3SBenjamin Herrenschmidt } 423b9c13fe3SBenjamin Herrenschmidt 424e679c5f4SStephen Rothwell /** 42571a157e8SGrant Likely * of_machine_is_compatible - Test root of device tree for a given compatible value 4261f43cfb9SGrant Likely * @compat: compatible string to look for in root node's compatible property. 4271f43cfb9SGrant Likely * 42825c7a1deSKevin Cernekee * Returns a positive integer if the root node has the given value in its 4291f43cfb9SGrant Likely * compatible property. 4301f43cfb9SGrant Likely */ 43171a157e8SGrant Likely int of_machine_is_compatible(const char *compat) 4321f43cfb9SGrant Likely { 4331f43cfb9SGrant Likely struct device_node *root; 4341f43cfb9SGrant Likely int rc = 0; 4351f43cfb9SGrant Likely 4361f43cfb9SGrant Likely root = of_find_node_by_path("/"); 4371f43cfb9SGrant Likely if (root) { 4381f43cfb9SGrant Likely rc = of_device_is_compatible(root, compat); 4391f43cfb9SGrant Likely of_node_put(root); 4401f43cfb9SGrant Likely } 4411f43cfb9SGrant Likely return rc; 4421f43cfb9SGrant Likely } 44371a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible); 4441f43cfb9SGrant Likely 4451f43cfb9SGrant Likely /** 446c31a0c05SStephen Warren * __of_device_is_available - check if a device is available for use 447834d97d4SJosh Boyer * 448c31a0c05SStephen Warren * @device: Node to check for availability, with locks already held 449834d97d4SJosh Boyer * 45053a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 45153a4ab96SKevin Cernekee * false otherwise 452834d97d4SJosh Boyer */ 45353a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device) 454834d97d4SJosh Boyer { 455834d97d4SJosh Boyer const char *status; 456834d97d4SJosh Boyer int statlen; 457834d97d4SJosh Boyer 45842ccd781SXiubo Li if (!device) 45953a4ab96SKevin Cernekee return false; 46042ccd781SXiubo Li 461c31a0c05SStephen Warren status = __of_get_property(device, "status", &statlen); 462834d97d4SJosh Boyer if (status == NULL) 46353a4ab96SKevin Cernekee return true; 464834d97d4SJosh Boyer 465834d97d4SJosh Boyer if (statlen > 0) { 466834d97d4SJosh Boyer if (!strcmp(status, "okay") || !strcmp(status, "ok")) 46753a4ab96SKevin Cernekee return true; 468834d97d4SJosh Boyer } 469834d97d4SJosh Boyer 47053a4ab96SKevin Cernekee return false; 471834d97d4SJosh Boyer } 472c31a0c05SStephen Warren 473c31a0c05SStephen Warren /** 474c31a0c05SStephen Warren * of_device_is_available - check if a device is available for use 475c31a0c05SStephen Warren * 476c31a0c05SStephen Warren * @device: Node to check for availability 477c31a0c05SStephen Warren * 47853a4ab96SKevin Cernekee * Returns true if the status property is absent or set to "okay" or "ok", 47953a4ab96SKevin Cernekee * false otherwise 480c31a0c05SStephen Warren */ 48153a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device) 482c31a0c05SStephen Warren { 483c31a0c05SStephen Warren unsigned long flags; 48453a4ab96SKevin Cernekee bool res; 485c31a0c05SStephen Warren 486c31a0c05SStephen Warren raw_spin_lock_irqsave(&devtree_lock, flags); 487c31a0c05SStephen Warren res = __of_device_is_available(device); 488c31a0c05SStephen Warren raw_spin_unlock_irqrestore(&devtree_lock, flags); 489c31a0c05SStephen Warren return res; 490c31a0c05SStephen Warren 491c31a0c05SStephen Warren } 492834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available); 493834d97d4SJosh Boyer 494834d97d4SJosh Boyer /** 49537786c7fSKevin Cernekee * of_device_is_big_endian - check if a device has BE registers 49637786c7fSKevin Cernekee * 49737786c7fSKevin Cernekee * @device: Node to check for endianness 49837786c7fSKevin Cernekee * 49937786c7fSKevin Cernekee * Returns true if the device has a "big-endian" property, or if the kernel 50037786c7fSKevin Cernekee * was compiled for BE *and* the device has a "native-endian" property. 50137786c7fSKevin Cernekee * Returns false otherwise. 50237786c7fSKevin Cernekee * 50337786c7fSKevin Cernekee * Callers would nominally use ioread32be/iowrite32be if 50437786c7fSKevin Cernekee * of_device_is_big_endian() == true, or readl/writel otherwise. 50537786c7fSKevin Cernekee */ 50637786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device) 50737786c7fSKevin Cernekee { 50837786c7fSKevin Cernekee if (of_property_read_bool(device, "big-endian")) 50937786c7fSKevin Cernekee return true; 51037786c7fSKevin Cernekee if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && 51137786c7fSKevin Cernekee of_property_read_bool(device, "native-endian")) 51237786c7fSKevin Cernekee return true; 51337786c7fSKevin Cernekee return false; 51437786c7fSKevin Cernekee } 51537786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian); 51637786c7fSKevin Cernekee 51737786c7fSKevin Cernekee /** 518e679c5f4SStephen Rothwell * of_get_parent - Get a node's parent if any 519e679c5f4SStephen Rothwell * @node: Node to get parent 520e679c5f4SStephen Rothwell * 521e679c5f4SStephen Rothwell * Returns a node pointer with refcount incremented, use 522e679c5f4SStephen Rothwell * of_node_put() on it when done. 523e679c5f4SStephen Rothwell */ 524e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node) 525e679c5f4SStephen Rothwell { 526e679c5f4SStephen Rothwell struct device_node *np; 527d6d3c4e6SThomas Gleixner unsigned long flags; 528e679c5f4SStephen Rothwell 529e679c5f4SStephen Rothwell if (!node) 530e679c5f4SStephen Rothwell return NULL; 531e679c5f4SStephen Rothwell 532d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 533e679c5f4SStephen Rothwell np = of_node_get(node->parent); 534d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 535e679c5f4SStephen Rothwell return np; 536e679c5f4SStephen Rothwell } 537e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent); 538d1cd355aSStephen Rothwell 539d1cd355aSStephen Rothwell /** 540f4eb0107SMichael Ellerman * of_get_next_parent - Iterate to a node's parent 541f4eb0107SMichael Ellerman * @node: Node to get parent of 542f4eb0107SMichael Ellerman * 543f4eb0107SMichael Ellerman * This is like of_get_parent() except that it drops the 544f4eb0107SMichael Ellerman * refcount on the passed node, making it suitable for iterating 545f4eb0107SMichael Ellerman * through a node's parents. 546f4eb0107SMichael Ellerman * 547f4eb0107SMichael Ellerman * Returns a node pointer with refcount incremented, use 548f4eb0107SMichael Ellerman * of_node_put() on it when done. 549f4eb0107SMichael Ellerman */ 550f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node) 551f4eb0107SMichael Ellerman { 552f4eb0107SMichael Ellerman struct device_node *parent; 553d6d3c4e6SThomas Gleixner unsigned long flags; 554f4eb0107SMichael Ellerman 555f4eb0107SMichael Ellerman if (!node) 556f4eb0107SMichael Ellerman return NULL; 557f4eb0107SMichael Ellerman 558d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 559f4eb0107SMichael Ellerman parent = of_node_get(node->parent); 560f4eb0107SMichael Ellerman of_node_put(node); 561d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 562f4eb0107SMichael Ellerman return parent; 563f4eb0107SMichael Ellerman } 5646695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent); 565f4eb0107SMichael Ellerman 5660d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node, 5670d0e02d6SGrant Likely struct device_node *prev) 5680d0e02d6SGrant Likely { 5690d0e02d6SGrant Likely struct device_node *next; 5700d0e02d6SGrant Likely 57143cb4367SFlorian Fainelli if (!node) 57243cb4367SFlorian Fainelli return NULL; 57343cb4367SFlorian Fainelli 5740d0e02d6SGrant Likely next = prev ? prev->sibling : node->child; 5750d0e02d6SGrant Likely for (; next; next = next->sibling) 5760d0e02d6SGrant Likely if (of_node_get(next)) 5770d0e02d6SGrant Likely break; 5780d0e02d6SGrant Likely of_node_put(prev); 5790d0e02d6SGrant Likely return next; 5800d0e02d6SGrant Likely } 5810d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \ 5820d0e02d6SGrant Likely for (child = __of_get_next_child(parent, NULL); child != NULL; \ 5830d0e02d6SGrant Likely child = __of_get_next_child(parent, child)) 5840d0e02d6SGrant Likely 585f4eb0107SMichael Ellerman /** 586d1cd355aSStephen Rothwell * of_get_next_child - Iterate a node childs 587d1cd355aSStephen Rothwell * @node: parent node 588d1cd355aSStephen Rothwell * @prev: previous child of the parent node, or NULL to get first 589d1cd355aSStephen Rothwell * 59064808273SBaruch Siach * Returns a node pointer with refcount incremented, use of_node_put() on 59164808273SBaruch Siach * it when done. Returns NULL when prev is the last child. Decrements the 59264808273SBaruch Siach * refcount of prev. 593d1cd355aSStephen Rothwell */ 594d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node, 595d1cd355aSStephen Rothwell struct device_node *prev) 596d1cd355aSStephen Rothwell { 597d1cd355aSStephen Rothwell struct device_node *next; 598d6d3c4e6SThomas Gleixner unsigned long flags; 599d1cd355aSStephen Rothwell 600d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 6010d0e02d6SGrant Likely next = __of_get_next_child(node, prev); 602d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 603d1cd355aSStephen Rothwell return next; 604d1cd355aSStephen Rothwell } 605d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child); 6061ef4d424SStephen Rothwell 6071ef4d424SStephen Rothwell /** 6083296193dSTimur Tabi * of_get_next_available_child - Find the next available child node 6093296193dSTimur Tabi * @node: parent node 6103296193dSTimur Tabi * @prev: previous child of the parent node, or NULL to get first 6113296193dSTimur Tabi * 6123296193dSTimur Tabi * This function is like of_get_next_child(), except that it 6133296193dSTimur Tabi * automatically skips any disabled nodes (i.e. status = "disabled"). 6143296193dSTimur Tabi */ 6153296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node, 6163296193dSTimur Tabi struct device_node *prev) 6173296193dSTimur Tabi { 6183296193dSTimur Tabi struct device_node *next; 619d25d8694SBenjamin Herrenschmidt unsigned long flags; 6203296193dSTimur Tabi 62143cb4367SFlorian Fainelli if (!node) 62243cb4367SFlorian Fainelli return NULL; 62343cb4367SFlorian Fainelli 624d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 6253296193dSTimur Tabi next = prev ? prev->sibling : node->child; 6263296193dSTimur Tabi for (; next; next = next->sibling) { 627c31a0c05SStephen Warren if (!__of_device_is_available(next)) 6283296193dSTimur Tabi continue; 6293296193dSTimur Tabi if (of_node_get(next)) 6303296193dSTimur Tabi break; 6313296193dSTimur Tabi } 6323296193dSTimur Tabi of_node_put(prev); 633d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 6343296193dSTimur Tabi return next; 6353296193dSTimur Tabi } 6363296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child); 6373296193dSTimur Tabi 6383296193dSTimur Tabi /** 6399c19761aSSrinivas Kandagatla * of_get_child_by_name - Find the child node by name for a given parent 6409c19761aSSrinivas Kandagatla * @node: parent node 6419c19761aSSrinivas Kandagatla * @name: child name to look for. 6429c19761aSSrinivas Kandagatla * 6439c19761aSSrinivas Kandagatla * This function looks for child node for given matching name 6449c19761aSSrinivas Kandagatla * 6459c19761aSSrinivas Kandagatla * Returns a node pointer if found, with refcount incremented, use 6469c19761aSSrinivas Kandagatla * of_node_put() on it when done. 6479c19761aSSrinivas Kandagatla * Returns NULL if node is not found. 6489c19761aSSrinivas Kandagatla */ 6499c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node, 6509c19761aSSrinivas Kandagatla const char *name) 6519c19761aSSrinivas Kandagatla { 6529c19761aSSrinivas Kandagatla struct device_node *child; 6539c19761aSSrinivas Kandagatla 6549c19761aSSrinivas Kandagatla for_each_child_of_node(node, child) 6559c19761aSSrinivas Kandagatla if (child->name && (of_node_cmp(child->name, name) == 0)) 6569c19761aSSrinivas Kandagatla break; 6579c19761aSSrinivas Kandagatla return child; 6589c19761aSSrinivas Kandagatla } 6599c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name); 6609c19761aSSrinivas Kandagatla 661e0a58f3eSFrank Rowand struct device_node *__of_find_node_by_path(struct device_node *parent, 662c22e650eSGrant Likely const char *path) 663c22e650eSGrant Likely { 664c22e650eSGrant Likely struct device_node *child; 665106937e8SLeif Lindholm int len; 666c22e650eSGrant Likely 667721a09e9SBrian Norris len = strcspn(path, "/:"); 668c22e650eSGrant Likely if (!len) 669c22e650eSGrant Likely return NULL; 670c22e650eSGrant Likely 671c22e650eSGrant Likely __for_each_child_of_node(parent, child) { 67295e6b1faSRob Herring const char *name = kbasename(child->full_name); 673c22e650eSGrant Likely if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 674c22e650eSGrant Likely return child; 675c22e650eSGrant Likely } 676c22e650eSGrant Likely return NULL; 677c22e650eSGrant Likely } 678c22e650eSGrant Likely 67927497e11SRob Herring struct device_node *__of_find_node_by_full_path(struct device_node *node, 68027497e11SRob Herring const char *path) 68127497e11SRob Herring { 68227497e11SRob Herring const char *separator = strchr(path, ':'); 68327497e11SRob Herring 68427497e11SRob Herring while (node && *path == '/') { 68527497e11SRob Herring struct device_node *tmp = node; 68627497e11SRob Herring 68727497e11SRob Herring path++; /* Increment past '/' delimiter */ 68827497e11SRob Herring node = __of_find_node_by_path(node, path); 68927497e11SRob Herring of_node_put(tmp); 69027497e11SRob Herring path = strchrnul(path, '/'); 69127497e11SRob Herring if (separator && separator < path) 69227497e11SRob Herring break; 69327497e11SRob Herring } 69427497e11SRob Herring return node; 69527497e11SRob Herring } 69627497e11SRob Herring 6979c19761aSSrinivas Kandagatla /** 69875c28c09SLeif Lindholm * of_find_node_opts_by_path - Find a node matching a full OF path 699c22e650eSGrant Likely * @path: Either the full path to match, or if the path does not 700c22e650eSGrant Likely * start with '/', the name of a property of the /aliases 701c22e650eSGrant Likely * node (an alias). In the case of an alias, the node 702c22e650eSGrant Likely * matching the alias' value will be returned. 70375c28c09SLeif Lindholm * @opts: Address of a pointer into which to store the start of 70475c28c09SLeif Lindholm * an options string appended to the end of the path with 70575c28c09SLeif Lindholm * a ':' separator. 706c22e650eSGrant Likely * 707c22e650eSGrant Likely * Valid paths: 708c22e650eSGrant Likely * /foo/bar Full path 709c22e650eSGrant Likely * foo Valid alias 710c22e650eSGrant Likely * foo/bar Valid alias + relative path 7111ef4d424SStephen Rothwell * 7121ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 7131ef4d424SStephen Rothwell * of_node_put() on it when done. 7141ef4d424SStephen Rothwell */ 71575c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) 7161ef4d424SStephen Rothwell { 717c22e650eSGrant Likely struct device_node *np = NULL; 718c22e650eSGrant Likely struct property *pp; 719d6d3c4e6SThomas Gleixner unsigned long flags; 72075c28c09SLeif Lindholm const char *separator = strchr(path, ':'); 72175c28c09SLeif Lindholm 72275c28c09SLeif Lindholm if (opts) 72375c28c09SLeif Lindholm *opts = separator ? separator + 1 : NULL; 7241ef4d424SStephen Rothwell 725c22e650eSGrant Likely if (strcmp(path, "/") == 0) 7265063e25aSGrant Likely return of_node_get(of_root); 727c22e650eSGrant Likely 728c22e650eSGrant Likely /* The path could begin with an alias */ 729c22e650eSGrant Likely if (*path != '/') { 730106937e8SLeif Lindholm int len; 731106937e8SLeif Lindholm const char *p = separator; 732106937e8SLeif Lindholm 733106937e8SLeif Lindholm if (!p) 734106937e8SLeif Lindholm p = strchrnul(path, '/'); 735106937e8SLeif Lindholm len = p - path; 736c22e650eSGrant Likely 737c22e650eSGrant Likely /* of_aliases must not be NULL */ 738c22e650eSGrant Likely if (!of_aliases) 739c22e650eSGrant Likely return NULL; 740c22e650eSGrant Likely 741c22e650eSGrant Likely for_each_property_of_node(of_aliases, pp) { 742c22e650eSGrant Likely if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) { 743c22e650eSGrant Likely np = of_find_node_by_path(pp->value); 7441ef4d424SStephen Rothwell break; 7451ef4d424SStephen Rothwell } 746c22e650eSGrant Likely } 747c22e650eSGrant Likely if (!np) 748c22e650eSGrant Likely return NULL; 749c22e650eSGrant Likely path = p; 750c22e650eSGrant Likely } 751c22e650eSGrant Likely 752c22e650eSGrant Likely /* Step down the tree matching path components */ 753c22e650eSGrant Likely raw_spin_lock_irqsave(&devtree_lock, flags); 754c22e650eSGrant Likely if (!np) 7555063e25aSGrant Likely np = of_node_get(of_root); 75627497e11SRob Herring np = __of_find_node_by_full_path(np, path); 757d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 7581ef4d424SStephen Rothwell return np; 7591ef4d424SStephen Rothwell } 76075c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path); 7611ef4d424SStephen Rothwell 7621ef4d424SStephen Rothwell /** 7631ef4d424SStephen Rothwell * of_find_node_by_name - Find a node by its "name" property 76402a876b5SStephen Boyd * @from: The node to start searching from or NULL; the node 7651ef4d424SStephen Rothwell * you pass will not be searched, only the next one 76602a876b5SStephen Boyd * will. Typically, you pass what the previous call 76702a876b5SStephen Boyd * returned. of_node_put() will be called on @from. 7681ef4d424SStephen Rothwell * @name: The name string to match against 7691ef4d424SStephen Rothwell * 7701ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 7711ef4d424SStephen Rothwell * of_node_put() on it when done. 7721ef4d424SStephen Rothwell */ 7731ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from, 7741ef4d424SStephen Rothwell const char *name) 7751ef4d424SStephen Rothwell { 7761ef4d424SStephen Rothwell struct device_node *np; 777d6d3c4e6SThomas Gleixner unsigned long flags; 7781ef4d424SStephen Rothwell 779d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 7805063e25aSGrant Likely for_each_of_allnodes_from(from, np) 7811ef4d424SStephen Rothwell if (np->name && (of_node_cmp(np->name, name) == 0) 7821ef4d424SStephen Rothwell && of_node_get(np)) 7831ef4d424SStephen Rothwell break; 7841ef4d424SStephen Rothwell of_node_put(from); 785d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 7861ef4d424SStephen Rothwell return np; 7871ef4d424SStephen Rothwell } 7881ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name); 7891ef4d424SStephen Rothwell 7901ef4d424SStephen Rothwell /** 7911ef4d424SStephen Rothwell * of_find_node_by_type - Find a node by its "device_type" property 7921ef4d424SStephen Rothwell * @from: The node to start searching from, or NULL to start searching 7931ef4d424SStephen Rothwell * the entire device tree. The node you pass will not be 7941ef4d424SStephen Rothwell * searched, only the next one will; typically, you pass 7951ef4d424SStephen Rothwell * what the previous call returned. of_node_put() will be 7961ef4d424SStephen Rothwell * called on from for you. 7971ef4d424SStephen Rothwell * @type: The type string to match against 7981ef4d424SStephen Rothwell * 7991ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8001ef4d424SStephen Rothwell * of_node_put() on it when done. 8011ef4d424SStephen Rothwell */ 8021ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from, 8031ef4d424SStephen Rothwell const char *type) 8041ef4d424SStephen Rothwell { 8051ef4d424SStephen Rothwell struct device_node *np; 806d6d3c4e6SThomas Gleixner unsigned long flags; 8071ef4d424SStephen Rothwell 808d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8095063e25aSGrant Likely for_each_of_allnodes_from(from, np) 8101ef4d424SStephen Rothwell if (np->type && (of_node_cmp(np->type, type) == 0) 8111ef4d424SStephen Rothwell && of_node_get(np)) 8121ef4d424SStephen Rothwell break; 8131ef4d424SStephen Rothwell of_node_put(from); 814d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8151ef4d424SStephen Rothwell return np; 8161ef4d424SStephen Rothwell } 8171ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type); 8181ef4d424SStephen Rothwell 8191ef4d424SStephen Rothwell /** 8201ef4d424SStephen Rothwell * of_find_compatible_node - Find a node based on type and one of the 8211ef4d424SStephen Rothwell * tokens in its "compatible" property 8221ef4d424SStephen Rothwell * @from: The node to start searching from or NULL, the node 8231ef4d424SStephen Rothwell * you pass will not be searched, only the next one 8241ef4d424SStephen Rothwell * will; typically, you pass what the previous call 8251ef4d424SStephen Rothwell * returned. of_node_put() will be called on it 8261ef4d424SStephen Rothwell * @type: The type string to match "device_type" or NULL to ignore 8271ef4d424SStephen Rothwell * @compatible: The string to match to one of the tokens in the device 8281ef4d424SStephen Rothwell * "compatible" list. 8291ef4d424SStephen Rothwell * 8301ef4d424SStephen Rothwell * Returns a node pointer with refcount incremented, use 8311ef4d424SStephen Rothwell * of_node_put() on it when done. 8321ef4d424SStephen Rothwell */ 8331ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from, 8341ef4d424SStephen Rothwell const char *type, const char *compatible) 8351ef4d424SStephen Rothwell { 8361ef4d424SStephen Rothwell struct device_node *np; 837d6d3c4e6SThomas Gleixner unsigned long flags; 8381ef4d424SStephen Rothwell 839d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8405063e25aSGrant Likely for_each_of_allnodes_from(from, np) 841215a14cfSKevin Hao if (__of_device_is_compatible(np, compatible, type, NULL) && 84228d0e36bSThomas Gleixner of_node_get(np)) 8431ef4d424SStephen Rothwell break; 8441ef4d424SStephen Rothwell of_node_put(from); 845d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8461ef4d424SStephen Rothwell return np; 8471ef4d424SStephen Rothwell } 8481ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node); 849283029d1SGrant Likely 850283029d1SGrant Likely /** 8511e291b14SMichael Ellerman * of_find_node_with_property - Find a node which has a property with 8521e291b14SMichael Ellerman * the given name. 8531e291b14SMichael Ellerman * @from: The node to start searching from or NULL, the node 8541e291b14SMichael Ellerman * you pass will not be searched, only the next one 8551e291b14SMichael Ellerman * will; typically, you pass what the previous call 8561e291b14SMichael Ellerman * returned. of_node_put() will be called on it 8571e291b14SMichael Ellerman * @prop_name: The name of the property to look for. 8581e291b14SMichael Ellerman * 8591e291b14SMichael Ellerman * Returns a node pointer with refcount incremented, use 8601e291b14SMichael Ellerman * of_node_put() on it when done. 8611e291b14SMichael Ellerman */ 8621e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from, 8631e291b14SMichael Ellerman const char *prop_name) 8641e291b14SMichael Ellerman { 8651e291b14SMichael Ellerman struct device_node *np; 8661e291b14SMichael Ellerman struct property *pp; 867d6d3c4e6SThomas Gleixner unsigned long flags; 8681e291b14SMichael Ellerman 869d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 8705063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 871a3a7cab1SSachin Kamat for (pp = np->properties; pp; pp = pp->next) { 8721e291b14SMichael Ellerman if (of_prop_cmp(pp->name, prop_name) == 0) { 8731e291b14SMichael Ellerman of_node_get(np); 8741e291b14SMichael Ellerman goto out; 8751e291b14SMichael Ellerman } 8761e291b14SMichael Ellerman } 8771e291b14SMichael Ellerman } 8781e291b14SMichael Ellerman out: 8791e291b14SMichael Ellerman of_node_put(from); 880d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 8811e291b14SMichael Ellerman return np; 8821e291b14SMichael Ellerman } 8831e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property); 8841e291b14SMichael Ellerman 88528d0e36bSThomas Gleixner static 88628d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches, 887283029d1SGrant Likely const struct device_node *node) 888283029d1SGrant Likely { 889215a14cfSKevin Hao const struct of_device_id *best_match = NULL; 890215a14cfSKevin Hao int score, best_score = 0; 891215a14cfSKevin Hao 892a52f07ecSGrant Likely if (!matches) 893a52f07ecSGrant Likely return NULL; 894a52f07ecSGrant Likely 895215a14cfSKevin Hao for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) { 896215a14cfSKevin Hao score = __of_device_is_compatible(node, matches->compatible, 897215a14cfSKevin Hao matches->type, matches->name); 898215a14cfSKevin Hao if (score > best_score) { 899215a14cfSKevin Hao best_match = matches; 900215a14cfSKevin Hao best_score = score; 901283029d1SGrant Likely } 902215a14cfSKevin Hao } 903215a14cfSKevin Hao 904215a14cfSKevin Hao return best_match; 905283029d1SGrant Likely } 90628d0e36bSThomas Gleixner 90728d0e36bSThomas Gleixner /** 908c50949d3SGeert Uytterhoeven * of_match_node - Tell if a device_node has a matching of_match structure 90928d0e36bSThomas Gleixner * @matches: array of of device match structures to search in 91028d0e36bSThomas Gleixner * @node: the of device structure to match against 91128d0e36bSThomas Gleixner * 91271c5498eSKevin Hao * Low level utility function used by device matching. 91328d0e36bSThomas Gleixner */ 91428d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches, 91528d0e36bSThomas Gleixner const struct device_node *node) 91628d0e36bSThomas Gleixner { 91728d0e36bSThomas Gleixner const struct of_device_id *match; 918d6d3c4e6SThomas Gleixner unsigned long flags; 91928d0e36bSThomas Gleixner 920d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 92128d0e36bSThomas Gleixner match = __of_match_node(matches, node); 922d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 92328d0e36bSThomas Gleixner return match; 92428d0e36bSThomas Gleixner } 925283029d1SGrant Likely EXPORT_SYMBOL(of_match_node); 926283029d1SGrant Likely 927283029d1SGrant Likely /** 92850c8af4cSStephen Warren * of_find_matching_node_and_match - Find a node based on an of_device_id 92950c8af4cSStephen Warren * match table. 930283029d1SGrant Likely * @from: The node to start searching from or NULL, the node 931283029d1SGrant Likely * you pass will not be searched, only the next one 932283029d1SGrant Likely * will; typically, you pass what the previous call 933283029d1SGrant Likely * returned. of_node_put() will be called on it 934283029d1SGrant Likely * @matches: array of of device match structures to search in 93550c8af4cSStephen Warren * @match Updated to point at the matches entry which matched 936283029d1SGrant Likely * 937283029d1SGrant Likely * Returns a node pointer with refcount incremented, use 938283029d1SGrant Likely * of_node_put() on it when done. 939283029d1SGrant Likely */ 94050c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from, 94150c8af4cSStephen Warren const struct of_device_id *matches, 94250c8af4cSStephen Warren const struct of_device_id **match) 943283029d1SGrant Likely { 944283029d1SGrant Likely struct device_node *np; 945dc71bcf1SThomas Abraham const struct of_device_id *m; 946d6d3c4e6SThomas Gleixner unsigned long flags; 947283029d1SGrant Likely 94850c8af4cSStephen Warren if (match) 94950c8af4cSStephen Warren *match = NULL; 95050c8af4cSStephen Warren 951d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 9525063e25aSGrant Likely for_each_of_allnodes_from(from, np) { 95328d0e36bSThomas Gleixner m = __of_match_node(matches, np); 954dc71bcf1SThomas Abraham if (m && of_node_get(np)) { 95550c8af4cSStephen Warren if (match) 956dc71bcf1SThomas Abraham *match = m; 957283029d1SGrant Likely break; 958283029d1SGrant Likely } 95950c8af4cSStephen Warren } 960283029d1SGrant Likely of_node_put(from); 961d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 962283029d1SGrant Likely return np; 963283029d1SGrant Likely } 96480c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match); 9653f07af49SGrant Likely 9663f07af49SGrant Likely /** 9673f07af49SGrant Likely * of_modalias_node - Lookup appropriate modalias for a device node 9683f07af49SGrant Likely * @node: pointer to a device tree node 9693f07af49SGrant Likely * @modalias: Pointer to buffer that modalias value will be copied into 9703f07af49SGrant Likely * @len: Length of modalias value 9713f07af49SGrant Likely * 9722ffe8c5fSGrant Likely * Based on the value of the compatible property, this routine will attempt 9732ffe8c5fSGrant Likely * to choose an appropriate modalias value for a particular device tree node. 9742ffe8c5fSGrant Likely * It does this by stripping the manufacturer prefix (as delimited by a ',') 9752ffe8c5fSGrant Likely * from the first entry in the compatible list property. 9763f07af49SGrant Likely * 9772ffe8c5fSGrant Likely * This routine returns 0 on success, <0 on failure. 9783f07af49SGrant Likely */ 9793f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len) 9803f07af49SGrant Likely { 9812ffe8c5fSGrant Likely const char *compatible, *p; 9822ffe8c5fSGrant Likely int cplen; 9833f07af49SGrant Likely 9843f07af49SGrant Likely compatible = of_get_property(node, "compatible", &cplen); 9852ffe8c5fSGrant Likely if (!compatible || strlen(compatible) > cplen) 9863f07af49SGrant Likely return -ENODEV; 9873f07af49SGrant Likely p = strchr(compatible, ','); 9882ffe8c5fSGrant Likely strlcpy(modalias, p ? p + 1 : compatible, len); 9893f07af49SGrant Likely return 0; 9903f07af49SGrant Likely } 9913f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node); 9923f07af49SGrant Likely 99364b60e09SAnton Vorontsov /** 99489751a7cSJeremy Kerr * of_find_node_by_phandle - Find a node given a phandle 99589751a7cSJeremy Kerr * @handle: phandle of the node to find 99689751a7cSJeremy Kerr * 99789751a7cSJeremy Kerr * Returns a node pointer with refcount incremented, use 99889751a7cSJeremy Kerr * of_node_put() on it when done. 99989751a7cSJeremy Kerr */ 100089751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle) 100189751a7cSJeremy Kerr { 100289751a7cSJeremy Kerr struct device_node *np; 1003d25d8694SBenjamin Herrenschmidt unsigned long flags; 100489751a7cSJeremy Kerr 1005fc59b447SGrant Likely if (!handle) 1006fc59b447SGrant Likely return NULL; 1007fc59b447SGrant Likely 1008d25d8694SBenjamin Herrenschmidt raw_spin_lock_irqsave(&devtree_lock, flags); 10095063e25aSGrant Likely for_each_of_allnodes(np) 101089751a7cSJeremy Kerr if (np->phandle == handle) 101189751a7cSJeremy Kerr break; 101289751a7cSJeremy Kerr of_node_get(np); 1013d25d8694SBenjamin Herrenschmidt raw_spin_unlock_irqrestore(&devtree_lock, flags); 101489751a7cSJeremy Kerr return np; 101589751a7cSJeremy Kerr } 101689751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle); 101789751a7cSJeremy Kerr 1018624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) 1019624cfca5SGrant Likely { 1020624cfca5SGrant Likely int i; 10210d638a07SRob Herring printk("%s %pOF", msg, args->np); 10224aa66344SMarcin Nowakowski for (i = 0; i < args->args_count; i++) { 10234aa66344SMarcin Nowakowski const char delim = i ? ',' : ':'; 10244aa66344SMarcin Nowakowski 10254aa66344SMarcin Nowakowski pr_cont("%c%08x", delim, args->args[i]); 10264aa66344SMarcin Nowakowski } 10274aa66344SMarcin Nowakowski pr_cont("\n"); 1028624cfca5SGrant Likely } 1029624cfca5SGrant Likely 103074e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it, 103174e1fbb1SJoerg Roedel const struct device_node *np, 103274e1fbb1SJoerg Roedel const char *list_name, 103374e1fbb1SJoerg Roedel const char *cells_name, 103474e1fbb1SJoerg Roedel int cell_count) 103574e1fbb1SJoerg Roedel { 103674e1fbb1SJoerg Roedel const __be32 *list; 103774e1fbb1SJoerg Roedel int size; 103874e1fbb1SJoerg Roedel 103974e1fbb1SJoerg Roedel memset(it, 0, sizeof(*it)); 104074e1fbb1SJoerg Roedel 104174e1fbb1SJoerg Roedel list = of_get_property(np, list_name, &size); 104274e1fbb1SJoerg Roedel if (!list) 104374e1fbb1SJoerg Roedel return -ENOENT; 104474e1fbb1SJoerg Roedel 104574e1fbb1SJoerg Roedel it->cells_name = cells_name; 104674e1fbb1SJoerg Roedel it->cell_count = cell_count; 104774e1fbb1SJoerg Roedel it->parent = np; 104874e1fbb1SJoerg Roedel it->list_end = list + size / sizeof(*list); 104974e1fbb1SJoerg Roedel it->phandle_end = list; 105074e1fbb1SJoerg Roedel it->cur = list; 105174e1fbb1SJoerg Roedel 105274e1fbb1SJoerg Roedel return 0; 105374e1fbb1SJoerg Roedel } 105400bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_init); 105574e1fbb1SJoerg Roedel 1056cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it) 1057cd209b41SJoerg Roedel { 1058cd209b41SJoerg Roedel uint32_t count = 0; 1059cd209b41SJoerg Roedel 1060cd209b41SJoerg Roedel if (it->node) { 1061cd209b41SJoerg Roedel of_node_put(it->node); 1062cd209b41SJoerg Roedel it->node = NULL; 1063cd209b41SJoerg Roedel } 1064cd209b41SJoerg Roedel 1065cd209b41SJoerg Roedel if (!it->cur || it->phandle_end >= it->list_end) 1066cd209b41SJoerg Roedel return -ENOENT; 1067cd209b41SJoerg Roedel 1068cd209b41SJoerg Roedel it->cur = it->phandle_end; 1069cd209b41SJoerg Roedel 1070cd209b41SJoerg Roedel /* If phandle is 0, then it is an empty entry with no arguments. */ 1071cd209b41SJoerg Roedel it->phandle = be32_to_cpup(it->cur++); 1072cd209b41SJoerg Roedel 1073cd209b41SJoerg Roedel if (it->phandle) { 1074cd209b41SJoerg Roedel 1075cd209b41SJoerg Roedel /* 1076cd209b41SJoerg Roedel * Find the provider node and parse the #*-cells property to 1077cd209b41SJoerg Roedel * determine the argument length. 1078cd209b41SJoerg Roedel */ 1079cd209b41SJoerg Roedel it->node = of_find_node_by_phandle(it->phandle); 1080cd209b41SJoerg Roedel 1081cd209b41SJoerg Roedel if (it->cells_name) { 1082cd209b41SJoerg Roedel if (!it->node) { 10830d638a07SRob Herring pr_err("%pOF: could not find phandle\n", 10840d638a07SRob Herring it->parent); 1085cd209b41SJoerg Roedel goto err; 1086cd209b41SJoerg Roedel } 1087cd209b41SJoerg Roedel 1088cd209b41SJoerg Roedel if (of_property_read_u32(it->node, it->cells_name, 1089cd209b41SJoerg Roedel &count)) { 10900d638a07SRob Herring pr_err("%pOF: could not get %s for %pOF\n", 10910d638a07SRob Herring it->parent, 1092cd209b41SJoerg Roedel it->cells_name, 10930d638a07SRob Herring it->node); 1094cd209b41SJoerg Roedel goto err; 1095cd209b41SJoerg Roedel } 1096cd209b41SJoerg Roedel } else { 1097cd209b41SJoerg Roedel count = it->cell_count; 1098cd209b41SJoerg Roedel } 1099cd209b41SJoerg Roedel 1100cd209b41SJoerg Roedel /* 1101cd209b41SJoerg Roedel * Make sure that the arguments actually fit in the remaining 1102cd209b41SJoerg Roedel * property data length 1103cd209b41SJoerg Roedel */ 1104cd209b41SJoerg Roedel if (it->cur + count > it->list_end) { 11050d638a07SRob Herring pr_err("%pOF: arguments longer than property\n", 11060d638a07SRob Herring it->parent); 1107cd209b41SJoerg Roedel goto err; 1108cd209b41SJoerg Roedel } 1109cd209b41SJoerg Roedel } 1110cd209b41SJoerg Roedel 1111cd209b41SJoerg Roedel it->phandle_end = it->cur + count; 1112cd209b41SJoerg Roedel it->cur_count = count; 1113cd209b41SJoerg Roedel 1114cd209b41SJoerg Roedel return 0; 1115cd209b41SJoerg Roedel 1116cd209b41SJoerg Roedel err: 1117cd209b41SJoerg Roedel if (it->node) { 1118cd209b41SJoerg Roedel of_node_put(it->node); 1119cd209b41SJoerg Roedel it->node = NULL; 1120cd209b41SJoerg Roedel } 1121cd209b41SJoerg Roedel 1122cd209b41SJoerg Roedel return -EINVAL; 1123cd209b41SJoerg Roedel } 112400bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_next); 1125cd209b41SJoerg Roedel 1126abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it, 1127abdaa77bSJoerg Roedel uint32_t *args, 1128abdaa77bSJoerg Roedel int size) 1129abdaa77bSJoerg Roedel { 1130abdaa77bSJoerg Roedel int i, count; 1131abdaa77bSJoerg Roedel 1132abdaa77bSJoerg Roedel count = it->cur_count; 1133abdaa77bSJoerg Roedel 1134abdaa77bSJoerg Roedel if (WARN_ON(size < count)) 1135abdaa77bSJoerg Roedel count = size; 1136abdaa77bSJoerg Roedel 1137abdaa77bSJoerg Roedel for (i = 0; i < count; i++) 1138abdaa77bSJoerg Roedel args[i] = be32_to_cpup(it->cur++); 1139abdaa77bSJoerg Roedel 1140abdaa77bSJoerg Roedel return count; 1141abdaa77bSJoerg Roedel } 1142abdaa77bSJoerg Roedel 1143bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np, 1144bd69f73fSGrant Likely const char *list_name, 1145035fd948SStephen Warren const char *cells_name, 1146035fd948SStephen Warren int cell_count, int index, 114715c9a0acSGrant Likely struct of_phandle_args *out_args) 114864b60e09SAnton Vorontsov { 114974e1fbb1SJoerg Roedel struct of_phandle_iterator it; 115074e1fbb1SJoerg Roedel int rc, cur_index = 0; 115115c9a0acSGrant Likely 115215c9a0acSGrant Likely /* Loop over the phandles until all the requested entry is found */ 1153f623ce95SJoerg Roedel of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) { 115415c9a0acSGrant Likely /* 1155cd209b41SJoerg Roedel * All of the error cases bail out of the loop, so at 115615c9a0acSGrant Likely * this point, the parsing is successful. If the requested 115715c9a0acSGrant Likely * index matches, then fill the out_args structure and return, 115815c9a0acSGrant Likely * or return -ENOENT for an empty entry. 115915c9a0acSGrant Likely */ 116023ce04c0SGrant Likely rc = -ENOENT; 116115c9a0acSGrant Likely if (cur_index == index) { 116274e1fbb1SJoerg Roedel if (!it.phandle) 116323ce04c0SGrant Likely goto err; 116415c9a0acSGrant Likely 116515c9a0acSGrant Likely if (out_args) { 1166abdaa77bSJoerg Roedel int c; 1167abdaa77bSJoerg Roedel 1168abdaa77bSJoerg Roedel c = of_phandle_iterator_args(&it, 1169abdaa77bSJoerg Roedel out_args->args, 1170abdaa77bSJoerg Roedel MAX_PHANDLE_ARGS); 117174e1fbb1SJoerg Roedel out_args->np = it.node; 1172abdaa77bSJoerg Roedel out_args->args_count = c; 1173b855f16bSTang Yuantian } else { 117474e1fbb1SJoerg Roedel of_node_put(it.node); 117515c9a0acSGrant Likely } 117623ce04c0SGrant Likely 117723ce04c0SGrant Likely /* Found it! return success */ 117815c9a0acSGrant Likely return 0; 117915c9a0acSGrant Likely } 118064b60e09SAnton Vorontsov 118164b60e09SAnton Vorontsov cur_index++; 118264b60e09SAnton Vorontsov } 118364b60e09SAnton Vorontsov 118423ce04c0SGrant Likely /* 118523ce04c0SGrant Likely * Unlock node before returning result; will be one of: 118623ce04c0SGrant Likely * -ENOENT : index is for empty phandle 118723ce04c0SGrant Likely * -EINVAL : parsing error on data 118823ce04c0SGrant Likely */ 1189cd209b41SJoerg Roedel 119023ce04c0SGrant Likely err: 119174e1fbb1SJoerg Roedel of_node_put(it.node); 119223ce04c0SGrant Likely return rc; 119364b60e09SAnton Vorontsov } 1194bd69f73fSGrant Likely 1195eded9dd4SStephen Warren /** 11965fba49e3SStephen Warren * of_parse_phandle - Resolve a phandle property to a device_node pointer 11975fba49e3SStephen Warren * @np: Pointer to device node holding phandle property 11985fba49e3SStephen Warren * @phandle_name: Name of property holding a phandle value 11995fba49e3SStephen Warren * @index: For properties holding a table of phandles, this is the index into 12005fba49e3SStephen Warren * the table 12015fba49e3SStephen Warren * 12025fba49e3SStephen Warren * Returns the device_node pointer with refcount incremented. Use 12035fba49e3SStephen Warren * of_node_put() on it when done. 12045fba49e3SStephen Warren */ 12055fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np, 12065fba49e3SStephen Warren const char *phandle_name, int index) 12075fba49e3SStephen Warren { 120891d9942cSStephen Warren struct of_phandle_args args; 12095fba49e3SStephen Warren 121091d9942cSStephen Warren if (index < 0) 12115fba49e3SStephen Warren return NULL; 12125fba49e3SStephen Warren 121391d9942cSStephen Warren if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, 121491d9942cSStephen Warren index, &args)) 121591d9942cSStephen Warren return NULL; 121691d9942cSStephen Warren 121791d9942cSStephen Warren return args.np; 12185fba49e3SStephen Warren } 12195fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle); 12205fba49e3SStephen Warren 12215fba49e3SStephen Warren /** 1222eded9dd4SStephen Warren * of_parse_phandle_with_args() - Find a node pointed by phandle in a list 1223eded9dd4SStephen Warren * @np: pointer to a device tree node containing a list 1224eded9dd4SStephen Warren * @list_name: property name that contains a list 1225eded9dd4SStephen Warren * @cells_name: property name that specifies phandles' arguments count 1226eded9dd4SStephen Warren * @index: index of a phandle to parse out 1227eded9dd4SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1228eded9dd4SStephen Warren * 1229eded9dd4SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1230eded9dd4SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1231eded9dd4SStephen Warren * errno value. 1232eded9dd4SStephen Warren * 1233d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1234eded9dd4SStephen Warren * pointer. 1235eded9dd4SStephen Warren * 1236eded9dd4SStephen Warren * Example: 1237eded9dd4SStephen Warren * 1238eded9dd4SStephen Warren * phandle1: node1 { 1239eded9dd4SStephen Warren * #list-cells = <2>; 1240eded9dd4SStephen Warren * } 1241eded9dd4SStephen Warren * 1242eded9dd4SStephen Warren * phandle2: node2 { 1243eded9dd4SStephen Warren * #list-cells = <1>; 1244eded9dd4SStephen Warren * } 1245eded9dd4SStephen Warren * 1246eded9dd4SStephen Warren * node3 { 1247eded9dd4SStephen Warren * list = <&phandle1 1 2 &phandle2 3>; 1248eded9dd4SStephen Warren * } 1249eded9dd4SStephen Warren * 1250eded9dd4SStephen Warren * To get a device_node of the `node2' node you may call this: 1251eded9dd4SStephen Warren * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); 1252eded9dd4SStephen Warren */ 1253bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, 1254bd69f73fSGrant Likely const char *cells_name, int index, 1255bd69f73fSGrant Likely struct of_phandle_args *out_args) 1256bd69f73fSGrant Likely { 1257bd69f73fSGrant Likely if (index < 0) 1258bd69f73fSGrant Likely return -EINVAL; 1259035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, cells_name, 0, 1260035fd948SStephen Warren index, out_args); 1261bd69f73fSGrant Likely } 126215c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args); 126302af11b0SGrant Likely 1264bd69f73fSGrant Likely /** 1265035fd948SStephen Warren * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list 1266035fd948SStephen Warren * @np: pointer to a device tree node containing a list 1267035fd948SStephen Warren * @list_name: property name that contains a list 1268035fd948SStephen Warren * @cell_count: number of argument cells following the phandle 1269035fd948SStephen Warren * @index: index of a phandle to parse out 1270035fd948SStephen Warren * @out_args: optional pointer to output arguments structure (will be filled) 1271035fd948SStephen Warren * 1272035fd948SStephen Warren * This function is useful to parse lists of phandles and their arguments. 1273035fd948SStephen Warren * Returns 0 on success and fills out_args, on error returns appropriate 1274035fd948SStephen Warren * errno value. 1275035fd948SStephen Warren * 1276d94a75c1SGeert Uytterhoeven * Caller is responsible to call of_node_put() on the returned out_args->np 1277035fd948SStephen Warren * pointer. 1278035fd948SStephen Warren * 1279035fd948SStephen Warren * Example: 1280035fd948SStephen Warren * 1281035fd948SStephen Warren * phandle1: node1 { 1282035fd948SStephen Warren * } 1283035fd948SStephen Warren * 1284035fd948SStephen Warren * phandle2: node2 { 1285035fd948SStephen Warren * } 1286035fd948SStephen Warren * 1287035fd948SStephen Warren * node3 { 1288035fd948SStephen Warren * list = <&phandle1 0 2 &phandle2 2 3>; 1289035fd948SStephen Warren * } 1290035fd948SStephen Warren * 1291035fd948SStephen Warren * To get a device_node of the `node2' node you may call this: 1292035fd948SStephen Warren * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); 1293035fd948SStephen Warren */ 1294035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np, 1295035fd948SStephen Warren const char *list_name, int cell_count, 1296035fd948SStephen Warren int index, struct of_phandle_args *out_args) 1297035fd948SStephen Warren { 1298035fd948SStephen Warren if (index < 0) 1299035fd948SStephen Warren return -EINVAL; 1300035fd948SStephen Warren return __of_parse_phandle_with_args(np, list_name, NULL, cell_count, 1301035fd948SStephen Warren index, out_args); 1302035fd948SStephen Warren } 1303035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); 1304035fd948SStephen Warren 1305035fd948SStephen Warren /** 1306bd69f73fSGrant Likely * of_count_phandle_with_args() - Find the number of phandles references in a property 1307bd69f73fSGrant Likely * @np: pointer to a device tree node containing a list 1308bd69f73fSGrant Likely * @list_name: property name that contains a list 1309bd69f73fSGrant Likely * @cells_name: property name that specifies phandles' arguments count 1310bd69f73fSGrant Likely * 1311bd69f73fSGrant Likely * Returns the number of phandle + argument tuples within a property. It 1312bd69f73fSGrant Likely * is a typical pattern to encode a list of phandle and variable 1313bd69f73fSGrant Likely * arguments into a single property. The number of arguments is encoded 1314bd69f73fSGrant Likely * by a property in the phandle-target node. For example, a gpios 1315bd69f73fSGrant Likely * property would contain a list of GPIO specifies consisting of a 1316bd69f73fSGrant Likely * phandle and 1 or more arguments. The number of arguments are 1317bd69f73fSGrant Likely * determined by the #gpio-cells property in the node pointed to by the 1318bd69f73fSGrant Likely * phandle. 1319bd69f73fSGrant Likely */ 1320bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name, 1321bd69f73fSGrant Likely const char *cells_name) 1322bd69f73fSGrant Likely { 13232021bd01SJoerg Roedel struct of_phandle_iterator it; 13242021bd01SJoerg Roedel int rc, cur_index = 0; 13252021bd01SJoerg Roedel 13262021bd01SJoerg Roedel rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0); 13272021bd01SJoerg Roedel if (rc) 13282021bd01SJoerg Roedel return rc; 13292021bd01SJoerg Roedel 13302021bd01SJoerg Roedel while ((rc = of_phandle_iterator_next(&it)) == 0) 13312021bd01SJoerg Roedel cur_index += 1; 13322021bd01SJoerg Roedel 13332021bd01SJoerg Roedel if (rc != -ENOENT) 13342021bd01SJoerg Roedel return rc; 13352021bd01SJoerg Roedel 13362021bd01SJoerg Roedel return cur_index; 1337bd69f73fSGrant Likely } 1338bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args); 1339bd69f73fSGrant Likely 134002af11b0SGrant Likely /** 134162664f67SXiubo Li * __of_add_property - Add a property to a node without lock operations 134262664f67SXiubo Li */ 1343d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop) 134462664f67SXiubo Li { 134562664f67SXiubo Li struct property **next; 134662664f67SXiubo Li 134762664f67SXiubo Li prop->next = NULL; 134862664f67SXiubo Li next = &np->properties; 134962664f67SXiubo Li while (*next) { 135062664f67SXiubo Li if (strcmp(prop->name, (*next)->name) == 0) 135162664f67SXiubo Li /* duplicate ! don't insert it */ 135262664f67SXiubo Li return -EEXIST; 135362664f67SXiubo Li 135462664f67SXiubo Li next = &(*next)->next; 135562664f67SXiubo Li } 135662664f67SXiubo Li *next = prop; 135762664f67SXiubo Li 135862664f67SXiubo Li return 0; 135962664f67SXiubo Li } 136062664f67SXiubo Li 136162664f67SXiubo Li /** 136279d1c712SNathan Fontenot * of_add_property - Add a property to a node 136302af11b0SGrant Likely */ 136479d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop) 136502af11b0SGrant Likely { 136602af11b0SGrant Likely unsigned long flags; 13671cf3d8b3SNathan Fontenot int rc; 13681cf3d8b3SNathan Fontenot 13698a2b22a2SGrant Likely mutex_lock(&of_mutex); 137002af11b0SGrant Likely 1371d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 137262664f67SXiubo Li rc = __of_add_property(np, prop); 1373d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 137402af11b0SGrant Likely 13758a2b22a2SGrant Likely if (!rc) 137675b57ecfSGrant Likely __of_add_property_sysfs(np, prop); 137702af11b0SGrant Likely 13788a2b22a2SGrant Likely mutex_unlock(&of_mutex); 13798a2b22a2SGrant Likely 1380259092a3SGrant Likely if (!rc) 1381259092a3SGrant Likely of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1382259092a3SGrant Likely 138362664f67SXiubo Li return rc; 138402af11b0SGrant Likely } 138502af11b0SGrant Likely 1386d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop) 1387d8c50088SPantelis Antoniou { 1388d8c50088SPantelis Antoniou struct property **next; 1389d8c50088SPantelis Antoniou 1390d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1391d8c50088SPantelis Antoniou if (*next == prop) 1392d8c50088SPantelis Antoniou break; 1393d8c50088SPantelis Antoniou } 1394d8c50088SPantelis Antoniou if (*next == NULL) 1395d8c50088SPantelis Antoniou return -ENODEV; 1396d8c50088SPantelis Antoniou 1397d8c50088SPantelis Antoniou /* found the node */ 1398d8c50088SPantelis Antoniou *next = prop->next; 1399d8c50088SPantelis Antoniou prop->next = np->deadprops; 1400d8c50088SPantelis Antoniou np->deadprops = prop; 1401d8c50088SPantelis Antoniou 1402d8c50088SPantelis Antoniou return 0; 1403d8c50088SPantelis Antoniou } 1404d8c50088SPantelis Antoniou 140502af11b0SGrant Likely /** 140679d1c712SNathan Fontenot * of_remove_property - Remove a property from a node. 140702af11b0SGrant Likely * 140802af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 140902af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 141002af11b0SGrant Likely * Instead we just move the property to the "dead properties" 141102af11b0SGrant Likely * list, so it won't be found any more. 141202af11b0SGrant Likely */ 141379d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop) 141402af11b0SGrant Likely { 141502af11b0SGrant Likely unsigned long flags; 14161cf3d8b3SNathan Fontenot int rc; 14171cf3d8b3SNathan Fontenot 1418201b3fe5SSuraj Jitindar Singh if (!prop) 1419201b3fe5SSuraj Jitindar Singh return -ENODEV; 1420201b3fe5SSuraj Jitindar Singh 14218a2b22a2SGrant Likely mutex_lock(&of_mutex); 142202af11b0SGrant Likely 1423d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1424d8c50088SPantelis Antoniou rc = __of_remove_property(np, prop); 1425d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 142602af11b0SGrant Likely 14278a2b22a2SGrant Likely if (!rc) 14288a2b22a2SGrant Likely __of_remove_property_sysfs(np, prop); 142902af11b0SGrant Likely 14308a2b22a2SGrant Likely mutex_unlock(&of_mutex); 14318a2b22a2SGrant Likely 1432259092a3SGrant Likely if (!rc) 1433259092a3SGrant Likely of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1434259092a3SGrant Likely 1435d8c50088SPantelis Antoniou return rc; 143602af11b0SGrant Likely } 143702af11b0SGrant Likely 1438d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop, 1439d8c50088SPantelis Antoniou struct property **oldpropp) 1440d8c50088SPantelis Antoniou { 1441d8c50088SPantelis Antoniou struct property **next, *oldprop; 1442d8c50088SPantelis Antoniou 1443d8c50088SPantelis Antoniou for (next = &np->properties; *next; next = &(*next)->next) { 1444d8c50088SPantelis Antoniou if (of_prop_cmp((*next)->name, newprop->name) == 0) 1445d8c50088SPantelis Antoniou break; 1446d8c50088SPantelis Antoniou } 1447d8c50088SPantelis Antoniou *oldpropp = oldprop = *next; 1448d8c50088SPantelis Antoniou 1449d8c50088SPantelis Antoniou if (oldprop) { 1450d8c50088SPantelis Antoniou /* replace the node */ 1451d8c50088SPantelis Antoniou newprop->next = oldprop->next; 1452d8c50088SPantelis Antoniou *next = newprop; 1453d8c50088SPantelis Antoniou oldprop->next = np->deadprops; 1454d8c50088SPantelis Antoniou np->deadprops = oldprop; 1455d8c50088SPantelis Antoniou } else { 1456d8c50088SPantelis Antoniou /* new node */ 1457d8c50088SPantelis Antoniou newprop->next = NULL; 1458d8c50088SPantelis Antoniou *next = newprop; 1459d8c50088SPantelis Antoniou } 1460d8c50088SPantelis Antoniou 1461d8c50088SPantelis Antoniou return 0; 1462d8c50088SPantelis Antoniou } 1463d8c50088SPantelis Antoniou 146402af11b0SGrant Likely /* 146579d1c712SNathan Fontenot * of_update_property - Update a property in a node, if the property does 1466475d0094SDong Aisheng * not exist, add it. 146702af11b0SGrant Likely * 146802af11b0SGrant Likely * Note that we don't actually remove it, since we have given out 146902af11b0SGrant Likely * who-knows-how-many pointers to the data using get-property. 147002af11b0SGrant Likely * Instead we just move the property to the "dead properties" list, 147102af11b0SGrant Likely * and add the new property to the property list 147202af11b0SGrant Likely */ 147379d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop) 147402af11b0SGrant Likely { 1475d8c50088SPantelis Antoniou struct property *oldprop; 147602af11b0SGrant Likely unsigned long flags; 1477947fdaadSXiubo Li int rc; 14781cf3d8b3SNathan Fontenot 1479475d0094SDong Aisheng if (!newprop->name) 1480475d0094SDong Aisheng return -EINVAL; 1481475d0094SDong Aisheng 14828a2b22a2SGrant Likely mutex_lock(&of_mutex); 1483fcdeb7feSGrant Likely 1484d6d3c4e6SThomas Gleixner raw_spin_lock_irqsave(&devtree_lock, flags); 1485d8c50088SPantelis Antoniou rc = __of_update_property(np, newprop, &oldprop); 1486d6d3c4e6SThomas Gleixner raw_spin_unlock_irqrestore(&devtree_lock, flags); 1487e81b3295SNathan Fontenot 14888a2b22a2SGrant Likely if (!rc) 14898a2b22a2SGrant Likely __of_update_property_sysfs(np, newprop, oldprop); 1490fcdeb7feSGrant Likely 14918a2b22a2SGrant Likely mutex_unlock(&of_mutex); 14921cf3d8b3SNathan Fontenot 1493259092a3SGrant Likely if (!rc) 1494259092a3SGrant Likely of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 1495fcdeb7feSGrant Likely 14961cf3d8b3SNathan Fontenot return rc; 1497e81b3295SNathan Fontenot } 1498e81b3295SNathan Fontenot 1499611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np, 1500611cad72SShawn Guo int id, const char *stem, int stem_len) 1501611cad72SShawn Guo { 1502611cad72SShawn Guo ap->np = np; 1503611cad72SShawn Guo ap->id = id; 1504611cad72SShawn Guo strncpy(ap->stem, stem, stem_len); 1505611cad72SShawn Guo ap->stem[stem_len] = 0; 1506611cad72SShawn Guo list_add_tail(&ap->link, &aliases_lookup); 15070d638a07SRob Herring pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n", 15080d638a07SRob Herring ap->alias, ap->stem, ap->id, np); 1509611cad72SShawn Guo } 1510611cad72SShawn Guo 1511611cad72SShawn Guo /** 15121821dda4SGeert Uytterhoeven * of_alias_scan - Scan all properties of the 'aliases' node 1513611cad72SShawn Guo * 15141821dda4SGeert Uytterhoeven * The function scans all the properties of the 'aliases' node and populates 15151821dda4SGeert Uytterhoeven * the global lookup table with the properties. It returns the 15161821dda4SGeert Uytterhoeven * number of alias properties found, or an error code in case of failure. 1517611cad72SShawn Guo * 1518611cad72SShawn Guo * @dt_alloc: An allocator that provides a virtual address to memory 15191821dda4SGeert Uytterhoeven * for storing the resulting tree 1520611cad72SShawn Guo */ 1521611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) 1522611cad72SShawn Guo { 1523611cad72SShawn Guo struct property *pp; 1524611cad72SShawn Guo 15257dbe5849SLaurentiu Tudor of_aliases = of_find_node_by_path("/aliases"); 1526611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen"); 1527611cad72SShawn Guo if (of_chosen == NULL) 1528611cad72SShawn Guo of_chosen = of_find_node_by_path("/chosen@0"); 15295c19e952SSascha Hauer 15305c19e952SSascha Hauer if (of_chosen) { 1531a752ee56SGrant Likely /* linux,stdout-path and /aliases/stdout are for legacy compatibility */ 1532b0d9d92fSSergei Shtylyov const char *name = NULL; 1533b0d9d92fSSergei Shtylyov 1534b0d9d92fSSergei Shtylyov if (of_property_read_string(of_chosen, "stdout-path", &name)) 1535b0d9d92fSSergei Shtylyov of_property_read_string(of_chosen, "linux,stdout-path", 1536b0d9d92fSSergei Shtylyov &name); 1537a752ee56SGrant Likely if (IS_ENABLED(CONFIG_PPC) && !name) 1538b0d9d92fSSergei Shtylyov of_property_read_string(of_aliases, "stdout", &name); 1539f64255b5SPeter Hurley if (name) 15407914a7c5SLeif Lindholm of_stdout = of_find_node_opts_by_path(name, &of_stdout_options); 15415c19e952SSascha Hauer } 15425c19e952SSascha Hauer 1543611cad72SShawn Guo if (!of_aliases) 1544611cad72SShawn Guo return; 1545611cad72SShawn Guo 15468af0da93SDong Aisheng for_each_property_of_node(of_aliases, pp) { 1547611cad72SShawn Guo const char *start = pp->name; 1548611cad72SShawn Guo const char *end = start + strlen(start); 1549611cad72SShawn Guo struct device_node *np; 1550611cad72SShawn Guo struct alias_prop *ap; 1551611cad72SShawn Guo int id, len; 1552611cad72SShawn Guo 1553611cad72SShawn Guo /* Skip those we do not want to proceed */ 1554611cad72SShawn Guo if (!strcmp(pp->name, "name") || 1555611cad72SShawn Guo !strcmp(pp->name, "phandle") || 1556611cad72SShawn Guo !strcmp(pp->name, "linux,phandle")) 1557611cad72SShawn Guo continue; 1558611cad72SShawn Guo 1559611cad72SShawn Guo np = of_find_node_by_path(pp->value); 1560611cad72SShawn Guo if (!np) 1561611cad72SShawn Guo continue; 1562611cad72SShawn Guo 1563611cad72SShawn Guo /* walk the alias backwards to extract the id and work out 1564611cad72SShawn Guo * the 'stem' string */ 1565611cad72SShawn Guo while (isdigit(*(end-1)) && end > start) 1566611cad72SShawn Guo end--; 1567611cad72SShawn Guo len = end - start; 1568611cad72SShawn Guo 1569611cad72SShawn Guo if (kstrtoint(end, 10, &id) < 0) 1570611cad72SShawn Guo continue; 1571611cad72SShawn Guo 1572611cad72SShawn Guo /* Allocate an alias_prop with enough space for the stem */ 1573de96ec2aSPaul Burton ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap)); 1574611cad72SShawn Guo if (!ap) 1575611cad72SShawn Guo continue; 15760640332eSGrant Likely memset(ap, 0, sizeof(*ap) + len + 1); 1577611cad72SShawn Guo ap->alias = start; 1578611cad72SShawn Guo of_alias_add(ap, np, id, start, len); 1579611cad72SShawn Guo } 1580611cad72SShawn Guo } 1581611cad72SShawn Guo 1582611cad72SShawn Guo /** 1583611cad72SShawn Guo * of_alias_get_id - Get alias id for the given device_node 1584611cad72SShawn Guo * @np: Pointer to the given device_node 1585611cad72SShawn Guo * @stem: Alias stem of the given device_node 1586611cad72SShawn Guo * 15875a53a07fSGeert Uytterhoeven * The function travels the lookup table to get the alias id for the given 15885a53a07fSGeert Uytterhoeven * device_node and alias stem. It returns the alias id if found. 1589611cad72SShawn Guo */ 1590611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem) 1591611cad72SShawn Guo { 1592611cad72SShawn Guo struct alias_prop *app; 1593611cad72SShawn Guo int id = -ENODEV; 1594611cad72SShawn Guo 1595c05aba2bSPantelis Antoniou mutex_lock(&of_mutex); 1596611cad72SShawn Guo list_for_each_entry(app, &aliases_lookup, link) { 1597611cad72SShawn Guo if (strcmp(app->stem, stem) != 0) 1598611cad72SShawn Guo continue; 1599611cad72SShawn Guo 1600611cad72SShawn Guo if (np == app->np) { 1601611cad72SShawn Guo id = app->id; 1602611cad72SShawn Guo break; 1603611cad72SShawn Guo } 1604611cad72SShawn Guo } 1605c05aba2bSPantelis Antoniou mutex_unlock(&of_mutex); 1606611cad72SShawn Guo 1607611cad72SShawn Guo return id; 1608611cad72SShawn Guo } 1609611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id); 1610c541adc6SStephen Warren 1611351d224fSWolfram Sang /** 1612351d224fSWolfram Sang * of_alias_get_highest_id - Get highest alias id for the given stem 1613351d224fSWolfram Sang * @stem: Alias stem to be examined 1614351d224fSWolfram Sang * 1615351d224fSWolfram Sang * The function travels the lookup table to get the highest alias id for the 1616351d224fSWolfram Sang * given alias stem. It returns the alias id if found. 1617351d224fSWolfram Sang */ 1618351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem) 1619351d224fSWolfram Sang { 1620351d224fSWolfram Sang struct alias_prop *app; 1621351d224fSWolfram Sang int id = -ENODEV; 1622351d224fSWolfram Sang 1623351d224fSWolfram Sang mutex_lock(&of_mutex); 1624351d224fSWolfram Sang list_for_each_entry(app, &aliases_lookup, link) { 1625351d224fSWolfram Sang if (strcmp(app->stem, stem) != 0) 1626351d224fSWolfram Sang continue; 1627351d224fSWolfram Sang 1628351d224fSWolfram Sang if (app->id > id) 1629351d224fSWolfram Sang id = app->id; 1630351d224fSWolfram Sang } 1631351d224fSWolfram Sang mutex_unlock(&of_mutex); 1632351d224fSWolfram Sang 1633351d224fSWolfram Sang return id; 1634351d224fSWolfram Sang } 1635351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id); 1636351d224fSWolfram Sang 16375c19e952SSascha Hauer /** 16383482f2c5SGrant Likely * of_console_check() - Test and setup console for DT setup 16393482f2c5SGrant Likely * @dn - Pointer to device node 16403482f2c5SGrant Likely * @name - Name to use for preferred console without index. ex. "ttyS" 16413482f2c5SGrant Likely * @index - Index to use for preferred console. 16425c19e952SSascha Hauer * 16433482f2c5SGrant Likely * Check if the given device node matches the stdout-path property in the 16443482f2c5SGrant Likely * /chosen node. If it does then register it as the preferred console and return 16453482f2c5SGrant Likely * TRUE. Otherwise return FALSE. 16465c19e952SSascha Hauer */ 16473482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index) 16485c19e952SSascha Hauer { 16493482f2c5SGrant Likely if (!dn || dn != of_stdout || console_set_on_cmdline) 16505c19e952SSascha Hauer return false; 16517914a7c5SLeif Lindholm return !add_preferred_console(name, index, 16527914a7c5SLeif Lindholm kstrdup(of_stdout_options, GFP_KERNEL)); 16535c19e952SSascha Hauer } 16543482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check); 1655a3e31b45SSudeep KarkadaNagesha 1656a3e31b45SSudeep KarkadaNagesha /** 1657a3e31b45SSudeep KarkadaNagesha * of_find_next_cache_node - Find a node's subsidiary cache 1658a3e31b45SSudeep KarkadaNagesha * @np: node of type "cpu" or "cache" 1659a3e31b45SSudeep KarkadaNagesha * 1660a3e31b45SSudeep KarkadaNagesha * Returns a node pointer with refcount incremented, use 1661a3e31b45SSudeep KarkadaNagesha * of_node_put() on it when done. Caller should hold a reference 1662a3e31b45SSudeep KarkadaNagesha * to np. 1663a3e31b45SSudeep KarkadaNagesha */ 1664a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np) 1665a3e31b45SSudeep KarkadaNagesha { 166691d96749SRob Herring struct device_node *child, *cache_node; 1667a3e31b45SSudeep KarkadaNagesha 166891d96749SRob Herring cache_node = of_parse_phandle(np, "l2-cache", 0); 166991d96749SRob Herring if (!cache_node) 167091d96749SRob Herring cache_node = of_parse_phandle(np, "next-level-cache", 0); 1671a3e31b45SSudeep KarkadaNagesha 167291d96749SRob Herring if (cache_node) 167391d96749SRob Herring return cache_node; 1674a3e31b45SSudeep KarkadaNagesha 1675a3e31b45SSudeep KarkadaNagesha /* OF on pmac has nodes instead of properties named "l2-cache" 1676a3e31b45SSudeep KarkadaNagesha * beneath CPU nodes. 1677a3e31b45SSudeep KarkadaNagesha */ 1678a3e31b45SSudeep KarkadaNagesha if (!strcmp(np->type, "cpu")) 1679a3e31b45SSudeep KarkadaNagesha for_each_child_of_node(np, child) 1680a3e31b45SSudeep KarkadaNagesha if (!strcmp(child->type, "cache")) 1681a3e31b45SSudeep KarkadaNagesha return child; 1682a3e31b45SSudeep KarkadaNagesha 1683a3e31b45SSudeep KarkadaNagesha return NULL; 1684a3e31b45SSudeep KarkadaNagesha } 1685fd9fdb78SPhilipp Zabel 1686fd9fdb78SPhilipp Zabel /** 16875fa23530SSudeep Holla * of_find_last_cache_level - Find the level at which the last cache is 16885fa23530SSudeep Holla * present for the given logical cpu 16895fa23530SSudeep Holla * 16905fa23530SSudeep Holla * @cpu: cpu number(logical index) for which the last cache level is needed 16915fa23530SSudeep Holla * 16925fa23530SSudeep Holla * Returns the the level at which the last cache is present. It is exactly 16935fa23530SSudeep Holla * same as the total number of cache levels for the given logical cpu. 16945fa23530SSudeep Holla */ 16955fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu) 16965fa23530SSudeep Holla { 16975fa23530SSudeep Holla u32 cache_level = 0; 16985fa23530SSudeep Holla struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu); 16995fa23530SSudeep Holla 17005fa23530SSudeep Holla while (np) { 17015fa23530SSudeep Holla prev = np; 17025fa23530SSudeep Holla of_node_put(np); 17035fa23530SSudeep Holla np = of_find_next_cache_node(np); 17045fa23530SSudeep Holla } 17055fa23530SSudeep Holla 17065fa23530SSudeep Holla of_property_read_u32(prev, "cache-level", &cache_level); 17075fa23530SSudeep Holla 17085fa23530SSudeep Holla return cache_level; 17095fa23530SSudeep Holla } 1710