aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2023-04-10 08:32:11 -0400
committerTom Rini <trini@konsulko.com>2023-04-10 08:32:11 -0400
commit11c25c6df0b56ee7eee2c4ddc7f075880daeb8c7 (patch)
treee4660057ce4770ebd72f05a365b01240b10a467c
parent7daa8dd59bc8455a43cdd2d0e34206e406e5cdcc (diff)
parentfbf368f176641029ac30843d4d3dbf26e384df38 (diff)
Merge https://source.denx.de/u-boot/custodians/u-boot-mmc
-rw-r--r--board/purism/librem5/librem5.c2
-rw-r--r--cmd/mmc.c18
-rw-r--r--cmd/mvebu/bubt.c3
-rw-r--r--common/spl/spl_mmc.c2
-rw-r--r--drivers/mmc/Kconfig1
-rw-r--r--drivers/mmc/mmc.c3
-rw-r--r--drivers/mmc/mmc_write.c34
-rw-r--r--drivers/mmc/mv_sdhci.c55
-rw-r--r--include/mmc.h4
-rw-r--r--test/dm/mmc.c14
10 files changed, 63 insertions, 73 deletions
diff --git a/board/purism/librem5/librem5.c b/board/purism/librem5/librem5.c
index caa02655fc4..386ed1b4fb2 100644
--- a/board/purism/librem5/librem5.c
+++ b/board/purism/librem5/librem5.c
@@ -41,7 +41,7 @@ int board_early_init_f(void)
#if IS_ENABLED(CONFIG_LOAD_ENV_FROM_MMC_BOOT_PARTITION)
uint board_mmc_get_env_part(struct mmc *mmc)
{
- uint part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+ uint part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
if (part == 7)
part = 0;
diff --git a/cmd/mmc.c b/cmd/mmc.c
index 94deb9a1686..c6bd81cebbc 100644
--- a/cmd/mmc.c
+++ b/cmd/mmc.c
@@ -175,7 +175,7 @@ static int do_mmcinfo(struct cmd_tbl *cmdtp, int flag, int argc,
curr_device = 0;
else {
puts("No MMC device available\n");
- return 1;
+ return CMD_RET_FAILURE;
}
}
@@ -927,7 +927,7 @@ static int mmc_partconf_print(struct mmc *mmc, const char *varname)
static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
{
- int dev;
+ int ret, dev;
struct mmc *mmc;
u8 ack, part_num, access;
@@ -953,13 +953,17 @@ static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag,
access = dectoul(argv[4], NULL);
/* acknowledge to be sent during boot operation */
- return mmc_set_part_conf(mmc, ack, part_num, access);
+ ret = mmc_set_part_conf(mmc, ack, part_num, access);
+ if (ret != 0)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
static int do_mmc_rst_func(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[])
{
- int dev;
+ int ret, dev;
struct mmc *mmc;
u8 enable;
@@ -988,7 +992,11 @@ static int do_mmc_rst_func(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_FAILURE;
}
- return mmc_set_rst_n_function(mmc, enable);
+ ret = mmc_set_rst_n_function(mmc, enable);
+ if (ret != 0)
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
}
#endif
static int do_mmc_setdsr(struct cmd_tbl *cmdtp, int flag,
diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c
index 49797b23144..37ff9c45522 100644
--- a/cmd/mvebu/bubt.c
+++ b/cmd/mvebu/bubt.c
@@ -223,8 +223,7 @@ static int mmc_burn_image(size_t image_size)
orig_part = mmc->block_dev.hwpart;
#endif
- part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
-
+ part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
if (part == 7)
part = 0;
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index bd5e6adf1ea..a0722167044 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -378,7 +378,7 @@ int default_spl_mmc_emmc_boot_partition(struct mmc *mmc)
* 1 and 2 match up to boot0 / boot1 and 7 is user data
* which is the first physical partition (0).
*/
- part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
+ part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
if (part == 7)
part = 0;
#endif
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 80641e13930..59fb0fb50fb 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -621,6 +621,7 @@ config MMC_SDHCI_MV
bool "SDHCI support on Marvell platform"
depends on ARCH_MVEBU
depends on MMC_SDHCI
+ depends on DM_MMC
help
This selects the Secure Digital Host Controller Interface on
Marvell platform.
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index dde251c87bc..1af6af82e6b 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -2432,6 +2432,9 @@ static int mmc_startup_v4(struct mmc *mmc)
mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET];
+ mmc->can_trim =
+ !!(ext_csd[EXT_CSD_SEC_FEATURE] & EXT_CSD_SEC_FEATURE_TRIM_EN);
+
return 0;
error:
if (mmc->ext_csd) {
diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c
index 5b7aeeb0121..a6f93380dd0 100644
--- a/drivers/mmc/mmc_write.c
+++ b/drivers/mmc/mmc_write.c
@@ -15,7 +15,7 @@
#include <linux/math64.h>
#include "mmc_private.h"
-static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
+static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt, u32 args)
{
struct mmc_cmd cmd;
ulong end;
@@ -52,7 +52,7 @@ static ulong mmc_erase_t(struct mmc *mmc, ulong start, lbaint_t blkcnt)
goto err_out;
cmd.cmdidx = MMC_CMD_ERASE;
- cmd.cmdarg = MMC_ERASE_ARG;
+ cmd.cmdarg = args ? args : MMC_ERASE_ARG;
cmd.resp_type = MMC_RSP_R1b;
err = mmc_send_cmd(mmc, &cmd, NULL);
@@ -77,7 +77,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
#endif
int dev_num = block_dev->devnum;
int err = 0;
- u32 start_rem, blkcnt_rem;
+ u32 start_rem, blkcnt_rem, erase_args = 0;
struct mmc *mmc = find_mmc_device(dev_num);
lbaint_t blk = 0, blk_r = 0;
int timeout_ms = 1000;
@@ -97,13 +97,25 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
*/
err = div_u64_rem(start, mmc->erase_grp_size, &start_rem);
err = div_u64_rem(blkcnt, mmc->erase_grp_size, &blkcnt_rem);
- if (start_rem || blkcnt_rem)
- printf("\n\nCaution! Your devices Erase group is 0x%x\n"
- "The erase range would be change to "
- "0x" LBAF "~0x" LBAF "\n\n",
- mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
- ((start + blkcnt + mmc->erase_grp_size - 1)
- & ~(mmc->erase_grp_size - 1)) - 1);
+ if (start_rem || blkcnt_rem) {
+ if (mmc->can_trim) {
+ /* Trim function applies the erase operation to write
+ * blocks instead of erase groups.
+ */
+ erase_args = MMC_TRIM_ARG;
+ } else {
+ /* The card ignores all LSB's below the erase group
+ * size, rounding down the addess to a erase group
+ * boundary.
+ */
+ printf("\n\nCaution! Your devices Erase group is 0x%x\n"
+ "The erase range would be change to "
+ "0x" LBAF "~0x" LBAF "\n\n",
+ mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
+ ((start + blkcnt + mmc->erase_grp_size - 1)
+ & ~(mmc->erase_grp_size - 1)) - 1);
+ }
+ }
while (blk < blkcnt) {
if (IS_SD(mmc) && mmc->ssr.au) {
@@ -113,7 +125,7 @@ ulong mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt)
blk_r = ((blkcnt - blk) > mmc->erase_grp_size) ?
mmc->erase_grp_size : (blkcnt - blk);
}
- err = mmc_erase_t(mmc, start + blk, blk_r);
+ err = mmc_erase_t(mmc, start + blk, blk_r, erase_args);
if (err)
break;
diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c
index 336ebf14102..dbdd671c88b 100644
--- a/drivers/mmc/mv_sdhci.c
+++ b/drivers/mmc/mv_sdhci.c
@@ -15,6 +15,13 @@
#define SDHCI_WINDOW_CTRL(win) (0x4080 + ((win) << 4))
#define SDHCI_WINDOW_BASE(win) (0x4084 + ((win) << 4))
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mv_sdhci_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
static void sdhci_mvebu_mbus_config(void __iomem *base)
{
const struct mbus_dram_target_info *dram;
@@ -40,47 +47,6 @@ static void sdhci_mvebu_mbus_config(void __iomem *base)
}
}
-#ifndef CONFIG_DM_MMC
-
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
-static struct sdhci_ops mv_ops;
-#endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */
-
-int mv_sdh_init(unsigned long regbase, u32 max_clk, u32 min_clk, u32 quirks)
-{
- struct sdhci_host *host = NULL;
- host = calloc(1, sizeof(*host));
- if (!host) {
- printf("sdh_host malloc fail!\n");
- return -ENOMEM;
- }
-
- host->name = MVSDH_NAME;
- host->ioaddr = (void *)regbase;
- host->quirks = quirks;
- host->max_clk = max_clk;
-#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
- memset(&mv_ops, 0, sizeof(struct sdhci_ops));
- host->ops = &mv_ops;
-#endif
-
- if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
- /* Configure SDHCI MBUS mbus bridge windows */
- sdhci_mvebu_mbus_config((void __iomem *)regbase);
- }
-
- return add_sdhci(host, 0, min_clk);
-}
-
-#else
-
-DECLARE_GLOBAL_DATA_PTR;
-
-struct mv_sdhci_plat {
- struct mmc_config cfg;
- struct mmc mmc;
-};
-
static int mv_sdhci_probe(struct udevice *dev)
{
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
@@ -103,10 +69,8 @@ static int mv_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
- if (CONFIG_IS_ENABLED(ARCH_MVEBU)) {
- /* Configure SDHCI MBUS mbus bridge windows */
- sdhci_mvebu_mbus_config(host->ioaddr);
- }
+ /* Configure SDHCI MBUS mbus bridge windows */
+ sdhci_mvebu_mbus_config(host->ioaddr);
upriv->mmc = host->mmc;
@@ -135,4 +99,3 @@ U_BOOT_DRIVER(mv_sdhci_drv) = {
.priv_auto = sizeof(struct sdhci_host),
.plat_auto = sizeof(struct mv_sdhci_plat),
};
-#endif /* CONFIG_DM_MMC */
diff --git a/include/mmc.h b/include/mmc.h
index 36dd841d5d1..b8fbff150de 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -241,6 +241,7 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
#define EXT_CSD_BOOT_MULT 226 /* RO */
+#define EXT_CSD_SEC_FEATURE 231 /* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
@@ -315,6 +316,8 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx)
#define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */
#define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */
+#define EXT_CSD_SEC_FEATURE_TRIM_EN (1 << 4) /* Support secure & insecure trim */
+
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5)
@@ -687,6 +690,7 @@ struct mmc {
uint tran_speed;
uint legacy_speed; /* speed for the legacy mode provided by the card */
uint read_bl_len;
+ bool can_trim;
#if CONFIG_IS_ENABLED(MMC_WRITE)
uint write_bl_len;
uint erase_grp_size; /* in 512-byte sectors */
diff --git a/test/dm/mmc.c b/test/dm/mmc.c
index f744452ff24..b1eb8bee2f9 100644
--- a/test/dm/mmc.c
+++ b/test/dm/mmc.c
@@ -30,7 +30,7 @@ static int dm_test_mmc_blk(struct unit_test_state *uts)
struct udevice *dev;
struct blk_desc *dev_desc;
int i;
- char write[1024], read[1024];
+ char write[4 * 512], read[4 * 512];
ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
ut_assertok(blk_get_device_by_str("mmc", "0", &dev_desc));
@@ -39,14 +39,14 @@ static int dm_test_mmc_blk(struct unit_test_state *uts)
ut_asserteq(512, dev_desc->blksz);
for (i = 0; i < sizeof(write); i++)
write[i] = i;
- ut_asserteq(2, blk_dwrite(dev_desc, 0, 2, write));
- ut_asserteq(2, blk_dread(dev_desc, 0, 2, read));
+ ut_asserteq(4, blk_dwrite(dev_desc, 0, 4, write));
+ ut_asserteq(4, blk_dread(dev_desc, 0, 4, read));
ut_asserteq_mem(write, read, sizeof(write));
- /* Now erase them */
- memset(write, '\0', sizeof(write));
- ut_asserteq(2, blk_derase(dev_desc, 0, 2));
- ut_asserteq(2, blk_dread(dev_desc, 0, 2, read));
+ /* Now erase two of them [1 - 2] and verify all blocks */
+ memset(&write[512], '\0', 2 * 512);
+ ut_asserteq(2, blk_derase(dev_desc, 1, 2));
+ ut_asserteq(4, blk_dread(dev_desc, 0, 4, read));
ut_asserteq_mem(write, read, sizeof(write));
return 0;