arm: K3: sysfw-loader: Add a config_pm_pre_callback()

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@ti.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
This commit is contained in:
Faiz Abbas 2020-02-26 13:44:36 +05:30 committed by Peng Fan
parent cf00825596
commit d45ffb7937
4 changed files with 70 additions and 4 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);