mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-11 15:37:23 +00:00
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:
parent
cf00825596
commit
d45ffb7937
4 changed files with 70 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue