syscon: update syscon_node_to_regmap to use the DM functions
authorPatrick Delaunay <patrick.delaunay@st.com>
Wed, 31 Oct 2018 15:49:03 +0000 (16:49 +0100)
committerTom Rini <trini@konsulko.com>
Sat, 15 Dec 2018 16:49:56 +0000 (11:49 -0500)
+ 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

index 661cf61d62abfb82167b29f895f7e6b1437c6332..3cf9dd9dbe43b65e89c1a0831653554673ae4818 100644 (file)
@@ -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);
 }