On 1/24/20 8:52 PM, Faiz Abbas wrote: > 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_ab...@ti.com> > Signed-off-by: Lokesh Vutla <lokeshvu...@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 --git a/arch/arm/mach-k3/am6_init.c b/arch/arm/mach-k3/am6_init.c > index 8d107b870b..9d3c62b3f4 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) > @@ -128,7 +156,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);
Use MMC_CLK_DISABLE instead of 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); ditto. > + } > +} > +#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 5903bbe12a..8386499ed6 100644 > --- a/arch/arm/mach-k3/sysfw-loader.c > +++ b/arch/arm/mach-k3/sysfw-loader.c > @@ -172,7 +172,8 @@ static void k3_sysfw_configure_using_fit(void *fit, > ret); > } > > -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 }; > @@ -264,6 +265,9 @@ void k3_sysfw_loader(void > (*config_pm_done_callback)(void)) > /* Parse and apply the different SYSFW configuration fragments */ > k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci); > > + if (config_pm_pre_callback) > + config_pm_pre_callback(); > + > /* > * Now that all clocks and PM aspects are setup, invoke a user- > * provided callback function. Usually this callback would be used >