|
@@ -37,6 +37,65 @@ struct udevice *dm_root(void)
|
|
|
return gd->dm_root;
|
|
|
}
|
|
|
|
|
|
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
|
|
+void fix_drivers(void)
|
|
|
+{
|
|
|
+ struct driver *drv =
|
|
|
+ ll_entry_start(struct driver, driver);
|
|
|
+ const int n_ents = ll_entry_count(struct driver, driver);
|
|
|
+ struct driver *entry;
|
|
|
+
|
|
|
+ for (entry = drv; entry != drv + n_ents; entry++) {
|
|
|
+ if (entry->of_match)
|
|
|
+ entry->of_match = (const struct udevice_id *)
|
|
|
+ ((u32)entry->of_match + gd->reloc_off);
|
|
|
+ if (entry->bind)
|
|
|
+ entry->bind += gd->reloc_off;
|
|
|
+ if (entry->probe)
|
|
|
+ entry->probe += gd->reloc_off;
|
|
|
+ if (entry->remove)
|
|
|
+ entry->remove += gd->reloc_off;
|
|
|
+ if (entry->unbind)
|
|
|
+ entry->unbind += gd->reloc_off;
|
|
|
+ if (entry->ofdata_to_platdata)
|
|
|
+ entry->ofdata_to_platdata += gd->reloc_off;
|
|
|
+ if (entry->child_pre_probe)
|
|
|
+ entry->child_pre_probe += gd->reloc_off;
|
|
|
+ if (entry->child_post_remove)
|
|
|
+ entry->child_post_remove += gd->reloc_off;
|
|
|
+ /* OPS are fixed in every uclass post_probe function */
|
|
|
+ if (entry->ops)
|
|
|
+ entry->ops += gd->reloc_off;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void fix_uclass(void)
|
|
|
+{
|
|
|
+ struct uclass_driver *uclass =
|
|
|
+ ll_entry_start(struct uclass_driver, uclass);
|
|
|
+ const int n_ents = ll_entry_count(struct uclass_driver, uclass);
|
|
|
+ struct uclass_driver *entry;
|
|
|
+
|
|
|
+ for (entry = uclass; entry != uclass + n_ents; entry++) {
|
|
|
+ if (entry->post_bind)
|
|
|
+ entry->post_bind += gd->reloc_off;
|
|
|
+ if (entry->pre_unbind)
|
|
|
+ entry->pre_unbind += gd->reloc_off;
|
|
|
+ if (entry->post_probe)
|
|
|
+ entry->post_probe += gd->reloc_off;
|
|
|
+ if (entry->pre_remove)
|
|
|
+ entry->pre_remove += gd->reloc_off;
|
|
|
+ if (entry->init)
|
|
|
+ entry->init += gd->reloc_off;
|
|
|
+ if (entry->destroy)
|
|
|
+ entry->destroy += gd->reloc_off;
|
|
|
+ /* FIXME maybe also need to fix these ops */
|
|
|
+ if (entry->ops)
|
|
|
+ entry->ops += gd->reloc_off;
|
|
|
+ }
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
int dm_init(void)
|
|
|
{
|
|
|
int ret;
|
|
@@ -47,6 +106,11 @@ int dm_init(void)
|
|
|
}
|
|
|
INIT_LIST_HEAD(&DM_UCLASS_ROOT_NON_CONST);
|
|
|
|
|
|
+#if defined(CONFIG_NEEDS_MANUAL_RELOC)
|
|
|
+ fix_drivers();
|
|
|
+ fix_uclass();
|
|
|
+#endif
|
|
|
+
|
|
|
ret = device_bind_by_name(NULL, false, &root_info, &DM_ROOT_NON_CONST);
|
|
|
if (ret)
|
|
|
return ret;
|