]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - drivers/core/root.c
sunxi: mmc: set transfer timeout according to byte_cnt.
[karo-tx-uboot.git] / drivers / core / root.c
index 47b3acfbe981da9fcfe5ca6d7c20e60dd63b0285..78ab00c7bfbf9e4d46cdf2c9e83e3cf2011d23e8 100644 (file)
@@ -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;
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+       DM_ROOT_NON_CONST->of_offset = 0;
+#endif
        ret = device_probe(DM_ROOT_NON_CONST);
        if (ret)
                return ret;
@@ -77,7 +145,7 @@ int dm_scan_platdata(bool pre_reloc_only)
        return ret;
 }
 
-#ifdef CONFIG_OF_CONTROL
+#if CONFIG_IS_ENABLED(OF_CONTROL)
 int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
                     bool pre_reloc_only)
 {
@@ -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;
@@ -125,13 +197,15 @@ int dm_init_and_scan(bool pre_reloc_only)
                debug("dm_scan_platdata() failed: %d\n", ret);
                return ret;
        }
-#ifdef CONFIG_OF_CONTROL
-       ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
-       if (ret) {
-               debug("dm_scan_fdt() failed: %d\n", ret);
-               return ret;
+
+       if (CONFIG_IS_ENABLED(OF_CONTROL)) {
+               ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only);
+               if (ret) {
+                       debug("dm_scan_fdt() failed: %d\n", ret);
+                       return ret;
+               }
        }
-#endif
+
        ret = dm_scan_other(pre_reloc_only);
        if (ret)
                return ret;