diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/device.c | 31 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 80 | ||||
-rw-r--r-- | drivers/of/unittest.c | 10 |
3 files changed, 97 insertions, 24 deletions
diff --git a/drivers/of/device.c b/drivers/of/device.c index 5053e5d532cc..c80426510ec2 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -35,44 +35,35 @@ EXPORT_SYMBOL(of_match_device); static void of_dma_set_restricted_buffer(struct device *dev, struct device_node *np) { - struct device_node *node, *of_node = dev->of_node; - int count, i; + struct device_node *of_node = dev->of_node; + struct of_phandle_iterator it; + int rc, i = 0; if (!IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL)) return; - count = of_property_count_elems_of_size(of_node, "memory-region", - sizeof(u32)); /* * If dev->of_node doesn't exist or doesn't contain memory-region, try * the OF node having DMA configuration. */ - if (count <= 0) { + if (!of_property_present(of_node, "memory-region")) of_node = np; - count = of_property_count_elems_of_size( - of_node, "memory-region", sizeof(u32)); - } - for (i = 0; i < count; i++) { - node = of_parse_phandle(of_node, "memory-region", i); + of_for_each_phandle(&it, rc, of_node, "memory-region", NULL, 0) { /* * There might be multiple memory regions, but only one * restricted-dma-pool region is allowed. */ - if (of_device_is_compatible(node, "restricted-dma-pool") && - of_device_is_available(node)) { - of_node_put(node); + if (of_device_is_compatible(it.node, "restricted-dma-pool") && + of_device_is_available(it.node)) { + if (of_reserved_mem_device_init_by_idx(dev, of_node, i)) + dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n"); + of_node_put(it.node); break; } - of_node_put(node); + i++; } - /* - * Attempt to initialize a restricted-dma-pool region if one was found. - * Note that count can hold a negative error code. - */ - if (i < count && of_reserved_mem_device_init_by_idx(dev, of_node, i)) - dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n"); } /** diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index ee2e31522d7e..77016c0cc296 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -12,6 +12,7 @@ #define pr_fmt(fmt) "OF: reserved mem: " fmt #include <linux/err.h> +#include <linux/ioport.h> #include <linux/libfdt.h> #include <linux/of.h> #include <linux/of_fdt.h> @@ -740,3 +741,82 @@ struct reserved_mem *of_reserved_mem_lookup(struct device_node *np) return NULL; } EXPORT_SYMBOL_GPL(of_reserved_mem_lookup); + +/** + * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource + * @np: node containing 'memory-region' property + * @idx: index of 'memory-region' property to lookup + * @res: Pointer to a struct resource to fill in with reserved region + * + * This function allows drivers to lookup a node's 'memory-region' property + * entries by index and return a struct resource for the entry. + * + * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region' + * is missing or unavailable, -EINVAL for any other error. + */ +int of_reserved_mem_region_to_resource(const struct device_node *np, + unsigned int idx, struct resource *res) +{ + struct reserved_mem *rmem; + + if (!np) + return -EINVAL; + + struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx); + if (!target || !of_device_is_available(target)) + return -ENODEV; + + rmem = of_reserved_mem_lookup(target); + if (!rmem) + return -EINVAL; + + resource_set_range(res, rmem->base, rmem->size); + res->name = rmem->name; + return 0; +} +EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource); + +/** + * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource + * @np: node containing 'memory-region' property + * @name: name of 'memory-region' property entry to lookup + * @res: Pointer to a struct resource to fill in with reserved region + * + * This function allows drivers to lookup a node's 'memory-region' property + * entries by name and return a struct resource for the entry. + * + * Returns 0 on success with @res filled in, or a negative error-code on + * failure. + */ +int of_reserved_mem_region_to_resource_byname(const struct device_node *np, + const char *name, + struct resource *res) +{ + int idx; + + if (!name) + return -EINVAL; + + idx = of_property_match_string(np, "memory-region-names", name); + if (idx < 0) + return idx; + + return of_reserved_mem_region_to_resource(np, idx, res); +} +EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname); + +/** + * of_reserved_mem_region_count() - Return the number of 'memory-region' entries + * @np: node containing 'memory-region' property + * + * This function allows drivers to retrieve the number of entries for a node's + * 'memory-region' property. + * + * Returns the number of entries on success, or negative error code on a + * malformed property. + */ +int of_reserved_mem_region_count(const struct device_node *np) +{ + return of_count_phandle_with_args(np, "memory-region", NULL); +} +EXPORT_SYMBOL_GPL(of_reserved_mem_region_count); diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 64d301893af7..eeb370e0f507 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -2029,15 +2029,16 @@ static int __init unittest_data_add(void) rc = of_resolve_phandles(unittest_data_node); if (rc) { pr_err("%s: Failed to resolve phandles (rc=%i)\n", __func__, rc); - of_overlay_mutex_unlock(); - return -EINVAL; + rc = -EINVAL; + goto unlock; } /* attach the sub-tree to live tree */ if (!of_root) { pr_warn("%s: no live tree to attach sub-tree\n", __func__); kfree(unittest_data); - return -ENODEV; + rc = -ENODEV; + goto unlock; } EXPECT_BEGIN(KERN_INFO, @@ -2056,9 +2057,10 @@ static int __init unittest_data_add(void) EXPECT_END(KERN_INFO, "Duplicate name in testcase-data, renamed to \"duplicate-name#1\""); +unlock: of_overlay_mutex_unlock(); - return 0; + return rc; } #ifdef CONFIG_OF_OVERLAY |