summaryrefslogtreecommitdiff
path: root/drivers/core/root.c
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2015-02-24 07:59:38 +0100
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2015-02-24 07:59:38 +0100
commite1cc4d31f889428a4ca73120951389c756404184 (patch)
tree4a2028c750e19f5d36d0aa7545bda7cbacea9dd4 /drivers/core/root.c
parent23d184d2fbc805bdd9fb41f2370cdce04a7894af (diff)
parent38dac81b3d0e777f301ca98100bfbcab01d616c2 (diff)
downloadu-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.zip
u-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.tar.gz
u-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.tar.bz2
Merge remote-tracking branch 'u-boot/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers/core/root.c')
-rw-r--r--drivers/core/root.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 47b3acf..9b5c6bb 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <errno.h>
+#include <fdtdec.h>
#include <malloc.h>
#include <libfdt.h>
#include <dm/device.h>
@@ -36,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;
@@ -46,9 +106,17 @@ 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;
+#ifdef CONFIG_OF_CONTROL
+ DM_ROOT_NON_CONST->of_offset = 0;
+#endif
ret = device_probe(DM_ROOT_NON_CONST);
if (ret)
return ret;
@@ -89,6 +157,10 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
if (pre_reloc_only &&
!fdt_getprop(blob, offset, "u-boot,dm-pre-reloc", NULL))
continue;
+ if (!fdtdec_get_is_enabled(blob, offset)) {
+ dm_dbg(" - ignoring disabled device\n");
+ continue;
+ }
err = lists_bind_fdt(parent, blob, offset, NULL);
if (err && !ret)
ret = err;