diff options
Diffstat (limited to 'drivers')
36 files changed, 491 insertions, 317 deletions
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index f3903d002819..41f0eadf1931 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -14,7 +14,7 @@ #include <linux/cpu.h> #include <linux/device.h> #include <linux/init.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/smp.h> diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index d51573ac525e..00cb792bda18 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -1179,74 +1179,32 @@ static int __init mbus_dt_setup_win(struct mvebu_mbus_state *mbus, return 0; } -static int __init -mbus_parse_ranges(struct device_node *node, - int *addr_cells, int *c_addr_cells, int *c_size_cells, - int *cell_count, const __be32 **ranges_start, - const __be32 **ranges_end) -{ - const __be32 *prop; - int ranges_len, tuple_len; - - /* Allow a node with no 'ranges' property */ - *ranges_start = of_get_property(node, "ranges", &ranges_len); - if (*ranges_start == NULL) { - *addr_cells = *c_addr_cells = *c_size_cells = *cell_count = 0; - *ranges_start = *ranges_end = NULL; - return 0; - } - *ranges_end = *ranges_start + ranges_len / sizeof(__be32); - - *addr_cells = of_n_addr_cells(node); - - prop = of_get_property(node, "#address-cells", NULL); - *c_addr_cells = be32_to_cpup(prop); - - prop = of_get_property(node, "#size-cells", NULL); - *c_size_cells = be32_to_cpup(prop); - - *cell_count = *addr_cells + *c_addr_cells + *c_size_cells; - tuple_len = (*cell_count) * sizeof(__be32); - - if (ranges_len % tuple_len) { - pr_warn("malformed ranges entry '%pOFn'\n", node); - return -EINVAL; - } - return 0; -} - static int __init mbus_dt_setup(struct mvebu_mbus_state *mbus, struct device_node *np) { - int addr_cells, c_addr_cells, c_size_cells; - int i, ret, cell_count; - const __be32 *r, *ranges_start, *ranges_end; + int ret; + struct of_range_parser parser; + struct of_range range; - ret = mbus_parse_ranges(np, &addr_cells, &c_addr_cells, - &c_size_cells, &cell_count, - &ranges_start, &ranges_end); + ret = of_range_parser_init(&parser, np); if (ret < 0) - return ret; + return 0; - for (i = 0, r = ranges_start; r < ranges_end; r += cell_count, i++) { - u32 windowid, base, size; + for_each_of_range(&parser, &range) { + u32 windowid = upper_32_bits(range.bus_addr); u8 target, attr; /* * An entry with a non-zero custom field do not * correspond to a static window, so skip it. */ - windowid = of_read_number(r, 1); if (CUSTOM(windowid)) continue; target = TARGET(windowid); attr = ATTR(windowid); - base = of_read_number(r + c_addr_cells, addr_cells); - size = of_read_number(r + c_addr_cells + addr_cells, - c_size_cells); - ret = mbus_dt_setup_win(mbus, base, size, target, attr); + ret = mbus_dt_setup_win(mbus, range.cpu_addr, range.size, target, attr); if (ret < 0) return ret; } diff --git a/drivers/bus/tegra-gmi.c b/drivers/bus/tegra-gmi.c index 662266719682..e3506ef37051 100644 --- a/drivers/bus/tegra-gmi.c +++ b/drivers/bus/tegra-gmi.c @@ -9,7 +9,9 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c index f70dedace20b..cb5c89ce7b86 100644 --- a/drivers/bus/uniphier-system-bus.c +++ b/drivers/bus/uniphier-system-bus.c @@ -176,10 +176,9 @@ static int uniphier_system_bus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct uniphier_system_bus_priv *priv; - const __be32 *ranges; - u32 cells, addr, size; - u64 paddr; - int pna, bank, rlen, rone, ret; + struct of_range_parser parser; + struct of_range range; + int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -191,48 +190,17 @@ static int uniphier_system_bus_probe(struct platform_device *pdev) priv->dev = dev; - pna = of_n_addr_cells(dev->of_node); - - ret = of_property_read_u32(dev->of_node, "#address-cells", &cells); - if (ret) { - dev_err(dev, "failed to get #address-cells\n"); - return ret; - } - if (cells != 2) { - dev_err(dev, "#address-cells must be 2\n"); - return -EINVAL; - } - - ret = of_property_read_u32(dev->of_node, "#size-cells", &cells); - if (ret) { - dev_err(dev, "failed to get #size-cells\n"); + ret = of_range_parser_init(&parser, dev->of_node); + if (ret) return ret; - } - if (cells != 1) { - dev_err(dev, "#size-cells must be 1\n"); - return -EINVAL; - } - ranges = of_get_property(dev->of_node, "ranges", &rlen); - if (!ranges) { - dev_err(dev, "failed to get ranges property\n"); - return -ENOENT; - } - - rlen /= sizeof(*ranges); - rone = pna + 2; - - for (; rlen >= rone; rlen -= rone) { - bank = be32_to_cpup(ranges++); - addr = be32_to_cpup(ranges++); - paddr = of_translate_address(dev->of_node, ranges); - if (paddr == OF_BAD_ADDR) + for_each_of_range(&parser, &range) { + if (range.cpu_addr == OF_BAD_ADDR) return -EINVAL; - ranges += pna; - size = be32_to_cpup(ranges++); - - ret = uniphier_system_bus_add_bank(priv, bank, addr, - paddr, size); + ret = uniphier_system_bus_add_bank(priv, + upper_32_bits(range.bus_addr), + lower_32_bits(range.bus_addr), + range.cpu_addr, range.size); if (ret) return ret; } diff --git a/drivers/clocksource/ingenic-timer.c b/drivers/clocksource/ingenic-timer.c index 24ed0f1f089b..089ce64b1c3f 100644 --- a/drivers/clocksource/ingenic-timer.c +++ b/drivers/clocksource/ingenic-timer.c @@ -9,13 +9,12 @@ #include <linux/clk.h> #include <linux/clockchips.h> #include <linux/clocksource.h> +#include <linux/cpuhotplug.h> #include <linux/interrupt.h> #include <linux/mfd/ingenic-tcu.h> #include <linux/mfd/syscon.h> #include <linux/of.h> -#include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/overflow.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index e1a5384cf21c..29904395e95f 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -20,6 +20,7 @@ #include <linux/dmi.h> #include <linux/slab.h> #include <linux/string_helpers.h> +#include <linux/platform_device.h> #include <linux/acpi.h> #include <linux/io.h> diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 452181434735..338cf6cc6596 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -6,7 +6,6 @@ #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include "cpufreq-dt.h" diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 70ad8fe1d78b..95588101efbd 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -9,7 +9,7 @@ #include <linux/module.h> #include <linux/clk.h> #include <linux/cpufreq.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/io.h> #include <asm/proc-fns.h> diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index 28d346062166..f9306410a07f 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -23,7 +23,7 @@ #include <linux/completion.h> #include <linux/mutex.h> #include <linux/time.h> -#include <linux/of_device.h> +#include <linux/of.h> #define DBG(fmt...) pr_debug(fmt) diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 0c362932ca60..1d2cfea9858a 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -31,6 +31,7 @@ #include <linux/cpufreq.h> #include <linux/compiler.h> #include <linux/slab.h> +#include <linux/platform_device.h> #include <linux/acpi.h> #include <linux/io.h> diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 7ec6d1bb4592..ec75e79659ac 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -23,7 +23,7 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/hardirq.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <asm/machdep.h> #include <asm/irq.h> diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index ba9c31d98bd6..2cd2b06849a2 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -21,7 +21,7 @@ #include <linux/init.h> #include <linux/completion.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <asm/machdep.h> #include <asm/irq.h> diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index eb54f7f17ab5..a78d7a27b4b5 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -11,8 +11,8 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index c6fdf019dbde..78b875db6b66 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -18,7 +18,7 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index 1583a370da39..4321d7bbe769 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -10,9 +10,10 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/cpu.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/slab.h> diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c index 788672c0c834..aae951d4e77c 100644 --- a/drivers/cpufreq/tegra124-cpufreq.c +++ b/drivers/cpufreq/tegra124-cpufreq.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> diff --git a/drivers/cpufreq/tegra20-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c index dfd2de4f8e07..a573186704a5 100644 --- a/drivers/cpufreq/tegra20-cpufreq.c +++ b/drivers/cpufreq/tegra20-cpufreq.c @@ -12,7 +12,7 @@ #include <linux/err.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/types.h> diff --git a/drivers/cpuidle/cpuidle-psci.c b/drivers/cpuidle/cpuidle-psci.c index 6de027f9f6f5..bf68920d038a 100644 --- a/drivers/cpuidle/cpuidle-psci.c +++ b/drivers/cpuidle/cpuidle-psci.c @@ -16,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/psci.h> #include <linux/pm_domain.h> diff --git a/drivers/cpuidle/cpuidle-qcom-spm.c b/drivers/cpuidle/cpuidle-qcom-spm.c index c6e2e91bb4c3..1fc9968eae19 100644 --- a/drivers/cpuidle/cpuidle-qcom-spm.c +++ b/drivers/cpuidle/cpuidle-qcom-spm.c @@ -11,8 +11,7 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of_platform.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/cpuidle.h> diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c index 1fab1abc6eb6..f2ccda2c3871 100644 --- a/drivers/cpuidle/cpuidle-riscv-sbi.c +++ b/drivers/cpuidle/cpuidle-riscv-sbi.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) "cpuidle-riscv-sbi: " fmt +#include <linux/cpuhotplug.h> #include <linux/cpuidle.h> #include <linux/cpumask.h> #include <linux/cpu_pm.h> @@ -15,7 +16,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c index 02aa0b39af9d..12fec92a85fd 100644 --- a/drivers/cpuidle/dt_idle_states.c +++ b/drivers/cpuidle/dt_idle_states.c @@ -14,7 +14,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include "dt_idle_states.h" diff --git a/drivers/hte/hte.c b/drivers/hte/hte.c index 7c3b4476f890..9f3221462e75 100644 --- a/drivers/hte/hte.c +++ b/drivers/hte/hte.c @@ -518,7 +518,7 @@ static struct hte_device *hte_of_get_dev(struct device *dev, np = dev->of_node; - if (!of_find_property(np, "timestamp-names", NULL)) { + if (!of_property_present(np, "timestamp-names")) { /* Let hte core construct it during request time */ desc->attr.name = NULL; } else { diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 90181c42840b..71ef19f77a5a 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -7,16 +7,13 @@ #define pr_fmt(fmt) "eiointc: " fmt +#include <linux/cpuhotplug.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqchip.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> #include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/syscore_ops.h> #define EIOINTC_REG_NODEMAP 0x14a0 diff --git a/drivers/of/Makefile b/drivers/of/Makefile index e0360a44306e..10f704592561 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-y = base.o device.o platform.o property.o +obj-y = base.o cpu.o device.o platform.o property.o obj-$(CONFIG_OF_KOBJ) += kobj.o obj-$(CONFIG_OF_DYNAMIC) += dynamic.o obj-$(CONFIG_OF_FLATTREE) += fdt.o diff --git a/drivers/of/address.c b/drivers/of/address.c index 3aaa63e66fcf..0d49f8c9ed88 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -90,11 +90,17 @@ static int of_bus_default_translate(__be32 *addr, u64 offset, int na) return 0; } +static unsigned int of_bus_default_flags_get_flags(const __be32 *addr) +{ + return of_read_number(addr, 1); +} + static unsigned int of_bus_default_get_flags(const __be32 *addr) { return IORESOURCE_MEM; } + #ifdef CONFIG_PCI static unsigned int of_bus_pci_get_flags(const __be32 *addr) { @@ -213,9 +219,6 @@ int of_pci_range_to_resource(struct of_pci_range *range, res->parent = res->child = res->sibling = NULL; res->name = np->full_name; - if (!IS_ENABLED(CONFIG_PCI)) - return -ENOSYS; - if (res->flags & IORESOURCE_IO) { unsigned long port; err = pci_register_io_range(&np->fwnode, range->cpu_addr, @@ -248,6 +251,34 @@ invalid_range: EXPORT_SYMBOL(of_pci_range_to_resource); /* + * of_range_to_resource - Create a resource from a ranges entry + * @np: device node where the range belongs to + * @index: the 'ranges' index to convert to a resource + * @res: pointer to a valid resource that will be updated to + * reflect the values contained in the range. + * + * Returns ENOENT if the entry is not found or EINVAL if the range cannot be + * converted to resource. + */ +int of_range_to_resource(struct device_node *np, int index, struct resource *res) +{ + int ret, i = 0; + struct of_range_parser parser; + struct of_range range; + + ret = of_range_parser_init(&parser, np); + if (ret) + return ret; + + for_each_of_range(&parser, &range) + if (i++ == index) + return of_pci_range_to_resource(&range, np, res); + + return -ENOENT; +} +EXPORT_SYMBOL(of_range_to_resource); + +/* * ISA bus specific translator */ @@ -303,6 +334,11 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr) return flags; } +static int of_bus_default_flags_match(struct device_node *np) +{ + return of_bus_n_addr_cells(np) == 3; +} + /* * Array of bus specific translators */ @@ -332,6 +368,17 @@ static struct of_bus of_busses[] = { .has_flags = true, .get_flags = of_bus_isa_get_flags, }, + /* Default with flags cell */ + { + .name = "default-flags", + .addresses = "reg", + .match = of_bus_default_flags_match, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .translate = of_bus_default_translate, + .has_flags = true, + .get_flags = of_bus_default_flags_get_flags, + }, /* Default */ { .name = "default", @@ -697,6 +744,29 @@ const __be32 *__of_get_address(struct device_node *dev, int index, int bar_no, } EXPORT_SYMBOL(__of_get_address); +/** + * of_property_read_reg - Retrieve the specified "reg" entry index without translating + * @np: device tree node for which to retrieve "reg" from + * @idx: "reg" entry index to read + * @addr: return value for the untranslated address + * @size: return value for the entry size + * + * Returns -EINVAL if "reg" is not found. Returns 0 on success with addr and + * size values filled in. + */ +int of_property_read_reg(struct device_node *np, int idx, u64 *addr, u64 *size) +{ + const __be32 *prop = of_get_address(np, idx, size, NULL); + + if (!prop) + return -EINVAL; + + *addr = of_read_number(prop, of_n_addr_cells(np)); + + return 0; +} +EXPORT_SYMBOL(of_property_read_reg); + static int parser_init(struct of_pci_range_parser *parser, struct device_node *node, const char *name) { diff --git a/drivers/of/base.c b/drivers/of/base.c index ac6fde53342f..7f1720af813c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -287,193 +287,6 @@ const void *of_get_property(const struct device_node *np, const char *name, EXPORT_SYMBOL(of_get_property); /** - * of_get_cpu_hwid - Get the hardware ID from a CPU device node - * - * @cpun: CPU number(logical index) for which device node is required - * @thread: The local thread number to get the hardware ID for. - * - * Return: The hardware ID for the CPU node or ~0ULL if not found. - */ -u64 of_get_cpu_hwid(struct device_node *cpun, unsigned int thread) -{ - const __be32 *cell; - int ac, len; - - ac = of_n_addr_cells(cpun); - cell = of_get_property(cpun, "reg", &len); - if (!cell || !ac || ((sizeof(*cell) * ac * (thread + 1)) > len)) - return ~0ULL; - - cell += ac * thread; - return of_read_number(cell, ac); -} - -/* - * 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 && arch_match_cpu_phys_id(cpu, 0)) - return true; - 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; - - return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); -} - -/** - * 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. - * - * Return: A node pointer for the logical cpu with refcount incremented, use - * of_node_put() on it when done. Returns NULL if not found. - */ -struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) -{ - struct device_node *cpun; - - for_each_of_cpu_node(cpun) { - if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) - return cpun; - } - return NULL; -} -EXPORT_SYMBOL(of_get_cpu_node); - -/** - * of_cpu_node_to_id: Get the logical CPU number for a given device_node - * - * @cpu_node: Pointer to the device_node for CPU. - * - * Return: The logical CPU number of the given CPU device_node or -ENODEV if the - * CPU is not found. - */ -int of_cpu_node_to_id(struct device_node *cpu_node) -{ - int cpu; - bool found = false; - struct device_node *np; - - for_each_possible_cpu(cpu) { - np = of_cpu_device_node_get(cpu); - found = (cpu_node == np); - of_node_put(np); - if (found) - return cpu; - } - - return -ENODEV; -} -EXPORT_SYMBOL(of_cpu_node_to_id); - -/** - * of_get_cpu_state_node - Get CPU's idle state node at the given index - * - * @cpu_node: The device node for the CPU - * @index: The index in the list of the idle states - * - * Two generic methods can be used to describe a CPU's idle states, either via - * a flattened description through the "cpu-idle-states" binding or via the - * hierarchical layout, using the "power-domains" and the "domain-idle-states" - * bindings. This function check for both and returns the idle state node for - * the requested index. - * - * Return: An idle state node if found at @index. The refcount is incremented - * for it, so call of_node_put() on it when done. Returns NULL if not found. - */ -struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, - int index) -{ - struct of_phandle_args args; - int err; - - err = of_parse_phandle_with_args(cpu_node, "power-domains", - "#power-domain-cells", 0, &args); - if (!err) { - struct device_node *state_node = - of_parse_phandle(args.np, "domain-idle-states", index); - - of_node_put(args.np); - if (state_node) - return state_node; - } - - return of_parse_phandle(cpu_node, "cpu-idle-states", index); -} -EXPORT_SYMBOL(of_get_cpu_state_node); - -/** * __of_device_is_compatible() - Check if the node matches given constraints * @device: pointer to node * @compat: required compatible string, NULL or "" for any match diff --git a/drivers/of/cpu.c b/drivers/of/cpu.c new file mode 100644 index 000000000000..d17b2f851082 --- /dev/null +++ b/drivers/of/cpu.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/cpu.h> +#include <linux/kernel.h> +#include <linux/of.h> + +/** + * of_get_cpu_hwid - Get the hardware ID from a CPU device node + * + * @cpun: CPU number(logical index) for which device node is required + * @thread: The local thread number to get the hardware ID for. + * + * Return: The hardware ID for the CPU node or ~0ULL if not found. + */ +u64 of_get_cpu_hwid(struct device_node *cpun, unsigned int thread) +{ + const __be32 *cell; + int ac, len; + + ac = of_n_addr_cells(cpun); + cell = of_get_property(cpun, "reg", &len); + if (!cell || !ac || ((sizeof(*cell) * ac * (thread + 1)) > len)) + return ~0ULL; + + cell += ac * thread; + return of_read_number(cell, ac); +} + +/* + * 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 && arch_match_cpu_phys_id(cpu, 0)) + return true; + 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; + + return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread); +} + +/** + * 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. + * + * Return: A node pointer for the logical cpu with refcount incremented, use + * of_node_put() on it when done. Returns NULL if not found. + */ +struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) +{ + struct device_node *cpun; + + for_each_of_cpu_node(cpun) { + if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread)) + return cpun; + } + return NULL; +} +EXPORT_SYMBOL(of_get_cpu_node); + +/** + * of_cpu_device_node_get: Get the CPU device_node for a given logical CPU number + * + * @cpu: The logical CPU number + * + * Return: Pointer to the device_node for CPU with its reference count + * incremented of the given logical CPU number or NULL if the CPU device_node + * is not found. + */ +struct device_node *of_cpu_device_node_get(int cpu) +{ + struct device *cpu_dev; + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) + return of_get_cpu_node(cpu, NULL); + return of_node_get(cpu_dev->of_node); +} +EXPORT_SYMBOL(of_cpu_device_node_get); + +/** + * of_cpu_node_to_id: Get the logical CPU number for a given device_node + * + * @cpu_node: Pointer to the device_node for CPU. + * + * Return: The logical CPU number of the given CPU device_node or -ENODEV if the + * CPU is not found. + */ +int of_cpu_node_to_id(struct device_node *cpu_node) +{ + int cpu; + bool found = false; + struct device_node *np; + + for_each_possible_cpu(cpu) { + np = of_cpu_device_node_get(cpu); + found = (cpu_node == np); + of_node_put(np); + if (found) + return cpu; + } + + return -ENODEV; +} +EXPORT_SYMBOL(of_cpu_node_to_id); + +/** + * of_get_cpu_state_node - Get CPU's idle state node at the given index + * + * @cpu_node: The device node for the CPU + * @index: The index in the list of the idle states + * + * Two generic methods can be used to describe a CPU's idle states, either via + * a flattened description through the "cpu-idle-states" binding or via the + * hierarchical layout, using the "power-domains" and the "domain-idle-states" + * bindings. This function check for both and returns the idle state node for + * the requested index. + * + * Return: An idle state node if found at @index. The refcount is incremented + * for it, so call of_node_put() on it when done. Returns NULL if not found. + */ +struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, + int index) +{ + struct of_phandle_args args; + int err; + + err = of_parse_phandle_with_args(cpu_node, "power-domains", + "#power-domain-cells", 0, &args); + if (!err) { + struct device_node *state_node = + of_parse_phandle(args.np, "domain-idle-states", index); + + of_node_put(args.np); + if (state_node) + return state_node; + } + + return of_parse_phandle(cpu_node, "cpu-idle-states", index); +} +EXPORT_SYMBOL(of_get_cpu_state_node); diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index fb6792d381a6..b57f1014e419 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -38,6 +38,7 @@ struct alias_prop { #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 extern struct mutex of_mutex; +extern raw_spinlock_t devtree_lock; extern struct list_head aliases_lookup; extern struct kset *of_kset; diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi index 6604a52bf6cb..bc0029cbf8ea 100644 --- a/drivers/of/unittest-data/tests-address.dtsi +++ b/drivers/of/unittest-data/tests-address.dtsi @@ -14,7 +14,7 @@ #size-cells = <1>; /* ranges here is to make sure we don't use it for * dma-ranges translation */ - ranges = <0x70000000 0x70000000 0x40000000>, + ranges = <0x70000000 0x70000000 0x50000000>, <0x00000000 0xd0000000 0x20000000>; dma-ranges = <0x0 0x20000000 0x40000000>; @@ -43,6 +43,13 @@ <0x42000000 0x0 0xc0000000 0x20000000 0x0 0x10000000>; }; + bus@a0000000 { + #address-cells = <3>; + #size-cells = <2>; + ranges = <0xf00baa 0x0 0x0 0xa0000000 0x0 0x100000>, + <0xf00bee 0x1 0x0 0xb0000000 0x0 0x200000>; + }; + }; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index ab3e91445256..2191c0136531 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1008,6 +1008,153 @@ static void __init of_unittest_pci_dma_ranges(void) of_node_put(np); } +static void __init of_unittest_bus_ranges(void) +{ + struct device_node *np; + struct of_range range; + struct of_range_parser parser; + struct resource res; + int ret, count, i = 0; + + np = of_find_node_by_path("/testcase-data/address-tests"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + if (of_range_parser_init(&parser, np)) { + pr_err("missing ranges property\n"); + return; + } + + ret = of_range_to_resource(np, 1, &res); + unittest(!ret, "of_range_to_resource returned error (%d) node %pOF\n", + ret, np); + unittest(resource_type(&res) == IORESOURCE_MEM, + "of_range_to_resource wrong resource type on node %pOF res=%pR\n", + np, &res); + unittest(res.start == 0xd0000000, + "of_range_to_resource wrong resource start address on node %pOF res=%pR\n", + np, &res); + unittest(resource_size(&res) == 0x20000000, + "of_range_to_resource wrong resource start address on node %pOF res=%pR\n", + np, &res); + + count = of_range_count(&parser); + unittest(count == 2, + "of_range_count wrong size on node %pOF count=%d\n", + np, count); + + /* + * Get the "ranges" from the device tree + */ + for_each_of_range(&parser, &range) { + unittest(range.flags == IORESOURCE_MEM, + "for_each_of_range wrong flags on node %pOF flags=%x (expected %x)\n", + np, range.flags, IORESOURCE_MEM); + if (!i) { + unittest(range.size == 0x50000000, + "for_each_of_range wrong size on node %pOF size=%llx\n", + np, range.size); + unittest(range.cpu_addr == 0x70000000, + "for_each_of_range wrong CPU addr (%llx) on node %pOF", + range.cpu_addr, np); + unittest(range.bus_addr == 0x70000000, + "for_each_of_range wrong bus addr (%llx) on node %pOF", + range.pci_addr, np); + } else { + unittest(range.size == 0x20000000, + "for_each_of_range wrong size on node %pOF size=%llx\n", + np, range.size); + unittest(range.cpu_addr == 0xd0000000, + "for_each_of_range wrong CPU addr (%llx) on node %pOF", + range.cpu_addr, np); + unittest(range.bus_addr == 0x00000000, + "for_each_of_range wrong bus addr (%llx) on node %pOF", + range.pci_addr, np); + } + i++; + } + + of_node_put(np); +} + +static void __init of_unittest_bus_3cell_ranges(void) +{ + struct device_node *np; + struct of_range range; + struct of_range_parser parser; + int i = 0; + + np = of_find_node_by_path("/testcase-data/address-tests/bus@a0000000"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + if (of_range_parser_init(&parser, np)) { + pr_err("missing ranges property\n"); + return; + } + + /* + * Get the "ranges" from the device tree + */ + for_each_of_range(&parser, &range) { + if (!i) { + unittest(range.flags == 0xf00baa, + "for_each_of_range wrong flags on node %pOF flags=%x\n", + np, range.flags); + unittest(range.size == 0x100000, + "for_each_of_range wrong size on node %pOF size=%llx\n", + np, range.size); + unittest(range.cpu_addr == 0xa0000000, + "for_each_of_range wrong CPU addr (%llx) on node %pOF", + range.cpu_addr, np); + unittest(range.bus_addr == 0x0, + "for_each_of_range wrong bus addr (%llx) on node %pOF", + range.pci_addr, np); + } else { + unittest(range.flags == 0xf00bee, + "for_each_of_range wrong flags on node %pOF flags=%x\n", + np, range.flags); + unittest(range.size == 0x200000, + "for_each_of_range wrong size on node %pOF size=%llx\n", + np, range.size); + unittest(range.cpu_addr == 0xb0000000, + "for_each_of_range wrong CPU addr (%llx) on node %pOF", + range.cpu_addr, np); + unittest(range.bus_addr == 0x100000000, + "for_each_of_range wrong bus addr (%llx) on node %pOF", + range.pci_addr, np); + } + i++; + } + + of_node_put(np); +} + +static void __init of_unittest_reg(void) +{ + struct device_node *np; + int ret; + u64 addr, size; + + np = of_find_node_by_path("/testcase-data/address-tests/bus@80000000/device@1000"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + ret = of_property_read_reg(np, 0, &addr, &size); + unittest(!ret, "of_property_read_reg(%pOF) returned error %d\n", + np, ret); + unittest(addr == 0x1000, "of_property_read_reg(%pOF) untranslated address (%llx) incorrect\n", + np, addr); + + of_node_put(np); +} + static void __init of_unittest_parse_interrupts(void) { struct device_node *np; @@ -3635,6 +3782,9 @@ static int __init of_unittest(void) of_unittest_dma_get_max_cpu_address(); of_unittest_parse_dma_ranges(); of_unittest_pci_dma_ranges(); + of_unittest_bus_ranges(); + of_unittest_bus_3cell_ranges(); + of_unittest_reg(); of_unittest_match_node(); of_unittest_platform_populate(); of_unittest_overlay(); diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 233eab70e15e..8246e9b7afe7 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -13,7 +13,7 @@ #include <linux/cpu.h> #include <linux/errno.h> #include <linux/device.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pm_domain.h> #include <linux/slab.h> #include <linux/export.h> diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index d93595b39afa..5368b6ba2884 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -200,9 +200,8 @@ static int d7s_probe(struct platform_device *op) */ regs = readb(p->regs); opts = of_find_node_by_path("/options"); - if (opts && - of_get_property(opts, "d7s-flipped?", NULL)) - p->flipped = true; + if (opts) + p->flipped = of_property_read_bool(opts, "d7s-flipped?"); if (p->flipped) regs |= D7S_FLIP; diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c index b9c96182a46a..81585733c8a9 100644 --- a/drivers/soc/mediatek/mtk-svs.c +++ b/drivers/soc/mediatek/mtk-svs.c @@ -7,6 +7,7 @@ #include <linux/bits.h> #include <linux/clk.h> #include <linux/completion.h> +#include <linux/cpu.h> #include <linux/cpuidle.h> #include <linux/debugfs.h> #include <linux/device.h> diff --git a/drivers/thermal/cpuidle_cooling.c b/drivers/thermal/cpuidle_cooling.c index 4f41102e8b16..6f6daead485e 100644 --- a/drivers/thermal/cpuidle_cooling.c +++ b/drivers/thermal/cpuidle_cooling.c @@ -7,12 +7,13 @@ */ #define pr_fmt(fmt) "cpuidle cooling: " fmt +#include <linux/cpu.h> #include <linux/cpu_cooling.h> #include <linux/cpuidle.h> #include <linux/device.h> #include <linux/err.h> #include <linux/idle_inject.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/slab.h> #include <linux/thermal.h> diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c index f8b4389d60d9..e92e2ceb12a4 100644 --- a/drivers/virt/fsl_hypervisor.c +++ b/drivers/virt/fsl_hypervisor.c @@ -796,7 +796,7 @@ static int has_fsl_hypervisor(void) if (!node) return 0; - ret = of_find_property(node, "fsl,hv-version", NULL) != NULL; + ret = of_property_present(node, "fsl,hv-version"); of_node_put(node); diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index d4632aace402..530c77b8d062 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -87,7 +87,7 @@ static int w1_gpio_probe(struct platform_device *pdev) * driver it high/low like we are in full control of the line and * open drain will happen transparently. */ - if (of_get_property(np, "linux,open-drain", NULL)) + if (of_property_present(np, "linux,open-drain")) gflags = GPIOD_OUT_LOW; pdev->dev.platform_data = pdata; |