diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/address.c | 2 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 14 | ||||
-rw-r--r-- | drivers/of/property.c | 89 | ||||
-rw-r--r-- | drivers/of/unittest-data/tests-address.dtsi | 10 | ||||
-rw-r--r-- | drivers/of/unittest.c | 2 |
5 files changed, 97 insertions, 20 deletions
diff --git a/drivers/of/address.c b/drivers/of/address.c index 8eea3f6e29a4..381dc9be7b22 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -864,7 +864,7 @@ EXPORT_SYMBOL_GPL(of_address_to_resource); /** * of_iomap - Maps the memory mapped IO for a given device_node - * @device: the device whose io range will be mapped + * @np: the device whose io range will be mapped * @index: index of the io range * * Returns a pointer to the mapped memory diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 6877080c8af9..46b9371c8a33 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -54,7 +54,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { - pr_err("not enough space all defined regions.\n"); + pr_err("not enough space for all defined regions.\n"); return; } @@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, /** * __reserved_mem_alloc_size() - allocate reserved memory described by - * 'size', 'align' and 'alloc-ranges' properties. + * 'size', 'alignment' and 'alloc-ranges' properties. */ static int __init __reserved_mem_alloc_size(unsigned long node, const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) @@ -79,7 +79,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, phys_addr_t base = 0, align = 0, size; int len; const __be32 *prop; - int nomap; + bool nomap; int ret; prop = of_get_flat_dt_prop(node, "size", &len); @@ -92,8 +92,6 @@ static int __init __reserved_mem_alloc_size(unsigned long node, } size = dt_mem_next_cell(dt_root_size_cells, &prop); - nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; - prop = of_get_flat_dt_prop(node, "alignment", &len); if (prop) { if (len != dt_root_addr_cells * sizeof(__be32)) { @@ -104,11 +102,13 @@ static int __init __reserved_mem_alloc_size(unsigned long node, align = dt_mem_next_cell(dt_root_addr_cells, &prop); } + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + /* Need adjust the alignment to satisfy the CMA requirement */ if (IS_ENABLED(CONFIG_CMA) && of_flat_dt_is_compatible(node, "shared-dma-pool") && of_get_flat_dt_prop(node, "reusable", NULL) - && !of_get_flat_dt_prop(node, "no-map", NULL)) { + && !nomap) { unsigned long order = max_t(unsigned long, MAX_ORDER - 1, pageblock_order); @@ -247,7 +247,7 @@ void __init fdt_init_reserved_mem(void) int len; const __be32 *prop; int err = 0; - int nomap; + bool nomap; nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; prop = of_get_flat_dt_prop(node, "phandle", &len); diff --git a/drivers/of/property.c b/drivers/of/property.c index 1f2086f4e7ce..d40d923ffeaf 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1015,6 +1015,30 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, } /** + * of_get_next_parent_dev - Add device link to supplier from supplier phandle + * @np: device tree node + * + * Given a device tree node (@np), this function finds its closest ancestor + * device tree node that has a corresponding struct device. + * + * The caller of this function is expected to call put_device() on the returned + * device when they are done. + */ +static struct device *of_get_next_parent_dev(struct device_node *np) +{ + struct device *dev = NULL; + + of_node_get(np); + do { + np = of_get_next_parent(np); + if (np) + dev = get_dev_from_fwnode(&np->fwnode); + } while (np && !dev); + of_node_put(np); + return dev; +} + +/** * of_link_to_phandle - Add device link to supplier from supplier phandle * @dev: consumer device * @sup_np: phandle to supplier device tree node @@ -1035,10 +1059,9 @@ static bool of_is_ancestor_of(struct device_node *test_ancestor, static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, u32 dl_flags) { - struct device *sup_dev; + struct device *sup_dev, *sup_par_dev; int ret = 0; struct device_node *tmp_np = sup_np; - int is_populated; of_node_get(sup_np); /* @@ -1075,16 +1098,43 @@ static int of_link_to_phandle(struct device *dev, struct device_node *sup_np, return -EINVAL; } sup_dev = get_dev_from_fwnode(&sup_np->fwnode); - is_populated = of_node_check_flag(sup_np, OF_POPULATED); - of_node_put(sup_np); - if (!sup_dev && is_populated) { + if (!sup_dev && of_node_check_flag(sup_np, OF_POPULATED)) { /* Early device without struct device. */ dev_dbg(dev, "Not linking to %pOFP - No struct device\n", sup_np); + of_node_put(sup_np); return -ENODEV; } else if (!sup_dev) { - return -EAGAIN; + /* + * DL_FLAG_SYNC_STATE_ONLY doesn't block probing and supports + * cycles. So cycle detection isn't necessary and shouldn't be + * done. + */ + if (dl_flags & DL_FLAG_SYNC_STATE_ONLY) { + of_node_put(sup_np); + return -EAGAIN; + } + + sup_par_dev = of_get_next_parent_dev(sup_np); + + if (sup_par_dev && device_is_dependent(dev, sup_par_dev)) { + /* Cyclic dependency detected, don't try to link */ + dev_dbg(dev, "Not linking to %pOFP - cycle detected\n", + sup_np); + ret = -EINVAL; + } else { + /* + * Can't check for cycles or no cycles. So let's try + * again later. + */ + ret = -EAGAIN; + } + + of_node_put(sup_np); + put_device(sup_par_dev); + return ret; } + of_node_put(sup_np); if (!device_link_add(dev, sup_dev, dl_flags)) ret = -EINVAL; put_device(sup_dev); @@ -1219,6 +1269,20 @@ DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells") DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells") DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells") DEFINE_SIMPLE_PROP(extcon, "extcon", NULL) +DEFINE_SIMPLE_PROP(interrupts_extended, "interrupts-extended", + "#interrupt-cells") +DEFINE_SIMPLE_PROP(nvmem_cells, "nvmem-cells", NULL) +DEFINE_SIMPLE_PROP(phys, "phys", "#phy-cells") +DEFINE_SIMPLE_PROP(wakeup_parent, "wakeup-parent", NULL) +DEFINE_SIMPLE_PROP(pinctrl0, "pinctrl-0", NULL) +DEFINE_SIMPLE_PROP(pinctrl1, "pinctrl-1", NULL) +DEFINE_SIMPLE_PROP(pinctrl2, "pinctrl-2", NULL) +DEFINE_SIMPLE_PROP(pinctrl3, "pinctrl-3", NULL) +DEFINE_SIMPLE_PROP(pinctrl4, "pinctrl-4", NULL) +DEFINE_SIMPLE_PROP(pinctrl5, "pinctrl-5", NULL) +DEFINE_SIMPLE_PROP(pinctrl6, "pinctrl-6", NULL) +DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) +DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") @@ -1244,6 +1308,19 @@ static const struct supplier_bindings of_supplier_bindings[] = { { .parse_prop = parse_power_domains, }, { .parse_prop = parse_hwlocks, }, { .parse_prop = parse_extcon, }, + { .parse_prop = parse_interrupts_extended, }, + { .parse_prop = parse_nvmem_cells, }, + { .parse_prop = parse_phys, }, + { .parse_prop = parse_wakeup_parent, }, + { .parse_prop = parse_pinctrl0, }, + { .parse_prop = parse_pinctrl1, }, + { .parse_prop = parse_pinctrl2, }, + { .parse_prop = parse_pinctrl3, }, + { .parse_prop = parse_pinctrl4, }, + { .parse_prop = parse_pinctrl5, }, + { .parse_prop = parse_pinctrl6, }, + { .parse_prop = parse_pinctrl7, }, + { .parse_prop = parse_pinctrl8, }, { .parse_prop = parse_regulators, }, { .parse_prop = parse_gpio, }, { .parse_prop = parse_gpios, }, diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi index 3fe5d3987beb..6604a52bf6cb 100644 --- a/drivers/of/unittest-data/tests-address.dtsi +++ b/drivers/of/unittest-data/tests-address.dtsi @@ -23,13 +23,13 @@ }; bus@80000000 { - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x80000000 0x100000>; - dma-ranges = <0x10000000 0x0 0x40000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges = <0x0 0x0 0x80000000 0x0 0x100000>; + dma-ranges = <0x1 0x0 0x0 0x20 0x0>; device@1000 { - reg = <0x1000 0x1000>; + reg = <0x0 0x1000 0x0 0x1000>; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 398de04fd19c..9b7e84bdc7d4 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -900,7 +900,7 @@ static void __init of_unittest_parse_dma_ranges(void) of_unittest_dma_ranges_one("/testcase-data/address-tests/device@70000000", 0x0, 0x20000000, 0x40000000); of_unittest_dma_ranges_one("/testcase-data/address-tests/bus@80000000/device@1000", - 0x10000000, 0x20000000, 0x40000000); + 0x100000000, 0x20000000, 0x2000000000); of_unittest_dma_ranges_one("/testcase-data/address-tests/pci@90000000", 0x80000000, 0x20000000, 0x10000000); } |