This patch adds a code to initialize memory regions also for child devices
if parent device has "memory-region" and "memory-region-names" device tree
properties and given device's name matches "<parent_name>:<region_name>"
template.

Signed-off-by: Marek Szyprowski <m.szyprow...@samsung.com>
---
 .../bindings/reserved-memory/reserved-memory.txt   |   6 +-
 drivers/of/of_reserved_mem.c                       | 101 ++++++++++++++-------
 2 files changed, 74 insertions(+), 33 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt 
b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
index 3da0ebdba8d9..69d28288ed37 100644
--- a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
@@ -73,7 +73,11 @@ Device node references to reserved memory
 Regions in the /reserved-memory node may be referenced by other device
 nodes by adding a memory-region property to the device node.
 
-memory-region (optional) - phandle, specifier pairs to children of 
/reserved-memory
+memory-region (optional) - arrays of phandles, specifier pairs to children
+      of /reserved-memory, first phandle is used as a default memory
+      region
+memory-region-names (optional) - array of strings with names of memory
+      regions, used when more than one region has been defined
 
 Example
 -------
diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c
index 7e7de03585f9..3ab9446ffa43 100644
--- a/drivers/of/of_reserved_mem.c
+++ b/drivers/of/of_reserved_mem.c
@@ -237,32 +237,82 @@ static inline struct reserved_mem *__find_rmem(struct 
device_node *node)
        return NULL;
 }
 
-/**
- * of_reserved_mem_device_init() - assign reserved memory region to given 
device
- *
- * This function assign memory region pointed by "memory-region" device tree
- * property to the given device.
- */
-int of_reserved_mem_device_init(struct device *dev)
+static int __rmem_dev_init(struct device *dev, struct device_node *np)
 {
-       struct reserved_mem *rmem;
-       struct device_node *np;
-
-       np = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!np)
-               return;
-
-       rmem = __find_rmem(np);
-       of_node_put(np);
-
+       struct reserved_mem *rmem = __find_rmem(np);
        if (!rmem || !rmem->ops || !rmem->ops->device_init)
-               return;
+               return -EINVAL;
 
        rmem->ops->device_init(rmem, dev);
        dev_info(dev, "assigned reserved memory node %s\n", rmem->name);
        return 0;
 }
 
+static int __rmem_dev_release(struct device *dev, struct device_node *np)
+{
+       struct reserved_mem *rmem = __find_rmem(np);
+       if (!rmem || !rmem->ops)
+               return -EINVAL;
+
+       if (rmem->ops->device_release)
+               rmem->ops->device_release(rmem, dev);
+       return 0;
+}
+
+static int __rmem_dev_call(struct device *dev,
+                       int (*func)(struct device *dev, struct device_node *np))
+{
+       int ret = -ENODEV;
+       if (of_get_property(dev->of_node, "memory-region", NULL)) {
+               struct device_node *np;
+               np = of_parse_phandle(dev->of_node, "memory-region", 0);
+               if (!np)
+                       return -ENODEV;
+               ret = func(dev, np);
+               of_node_put(np);
+       } else if (dev->parent &&
+                  of_get_property(dev->parent->of_node, "memory-region",
+                                  NULL)) {
+               struct device *parent = dev->parent;
+               struct device_node *np;
+               char *name;
+               int idx;
+
+               name = strrchr(dev_name(dev), ':');
+               if (!name)
+                       return -ENODEV;
+               name++;
+
+               idx = of_property_match_string(parent->of_node,
+                                              "memory-region-names", name);
+               if (idx < 0)
+                       return -ENODEV;
+
+               np = of_parse_phandle(parent->of_node, "memory-region", idx);
+               if (!np)
+                       return -ENODEV;
+
+               ret = func(dev, np);
+               of_node_put(np);
+       }
+       return ret;
+}
+
+/**
+ * of_reserved_mem_device_init() - assign reserved memory region to given 
device
+ *
+ * This function assigns default memory region pointed by first entry of
+ * "memory-region" device tree property (if available) to the given device or
+ * checks if the given device can be used to give access to named memory region
+ * if parent device has "memory-region" and "memory-region-names" device tree
+ * properties and given device's name matches "<parent_name>:<region_name>"
+ * template.
+ */
+int of_reserved_mem_device_init(struct device *dev)
+{
+       return __rmem_dev_call(dev, __rmem_dev_init);
+}
+
 /**
  * of_reserved_mem_device_release() - release reserved memory device structures
  *
@@ -271,18 +321,5 @@ int of_reserved_mem_device_init(struct device *dev)
  */
 void of_reserved_mem_device_release(struct device *dev)
 {
-       struct reserved_mem *rmem;
-       struct device_node *np;
-
-       np = of_parse_phandle(dev->of_node, "memory-region", 0);
-       if (!np)
-               return;
-
-       rmem = __find_rmem(np);
-       of_node_put(np);
-
-       if (!rmem || !rmem->ops || !rmem->ops->device_release)
-               return;
-
-       rmem->ops->device_release(rmem, dev);
+       __rmem_dev_call(dev, __rmem_dev_release);
 }
-- 
1.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to