X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fmmc%2Fmmc.c;h=c93089330030f07a42bd38502c4a536ffec75447;hb=2dc5165ee04dedfa88ebc9fc79c29bd56a54681d;hp=24b5e16a3bfe0ecf7aaa3c29220316aaaacc5963;hpb=aff5d3c83fb8c294b3c4b97c5b6386306b47f1a0;p=u-boot diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 24b5e16a3b..c930893300 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -22,15 +22,9 @@ #include #include "mmc_private.h" -static const unsigned int sd_au_size[] = { - 0, SZ_16K / 512, SZ_32K / 512, - SZ_64K / 512, SZ_128K / 512, SZ_256K / 512, - SZ_512K / 512, SZ_1M / 512, SZ_2M / 512, - SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, - SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, SZ_64M / 512, -}; - static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage); +static int mmc_power_cycle(struct mmc *mmc); +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps); #if CONFIG_IS_ENABLED(MMC_TINY) static struct mmc mmc_static; @@ -56,6 +50,14 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) #endif #if !CONFIG_IS_ENABLED(DM_MMC) + +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) +static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout) +{ + return -ENOSYS; +} +#endif + __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -179,16 +181,17 @@ const char *mmc_mode_name(enum bus_mode mode) 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, + [MMC_DDR_52] = 52000000, [UHS_SDR12] = 25000000, [UHS_SDR25] = 50000000, [UHS_SDR50] = 100000000, - [UHS_SDR104] = 208000000, [UHS_DDR50] = 50000000, - [MMC_HS_52] = 52000000, - [MMC_DDR_52] = 52000000, + [UHS_SDR104] = 208000000, [MMC_HS_200] = 200000000, }; @@ -205,8 +208,8 @@ static int mmc_select_mode(struct mmc *mmc, enum bus_mode mode) mmc->selected_mode = mode; mmc->tran_speed = mmc_mode2freq(mmc, mode); mmc->ddr_mode = mmc_is_mode_ddr(mode); - debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode), - mmc->tran_speed / 1000000); + pr_debug("selecting mode %s (freq : %d MHz)\n", mmc_mode_name(mode), + mmc->tran_speed / 1000000); return 0; } @@ -243,8 +246,8 @@ int mmc_send_status(struct mmc *mmc, int timeout) if (cmd.response[0] & MMC_STATUS_MASK) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("Status Error: 0x%08X\n", - cmd.response[0]); + pr_err("Status Error: 0x%08X\n", + cmd.response[0]); #endif return -ECOMM; } @@ -260,7 +263,7 @@ int mmc_send_status(struct mmc *mmc, int timeout) mmc_trace_state(mmc, &cmd); if (timeout <= 0) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("Timeout waiting card ready\n"); + pr_err("Timeout waiting card ready\n"); #endif return -ETIMEDOUT; } @@ -271,6 +274,7 @@ int mmc_send_status(struct mmc *mmc, int timeout) int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd; + int err; if (mmc->ddr_mode) return 0; @@ -279,8 +283,95 @@ int mmc_set_blocklen(struct mmc *mmc, int len) cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = len; - return mmc_send_cmd(mmc, &cmd, NULL); + err = mmc_send_cmd(mmc, &cmd, NULL); + +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_SET_BLOCKLEN)) { + int retries = 4; + /* + * It has been seen that SET_BLOCKLEN may fail on the first + * attempt, let's try a few more time + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif + + return err; +} + +#ifdef MMC_SUPPORTS_TUNING +static const u8 tuning_blk_pattern_4bit[] = { + 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, + 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, + 0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb, + 0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef, + 0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c, + 0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee, + 0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff, + 0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde, +}; + +static const u8 tuning_blk_pattern_8bit[] = { + 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc, + 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff, + 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff, + 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd, + 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, + 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff, + 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, + 0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, + 0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, + 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, + 0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, + 0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, + 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, +}; + +int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error) +{ + struct mmc_cmd cmd; + struct mmc_data data; + const u8 *tuning_block_pattern; + int size, err; + + if (mmc->bus_width == 8) { + tuning_block_pattern = tuning_blk_pattern_8bit; + size = sizeof(tuning_blk_pattern_8bit); + } else if (mmc->bus_width == 4) { + tuning_block_pattern = tuning_blk_pattern_4bit; + size = sizeof(tuning_blk_pattern_4bit); + } else { + return -EINVAL; + } + + ALLOC_CACHE_ALIGN_BUFFER(u8, data_buf, size); + + cmd.cmdidx = opcode; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1; + + data.dest = (void *)data_buf; + data.blocks = 1; + data.blocksize = size; + data.flags = MMC_DATA_READ; + + err = mmc_send_cmd(mmc, &cmd, &data); + if (err) + return err; + + if (memcmp(data_buf, tuning_block_pattern, size)) + return -EIO; + + return 0; } +#endif static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, lbaint_t blkcnt) @@ -314,7 +405,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, cmd.resp_type = MMC_RSP_R1b; if (mmc_send_cmd(mmc, &cmd, NULL)) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("mmc fail to send stop cmd\n"); + pr_err("mmc fail to send stop cmd\n"); #endif return 0; } @@ -354,14 +445,14 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, if ((start + blkcnt) > block_dev->lba) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", - start + blkcnt, block_dev->lba); + pr_err("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n", + start + blkcnt, block_dev->lba); #endif return 0; } if (mmc_set_blocklen(mmc, mmc->read_bl_len)) { - debug("%s: Failed to set blocklen\n", __func__); + pr_debug("%s: Failed to set blocklen\n", __func__); return 0; } @@ -369,7 +460,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, cur = (blocks_todo > mmc->cfg->b_max) ? mmc->cfg->b_max : blocks_todo; if (mmc_read_blocks(mmc, dst, start, cur) != cur) { - debug("%s: Failed to read blocks\n", __func__); + pr_debug("%s: Failed to read blocks\n", __func__); return 0; } blocks_todo -= cur; @@ -401,7 +492,69 @@ static int mmc_go_idle(struct mmc *mmc) return 0; } -static int sd_send_op_cond(struct mmc *mmc) +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) +static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) +{ + struct mmc_cmd cmd; + int err = 0; + + /* + * Send CMD11 only if the request is to switch the card to + * 1.8V signalling. + */ + if (signal_voltage == MMC_SIGNAL_VOLTAGE_330) + return mmc_set_signal_voltage(mmc, signal_voltage); + + cmd.cmdidx = SD_CMD_SWITCH_UHS18V; + cmd.cmdarg = 0; + cmd.resp_type = MMC_RSP_R1; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) + return err; + + if (!mmc_host_is_spi(mmc) && (cmd.response[0] & MMC_STATUS_ERROR)) + return -EIO; + + /* + * The card should drive cmd and dat[0:3] low immediately + * after the response of cmd11, but wait 100 us to be sure + */ + err = mmc_wait_dat0(mmc, 0, 100); + if (err == -ENOSYS) + udelay(100); + else if (err) + return -ETIMEDOUT; + + /* + * During a signal voltage level switch, the clock must be gated + * for 5 ms according to the SD spec + */ + mmc_set_clock(mmc, mmc->clock, true); + + err = mmc_set_signal_voltage(mmc, signal_voltage); + if (err) + return err; + + /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ + mdelay(10); + mmc_set_clock(mmc, mmc->clock, false); + + /* + * Failure to switch is indicated by the card holding + * dat[0:3] low. Wait for at least 1 ms according to spec + */ + err = mmc_wait_dat0(mmc, 1, 1000); + if (err == -ENOSYS) + udelay(1000); + else if (err) + return -ETIMEDOUT; + + return 0; +} +#endif + +static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) { int timeout = 1000; int err; @@ -433,6 +586,9 @@ static int sd_send_op_cond(struct mmc *mmc) if (mmc->version == SD_VERSION_2) cmd.cmdarg |= OCR_HCS; + if (uhs_en) + cmd.cmdarg |= OCR_S18R; + err = mmc_send_cmd(mmc, &cmd, NULL); if (err) @@ -463,6 +619,15 @@ static int sd_send_op_cond(struct mmc *mmc) mmc->ocr = cmd.response[0]; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + if (uhs_en && !(mmc_host_is_spi(mmc)) && (cmd.response[0] & 0x41000000) + == 0x41000000) { + err = mmc_switch_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); + if (err) + return err; + } +#endif + mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 0; @@ -620,6 +785,12 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) case MMC_HS_52: case MMC_DDR_52: speed_bits = EXT_CSD_TIMING_HS; + break; +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) + case MMC_HS_200: + speed_bits = EXT_CSD_TIMING_HS200; + break; +#endif case MMC_LEGACY: speed_bits = EXT_CSD_TIMING_LEGACY; break; @@ -650,7 +821,7 @@ static int mmc_get_capabilities(struct mmc *mmc) u8 *ext_csd = mmc->ext_csd; char cardtype; - mmc->card_caps = MMC_MODE_1BIT; + mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); if (mmc_host_is_spi(mmc)) return 0; @@ -660,15 +831,21 @@ static int mmc_get_capabilities(struct mmc *mmc) return 0; if (!ext_csd) { - printf("No ext_csd found!\n"); /* this should enver happen */ + pr_err("No ext_csd found!\n"); /* this should enver happen */ return -ENOTSUPP; } mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0xf; + cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f; + mmc->cardtype = cardtype; - /* High Speed is set, there are two types: 52MHz and 26MHz */ +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) + if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | + EXT_CSD_CARD_TYPE_HS200_1_8V)) { + mmc->card_caps |= MMC_MODE_HS200; + } +#endif if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) mmc->card_caps |= MMC_MODE_DDR_52MHz; @@ -708,10 +885,46 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; } +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) +static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num) +{ + int forbidden = 0; + bool change = false; + + if (part_num & PART_ACCESS_MASK) + forbidden = MMC_CAP(MMC_HS_200); + + if (MMC_CAP(mmc->selected_mode) & forbidden) { + pr_debug("selected mode (%s) is forbidden for part %d\n", + mmc_mode_name(mmc->selected_mode), part_num); + change = true; + } else if (mmc->selected_mode != mmc->best_mode) { + pr_debug("selected mode is not optimal\n"); + change = true; + } + + if (change) + return mmc_select_mode_and_width(mmc, + mmc->card_caps & ~forbidden); + + return 0; +} +#else +static inline int mmc_boot_part_access_chk(struct mmc *mmc, + unsigned int part_num) +{ + return 0; +} +#endif + int mmc_switch_part(struct mmc *mmc, unsigned int part_num) { int ret; + ret = mmc_boot_part_access_chk(mmc, part_num); + if (ret) + return ret; + ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, (mmc->part_config & ~PART_ACCESS_MASK) | (part_num & PART_ACCESS_MASK)); @@ -728,6 +941,7 @@ int mmc_switch_part(struct mmc *mmc, unsigned int part_num) return ret; } +#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, enum mmc_hwpart_conf_mode mode) @@ -746,17 +960,17 @@ int mmc_hwpart_config(struct mmc *mmc, return -EINVAL; if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4_41)) { - printf("eMMC >= 4.4 required for enhanced user data area\n"); + pr_err("eMMC >= 4.4 required for enhanced user data area\n"); return -EMEDIUMTYPE; } if (!(mmc->part_support & PART_SUPPORT)) { - printf("Card does not support partitioning\n"); + pr_err("Card does not support partitioning\n"); return -EMEDIUMTYPE; } if (!mmc->hc_wp_grp_size) { - printf("Card does not define HC WP group size\n"); + pr_err("Card does not define HC WP group size\n"); return -EMEDIUMTYPE; } @@ -764,7 +978,7 @@ int mmc_hwpart_config(struct mmc *mmc, if (conf->user.enh_size) { if (conf->user.enh_size % mmc->hc_wp_grp_size || conf->user.enh_start % mmc->hc_wp_grp_size) { - printf("User data enhanced area not HC WP group " + pr_err("User data enhanced area not HC WP group " "size aligned\n"); return -EINVAL; } @@ -783,7 +997,7 @@ int mmc_hwpart_config(struct mmc *mmc, for (pidx = 0; pidx < 4; pidx++) { if (conf->gp_part[pidx].size % mmc->hc_wp_grp_size) { - printf("GP%i partition not HC WP group size " + pr_err("GP%i partition not HC WP group size " "aligned\n", pidx+1); return -EINVAL; } @@ -795,7 +1009,7 @@ int mmc_hwpart_config(struct mmc *mmc, } if (part_attrs && ! (mmc->part_support & ENHNCD_SUPPORT)) { - printf("Card does not support enhanced attribute\n"); + pr_err("Card does not support enhanced attribute\n"); return -EMEDIUMTYPE; } @@ -808,7 +1022,7 @@ int mmc_hwpart_config(struct mmc *mmc, (ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT+1] << 8) + ext_csd[EXT_CSD_MAX_ENH_SIZE_MULT]; if (tot_enh_size_mult > max_enh_size_mult) { - printf("Total enhanced size exceeds maximum (%u > %u)\n", + pr_err("Total enhanced size exceeds maximum (%u > %u)\n", tot_enh_size_mult, max_enh_size_mult); return -EMEDIUMTYPE; } @@ -842,7 +1056,7 @@ int mmc_hwpart_config(struct mmc *mmc, if (ext_csd[EXT_CSD_PARTITION_SETTING] & EXT_CSD_PARTITION_SETTING_COMPLETED) { - printf("Card already partitioned\n"); + pr_err("Card already partitioned\n"); return -EPERM; } @@ -921,6 +1135,7 @@ int mmc_hwpart_config(struct mmc *mmc, return 0; } +#endif #if !CONFIG_IS_ENABLED(DM_MMC) int mmc_getcd(struct mmc *mmc) @@ -969,8 +1184,11 @@ static int sd_get_capabilities(struct mmc *mmc) ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); struct mmc_data data; int timeout; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + u32 sd3_bus_mode; +#endif - mmc->card_caps = MMC_MODE_1BIT; + mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(SD_LEGACY); if (mmc_host_is_spi(mmc)) return 0; @@ -1050,6 +1268,24 @@ retry_scr: if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED) mmc->card_caps |= MMC_CAP(SD_HS); +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + /* Version before 3.0 don't support UHS modes */ + if (mmc->version < SD_VERSION_3) + return 0; + + sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; + if (sd3_bus_mode & SD_MODE_UHS_SDR104) + mmc->card_caps |= MMC_CAP(UHS_SDR104); + if (sd3_bus_mode & SD_MODE_UHS_SDR50) + mmc->card_caps |= MMC_CAP(UHS_SDR50); + if (sd3_bus_mode & SD_MODE_UHS_SDR25) + mmc->card_caps |= MMC_CAP(UHS_SDR25); + if (sd3_bus_mode & SD_MODE_UHS_SDR12) + mmc->card_caps |= MMC_CAP(UHS_SDR12); + if (sd3_bus_mode & SD_MODE_UHS_DDR50) + mmc->card_caps |= MMC_CAP(UHS_DDR50); +#endif + return 0; } @@ -1058,12 +1294,41 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) int err; ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16); + int speed; - err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, 1, (u8 *)switch_status); + switch (mode) { + case SD_LEGACY: + speed = UHS_SDR12_BUS_SPEED; + break; + case SD_HS: + speed = HIGH_SPEED_BUS_SPEED; + break; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + case UHS_SDR12: + speed = UHS_SDR12_BUS_SPEED; + break; + case UHS_SDR25: + speed = UHS_SDR25_BUS_SPEED; + break; + case UHS_SDR50: + speed = UHS_SDR50_BUS_SPEED; + break; + case UHS_DDR50: + speed = UHS_DDR50_BUS_SPEED; + break; + case UHS_SDR104: + speed = UHS_SDR104_BUS_SPEED; + break; +#endif + default: + return -EINVAL; + } + + err = sd_switch(mmc, SD_SWITCH_SWITCH, 0, speed, (u8 *)switch_status); if (err) return err; - if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) != 0x01000000) + if (((__be32_to_cpu(switch_status[4]) >> 24) & 0xF) != speed) return -ENOTSUPP; return 0; @@ -1098,8 +1363,17 @@ int sd_select_bus_width(struct mmc *mmc, int w) return 0; } +#if CONFIG_IS_ENABLED(MMC_WRITE) static int sd_read_ssr(struct mmc *mmc) { + static const unsigned int sd_au_size[] = { + 0, SZ_16K / 512, SZ_32K / 512, + SZ_64K / 512, SZ_128K / 512, SZ_256K / 512, + SZ_512K / 512, SZ_1M / 512, SZ_2M / 512, + SZ_4M / 512, SZ_8M / 512, (SZ_8M + SZ_4M) / 512, + SZ_16M / 512, (SZ_16M + SZ_8M) / 512, SZ_32M / 512, + SZ_64M / 512, + }; int err, i; struct mmc_cmd cmd; ALLOC_CACHE_ALIGN_BUFFER(uint, ssr, 16); @@ -1148,12 +1422,12 @@ retry_ssr: mmc->ssr.erase_offset = eo * 1000; } } else { - debug("Invalid Allocation Unit Size.\n"); + pr_debug("Invalid Allocation Unit Size.\n"); } return 0; } - +#endif /* frequency bases */ /* divided by 10 to be nice to platforms without floating point */ static const int fbase[] = { @@ -1193,11 +1467,22 @@ static inline int bus_width(uint cap) return 4; if (cap == MMC_MODE_1BIT) return 1; - printf("invalid bus witdh capability 0x%x\n", cap); + pr_warn("invalid bus witdh capability 0x%x\n", cap); return 0; } #if !CONFIG_IS_ENABLED(DM_MMC) +#ifdef MMC_SUPPORTS_TUNING +static int mmc_execute_tuning(struct mmc *mmc, uint opcode) +{ + return -ENOTSUPP; +} +#endif + +static void mmc_send_init_stream(struct mmc *mmc) +{ +} + static int mmc_set_ios(struct mmc *mmc) { int ret = 0; @@ -1209,15 +1494,18 @@ static int mmc_set_ios(struct mmc *mmc) } #endif -int mmc_set_clock(struct mmc *mmc, uint clock) +int mmc_set_clock(struct mmc *mmc, uint clock, bool disable) { - if (clock > mmc->cfg->f_max) - clock = mmc->cfg->f_max; + if (!disable) { + if (clock > mmc->cfg->f_max) + clock = mmc->cfg->f_max; - if (clock < mmc->cfg->f_min) - clock = mmc->cfg->f_min; + if (clock < mmc->cfg->f_min) + clock = mmc->cfg->f_min; + } mmc->clock = clock; + mmc->clk_disable = disable; return mmc_set_ios(mmc); } @@ -1239,37 +1527,94 @@ void mmc_dump_capabilities(const char *text, uint caps) { enum bus_mode mode; - printf("%s: widths [", text); + pr_debug("%s: widths [", text); if (caps & MMC_MODE_8BIT) - printf("8, "); + pr_debug("8, "); if (caps & MMC_MODE_4BIT) - printf("4, "); + pr_debug("4, "); if (caps & MMC_MODE_1BIT) - printf("1, "); - printf("\b\b] modes ["); + pr_debug("1, "); + pr_debug("\b\b] modes ["); for (mode = MMC_LEGACY; mode < MMC_MODES_END; mode++) if (MMC_CAP(mode) & caps) - printf("%s, ", mmc_mode_name(mode)); - printf("\b\b]\n"); + pr_debug("%s, ", mmc_mode_name(mode)); + pr_debug("\b\b]\n"); } #endif struct mode_width_tuning { enum bus_mode mode; uint widths; +#ifdef MMC_SUPPORTS_TUNING + uint tuning; +#endif }; +#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE) +int mmc_voltage_to_mv(enum mmc_voltage voltage) +{ + switch (voltage) { + case MMC_SIGNAL_VOLTAGE_000: return 0; + case MMC_SIGNAL_VOLTAGE_330: return 3300; + case MMC_SIGNAL_VOLTAGE_180: return 1800; + case MMC_SIGNAL_VOLTAGE_120: return 1200; + } + return -EINVAL; +} + static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) { + int err; + + if (mmc->signal_voltage == signal_voltage) + return 0; + mmc->signal_voltage = signal_voltage; - return mmc_set_ios(mmc); + err = mmc_set_ios(mmc); + if (err) + pr_debug("unable to set voltage (err %d)\n", err); + + return err; +} +#else +static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) +{ + return 0; } +#endif static const struct mode_width_tuning sd_modes_by_pref[] = { +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) +#ifdef MMC_SUPPORTS_TUNING + { + .mode = UHS_SDR104, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK + }, +#endif + { + .mode = UHS_SDR50, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + }, + { + .mode = UHS_DDR50, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + }, + { + .mode = UHS_SDR25, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + }, +#endif { .mode = SD_HS, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, }, +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + { + .mode = UHS_SDR12, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + }, +#endif { .mode = SD_LEGACY, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, @@ -1282,27 +1627,38 @@ static const struct mode_width_tuning sd_modes_by_pref[] = { mwt++) \ if (caps & MMC_CAP(mwt->mode)) -static int sd_select_mode_and_width(struct mmc *mmc) +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) { int err; uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; const struct mode_width_tuning *mwt; +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; +#else + bool uhs_en = false; +#endif + uint caps; + +#ifdef DEBUG + mmc_dump_capabilities("sd card", card_caps); + mmc_dump_capabilities("host", mmc->host_caps); +#endif - err = sd_get_capabilities(mmc); - if (err) - return err; /* Restrict card's capabilities by what the host can do */ - mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT); + caps = card_caps & mmc->host_caps; - for_each_sd_mode_by_pref(mmc->card_caps, mwt) { + if (!uhs_en) + caps &= ~UHS_CAPS; + + for_each_sd_mode_by_pref(caps, mwt) { uint *w; for (w = widths; w < widths + ARRAY_SIZE(widths); w++) { - if (*w & mmc->card_caps & mwt->widths) { - debug("trying mode %s width %d (at %d MHz)\n", - mmc_mode_name(mwt->mode), - bus_width(*w), - mmc_mode2freq(mmc, mwt->mode) / 1000000); + if (*w & caps & mwt->widths) { + pr_debug("trying mode %s width %d (at %d MHz)\n", + mmc_mode_name(mwt->mode), + bus_width(*w), + mmc_mode2freq(mmc, mwt->mode) / 1000000); /* configure the bus width (card + host) */ err = sd_select_bus_width(mmc, bus_width(*w)); @@ -1317,23 +1673,37 @@ static int sd_select_mode_and_width(struct mmc *mmc) /* configure the bus mode (host) */ mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed); + mmc_set_clock(mmc, mmc->tran_speed, false); + +#ifdef MMC_SUPPORTS_TUNING + /* execute tuning if needed */ + if (mwt->tuning && !mmc_host_is_spi(mmc)) { + err = mmc_execute_tuning(mmc, + mwt->tuning); + if (err) { + pr_debug("tuning failed\n"); + goto error; + } + } +#endif +#if CONFIG_IS_ENABLED(MMC_WRITE) err = sd_read_ssr(mmc); + if (!err) + pr_warn("unable to read ssr\n"); +#endif if (!err) return 0; - printf("bad ssr\n"); - error: /* revert to a safer bus speed */ mmc_select_mode(mmc, SD_LEGACY); - mmc_set_clock(mmc, mmc->tran_speed); + mmc_set_clock(mmc, mmc->tran_speed, false); } } } - printf("unable to select a mode\n"); + pr_err("unable to select a mode\n"); return -ENOTSUPP; } @@ -1348,6 +1718,9 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc) const u8 *ext_csd = mmc->ext_csd; ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN); + if (mmc->version < MMC_VERSION_4) + return 0; + err = mmc_send_ext_csd(mmc, test_csd); if (err) return err; @@ -1368,11 +1741,59 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc) return -EBADMSG; } +#if CONFIG_IS_ENABLED(MMC_IO_VOLTAGE) +static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, + uint32_t allowed_mask) +{ + u32 card_mask = 0; + + switch (mode) { + case MMC_HS_200: + if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V) + card_mask |= MMC_SIGNAL_VOLTAGE_180; + if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V) + card_mask |= MMC_SIGNAL_VOLTAGE_120; + break; + case MMC_DDR_52: + if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) + card_mask |= MMC_SIGNAL_VOLTAGE_330 | + MMC_SIGNAL_VOLTAGE_180; + if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V) + card_mask |= MMC_SIGNAL_VOLTAGE_120; + break; + default: + card_mask |= MMC_SIGNAL_VOLTAGE_330; + break; + } + + while (card_mask & allowed_mask) { + enum mmc_voltage best_match; + + best_match = 1 << (ffs(card_mask & allowed_mask) - 1); + if (!mmc_set_signal_voltage(mmc, best_match)) + return 0; + + allowed_mask &= ~best_match; + } + + return -ENOTSUPP; +} +#else +static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, + uint32_t allowed_mask) +{ + return 0; +} +#endif + static const struct mode_width_tuning mmc_modes_by_pref[] = { +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) { .mode = MMC_HS_200, .widths = MMC_MODE_8BIT | MMC_MODE_4BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200 }, +#endif { .mode = MMC_DDR_52, .widths = MMC_MODE_8BIT | MMC_MODE_4BIT, @@ -1415,35 +1836,45 @@ static const struct ext_csd_bus_width { ecbv++) \ if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap)) -static int mmc_select_mode_and_width(struct mmc *mmc) +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) { int err; const struct mode_width_tuning *mwt; const struct ext_csd_bus_width *ecbw; - err = mmc_get_capabilities(mmc); - if (err) - return err; +#ifdef DEBUG + mmc_dump_capabilities("mmc", card_caps); + mmc_dump_capabilities("host", mmc->host_caps); +#endif /* Restrict card's capabilities by what the host can do */ - mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT); + card_caps &= mmc->host_caps; /* Only version 4 of MMC supports wider bus widths */ if (mmc->version < MMC_VERSION_4) return 0; if (!mmc->ext_csd) { - debug("No ext_csd found!\n"); /* this should enver happen */ + pr_debug("No ext_csd found!\n"); /* this should enver happen */ return -ENOTSUPP; } - for_each_mmc_mode_by_pref(mmc->card_caps, mwt) { - for_each_supported_width(mmc->card_caps & mwt->widths, + mmc_set_clock(mmc, mmc->legacy_speed, false); + + for_each_mmc_mode_by_pref(card_caps, mwt) { + for_each_supported_width(card_caps & mwt->widths, mmc_is_mode_ddr(mwt->mode), ecbw) { - debug("trying mode %s width %d (at %d MHz)\n", - mmc_mode_name(mwt->mode), - bus_width(ecbw->cap), - mmc_mode2freq(mmc, mwt->mode) / 1000000); + enum mmc_voltage old_voltage; + pr_debug("trying mode %s width %d (at %d MHz)\n", + mmc_mode_name(mwt->mode), + bus_width(ecbw->cap), + mmc_mode2freq(mmc, mwt->mode) / 1000000); + old_voltage = mmc->signal_voltage; + err = mmc_set_lowest_voltage(mmc, mwt->mode, + MMC_ALL_SIGNAL_VOLTAGE); + if (err) + continue; + /* configure the bus width (card + host) */ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, @@ -1471,13 +1902,25 @@ static int mmc_select_mode_and_width(struct mmc *mmc) /* configure the bus mode (host) */ mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed); + mmc_set_clock(mmc, mmc->tran_speed, false); +#ifdef MMC_SUPPORTS_TUNING + + /* execute tuning if needed */ + if (mwt->tuning) { + err = mmc_execute_tuning(mmc, mwt->tuning); + if (err) { + pr_debug("tuning failed\n"); + goto error; + } + } +#endif /* do a transfer to check the configuration */ err = mmc_read_and_compare_ext_csd(mmc); if (!err) return 0; error: + mmc_set_signal_voltage(mmc, old_voltage); /* if an error occured, revert to a safer bus mode */ mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1); @@ -1486,7 +1929,7 @@ error: } } - printf("unable to select a mode\n"); + pr_err("unable to select a mode\n"); return -ENOTSUPP; } @@ -1497,22 +1940,41 @@ static int mmc_startup_v4(struct mmc *mmc) u64 capacity; bool has_parts = false; bool part_completed; - u8 *ext_csd; + static const u32 mmc_versions[] = { + MMC_VERSION_4, + MMC_VERSION_4_1, + MMC_VERSION_4_2, + MMC_VERSION_4_3, + MMC_VERSION_4_4, + MMC_VERSION_4_41, + MMC_VERSION_4_5, + MMC_VERSION_5_0, + MMC_VERSION_5_1 + }; + + ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4)) return 0; - ext_csd = malloc_cache_aligned(MMC_MAX_BLOCK_LEN); - if (!ext_csd) - return -ENOMEM; - - mmc->ext_csd = ext_csd; - /* check ext_csd version and capacity */ err = mmc_send_ext_csd(mmc, ext_csd); if (err) - return err; - if (ext_csd[EXT_CSD_REV] >= 2) { + goto error; + + /* store the ext csd for future reference */ + if (!mmc->ext_csd) + mmc->ext_csd = malloc(MMC_MAX_BLOCK_LEN); + if (!mmc->ext_csd) + return -ENOMEM; + memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN); + + if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions)) + return -EINVAL; + + mmc->version = mmc_versions[ext_csd[EXT_CSD_REV]]; + + if (mmc->version >= MMC_VERSION_4_2) { /* * According to the JEDEC Standard, the value of * ext_csd's capacity is valid if the value is more @@ -1527,30 +1989,6 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->capacity_user = capacity; } - switch (ext_csd[EXT_CSD_REV]) { - case 1: - mmc->version = MMC_VERSION_4_1; - break; - case 2: - mmc->version = MMC_VERSION_4_2; - break; - case 3: - mmc->version = MMC_VERSION_4_3; - break; - case 5: - mmc->version = MMC_VERSION_4_41; - break; - case 6: - mmc->version = MMC_VERSION_4_5; - break; - case 7: - mmc->version = MMC_VERSION_5_0; - break; - case 8: - mmc->version = MMC_VERSION_5_1; - break; - } - /* The partition data may be non-zero but it is only * effective if PARTITION_SETTING_COMPLETED is set in * EXT_CSD, so ignore any data if this bit is not set, @@ -1588,6 +2026,7 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->capacity_gp[i] <<= 19; } +#ifndef CONFIG_SPL_BUILD if (part_completed) { mmc->enh_user_size = (ext_csd[EXT_CSD_ENH_SIZE_MULT + 2] << 16) + @@ -1604,6 +2043,7 @@ static int mmc_startup_v4(struct mmc *mmc) if (mmc->high_capacity) mmc->enh_user_start <<= 9; } +#endif /* * Host needs to enable ERASE_GRP_DEF bit if device is @@ -1620,15 +2060,17 @@ static int mmc_startup_v4(struct mmc *mmc) EXT_CSD_ERASE_GROUP_DEF, 1); if (err) - return err; + goto error; ext_csd[EXT_CSD_ERASE_GROUP_DEF] = 1; } if (ext_csd[EXT_CSD_ERASE_GROUP_DEF] & 0x01) { +#if CONFIG_IS_ENABLED(MMC_WRITE) /* Read out group size from ext_csd */ mmc->erase_grp_size = ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * 1024; +#endif /* * if high capacity and partition setting completed * SEC_COUNT is valid even if it is smaller than 2 GiB @@ -1642,7 +2084,9 @@ static int mmc_startup_v4(struct mmc *mmc) capacity *= MMC_MAX_BLOCK_LEN; mmc->capacity_user = capacity; } - } else { + } +#if CONFIG_IS_ENABLED(MMC_WRITE) + else { /* Calculate the group size from the csd value. */ int erase_gsz, erase_gmul; @@ -1651,14 +2095,22 @@ static int mmc_startup_v4(struct mmc *mmc) mmc->erase_grp_size = (erase_gsz + 1) * (erase_gmul + 1); } - +#endif +#if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) mmc->hc_wp_grp_size = 1024 * ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE] * ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; +#endif mmc->wr_rel_set = ext_csd[EXT_CSD_WR_REL_SET]; return 0; +error: + if (mmc->ext_csd) { + free(mmc->ext_csd); + mmc->ext_csd = NULL; + } + return err; } static int mmc_startup(struct mmc *mmc) @@ -1675,7 +2127,6 @@ static int mmc_startup(struct mmc *mmc) cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = 1; err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) return err; } @@ -1689,6 +2140,21 @@ static int mmc_startup(struct mmc *mmc) err = mmc_send_cmd(mmc, &cmd, NULL); +#ifdef CONFIG_MMC_QUIRKS + if (err && (mmc->quirks & MMC_QUIRK_RETRY_SEND_CID)) { + int retries = 4; + /* + * It has been seen that SEND_CID may fail on the first + * attempt, let's try a few more time + */ + do { + err = mmc_send_cmd(mmc, &cmd, NULL); + if (!err) + break; + } while (retries--); + } +#endif + if (err) return err; @@ -1762,11 +2228,13 @@ static int mmc_startup(struct mmc *mmc) mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1); mmc->read_bl_len = 1 << ((cmd.response[1] >> 16) & 0xf); +#if CONFIG_IS_ENABLED(MMC_WRITE) if (IS_SD(mmc)) mmc->write_bl_len = mmc->read_bl_len; else mmc->write_bl_len = 1 << ((cmd.response[3] >> 22) & 0xf); +#endif if (mmc->high_capacity) { csize = (mmc->csd[1] & 0x3f) << 16 @@ -1788,15 +2256,17 @@ static int mmc_startup(struct mmc *mmc) if (mmc->read_bl_len > MMC_MAX_BLOCK_LEN) mmc->read_bl_len = MMC_MAX_BLOCK_LEN; +#if CONFIG_IS_ENABLED(MMC_WRITE) if (mmc->write_bl_len > MMC_MAX_BLOCK_LEN) mmc->write_bl_len = MMC_MAX_BLOCK_LEN; +#endif if ((mmc->dsr_imp) && (0xffffffff != mmc->dsr)) { cmd.cmdidx = MMC_CMD_SET_DSR; cmd.cmdarg = (mmc->dsr & 0xffff) << 16; cmd.resp_type = MMC_RSP_NONE; if (mmc_send_cmd(mmc, &cmd, NULL)) - printf("MMC: SET_DSR failed\n"); + pr_warn("MMC: SET_DSR failed\n"); } /* Select the card, and put it into Transfer Mode */ @@ -1813,7 +2283,9 @@ static int mmc_startup(struct mmc *mmc) /* * For SD, its erase group is always one sector */ +#if CONFIG_IS_ENABLED(MMC_WRITE) mmc->erase_grp_size = 1; +#endif mmc->part_config = MMCPART_NOAVAILABLE; err = mmc_startup_v4(mmc); @@ -1824,19 +2296,29 @@ static int mmc_startup(struct mmc *mmc) if (err) return err; - if (IS_SD(mmc)) - err = sd_select_mode_and_width(mmc); - else - err = mmc_select_mode_and_width(mmc); + if (IS_SD(mmc)) { + err = sd_get_capabilities(mmc); + if (err) + return err; + err = sd_select_mode_and_width(mmc, mmc->card_caps); + } else { + err = mmc_get_capabilities(mmc); + if (err) + return err; + mmc_select_mode_and_width(mmc, mmc->card_caps); + } if (err) return err; + mmc->best_mode = mmc->selected_mode; /* Fix the block length for DDR mode */ if (mmc->ddr_mode) { mmc->read_bl_len = MMC_MAX_BLOCK_LEN; +#if CONFIG_IS_ENABLED(MMC_WRITE) mmc->write_bl_len = MMC_MAX_BLOCK_LEN; +#endif } /* fill in device description */ @@ -1910,45 +2392,116 @@ static int mmc_power_init(struct mmc *mmc) ret = device_get_supply_regulator(mmc->dev, "vmmc-supply", &mmc->vmmc_supply); if (ret) - debug("%s: No vmmc supply\n", mmc->dev->name); + pr_debug("%s: No vmmc supply\n", mmc->dev->name); ret = device_get_supply_regulator(mmc->dev, "vqmmc-supply", &mmc->vqmmc_supply); if (ret) - debug("%s: No vqmmc supply\n", mmc->dev->name); + pr_debug("%s: No vqmmc supply\n", mmc->dev->name); +#endif +#else /* !CONFIG_DM_MMC */ + /* + * Driver model should use a regulator, as above, rather than calling + * out to board code. + */ + board_mmc_power_init(); +#endif + return 0; +} + +/* + * put the host in the initial state: + * - turn on Vdd (card power supply) + * - configure the bus width and clock to minimal values + */ +static void mmc_set_initial_state(struct mmc *mmc) +{ + int err; + + /* First try to set 3.3V. If it fails set to 1.8V */ + err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330); + if (err != 0) + err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); + if (err != 0) + pr_warn("mmc: failed to set signal voltage\n"); + mmc_select_mode(mmc, MMC_LEGACY); + mmc_set_bus_width(mmc, 1); + mmc_set_clock(mmc, 0, false); +} + +static int mmc_power_on(struct mmc *mmc) +{ +#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR) if (mmc->vmmc_supply) { - ret = regulator_set_enable(mmc->vmmc_supply, true); + int ret = regulator_set_enable(mmc->vmmc_supply, true); + if (ret) { puts("Error enabling VMMC supply\n"); return ret; } } #endif -#else /* !CONFIG_DM_MMC */ - /* - * Driver model should use a regulator, as above, rather than calling - * out to board code. - */ - board_mmc_power_init(); + return 0; +} + +static int mmc_power_off(struct mmc *mmc) +{ + mmc_set_clock(mmc, 0, true); +#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(DM_REGULATOR) + if (mmc->vmmc_supply) { + int ret = regulator_set_enable(mmc->vmmc_supply, false); + + if (ret) { + pr_debug("Error disabling VMMC supply\n"); + return ret; + } + } #endif return 0; } +static int mmc_power_cycle(struct mmc *mmc) +{ + int ret; + + ret = mmc_power_off(mmc); + if (ret) + return ret; + /* + * SD spec recommends at least 1ms of delay. Let's wait for 2ms + * to be on the safer side. + */ + udelay(2000); + return mmc_power_on(mmc); +} + int mmc_start_init(struct mmc *mmc) { bool no_card; + bool uhs_en = supports_uhs(mmc->cfg->host_caps); int err; + /* + * 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_CAP(MMC_LEGACY) | MMC_MODE_1BIT; + +#if !defined(CONFIG_MMC_BROKEN_CD) /* we pretend there's no card when init is NULL */ no_card = mmc_getcd(mmc) == 0; +#else + no_card = 0; +#endif #if !CONFIG_IS_ENABLED(DM_MMC) no_card = no_card || (mmc->cfg->ops->init == NULL); #endif if (no_card) { mmc->has_init = 0; #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("MMC: no card present\n"); + pr_err("MMC: no card present\n"); #endif return -ENOMEDIUM; } @@ -1963,6 +2516,26 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; +#ifdef CONFIG_MMC_QUIRKS + mmc->quirks = MMC_QUIRK_RETRY_SET_BLOCKLEN | + MMC_QUIRK_RETRY_SEND_CID; +#endif + + err = mmc_power_cycle(mmc); + if (err) { + /* + * if power cycling is not supported, we should not try + * to use the UHS modes, because we wouldn't be able to + * recover from an error during the UHS initialization. + */ + pr_debug("Unable to do a full power cycle. Disabling the UHS modes for safety\n"); + uhs_en = false; + mmc->host_caps &= ~UHS_CAPS; + err = mmc_power_on(mmc); + } + if (err) + return err; + #if CONFIG_IS_ENABLED(DM_MMC) /* The device has already been probed ready for use */ #else @@ -1973,15 +2546,9 @@ int mmc_start_init(struct mmc *mmc) #endif mmc->ddr_mode = 0; - /* First try to set 3.3V. If it fails set to 1.8V */ - err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_330); - if (err != 0) - err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); - if (err != 0) - printf("failed to set signal voltage\n"); - - mmc_set_bus_width(mmc, 1); - mmc_set_clock(mmc, 1); +retry: + mmc_set_initial_state(mmc); + mmc_send_init_stream(mmc); /* Reset the Card */ err = mmc_go_idle(mmc); @@ -1996,7 +2563,12 @@ int mmc_start_init(struct mmc *mmc) err = mmc_send_if_cond(mmc); /* Now try to get the SD card's operating condition */ - err = sd_send_op_cond(mmc); + err = sd_send_op_cond(mmc, uhs_en); + if (err && uhs_en) { + uhs_en = false; + mmc_power_cycle(mmc); + goto retry; + } /* If the command timed out, we check for an MMC card */ if (err == -ETIMEDOUT) { @@ -2004,7 +2576,7 @@ int mmc_start_init(struct mmc *mmc) if (err) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) - printf("Card did not respond to voltage select!\n"); + pr_err("Card did not respond to voltage select!\n"); #endif return -EOPNOTSUPP; } @@ -2053,7 +2625,7 @@ int mmc_init(struct mmc *mmc) if (!err) err = mmc_complete_init(mmc); if (err) - printf("%s: %d, time %lu\n", __func__, err, get_timer(start)); + pr_info("%s: %d, time %lu\n", __func__, err, get_timer(start)); return err; } @@ -2081,12 +2653,7 @@ void mmc_set_preinit(struct mmc *mmc, int preinit) mmc->preinit = preinit; } -#if CONFIG_IS_ENABLED(DM_MMC) && defined(CONFIG_SPL_BUILD) -static int mmc_probe(bd_t *bis) -{ - return 0; -} -#elif CONFIG_IS_ENABLED(DM_MMC) +#if CONFIG_IS_ENABLED(DM_MMC) static int mmc_probe(bd_t *bis) { int ret, i; @@ -2110,7 +2677,7 @@ static int mmc_probe(bd_t *bis) uclass_foreach_dev(dev, uc) { ret = device_probe(dev); if (ret) - printf("%s - probe failed: %d\n", dev->name, ret); + pr_err("%s - probe failed: %d\n", dev->name, ret); } return 0;