diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 6 | ||||
-rw-r--r-- | drivers/of/Makefile | 1 | ||||
-rw-r--r-- | drivers/of/base.c | 121 | ||||
-rw-r--r-- | drivers/of/fdt.c | 2 | ||||
-rw-r--r-- | drivers/of/of_i2c.c | 114 |
5 files changed, 123 insertions, 121 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 80e5c13b930d..78cc76053328 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -48,12 +48,6 @@ config OF_IRQ def_bool y depends on !SPARC -config OF_I2C - def_tristate I2C - depends on I2C - help - OpenFirmware I2C accessors - config OF_NET depends on NETDEVICES def_bool y diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 1f9c0c492ef9..efd05102c405 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_ADDRESS) += address.o obj-$(CONFIG_OF_IRQ) += irq.o -obj-$(CONFIG_OF_I2C) += of_i2c.o obj-$(CONFIG_OF_NET) += of_net.o obj-$(CONFIG_OF_SELFTEST) += selftest.o obj-$(CONFIG_OF_MDIO) += of_mdio.o diff --git a/drivers/of/base.c b/drivers/of/base.c index 5c5427918eb2..e486e416d5a0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -18,6 +18,7 @@ * 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> @@ -32,6 +33,7 @@ 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); @@ -230,6 +232,100 @@ const void *of_get_property(const struct device_node *np, const char *name, } 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) + return false; + prop_len /= sizeof(*cell); + 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; +} + +/** + * 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, *cpus; + + cpus = of_find_node_by_path("/cpus"); + if (!cpus) { + pr_warn("Missing cpus node, bailing out\n"); + return NULL; + } + + for_each_child_of_node(cpus, cpun) { + if (of_node_cmp(cpun->type, "cpu")) + continue; + /* 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 cpun; + if (__of_find_n_match_cpu_property(cpun, "reg", 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 */ @@ -1595,6 +1691,15 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) of_chosen = of_find_node_by_path("/chosen"); if (of_chosen == NULL) of_chosen = of_find_node_by_path("/chosen@0"); + + if (of_chosen) { + const char *name; + + name = of_get_property(of_chosen, "linux,stdout-path", NULL); + if (name) + of_stdout = of_find_node_by_path(name); + } + of_aliases = of_find_node_by_path("/aliases"); if (!of_aliases) return; @@ -1703,3 +1808,19 @@ const char *of_prop_next_string(struct property *prop, const char *cur) return curv; } EXPORT_SYMBOL_GPL(of_prop_next_string); + +/** + * of_device_is_stdout_path - check if a device node matches the + * linux,stdout-path property + * + * Check if this device node matches the linux,stdout-path property + * in the chosen node. return true if yes, false otherwise. + */ +int of_device_is_stdout_path(struct device_node *dn) +{ + if (!of_stdout) + return false; + + return of_stdout == dn; +} +EXPORT_SYMBOL_GPL(of_device_is_stdout_path); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 6bb7cf2de556..b10ba00cc3e6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -392,6 +392,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, mem = (unsigned long) dt_alloc(size + 4, __alignof__(struct device_node)); + memset((void *)mem, 0, size); + ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); pr_debug(" unflattening %lx...\n", mem); diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c deleted file mode 100644 index b667264222cc..000000000000 --- a/drivers/of/of_i2c.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * OF helpers for the I2C API - * - * Copyright (c) 2008 Jochen Friedrich <jochen@scram.de> - * - * Based on a previous patch from Jon Smirl <jonsmirl@gmail.com> - * - * 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/i2c.h> -#include <linux/irq.h> -#include <linux/of.h> -#include <linux/of_i2c.h> -#include <linux/of_irq.h> -#include <linux/module.h> - -void of_i2c_register_devices(struct i2c_adapter *adap) -{ - void *result; - struct device_node *node; - - /* Only register child devices if the adapter has a node pointer set */ - if (!adap->dev.of_node) - return; - - dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); - - for_each_available_child_of_node(adap->dev.of_node, node) { - struct i2c_board_info info = {}; - struct dev_archdata dev_ad = {}; - const __be32 *addr; - int len; - - dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); - - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { - dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", - node->full_name); - continue; - } - - addr = of_get_property(node, "reg", &len); - if (!addr || (len < sizeof(int))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", - node->full_name); - continue; - } - - info.addr = be32_to_cpup(addr); - if (info.addr > (1 << 10) - 1) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", - info.addr, node->full_name); - continue; - } - - info.irq = irq_of_parse_and_map(node, 0); - info.of_node = of_node_get(node); - info.archdata = &dev_ad; - - if (of_get_property(node, "wakeup-source", NULL)) - info.flags |= I2C_CLIENT_WAKE; - - request_module("%s%s", I2C_MODULE_PREFIX, info.type); - - result = i2c_new_device(adap, &info); - if (result == NULL) { - dev_err(&adap->dev, "of_i2c: Failure registering %s\n", - node->full_name); - of_node_put(node); - irq_dispose_mapping(info.irq); - continue; - } - } -} -EXPORT_SYMBOL(of_i2c_register_devices); - -static int of_dev_node_match(struct device *dev, void *data) -{ - return dev->of_node == data; -} - -/* must call put_device() when done with returned i2c_client device */ -struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_client(dev); -} -EXPORT_SYMBOL(of_find_i2c_device_by_node); - -/* must call put_device() when done with returned i2c_adapter device */ -struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node) -{ - struct device *dev; - - dev = bus_find_device(&i2c_bus_type, NULL, node, - of_dev_node_match); - if (!dev) - return NULL; - - return i2c_verify_adapter(dev); -} -EXPORT_SYMBOL(of_find_i2c_adapter_by_node); - -MODULE_LICENSE("GPL"); |