[U-Boot] [PATCH v3 16/19] lib: fdtdec: Add function re-setup the fdt more effeciently

Jean-Jacques Hiblot jjhiblot at ti.com
Mon Oct 22 14:12:54 UTC 2018


In some cases it may be useful to be able to change the fdt we have been
using and use another one instead. For example, the TI platforms uses an
EEPROM to store board information and, based on the type of board,
different dtbs are used by the SPL. When DM_I2C is used, a first dtb must
be used before the I2C is initialized and only then the final dtb can be
selected.
To speed up the process and reduce memory usage, introduce a new function
fdtdec_setup_best_match() that re-use the DTBs loaded in memory by
fdtdec_setup() to select the best match.

Signed-off-by: Jean-Jacques Hiblot <jjhiblot at ti.com>

---

Changes in v3:
- fdtdec_resetup() need not call fdtdec_setup() when only a single DTB is
  used.
- Add documentation in README-fdt-control explaining why and how to use
  fdtdec_resetup()

Changes in v2: None

 doc/README.fdt-control            | 18 ++++++++++++++++
 include/asm-generic/global_data.h |  4 ++++
 include/fdtdec.h                  | 21 +++++++++++++++++++
 lib/fdtdec.c                      | 43 ++++++++++++++++++++++++++++++++++++++-
 4 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/doc/README.fdt-control b/doc/README.fdt-control
index d6ab7bf..446401c 100644
--- a/doc/README.fdt-control
+++ b/doc/README.fdt-control
@@ -184,6 +184,24 @@ The full device tree is available to U-Boot proper, but normally only a subset
 'SPL Support' in doc/driver-model/README.txt for more details.
 
 
+Using several DTBs in the SPL (CONFIG_SPL_MULTI_DTB)
+----------------------------------------------------
+In some rare cases it is desirable to let SPL be able to select one DTB among
+many. This usually not very useful as the DTB for the SPL is small and usually
+fits several platforms. However the DTB sometimes include information that do
+work on several platforms (like IO tuning parameters).
+In this case it is possible to use CONFIG_SPL_MULTI_DTB. This option appends to
+the SPL a FIT image containing several DTBs listed in SPL_OF_LIST.
+board_fit_config_name_match() is called to select the right DTB.
+
+If board_fit_config_name_match() relies on DM (DM driver to access an EEPROM
+containing the board ID for example), it possible to start with a generic DTB
+and then switch over to the right DTB after the detection. For this purpose,
+the platform code must call fdtdec_resetup(). Based on the returned flag, the
+platform may have to re-initiliaze the DM subusystem using dm_uninit() and
+dm_init_and_scan().
+
+
 Limitations
 -----------
 
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index c83fc01..a23aaee 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -77,6 +77,10 @@ typedef struct global_data {
 #ifdef CONFIG_OF_LIVE
 	struct device_node *of_root;
 #endif
+
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+	const void *multi_dtb_fit;	/* uncompressed multi-dtb FIT image */
+#endif
 	struct jt_funcs *jt;		/* jump table */
 	char env_buf[32];		/* buffer for env_get() before reloc. */
 #ifdef CONFIG_TRACE
diff --git a/include/fdtdec.h b/include/fdtdec.h
index c26df50..d414ba2 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -951,6 +951,27 @@ int fdtdec_setup_memory_banksize(void);
  */
 int fdtdec_setup(void);
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+/**
+ * fdtdec_resetup()  - Set up the device tree again
+ *
+ * The main difference with fdtdec_setup() is that it returns if the fdt has
+ * changed because a better match has been found.
+ * This is typically used for boards that rely on a DM driver to detect the
+ * board type. This function sould be called by the board code after the stuff
+ * needed by board_fit_config_name_match() to operate porperly is available.
+ * If this functions signals that a rescan is necessary, the board code must
+ * unbind all the drivers using dm_uninit() and then rescan the DT with
+ * dm_init_and_scan().
+ *
+ * @param rescan Returns a flag indicating that fdt has changed and rescanning
+ *               the fdt is required
+ *
+ * @return 0 if OK, -ve on error
+ */
+int fdtdec_resetup(int *rescan);
+#endif
+
 /**
  * Board-specific FDT initialization. Returns the address to a device tree blob.
  * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index a420ba1..7fe2fd8 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1272,14 +1272,55 @@ int fdtdec_setup(void)
 	 * If so, pick the most relevant
 	 */
 	fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
-	if (fdt_blob)
+	if (fdt_blob) {
+		gd->multi_dtb_fit = gd->fdt_blob;
 		gd->fdt_blob = fdt_blob;
+	}
+
 # endif
 #endif
 
 	return fdtdec_prepare_fdt();
 }
 
+#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
+int fdtdec_resetup(int *rescan)
+{
+	void *fdt_blob;
+
+	/*
+	 * If the current DTB is part of a compressed FIT image,
+	 * try to locate the best match from the uncompressed
+	 * FIT image stillpresent there. Save the time and space
+	 * required to uncompress it again.
+	 */
+	if (gd->multi_dtb_fit) {
+		fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit);
+
+		if (fdt_blob == gd->fdt_blob) {
+			/*
+			 * The best match did not change. no need to tear down
+			 * the DM and rescan the fdt.
+			 */
+			*rescan = 0;
+			return 0;
+		}
+
+		*rescan = 1;
+		gd->fdt_blob = fdt_blob;
+		return fdtdec_prepare_fdt();
+	}
+
+	/*
+	 * If multi_dtb_fit is NULL, it means that blob appended to u-boot is
+	 * not a FIT image containings DTB, but a single DTB. There is no need
+	 * to teard down DM and rescan the DT in this case.
+	 */
+	*rescan = 0;
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_NR_DRAM_BANKS
 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
 			   phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)
-- 
2.7.4



More information about the U-Boot mailing list