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
> 

Reply via email to