X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fmmc%2Fmmc.c;h=02494db75a7d796a7779769b3a1ed14998f8c044;hb=c05ed00afb95fa5237f16962fccf5810437317bf;hp=f683b52eada39eabf3f3adbc2bfbadc9135d2f78;hpb=6891152a4596d38ac25d2fe1238e3b6a938554b8;p=oweals%2Fu-boot.git diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index f683b52ead..02494db75a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -8,12 +8,15 @@ #include #include +#include #include #include +#include #include #include #include #include +#include #include #include #include @@ -24,10 +27,6 @@ #define DEFAULT_CMD6_TIMEOUT_MS 500 static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage); -static int mmc_power_cycle(struct mmc *mmc); -#if !CONFIG_IS_ENABLED(MMC_TINY) -static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps); -#endif #if !CONFIG_IS_ENABLED(DM_MMC) @@ -136,7 +135,6 @@ const char *mmc_mode_name(enum bus_mode mode) { static const char *const names[] = { [MMC_LEGACY] = "MMC legacy", - [SD_LEGACY] = "SD Legacy", [MMC_HS] = "MMC High Speed (26MHz)", [SD_HS] = "SD High Speed (50MHz)", [UHS_SDR12] = "UHS SDR12 (25MHz)", @@ -162,7 +160,6 @@ static uint mmc_mode2freq(struct mmc *mmc, enum bus_mode mode) { static const int freqs[] = { [MMC_LEGACY] = 25000000, - [SD_LEGACY] = 25000000, [MMC_HS] = 26000000, [SD_HS] = 50000000, [MMC_HS_52] = 52000000, @@ -415,6 +412,16 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, return blkcnt; } +#if !CONFIG_IS_ENABLED(DM_MMC) +static int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt) +{ + if (mmc->cfg->ops->get_b_max) + return mmc->cfg->ops->get_b_max(mmc, dst, blkcnt); + else + return mmc->cfg->b_max; +} +#endif + #if CONFIG_IS_ENABLED(BLK) ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst) #else @@ -428,6 +435,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, int dev_num = block_dev->devnum; int err; lbaint_t cur, blocks_todo = blkcnt; + uint b_max; if (blkcnt == 0) return 0; @@ -457,9 +465,10 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, return 0; } + b_max = mmc_get_b_max(mmc, dst, blkcnt); + do { - cur = (blocks_todo > mmc->cfg->b_max) ? - mmc->cfg->b_max : blocks_todo; + cur = (blocks_todo > b_max) ? b_max : blocks_todo; if (mmc_read_blocks(mmc, dst, start, cur) != cur) { pr_debug("%s: Failed to read blocks\n", __func__); return 0; @@ -724,7 +733,7 @@ static int mmc_complete_op_cond(struct mmc *mmc) } -static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd) +int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd) { struct mmc_cmd cmd; struct mmc_data data; @@ -816,6 +825,11 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) return __mmc_switch(mmc, set, index, value, true); } +int mmc_boot_wp(struct mmc *mmc) +{ + return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 1); +} + #if !CONFIG_IS_ENABLED(MMC_TINY) static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode, bool hsdowngrade) @@ -1126,9 +1140,11 @@ int mmc_hwpart_config(struct mmc *mmc, ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1; +#if CONFIG_IS_ENABLED(MMC_WRITE) /* update erase group size to be high-capacity */ mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024; +#endif } @@ -1241,7 +1257,7 @@ static int sd_get_capabilities(struct mmc *mmc) u32 sd3_bus_mode; #endif - mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(SD_LEGACY); + mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); if (mmc_host_is_spi(mmc)) return 0; @@ -1354,7 +1370,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) return 0; switch (mode) { - case SD_LEGACY: + case MMC_LEGACY: speed = UHS_SDR12_BUS_SPEED; break; case SD_HS: @@ -1444,6 +1460,20 @@ static int sd_read_ssr(struct mmc *mmc) cmd.cmdarg = mmc->rca << 16; err = mmc_send_cmd(mmc, &cmd, NULL); +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_APP_CMD)) { + int retries = 4; + /* + * It has been seen that APP_CMD may fail on the first + * attempt, let's try a few more times + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif if (err) return err; @@ -1683,7 +1713,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = { }, #endif { - .mode = SD_LEGACY, + .mode = MMC_LEGACY, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, } }; @@ -1713,7 +1743,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) if (mmc_host_is_spi(mmc)) { mmc_set_bus_width(mmc, 1); - mmc_select_mode(mmc, SD_LEGACY); + mmc_select_mode(mmc, MMC_LEGACY); mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); return 0; } @@ -1772,7 +1802,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) error: /* revert to a safer bus speed */ - mmc_select_mode(mmc, SD_LEGACY); + mmc_select_mode(mmc, MMC_LEGACY); mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); } @@ -2549,7 +2579,7 @@ static int mmc_startup(struct mmc *mmc) #if CONFIG_IS_ENABLED(MMC_TINY) mmc_set_clock(mmc, mmc->legacy_speed, false); - mmc_select_mode(mmc, IS_SD(mmc) ? SD_LEGACY : MMC_LEGACY); + mmc_select_mode(mmc, MMC_LEGACY); mmc_set_bus_width(mmc, 1); #else if (IS_SD(mmc)) { @@ -2561,7 +2591,7 @@ static int mmc_startup(struct mmc *mmc) err = mmc_get_capabilities(mmc); if (err) return err; - mmc_select_mode_and_width(mmc, mmc->card_caps); + err = mmc_select_mode_and_width(mmc, mmc->card_caps); } #endif if (err) @@ -2755,7 +2785,8 @@ int mmc_get_op_cond(struct mmc *mmc) #ifdef CONFIG_MMC_QUIRKS mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN | - MMC_QUIRK_RETRY_SEND_CID; + MMC_QUIRK_RETRY_SEND_CID | + MMC_QUIRK_RETRY_APP_CMD; #endif err = mmc_power_cycle(mmc); @@ -2830,9 +2861,11 @@ int mmc_start_init(struct mmc *mmc) * all hosts are capable of 1 bit bus-width and able to use the legacy * timings. */ - mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(SD_LEGACY) | + mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(MMC_LEGACY) | MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT; - +#if CONFIG_IS_ENABLED(DM_MMC) + mmc_deferred_probe(mmc); +#endif #if !defined(CONFIG_MMC_BROKEN_CD) no_card = mmc_getcd(mmc) == 0; #else