/* * Procedures for creating, accessing and interpreting the device tree. * * Paul Mackerras August 1996. * Copyright (C) 1996-2005 Paul Mackerras. * * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. * {engebret|bergner}@us.ibm.com * * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net * * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and * Grant Likely. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/ctype.h>#include <linux/cpu.h>#include <linux/module.h>#include <linux/of.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <linux/proc_fs.h> #include "of_private.h" LIST_HEAD(aliases_lookup); struct device_node *of_allnodes;EXPORT_SYMBOL(of_allnodes);struct device_node *of_chosen;struct device_node *of_aliases;static struct device_node *of_stdout; DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */DEFINE_RAW_SPINLOCK(devtree_lock); int of_n_addr_cells(struct device_node *np){ const __be32 *ip; do { if (np->parent) np = np->parent; ip = of_get_property(np, "#address-cells", NULL); if (ip) return be32_to_cpup(ip); } while (np->parent); /* No #address-cells property for the root node */ return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;}EXPORT_SYMBOL(of_n_addr_cells); int of_n_size_cells(struct device_node *np){ const __be32 *ip; do { if (np->parent) np = np->parent; ip = of_get_property(np, "#size-cells", NULL); if (ip) return be32_to_cpup(ip); } while (np->parent); /* No #size-cells property for the root node */ return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;}EXPORT_SYMBOL(of_n_size_cells); #ifdef CONFIG_NUMAint __weak of_node_to_nid(struct device_node *np){ return numa_node_id();}#endif #if defined(CONFIG_OF_DYNAMIC)/** * of_node_get - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to * simplify writing of callers * * Returns node. */struct device_node *of_node_get(struct device_node *node){ if (node) kref_get(&node->kref); return node;}EXPORT_SYMBOL(of_node_get); static inline struct device_node *kref_to_device_node(struct kref *kref){ return container_of(kref, struct device_node, kref);} /** * of_node_release - release a dynamically allocated node * @kref: kref element of the node to be released * * In of_node_put() this function is passed to kref_put() * as the destructor. */static void of_node_release(struct kref *kref){ struct device_node *node = kref_to_device_node(kref); struct property *prop = node->properties; /* We should never be releasing nodes that haven't been detached. */ if (!of_node_check_flag(node, OF_DETACHED)) { pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); dump_stack(); kref_init(&node->kref); return; } if (!of_node_check_flag(node, OF_DYNAMIC)) return; while (prop) { struct property *next = prop->next; kfree(prop->name); kfree(prop->value); kfree(prop); prop = next; if (!prop) { prop = node->deadprops; node->deadprops = NULL; } } kfree(node->full_name); kfree(node->data); kfree(node);} /** * of_node_put - Decrement refcount of a node * @node: Node to dec refcount, NULL is supported to * simplify writing of callers * */void of_node_put(struct device_node *node){ if (node) kref_put(&node->kref, of_node_release);}EXPORT_SYMBOL(of_node_put);#endif /* CONFIG_OF_DYNAMIC */ static struct property *__of_find_property(const struct device_node *np, const char *name, int *lenp){ struct property *pp; if (!np) return NULL; for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { if (lenp) *lenp = pp->length; break; } } return pp;} struct property *of_find_property(const struct device_node *np, const char *name, int *lenp){ struct property *pp; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); pp = __of_find_property(np, name, lenp); raw_spin_unlock_irqrestore(&devtree_lock, flags); return pp;}EXPORT_SYMBOL(of_find_property); /** * of_find_all_nodes - Get next node in global list * @prev: Previous node or NULL to start iteration * of_node_put() will be called on it * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_find_all_nodes(struct device_node *prev){ struct device_node *np; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); np = prev ? prev->allnext : of_allnodes; for (; np != NULL; np = np->allnext) if (of_node_get(np)) break; of_node_put(prev); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np;}EXPORT_SYMBOL(of_find_all_nodes); /* * Find a property with a given name for a given node * and return the value. */static const void *__of_get_property(const struct device_node *np, const char *name, int *lenp){ struct property *pp = __of_find_property(np, name, lenp); return pp ? pp->value : NULL;} /* * Find a property with a given name for a given node * and return the value. */const void *of_get_property(const struct device_node *np, const char *name, int *lenp){ struct property *pp = of_find_property(np, name, lenp); return pp ? pp->value : NULL;}EXPORT_SYMBOL(of_get_property); /* * arch_match_cpu_phys_id - Match the given logical CPU and physical id * * @cpu: logical cpu index of a core/thread * @phys_id: physical identifier of a core/thread * * CPU logical to physical index mapping is architecture specific. * However this __weak function provides a default match of physical * id to logical cpu index. phys_id provided here is usually values read * from the device tree which must match the hardware internal registers. * * Returns true if the physical identifier and the logical cpu index * correspond to the same core/thread, false otherwise. */bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id){ return (u32)phys_id == cpu;} /** * Checks if the given "prop_name" property holds the physical id of the * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not * NULL, local thread number within the core is returned in it. */static bool __of_find_n_match_cpu_property(struct device_node *cpun, const char *prop_name, int cpu, unsigned int *thread){ const __be32 *cell; int ac, prop_len, tid; u64 hwid; ac = of_n_addr_cells(cpun); cell = of_get_property(cpun, prop_name, &prop_len); if (!cell || !ac) return false; prop_len /= sizeof(*cell) * ac; for (tid = 0; tid < prop_len; tid++) { hwid = of_read_number(cell, ac); if (arch_match_cpu_phys_id(cpu, hwid)) { if (thread) *thread = tid; return true; } cell += ac; } return false;} /* * arch_find_n_match_cpu_physical_id - See if the given device node is * for the cpu corresponding to logical cpu 'cpu'. Return true if so, * else false. If 'thread' is non-NULL, the local thread number within the * core is returned in it. */bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, int cpu, unsigned int *thread){ /* Check for non-standard "ibm,ppc-interrupt-server#s" property * for thread ids on PowerPC. If it doesn't exist fallback to * standard "reg" property. */ if (IS_ENABLED(CONFIG_PPC) && __of_find_n_match_cpu_property(cpun, "ibm,ppc-interrupt-server#s", cpu, thread)) return true; if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) return true; return false;} /** * of_get_cpu_node - Get device node associated with the given logical CPU * * @cpu: CPU number(logical index) for which device node is required * @thread: if not NULL, local thread number within the physical core is * returned * * The main purpose of this function is to retrieve the device node for the * given logical CPU index. It should be used to initialize the of_node in * cpu device. Once of_node in cpu device is populated, all the further * references can use that instead. * * CPU logical to physical index mapping is architecture specific and is built * before booting secondary cores. This function uses arch_match_cpu_phys_id * which can be overridden by architecture specific implementation. * * Returns a node pointer for the logical cpu if found, else NULL. */struct device_node *of_get_cpu_node(int cpu, unsigned int *thread){ struct device_node *cpun; for_each_node_by_type(cpun, "cpu") { if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) return cpun; } return NULL;}EXPORT_SYMBOL(of_get_cpu_node); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */static int __of_device_is_compatible(const struct device_node *device, const char *compat){ const char* cp; int cplen, l; cp = __of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { if (of_compat_cmp(cp, compat, strlen(compat)) == 0) return 1; l = strlen(cp) + 1; cp += l; cplen -= l; } return 0;} /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */int of_device_is_compatible(const struct device_node *device, const char *compat){ unsigned long flags; int res; raw_spin_lock_irqsave(&devtree_lock, flags); res = __of_device_is_compatible(device, compat); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res;}EXPORT_SYMBOL(of_device_is_compatible); /** * of_machine_is_compatible - Test root of device tree for a given compatible value * @compat: compatible string to look for in root node's compatible property. * * Returns true if the root node has the given value in its * compatible property. */int of_machine_is_compatible(const char *compat){ struct device_node *root; int rc = 0; root = of_find_node_by_path("/"); if (root) { rc = of_device_is_compatible(root, compat); of_node_put(root); } return rc;}EXPORT_SYMBOL(of_machine_is_compatible); /** * __of_device_is_available - check if a device is available for use * * @device: Node to check for availability, with locks already held * * Returns 1 if the status property is absent or set to "okay" or "ok", * 0 otherwise */static int __of_device_is_available(const struct device_node *device){ const char *status; int statlen; status = __of_get_property(device, "status", &statlen); if (status == NULL) return 1; if (statlen > 0) { if (!strcmp(status, "okay") || !strcmp(status, "ok")) return 1; } return 0;} /** * of_device_is_available - check if a device is available for use * * @device: Node to check for availability * * Returns 1 if the status property is absent or set to "okay" or "ok", * 0 otherwise */int of_device_is_available(const struct device_node *device){ unsigned long flags; int res; raw_spin_lock_irqsave(&devtree_lock, flags); res = __of_device_is_available(device); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; }EXPORT_SYMBOL(of_device_is_available); /** * of_get_parent - Get a node's parent if any * @node: Node to get parent * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_get_parent(const struct device_node *node){ struct device_node *np; unsigned long flags; if (!node) return NULL; raw_spin_lock_irqsave(&devtree_lock, flags); np = of_node_get(node->parent); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np;}EXPORT_SYMBOL(of_get_parent); /** * of_get_next_parent - Iterate to a node's parent * @node: Node to get parent of * * This is like of_get_parent() except that it drops the * refcount on the passed node, making it suitable for iterating * through a node's parents. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_get_next_parent(struct device_node *node){ struct device_node *parent; unsigned long flags; if (!node) return NULL; raw_spin_lock_irqsave(&devtree_lock, flags); parent = of_node_get(node->parent); of_node_put(node); raw_spin_unlock_irqrestore(&devtree_lock, flags); return parent;}EXPORT_SYMBOL(of_get_next_parent); /**Lines 1–500 of 1942. Load more
/* * Procedures for creating, accessing and interpreting the device tree. * * Paul Mackerras August 1996. * Copyright (C) 1996-2005 Paul Mackerras. * * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. * {engebret|bergner}@us.ibm.com * * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net * * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and * Grant Likely. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/ctype.h> #include <linux/cpu.h> #include <linux/module.h> #include <linux/of.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/proc_fs.h> #include "of_private.h" LIST_HEAD(aliases_lookup); struct device_node *of_allnodes; EXPORT_SYMBOL(of_allnodes); struct device_node *of_chosen; struct device_node *of_aliases; static struct device_node *of_stdout; DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */ DEFINE_RAW_SPINLOCK(devtree_lock); int of_n_addr_cells(struct device_node *np) { const __be32 *ip; do { if (np->parent) np = np->parent; ip = of_get_property(np, "#address-cells", NULL); if (ip) return be32_to_cpup(ip); } while (np->parent); /* No #address-cells property for the root node */ return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; } EXPORT_SYMBOL(of_n_addr_cells); int of_n_size_cells(struct device_node *np) { const __be32 *ip; do { if (np->parent) np = np->parent; ip = of_get_property(np, "#size-cells", NULL); if (ip) return be32_to_cpup(ip); } while (np->parent); /* No #size-cells property for the root node */ return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; } EXPORT_SYMBOL(of_n_size_cells); #ifdef CONFIG_NUMA int __weak of_node_to_nid(struct device_node *np) { return numa_node_id(); } #endif #if defined(CONFIG_OF_DYNAMIC) /** * of_node_get - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to * simplify writing of callers * * Returns node. */ struct device_node *of_node_get(struct device_node *node) { if (node) kref_get(&node->kref); return node; } EXPORT_SYMBOL(of_node_get); static inline struct device_node *kref_to_device_node(struct kref *kref) { return container_of(kref, struct device_node, kref); } /** * of_node_release - release a dynamically allocated node * @kref: kref element of the node to be released * * In of_node_put() this function is passed to kref_put() * as the destructor. */ static void of_node_release(struct kref *kref) { struct device_node *node = kref_to_device_node(kref); struct property *prop = node->properties; /* We should never be releasing nodes that haven't been detached. */ if (!of_node_check_flag(node, OF_DETACHED)) { pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); dump_stack(); kref_init(&node->kref); return; } if (!of_node_check_flag(node, OF_DYNAMIC)) return; while (prop) { struct property *next = prop->next; kfree(prop->name); kfree(prop->value); kfree(prop); prop = next; if (!prop) { prop = node->deadprops; node->deadprops = NULL; } } kfree(node->full_name); kfree(node->data); kfree(node); } /** * of_node_put - Decrement refcount of a node * @node: Node to dec refcount, NULL is supported to * simplify writing of callers * */ void of_node_put(struct device_node *node) { if (node) kref_put(&node->kref, of_node_release); } EXPORT_SYMBOL(of_node_put); #endif /* CONFIG_OF_DYNAMIC */ static struct property *__of_find_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp; if (!np) return NULL; for (pp = np->properties; pp; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { if (lenp) *lenp = pp->length; break; } } return pp; } struct property *of_find_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); pp = __of_find_property(np, name, lenp); raw_spin_unlock_irqrestore(&devtree_lock, flags); return pp; } EXPORT_SYMBOL(of_find_property); /** * of_find_all_nodes - Get next node in global list * @prev: Previous node or NULL to start iteration * of_node_put() will be called on it * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_find_all_nodes(struct device_node *prev) { struct device_node *np; unsigned long flags; raw_spin_lock_irqsave(&devtree_lock, flags); np = prev ? prev->allnext : of_allnodes; for (; np != NULL; np = np->allnext) if (of_node_get(np)) break; of_node_put(prev); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_find_all_nodes); /* * Find a property with a given name for a given node * and return the value. */ static const void *__of_get_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp = __of_find_property(np, name, lenp); return pp ? pp->value : NULL; } /* * Find a property with a given name for a given node * and return the value. */ const void *of_get_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np, name, lenp); return pp ? pp->value : NULL; } EXPORT_SYMBOL(of_get_property); /* * arch_match_cpu_phys_id - Match the given logical CPU and physical id * * @cpu: logical cpu index of a core/thread * @phys_id: physical identifier of a core/thread * * CPU logical to physical index mapping is architecture specific. * However this __weak function provides a default match of physical * id to logical cpu index. phys_id provided here is usually values read * from the device tree which must match the hardware internal registers. * * Returns true if the physical identifier and the logical cpu index * correspond to the same core/thread, false otherwise. */ bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) { return (u32)phys_id == cpu; } /** * Checks if the given "prop_name" property holds the physical id of the * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not * NULL, local thread number within the core is returned in it. */ static bool __of_find_n_match_cpu_property(struct device_node *cpun, const char *prop_name, int cpu, unsigned int *thread) { const __be32 *cell; int ac, prop_len, tid; u64 hwid; ac = of_n_addr_cells(cpun); cell = of_get_property(cpun, prop_name, &prop_len); if (!cell || !ac) return false; prop_len /= sizeof(*cell) * ac; for (tid = 0; tid < prop_len; tid++) { hwid = of_read_number(cell, ac); if (arch_match_cpu_phys_id(cpu, hwid)) { if (thread) *thread = tid; return true; } cell += ac; } return false; } /* * arch_find_n_match_cpu_physical_id - See if the given device node is * for the cpu corresponding to logical cpu 'cpu'. Return true if so, * else false. If 'thread' is non-NULL, the local thread number within the * core is returned in it. */ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, int cpu, unsigned int *thread) { /* Check for non-standard "ibm,ppc-interrupt-server#s" property * for thread ids on PowerPC. If it doesn't exist fallback to * standard "reg" property. */ if (IS_ENABLED(CONFIG_PPC) && __of_find_n_match_cpu_property(cpun, "ibm,ppc-interrupt-server#s", cpu, thread)) return true; if (__of_find_n_match_cpu_property(cpun, "reg", cpu, thread)) return true; return false; } /** * of_get_cpu_node - Get device node associated with the given logical CPU * * @cpu: CPU number(logical index) for which device node is required * @thread: if not NULL, local thread number within the physical core is * returned * * The main purpose of this function is to retrieve the device node for the * given logical CPU index. It should be used to initialize the of_node in * cpu device. Once of_node in cpu device is populated, all the further * references can use that instead. * * CPU logical to physical index mapping is architecture specific and is built * before booting secondary cores. This function uses arch_match_cpu_phys_id * which can be overridden by architecture specific implementation. * * Returns a node pointer for the logical cpu if found, else NULL. */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) { struct device_node *cpun; for_each_node_by_type(cpun, "cpu") { if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) return cpun; } return NULL; } EXPORT_SYMBOL(of_get_cpu_node); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ static int __of_device_is_compatible(const struct device_node *device, const char *compat) { const char* cp; int cplen, l; cp = __of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { if (of_compat_cmp(cp, compat, strlen(compat)) == 0) return 1; l = strlen(cp) + 1; cp += l; cplen -= l; } return 0; } /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ int of_device_is_compatible(const struct device_node *device, const char *compat) { unsigned long flags; int res; raw_spin_lock_irqsave(&devtree_lock, flags); res = __of_device_is_compatible(device, compat); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } EXPORT_SYMBOL(of_device_is_compatible); /** * of_machine_is_compatible - Test root of device tree for a given compatible value * @compat: compatible string to look for in root node's compatible property. * * Returns true if the root node has the given value in its * compatible property. */ int of_machine_is_compatible(const char *compat) { struct device_node *root; int rc = 0; root = of_find_node_by_path("/"); if (root) { rc = of_device_is_compatible(root, compat); of_node_put(root); } return rc; } EXPORT_SYMBOL(of_machine_is_compatible); /** * __of_device_is_available - check if a device is available for use * * @device: Node to check for availability, with locks already held * * Returns 1 if the status property is absent or set to "okay" or "ok", * 0 otherwise */ static int __of_device_is_available(const struct device_node *device) { const char *status; int statlen; status = __of_get_property(device, "status", &statlen); if (status == NULL) return 1; if (statlen > 0) { if (!strcmp(status, "okay") || !strcmp(status, "ok")) return 1; } return 0; } /** * of_device_is_available - check if a device is available for use * * @device: Node to check for availability * * Returns 1 if the status property is absent or set to "okay" or "ok", * 0 otherwise */ int of_device_is_available(const struct device_node *device) { unsigned long flags; int res; raw_spin_lock_irqsave(&devtree_lock, flags); res = __of_device_is_available(device); raw_spin_unlock_irqrestore(&devtree_lock, flags); return res; } EXPORT_SYMBOL(of_device_is_available); /** * of_get_parent - Get a node's parent if any * @node: Node to get parent * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_get_parent(const struct device_node *node) { struct device_node *np; unsigned long flags; if (!node) return NULL; raw_spin_lock_irqsave(&devtree_lock, flags); np = of_node_get(node->parent); raw_spin_unlock_irqrestore(&devtree_lock, flags); return np; } EXPORT_SYMBOL(of_get_parent); /** * of_get_next_parent - Iterate to a node's parent * @node: Node to get parent of * * This is like of_get_parent() except that it drops the * refcount on the passed node, making it suitable for iterating * through a node's parents. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */ struct device_node *of_get_next_parent(struct device_node *node) { struct device_node *parent; unsigned long flags; if (!node) return NULL; raw_spin_lock_irqsave(&devtree_lock, flags); parent = of_node_get(node->parent); of_node_put(node); raw_spin_unlock_irqrestore(&devtree_lock, flags); return parent; } EXPORT_SYMBOL(of_get_next_parent); /**