From 429d5b385d9554f73b176b9861c9c3bc7bdc2573 Mon Sep 17 00:00:00 2001
From: Russell King <rmk+kernel@armlinux.org.uk>
Date: Sun, 24 Jun 2018 14:03:31 +0100
Subject: [PATCH] drm/armada: add reserved memory support

Existing Armada DRM makes use of reserved memory for allocating
contiguous screen buffers, which currently prevents its use with
DT systems.  Add support for this for DT systems.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_drv.c | 52 +++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index cae25ad66c749d..a2ceaf9f4e7bfe 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 
 #include <drm/clients/drm_client_setup.h>
@@ -57,11 +58,40 @@ static const struct drm_mode_config_funcs armada_drm_mode_config_funcs = {
 	.atomic_commit		= drm_atomic_helper_commit,
 };
 
-static int armada_drm_bind(struct device *dev)
+static struct reserved_mem *armada_drm_get_rmem(struct device *dev,
+	const char *compatible)
+{
+	struct device_node *np;
+	struct reserved_mem *rmem;
+
+	np = of_find_compatible_node(NULL, NULL, compatible);
+	if (!np)
+		return NULL;
+
+	rmem = of_reserved_mem_lookup(np);
+	of_node_put(np);
+
+	return rmem;
+}
+
+static struct resource *armada_drm_get_mem(struct device *dev)
 {
-	struct armada_private *priv;
 	struct resource *mem = NULL;
-	int ret, n;
+	struct reserved_mem *rmem;
+	int n;
+
+	rmem = armada_drm_get_rmem(dev, "marvell,armada-framebuffer");
+	if (rmem) {
+		mem = devm_kzalloc(dev, sizeof(*mem), GFP_KERNEL);
+		if (!mem)
+			return ERR_PTR(-ENOMEM);
+
+		mem->start = rmem->base;
+		mem->end = rmem->base + rmem->size - 1;
+		mem->flags = IORESOURCE_MEM;
+
+		return mem;
+	}
 
 	for (n = 0; ; n++) {
 		struct resource *r = platform_get_resource(to_platform_device(dev),
@@ -73,11 +103,21 @@ static int armada_drm_bind(struct device *dev)
 		if (resource_size(r) > SZ_64K)
 			mem = r;
 		else
-			return -EINVAL;
+			return ERR_PTR(-EINVAL);
 	}
 
-	if (!mem)
-		return -ENXIO;
+	return mem ? : ERR_PTR(-ENXIO);
+}
+
+static int armada_drm_bind(struct device *dev)
+{
+	struct armada_private *priv;
+	struct resource *mem;
+	int ret;
+
+	mem = armada_drm_get_mem(dev);
+	if (IS_ERR(mem))
+		return PTR_ERR(mem);
 
 	if (!devm_request_mem_region(dev, mem->start, resource_size(mem),
 				     "armada-drm"))
