mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
mmc: Downgrade SD/MMC from UHS/HS200/HS400 modes before boot
Older kernel versions or systems which do not connect eMMC reset line properly may not be able to handle situations where either the eMMC is left in HS200/HS400 mode or SD card in UHS modes by the bootloader and may misbehave. Downgrade the eMMC to HS/HS52 mode and/or SD card to non-UHS mode before booting the kernel to allow such older kernels to work with modern U-Boot. Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com> Cc: Tom Rini <trini@konsulko.com>
This commit is contained in:
parent
d391c13c99
commit
fceea99268
3 changed files with 51 additions and 0 deletions
|
@ -368,6 +368,19 @@ static int mmc_blk_probe(struct udevice *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
static int mmc_blk_remove(struct udevice *dev)
|
||||
{
|
||||
struct udevice *mmc_dev = dev_get_parent(dev);
|
||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc_dev);
|
||||
struct mmc *mmc = upriv->mmc;
|
||||
|
||||
return mmc_deinit(mmc);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct blk_ops mmc_blk_ops = {
|
||||
.read = mmc_bread,
|
||||
#if CONFIG_IS_ENABLED(MMC_WRITE)
|
||||
|
@ -382,6 +395,12 @@ U_BOOT_DRIVER(mmc_blk) = {
|
|||
.id = UCLASS_BLK,
|
||||
.ops = &mmc_blk_ops,
|
||||
.probe = mmc_blk_probe,
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
.remove = mmc_blk_remove,
|
||||
.flags = DM_FLAG_OS_PREPARE,
|
||||
#endif
|
||||
};
|
||||
#endif /* CONFIG_BLK */
|
||||
|
||||
|
|
|
@ -2781,6 +2781,32 @@ int mmc_init(struct mmc *mmc)
|
|||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
int mmc_deinit(struct mmc *mmc)
|
||||
{
|
||||
u32 caps_filtered;
|
||||
|
||||
if (!mmc->has_init)
|
||||
return 0;
|
||||
|
||||
if (IS_SD(mmc)) {
|
||||
caps_filtered = mmc->card_caps &
|
||||
~(MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25) |
|
||||
MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
|
||||
MMC_CAP(UHS_SDR104));
|
||||
|
||||
return sd_select_mode_and_width(mmc, caps_filtered);
|
||||
} else {
|
||||
caps_filtered = mmc->card_caps &
|
||||
~(MMC_CAP(MMC_HS_200) | MMC_CAP(MMC_HS_400));
|
||||
|
||||
return mmc_select_mode_and_width(mmc, caps_filtered);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int mmc_set_dsr(struct mmc *mmc, u16 val)
|
||||
{
|
||||
mmc->dsr = val;
|
||||
|
|
|
@ -690,6 +690,12 @@ int mmc_initialize(bd_t *bis);
|
|||
int mmc_init(struct mmc *mmc);
|
||||
int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error);
|
||||
|
||||
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
|
||||
CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
|
||||
int mmc_deinit(struct mmc *mmc);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mmc_of_parse() - Parse the device tree to get the capabilities of the host
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue