From de5bab9c59807b109f89a39855c9eacfe4d08822 Mon Sep 17 00:00:00 2001
From: Patrick Delaunay <patrick.delaunay@st.com>
Date: Wed, 31 Oct 2018 16:49:03 +0100
Subject: [PATCH] syscon: update syscon_node_to_regmap to use the DM functions

+ Update the function syscon_node_to_regmap() to force bound on
  syscon uclass and directly use the list of device from DM.
+ Remove the static list syscon_list.

This patch avoid issue (crash) when syscon_node_to_regmap() is called
before and after reallocation (list content is invalid).

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
---
 drivers/core/syscon-uclass.c | 55 +++++++++++-------------------------
 1 file changed, 17 insertions(+), 38 deletions(-)

diff --git a/drivers/core/syscon-uclass.c b/drivers/core/syscon-uclass.c
index 661cf61d62..3cf9dd9dbe 100644
--- a/drivers/core/syscon-uclass.c
+++ b/drivers/core/syscon-uclass.c
@@ -146,52 +146,31 @@ U_BOOT_DRIVER(generic_syscon) = {
  * The syscon node can be bound to another driver, but still works
  * as a syscon provider.
  */
-static LIST_HEAD(syscon_list);
-
-struct syscon {
-	ofnode node;
-	struct regmap *regmap;
-	struct list_head list;
-};
-
-static struct syscon *of_syscon_register(ofnode node)
+struct regmap *syscon_node_to_regmap(ofnode node)
 {
-	struct syscon *syscon;
+	struct udevice *dev, *parent;
 	int ret;
 
+	if (!uclass_get_device_by_ofnode(UCLASS_SYSCON, node, &dev))
+		return syscon_get_regmap(dev);
+
 	if (!ofnode_device_is_compatible(node, "syscon"))
 		return ERR_PTR(-EINVAL);
 
-	syscon = malloc(sizeof(*syscon));
-	if (!syscon)
-		return ERR_PTR(-ENOMEM);
+	/* bound to driver with same ofnode or to root if not found */
+	if (device_find_global_by_ofnode(node, &parent))
+		parent = dm_root();
 
-	ret = regmap_init_mem(node, &syscon->regmap);
-	if (ret) {
-		free(syscon);
+	/* force bound to syscon class */
+	ret = device_bind_driver_to_node(parent, "syscon",
+					 ofnode_get_name(node),
+					 node, &dev);
+	if (ret)
 		return ERR_PTR(ret);
-	}
-
-	list_add_tail(&syscon->list, &syscon_list);
-
-	return syscon;
-}
 
-struct regmap *syscon_node_to_regmap(ofnode node)
-{
-	struct syscon *entry, *syscon = NULL;
-
-	list_for_each_entry(entry, &syscon_list, list)
-		if (ofnode_equal(entry->node, node)) {
-			syscon = entry;
-			break;
-		}
-
-	if (!syscon)
-		syscon = of_syscon_register(node);
-
-	if (IS_ERR(syscon))
-		return ERR_CAST(syscon);
+	ret = device_probe(dev);
+	if (ret)
+		return ERR_PTR(ret);
 
-	return syscon->regmap;
+	return syscon_get_regmap(dev);
 }
-- 
2.39.5