diff options
| -rw-r--r-- | common/spl/spl.c | 3 | ||||
| -rw-r--r-- | drivers/core/root.c | 7 | ||||
| -rw-r--r-- | include/dm/root.h | 10 | 
3 files changed, 20 insertions, 0 deletions
| diff --git a/common/spl/spl.c b/common/spl/spl.c index 32b9f1e95cd..9bcbd09ff38 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 33dc9c0b2db..9edfc1efb66 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 c7f0c1d5ca3..3cf730dcee1 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   * | 
