mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-04 20:26:13 +02:00
Merge tag 'mmc-2025-04-11' of https://source.denx.de/u-boot/custodians/u-boot-mmc
CI: https://source.denx.de/u-boot/custodians/u-boot-mmc/-/pipelines/25640 - Support Sandisk and Micron eMMC BOOT/RPMB hardware partition resizing - Optimize eMMC erasing time - Simplify poll CD logic - Fix possible Synchronous Abort for sdhci - Kconfig dependencies fix - Minor code update, return fail if mmc_complete_init, avoid uniniting twice
This commit is contained in:
commit
048266be42
@ -528,6 +528,7 @@ config SPL_MMC_SDHCI_ADMA
|
||||
|
||||
config MMC_SDHCI_ADMA_FORCE_32BIT
|
||||
bool "Force 32 bit mode for ADMA on 64 bit platforms"
|
||||
depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA
|
||||
help
|
||||
This forces SDHCI ADMA to be built for 32 bit descriptors, even
|
||||
on a 64 bit platform where they would otherwise be assumed to
|
||||
@ -537,6 +538,7 @@ config MMC_SDHCI_ADMA_FORCE_32BIT
|
||||
|
||||
config MMC_SDHCI_ADMA_64BIT
|
||||
bool "Use SHDCI ADMA with 64 bit descriptors"
|
||||
depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA
|
||||
depends on !MMC_SDHCI_ADMA_FORCE_32BIT
|
||||
default y if DMA_ADDR_T_64BIT
|
||||
help
|
||||
|
||||
@ -498,22 +498,12 @@ static int mmc_blk_probe(struct udevice *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_probe(dev);
|
||||
if (ret) {
|
||||
debug("Probing %s failed (err=%d)\n", dev->name, ret);
|
||||
|
||||
mmc_deinit(mmc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_blk_remove(struct udevice *dev)
|
||||
static int mmc_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_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||
struct mmc *mmc = upriv->mmc;
|
||||
|
||||
return mmc_deinit(mmc);
|
||||
@ -533,7 +523,6 @@ U_BOOT_DRIVER(mmc_blk) = {
|
||||
.id = UCLASS_BLK,
|
||||
.ops = &mmc_blk_ops,
|
||||
.probe = mmc_blk_probe,
|
||||
.remove = mmc_blk_remove,
|
||||
.flags = DM_FLAG_OS_PREPARE,
|
||||
};
|
||||
#endif /* CONFIG_BLK */
|
||||
@ -543,4 +532,5 @@ UCLASS_DRIVER(mmc) = {
|
||||
.name = "mmc",
|
||||
.flags = DM_UC_FLAG_SEQ_ALIAS,
|
||||
.per_device_auto = sizeof(struct mmc_uclass_priv),
|
||||
.pre_remove = mmc_remove,
|
||||
};
|
||||
|
||||
@ -3040,9 +3040,9 @@ static int mmc_complete_init(struct mmc *mmc)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __maybe_unused mmc_cyclic_cd_poll(struct cyclic_info *c)
|
||||
static void mmc_cyclic_cd_poll(struct cyclic_info *c)
|
||||
{
|
||||
struct mmc *m = CONFIG_IS_ENABLED(CYCLIC, (container_of(c, struct mmc, cyclic)), (NULL));
|
||||
struct mmc *m = container_of(c, struct mmc, cyclic);
|
||||
|
||||
if (!m->has_init)
|
||||
return;
|
||||
@ -3073,15 +3073,15 @@ int mmc_init(struct mmc *mmc)
|
||||
|
||||
if (!err)
|
||||
err = mmc_complete_init(mmc);
|
||||
if (err)
|
||||
if (err) {
|
||||
pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start));
|
||||
return err;
|
||||
}
|
||||
|
||||
if (CONFIG_IS_ENABLED(CYCLIC, (!mmc->cyclic.func), (NULL))) {
|
||||
/* Register cyclic function for card detect polling */
|
||||
CONFIG_IS_ENABLED(CYCLIC, (cyclic_register(&mmc->cyclic,
|
||||
mmc_cyclic_cd_poll,
|
||||
100 * 1000,
|
||||
mmc->cfg->name)));
|
||||
cyclic_register(&mmc->cyclic, mmc_cyclic_cd_poll, 100 * 1000,
|
||||
mmc->cfg->name);
|
||||
}
|
||||
|
||||
return err;
|
||||
@ -3092,7 +3092,7 @@ int mmc_deinit(struct mmc *mmc)
|
||||
u32 caps_filtered;
|
||||
|
||||
if (CONFIG_IS_ENABLED(CYCLIC, (mmc->cyclic.func), (NULL)))
|
||||
CONFIG_IS_ENABLED(CYCLIC, (cyclic_unregister(&mmc->cyclic)));
|
||||
cyclic_unregister(&mmc->cyclic);
|
||||
|
||||
if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) &&
|
||||
!CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) &&
|
||||
|
||||
@ -8,20 +8,107 @@
|
||||
#include <mmc.h>
|
||||
#include "mmc_private.h"
|
||||
|
||||
/*
|
||||
* This function changes the size of boot partition and the size of rpmb
|
||||
* partition present on EMMC devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* struct *mmc: pointer for the mmc device strcuture
|
||||
* bootsize: size of boot partition
|
||||
* rpmbsize: size of rpmb partition
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
static int mmc_resize_boot_micron(struct mmc *mmc, unsigned long bootsize,
|
||||
unsigned long rpmbsize)
|
||||
{
|
||||
int err;
|
||||
|
||||
int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
unsigned long rpmbsize)
|
||||
/* Micron eMMC doesn't support resizing RPMB partition */
|
||||
(void)rpmbsize;
|
||||
|
||||
/* BOOT partition size is multiple of 128KB */
|
||||
bootsize = (bootsize * 1024) / 128;
|
||||
|
||||
if (bootsize > 0xff)
|
||||
bootsize = 0xff;
|
||||
|
||||
/* Set EXT_CSD[175] ERASE_GROUP_DEF to 0x01 */
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_ERASE_GROUP_DEF, 0x01);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Set EXT_CSD[127:125] for BOOT partition size, [125] is low byte */
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BOOT_SIZE_MULT_MICRON, bootsize);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BOOT_SIZE_MULT_MICRON + 1, 0x00);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BOOT_SIZE_MULT_MICRON + 2, 0x00);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Set EXT_CSD[155] PARTITION_SETTING_COMPLETE to 0x01 */
|
||||
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_PARTITION_SETTING, 0x01);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
debug("%s: Error = %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mmc_resize_boot_sandisk(struct mmc *mmc, unsigned long bootsize,
|
||||
unsigned long rpmbsize)
|
||||
{
|
||||
int err;
|
||||
struct mmc_cmd cmd;
|
||||
|
||||
/* BOOT/RPMB partition size is multiple of 128KB */
|
||||
bootsize = (bootsize * 1024) / 128;
|
||||
rpmbsize = (rpmbsize * 1024) / 128;
|
||||
|
||||
if (bootsize > 0xff)
|
||||
bootsize = 0xff;
|
||||
|
||||
if (rpmbsize > 0xff)
|
||||
rpmbsize = 0xff;
|
||||
|
||||
/* Send BOOT/RPMB resize op code */
|
||||
cmd.cmdidx = MMC_CMD_RES_MAN;
|
||||
cmd.resp_type = MMC_RSP_R1b;
|
||||
cmd.cmdarg = MMC_CMD62_ARG_SANDISK;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Arg: BOOT partition size */
|
||||
cmd.cmdidx = MMC_CMD_RES_MAN;
|
||||
cmd.resp_type = MMC_RSP_R1b;
|
||||
cmd.cmdarg = bootsize;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Arg: RPMB partition size */
|
||||
cmd.cmdidx = MMC_CMD_RES_MAN;
|
||||
cmd.resp_type = MMC_RSP_R1b;
|
||||
cmd.cmdarg = rpmbsize;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
debug("%s: Error = %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mmc_resize_boot_samsung(struct mmc *mmc, unsigned long bootsize,
|
||||
unsigned long rpmbsize)
|
||||
{
|
||||
int err;
|
||||
struct mmc_cmd cmd;
|
||||
@ -32,10 +119,8 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
cmd.cmdarg = MMC_CMD62_ARG1;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err) {
|
||||
debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* Boot partition changing mode */
|
||||
cmd.cmdidx = MMC_CMD_RES_MAN;
|
||||
@ -43,10 +128,9 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
cmd.cmdarg = MMC_CMD62_ARG2;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err) {
|
||||
debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* boot partition size is multiple of 128KB */
|
||||
bootsize = (bootsize * 1024) / 128;
|
||||
|
||||
@ -56,10 +140,9 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
cmd.cmdarg = bootsize;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err) {
|
||||
debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
/* RPMB partition size is multiple of 128KB */
|
||||
rpmbsize = (rpmbsize * 1024) / 128;
|
||||
/* Arg: RPMB partition size */
|
||||
@ -68,11 +151,43 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
cmd.cmdarg = rpmbsize;
|
||||
|
||||
err = mmc_send_cmd(mmc, &cmd, NULL);
|
||||
if (err) {
|
||||
debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
debug("%s: Error = %d\n", __func__, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function changes the size of BOOT partition and the size of RPMB
|
||||
* partition present on eMMC devices.
|
||||
*
|
||||
* Input Parameters:
|
||||
* struct *mmc: pointer for the mmc device strcuture
|
||||
* bootsize: size of BOOT partition
|
||||
* rpmbsize: size of RPMB partition
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
|
||||
int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
|
||||
unsigned long rpmbsize)
|
||||
{
|
||||
switch (mmc->cid[0] >> 24) {
|
||||
case CID_MANFID_MICRON:
|
||||
return mmc_resize_boot_micron(mmc, bootsize, rpmbsize);
|
||||
case CID_MANFID_SAMSUNG:
|
||||
return mmc_resize_boot_samsung(mmc, bootsize, rpmbsize);
|
||||
case CID_MANFID_SANDISK:
|
||||
return mmc_resize_boot_sandisk(mmc, bootsize, rpmbsize);
|
||||
default:
|
||||
printf("Unsupported manufacturer id 0x%02x\n",
|
||||
mmc->cid[0] >> 24);
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -80,6 +80,8 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
|
||||
struct mmc *mmc = find_mmc_device(dev_num);
|
||||
lbaint_t blk = 0, blk_r = 0;
|
||||
int timeout_ms = 1000;
|
||||
u32 grpcnt;
|
||||
|
||||
|
||||
if (!mmc)
|
||||
return -1;
|
||||
@ -123,6 +125,15 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
|
||||
} else {
|
||||
blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
|
||||
mmc->erase_grp_size : (blkcnt - blk);
|
||||
|
||||
grpcnt = (blkcnt - blk) / mmc->erase_grp_size;
|
||||
/* Max 2GB per spec */
|
||||
if ((blkcnt - blk) > 0x400000)
|
||||
blk_r = 0x400000;
|
||||
else if (grpcnt)
|
||||
blk_r = grpcnt * mmc->erase_grp_size;
|
||||
else
|
||||
blk_r = blkcnt - blk;
|
||||
}
|
||||
err = mmc_erase_t(mmc, start + blk, blk_r, erase_args);
|
||||
if (err)
|
||||
|
||||
@ -177,8 +177,10 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
|
||||
} while (!(stat & SDHCI_INT_DATA_END));
|
||||
|
||||
#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
|
||||
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
|
||||
mmc_get_dma_dir(data));
|
||||
if (host->flags & USE_DMA) {
|
||||
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
|
||||
mmc_get_dma_dir(data));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@ -79,6 +79,10 @@ struct bd_info;
|
||||
#define IS_SD(x) ((x)->version & SD_VERSION_SD)
|
||||
#define IS_MMC(x) ((x)->version & MMC_VERSION_MMC)
|
||||
|
||||
#define CID_MANFID_MICRON 0x13
|
||||
#define CID_MANFID_SAMSUNG 0x15
|
||||
#define CID_MANFID_SANDISK 0x45
|
||||
|
||||
#define MMC_DATA_READ 1
|
||||
#define MMC_DATA_WRITE 2
|
||||
|
||||
@ -112,6 +116,7 @@ struct bd_info;
|
||||
|
||||
#define MMC_CMD62_ARG1 0xefac62ec
|
||||
#define MMC_CMD62_ARG2 0xcbaea7
|
||||
#define MMC_CMD62_ARG_SANDISK 0x254ddec4
|
||||
|
||||
#define SD_CMD_SEND_RELATIVE_ADDR 3
|
||||
#define SD_CMD_SWITCH_FUNC 6
|
||||
@ -205,6 +210,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
#define EXT_CSD_BOOT_SIZE_MULT_MICRON 125 /* R/W, vendor specific field */
|
||||
#define EXT_CSD_ENH_START_ADDR 136 /* R/W */
|
||||
#define EXT_CSD_ENH_SIZE_MULT 140 /* R/W */
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
@ -759,7 +765,11 @@ struct mmc {
|
||||
|
||||
enum bus_mode user_speed_mode; /* input speed mode from user */
|
||||
|
||||
CONFIG_IS_ENABLED(CYCLIC, (struct cyclic_info cyclic));
|
||||
/*
|
||||
* If CONFIG_CYCLIC is not set, struct cyclic_info is
|
||||
* zero-size structure and does not add any space here.
|
||||
*/
|
||||
struct cyclic_info cyclic;
|
||||
};
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_MMC)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user