X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=drivers%2Fmmc%2Fmmc.c;h=877ce1757da38bce892e0d6c319e29d39a5e7bf9;hb=bc1e3272ff3437f7cfc5e8bf1d1f2767f6d78262;hp=664b71affd81ddee6a5ba0a17f1e9664714b1610;hpb=35f6782055c99410fbeae33ab28ea68de154360c;p=people%2Fms%2Fu-boot.git diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 664b71affd..877ce1757d 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -32,6 +32,7 @@ static const unsigned int sd_au_size[] = { 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; @@ -57,6 +58,12 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) #endif #if !CONFIG_IS_ENABLED(DM_MMC) + +static int mmc_wait_dat0(struct mmc *mmc, int state, int timeout) +{ + return -ENOSYS; +} + __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -272,6 +279,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; @@ -280,7 +288,24 @@ 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; } static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, @@ -402,7 +427,67 @@ static int mmc_go_idle(struct mmc *mmc) return 0; } -static int sd_send_op_cond(struct mmc *mmc) +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; +} + +static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) { int timeout = 1000; int err; @@ -434,6 +519,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) @@ -464,6 +552,13 @@ static int sd_send_op_cond(struct mmc *mmc) mmc->ocr = cmd.response[0]; + 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; + } + mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); mmc->rca = 0; @@ -621,6 +716,10 @@ 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; + case MMC_HS_200: + speed_bits = EXT_CSD_TIMING_HS200; + break; case MMC_LEGACY: speed_bits = EXT_CSD_TIMING_LEGACY; break; @@ -667,9 +766,13 @@ static int mmc_get_capabilities(struct mmc *mmc) 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 (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | + EXT_CSD_CARD_TYPE_HS200_1_8V)) { + mmc->card_caps |= MMC_MODE_HS200; + } if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) mmc->card_caps |= MMC_MODE_DDR_52MHz; @@ -709,10 +812,38 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; } +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) { + 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) { + debug("selected mode is not optimal\n"); + change = true; + } + + if (change) + return mmc_select_mode_and_width(mmc, + mmc->card_caps & ~forbidden); + + return 0; +} + 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)); @@ -970,6 +1101,7 @@ static int sd_get_capabilities(struct mmc *mmc) ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); struct mmc_data data; int timeout; + u32 sd3_bus_mode; mmc->card_caps = MMC_MODE_1BIT; @@ -1051,6 +1183,22 @@ retry_scr: if (__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED) mmc->card_caps |= MMC_CAP(SD_HS); + /* 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); + return 0; } @@ -1059,12 +1207,35 @@ 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: + case UHS_SDR12: + speed = UHS_SDR12_BUS_SPEED; + break; + case SD_HS: + 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; + 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) != speed) return -ENOTSUPP; return 0; @@ -1199,6 +1370,11 @@ static inline int bus_width(uint cap) } #if !CONFIG_IS_ENABLED(DM_MMC) +static int mmc_execute_tuning(struct mmc *mmc, uint opcode) +{ + return -ENOTSUPP; +} + static void mmc_send_init_stream(struct mmc *mmc) { } @@ -1263,19 +1439,61 @@ void mmc_dump_capabilities(const char *text, uint caps) struct mode_width_tuning { enum bus_mode mode; uint widths; + uint tuning; }; +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) + debug("unable to set voltage (err %d)\n", err); + + return err; } static const struct mode_width_tuning sd_modes_by_pref[] = { + { + .mode = UHS_SDR104, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK + }, + { + .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, + }, { .mode = SD_HS, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, }, + { + .mode = UHS_SDR12, + .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, + }, { .mode = SD_LEGACY, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, @@ -1288,23 +1506,26 @@ 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; + bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; + uint caps; + - 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 | MMC_MODE_1BIT); + + if (!uhs_en) + caps &= ~UHS_CAPS; - for_each_sd_mode_by_pref(mmc->card_caps, mwt) { + 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) { + if (*w & caps & mwt->widths) { debug("trying mode %s width %d (at %d MHz)\n", mmc_mode_name(mwt->mode), bus_width(*w), @@ -1325,6 +1546,16 @@ static int sd_select_mode_and_width(struct mmc *mmc) mmc_select_mode(mmc, mwt->mode); mmc_set_clock(mmc, mmc->tran_speed, false); + /* execute tuning if needed */ + if (mwt->tuning && !mmc_host_is_spi(mmc)) { + err = mmc_execute_tuning(mmc, + mwt->tuning); + if (err) { + debug("tuning failed\n"); + goto error; + } + } + err = sd_read_ssr(mmc); if (!err) return 0; @@ -1374,10 +1605,48 @@ static int mmc_read_and_compare_ext_csd(struct mmc *mmc) return -EBADMSG; } +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; +} + static const struct mode_width_tuning mmc_modes_by_pref[] = { { .mode = MMC_HS_200, .widths = MMC_MODE_8BIT | MMC_MODE_4BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200 }, { .mode = MMC_DDR_52, @@ -1421,18 +1690,14 @@ 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; - /* 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 | MMC_MODE_1BIT); /* Only version 4 of MMC supports wider bus widths */ if (mmc->version < MMC_VERSION_4) @@ -1443,13 +1708,22 @@ static int mmc_select_mode_and_width(struct mmc *mmc) 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) { + enum mmc_voltage old_voltage; 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, @@ -1479,11 +1753,21 @@ static int mmc_select_mode_and_width(struct mmc *mmc) mmc_select_mode(mmc, mwt->mode); mmc_set_clock(mmc, mmc->tran_speed, false); + /* execute tuning if needed */ + if (mwt->tuning) { + err = mmc_execute_tuning(mmc, mwt->tuning); + if (err) { + debug("tuning failed\n"); + goto error; + } + } + /* 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); @@ -1681,7 +1965,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; } @@ -1695,6 +1978,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; @@ -1830,14 +2128,22 @@ 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) { @@ -1971,12 +2277,13 @@ static int mmc_power_on(struct mmc *mmc) static int mmc_power_off(struct mmc *mmc) { + mmc_set_clock(mmc, 1, 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) { - puts("Error disabling VMMC supply\n"); + debug("Error disabling VMMC supply\n"); return ret; } } @@ -2002,8 +2309,11 @@ static int mmc_power_cycle(struct mmc *mmc) int mmc_start_init(struct mmc *mmc) { bool no_card; + bool uhs_en = supports_uhs(mmc->cfg->host_caps); int err; + mmc->host_caps = mmc->cfg->host_caps; + /* we pretend there's no card when init is NULL */ no_card = mmc_getcd(mmc) == 0; #if !CONFIG_IS_ENABLED(DM_MMC) @@ -2027,7 +2337,23 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; - err = mmc_power_on(mmc); +#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. + */ + 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; @@ -2041,6 +2367,7 @@ int mmc_start_init(struct mmc *mmc) #endif mmc->ddr_mode = 0; +retry: mmc_set_initial_state(mmc); mmc_send_init_stream(mmc); @@ -2057,7 +2384,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) {