Message ID | 20200124115252.15712-9-faiz_abbas@ti.com |
---|---|
State | New |
Headers | show |
Series | Add Support for eMMC boot in AM65x and J721e | expand |
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_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 --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 >
Hi, On 29/01/20 5:00 am, Jaehoon Chung wrote: > 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_abbas at ti.com> >> Signed-off-by: Lokesh Vutla <lokeshvutla at ti.com> >> --- >> >> +#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. Ok. > >> + } >> +} >> + >> +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. Ok. Thanks, Faiz
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); + } +} + +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 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