diff mbox

[Linaro-mm-sig,2/7] drivers: of: add support for named memory regions

Message ID 1409054988-32758-3-git-send-email-m.szyprowski@samsung.com
State New
Headers show

Commit Message

Marek Szyprowski Aug. 26, 2014, 12:09 p.m. UTC
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.szyprowski@samsung.com>
---
 .../bindings/reserved-memory/reserved-memory.txt   |   6 +-
 drivers/of/of_reserved_mem.c                       | 101 ++++++++++++++-------
 2 files changed, 74 insertions(+), 33 deletions(-)
diff mbox

Patch

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);
 }