diff options
-rw-r--r-- | board/purism/librem5/librem5.c | 2 | ||||
-rw-r--r-- | cmd/mmc.c | 18 | ||||
-rw-r--r-- | cmd/mvebu/bubt.c | 3 | ||||
-rw-r--r-- | common/spl/spl_mmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 3 | ||||
-rw-r--r-- | drivers/mmc/mmc_write.c | 34 | ||||
-rw-r--r-- | drivers/mmc/mv_sdhci.c | 55 | ||||
-rw-r--r-- | include/mmc.h | 4 | ||||
-rw-r--r-- | test/dm/mmc.c | 14 |
10 files changed, 63 insertions, 73 deletions
diff --git a/board/purism/librem5/librem5.c b/board/purism/librem5/librem5.c index caa0265..386ed1b 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; @@ -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 49797b2..37ff9c4 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 bd5e6ad..a072216 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 80641e1..59fb0fb 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 dde251c..1af6af8 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 5b7aeeb..a6f9338 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 336ebf1..dbdd671 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 36dd841..b8fbff1 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 f744452..b1eb8be 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; |