diff mbox series

[v3,08/11] arm: K3: sysfw-loader: Add a config_pm_pre_callback()

Message ID 20200226081439.15994-9-faiz_abbas@ti.com
State Superseded
Headers show
Series Add Support for eMMC boot in AM65x and J721e | expand

Commit Message

Faiz Abbas Feb. 26, 2020, 8:14 a.m. UTC
System firmware does not guarantee that clocks going out of the device
will be stable during power management configuration. There are some
DCRC errors when SPL tries to get the next stage during eMMC boot after
sysfw pm configuration.

Therefore add a config_pm_pre_callback() to switch off the eMMC clock
before power management and restart it after it is done.

Signed-off-by: Faiz Abbas <faiz_abbas at ti.com>
Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com>
---
 arch/arm/mach-k3/am6_init.c                  | 33 +++++++++++++++++++-
 arch/arm/mach-k3/include/mach/sysfw-loader.h |  2 +-
 arch/arm/mach-k3/j721e_init.c                | 33 +++++++++++++++++++-
 arch/arm/mach-k3/sysfw-loader.c              |  6 +++-
 4 files changed, 70 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c
index 63cd7e0458..d0b10e58ad 100644
--- a/arch/arm/mach-k3/am6_init.c
+++ b/arch/arm/mach-k3/am6_init.c
@@ -17,6 +17,7 @@ 
 #include <dm/uclass-internal.h>
 #include <dm/pinctrl.h>
 #include <linux/soc/ti/ti_sci_protocol.h>
+#include <mmc.h>
 
 #ifdef CONFIG_SPL_BUILD
 #ifdef CONFIG_K3_LOAD_SYSFW
@@ -86,6 +87,33 @@  static void store_boot_index_from_rom(void)
 	bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
 }
 
+#if defined(CONFIG_K3_LOAD_SYSFW)
+void k3_mmc_stop_clock(void)
+{
+	if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+		struct mmc *mmc = find_mmc_device(0);
+
+		if (!mmc)
+			return;
+
+		mmc->saved_clock = mmc->clock;
+		mmc_set_clock(mmc, 0, true);
+	}
+}
+
+void k3_mmc_restart_clock(void)
+{
+	if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+		struct mmc *mmc = find_mmc_device(0);
+
+		if (!mmc)
+			return;
+
+		mmc_set_clock(mmc, mmc->saved_clock, false);
+	}
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
 #if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
@@ -138,7 +166,10 @@  void board_init_f(ulong dummy)
 	 * callback hook, effectively switching on (or over) the console
 	 * output.
 	 */
-	k3_sysfw_loader(preloader_console_init);
+	k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
+
+	/* Prepare console output */
+	preloader_console_init();
 
 	/* Disable ROM configured firewalls right after loading sysfw */
 #ifdef CONFIG_TI_SECURE_DEVICE
diff --git a/arch/arm/mach-k3/include/mach/sysfw-loader.h b/arch/arm/mach-k3/include/mach/sysfw-loader.h
index 36eb265348..6f5612b4fd 100644
--- a/arch/arm/mach-k3/include/mach/sysfw-loader.h
+++ b/arch/arm/mach-k3/include/mach/sysfw-loader.h
@@ -7,6 +7,6 @@ 
 #ifndef _SYSFW_LOADER_H_
 #define _SYSFW_LOADER_H_
 
-void k3_sysfw_loader(void (*config_pm_done_callback)(void));
+void k3_sysfw_loader(void (*config_pm_pre_callback)(void), void (*config_pm_done_callback)(void));
 
 #endif
diff --git a/arch/arm/mach-k3/j721e_init.c b/arch/arm/mach-k3/j721e_init.c
index f7f7398081..0994522f6c 100644
--- a/arch/arm/mach-k3/j721e_init.c
+++ b/arch/arm/mach-k3/j721e_init.c
@@ -18,6 +18,7 @@ 
 #include <dm.h>
 #include <dm/uclass-internal.h>
 #include <dm/pinctrl.h>
+#include <mmc.h>
 
 #ifdef CONFIG_SPL_BUILD
 #ifdef CONFIG_K3_LOAD_SYSFW
@@ -100,6 +101,33 @@  static void ctrl_mmr_unlock(void)
 	mmr_unlock(CTRL_MMR0_BASE, 7);
 }
 
+#if defined(CONFIG_K3_LOAD_SYSFW)
+void k3_mmc_stop_clock(void)
+{
+	if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+		struct mmc *mmc = find_mmc_device(0);
+
+		if (!mmc)
+			return;
+
+		mmc->saved_clock = mmc->clock;
+		mmc_set_clock(mmc, 0, true);
+	}
+}
+
+void k3_mmc_restart_clock(void)
+{
+	if (spl_boot_device() == BOOT_DEVICE_MMC1) {
+		struct mmc *mmc = find_mmc_device(0);
+
+		if (!mmc)
+			return;
+
+		mmc_set_clock(mmc, mmc->saved_clock, false);
+	}
+}
+#endif
+
 /*
  * This uninitialized global variable would normal end up in the .bss section,
  * but the .bss is cleared between writing and reading this variable, so move
@@ -154,7 +182,10 @@  void board_init_f(ulong dummy)
 	 * callback hook, effectively switching on (or over) the console
 	 * output.
 	 */
-	k3_sysfw_loader(preloader_console_init);
+	k3_sysfw_loader(k3_mmc_stop_clock, k3_mmc_restart_clock);
+
+	/* Prepare console output */
+	preloader_console_init();
 
 	/* Disable ROM configured firewalls right after loading sysfw */
 #ifdef CONFIG_TI_SECURE_DEVICE
diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c
index 94dbeb9437..db02607b17 100644
--- a/arch/arm/mach-k3/sysfw-loader.c
+++ b/arch/arm/mach-k3/sysfw-loader.c
@@ -197,7 +197,8 @@  exit:
 }
 #endif
 
-void k3_sysfw_loader(void (*config_pm_done_callback)(void))
+void k3_sysfw_loader(void (*config_pm_pre_callback) (void),
+		     void (*config_pm_done_callback)(void))
 {
 	struct spl_image_info spl_image = { 0 };
 	struct spl_boot_device bootdev = { 0 };
@@ -291,6 +292,9 @@  void k3_sysfw_loader(void (*config_pm_done_callback)(void))
 	/* Get handle for accessing SYSFW services */
 	ti_sci = get_ti_sci_handle();
 
+	if (config_pm_pre_callback)
+		config_pm_pre_callback();
+
 	/* Parse and apply the different SYSFW configuration fragments */
 	k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);