summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/spl/spl.c3
-rw-r--r--drivers/core/root.c7
-rw-r--r--include/dm/root.h10
3 files changed, 20 insertions, 0 deletions
diff --git a/common/spl/spl.c b/common/spl/spl.c
index 32b9f1e..9bcbd09 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -513,6 +513,9 @@ ulong spl_relocate_stack_gd(void)
ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
new_gd = (gd_t *)ptr;
memcpy(new_gd, (void *)gd, sizeof(gd_t));
+#if CONFIG_IS_ENABLED(DM)
+ dm_fixup_for_gd_move(new_gd);
+#endif
#if !defined(CONFIG_ARM)
gd = new_gd;
#endif
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 33dc9c0..9edfc1e 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -41,6 +41,13 @@ struct udevice *dm_root(void)
return gd->dm_root;
}
+void dm_fixup_for_gd_move(struct global_data *new_gd)
+{
+ /* The sentinel node has moved, so update things that point to it */
+ new_gd->uclass_root.next->prev = &new_gd->uclass_root;
+ new_gd->uclass_root.prev->next = &new_gd->uclass_root;
+}
+
fdt_addr_t dm_get_translation_offset(void)
{
struct udevice *root = dm_root();
diff --git a/include/dm/root.h b/include/dm/root.h
index c7f0c1d..3cf730d 100644
--- a/include/dm/root.h
+++ b/include/dm/root.h
@@ -21,6 +21,16 @@ struct udevice;
*/
struct udevice *dm_root(void);
+struct global_data;
+/**
+ * dm_fixup_for_gd_move() - Handle global_data moving to a new place
+ *
+ * The uclass list is part of global_data. Due to the way lists work, moving
+ * the list will cause it to become invalid. This function fixes that up so
+ * that the uclass list will work correctly.
+ */
+void dm_fixup_for_gd_move(struct global_data *new_gd);
+
/**
* dm_scan_platdata() - Scan all platform data and bind drivers
*