X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fmmc%2Fmmc.c;h=f5c821e308cba8331a8109a3e109cbf79c8ebfb9;hb=10d3e90f46feace58f4141b696d91644e594e3ed;hp=400e1633402d2fa56f0ee440766839966cc6cfc9;hpb=f99c2efe5672d7355a632dcae3551ffadea1163a;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 400e163..f5c821e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1,10 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2008, Freescale Semiconductor, Inc * Andy Fleming * * Based vaguely on the Linux code - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -22,39 +21,10 @@ #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); +#if !CONFIG_IS_ENABLED(MMC_TINY) static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps); - -#if CONFIG_IS_ENABLED(MMC_TINY) -static struct mmc mmc_static; -struct mmc *find_mmc_device(int dev_num) -{ - return &mmc_static; -} - -void mmc_do_preinit(void) -{ - struct mmc *m = &mmc_static; -#ifdef CONFIG_FSL_ESDHC_ADAPTER_IDENT - mmc_set_preinit(m, 1); -#endif - if (m->preinit) - mmc_start_init(m); -} - -struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) -{ - return &mmc->block_dev; -} #endif #if !CONFIG_IS_ENABLED(DM_MMC) @@ -177,6 +147,7 @@ const char *mmc_mode_name(enum bus_mode mode) [MMC_HS_52] = "MMC High Speed (52MHz)", [MMC_DDR_52] = "MMC DDR52 (52MHz)", [MMC_HS_200] = "HS200 (200MHz)", + [MMC_HS_400] = "HS400 (200MHz)", }; if (mode >= MMC_MODES_END) @@ -189,23 +160,19 @@ 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, -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + [MMC_HS_52] = 52000000, + [MMC_DDR_52] = 52000000, [UHS_SDR12] = 25000000, [UHS_SDR25] = 50000000, [UHS_SDR50] = 100000000, [UHS_DDR50] = 50000000, -#ifdef MMC_SUPPORTS_TUNING [UHS_SDR104] = 208000000, -#endif -#endif - [MMC_HS_52] = 52000000, - [MMC_DDR_52] = 52000000, -#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) [MMC_HS_200] = 200000000, -#endif + [MMC_HS_400] = 200000000, }; if (mode == MMC_LEGACY) @@ -221,8 +188,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; } @@ -465,7 +432,7 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, } 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; } @@ -473,7 +440,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; @@ -543,7 +510,7 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) * 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); + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); err = mmc_set_signal_voltage(mmc, signal_voltage); if (err) @@ -551,7 +518,7 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ mdelay(10); - mmc_set_clock(mmc, mmc->clock, false); + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); /* * Failure to switch is indicated by the card holding @@ -693,7 +660,7 @@ static int mmc_complete_op_cond(struct mmc *mmc) { struct mmc_cmd cmd; int timeout = 1000; - uint start; + ulong start; int err; mmc->op_cond_pending = 0; @@ -786,6 +753,7 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) } +#if !CONFIG_IS_ENABLED(MMC_TINY) static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) { int err; @@ -799,9 +767,16 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) 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 +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + case MMC_HS_400: + speed_bits = EXT_CSD_TIMING_HS400; + break; +#endif case MMC_LEGACY: speed_bits = EXT_CSD_TIMING_LEGACY; break; @@ -848,13 +823,21 @@ static int mmc_get_capabilities(struct mmc *mmc) mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; - cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f; + cardtype = ext_csd[EXT_CSD_CARD_TYPE]; mmc->cardtype = cardtype; +#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 CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + if (cardtype & (EXT_CSD_CARD_TYPE_HS400_1_2V | + EXT_CSD_CARD_TYPE_HS400_1_8V)) { + mmc->card_caps |= MMC_MODE_HS400; + } +#endif if (cardtype & EXT_CSD_CARD_TYPE_52) { if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) mmc->card_caps |= MMC_MODE_DDR_52MHz; @@ -865,6 +848,7 @@ static int mmc_get_capabilities(struct mmc *mmc) return 0; } +#endif static int mmc_set_capacity(struct mmc *mmc, int part_num) { @@ -904,11 +888,11 @@ static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num) 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); + 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) { - debug("selected mode is not optimal\n"); + pr_debug("selected mode is not optimal\n"); change = true; } @@ -950,6 +934,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) @@ -1143,6 +1128,7 @@ int mmc_hwpart_config(struct mmc *mmc, return 0; } +#endif #if !CONFIG_IS_ENABLED(DM_MMC) int mmc_getcd(struct mmc *mmc) @@ -1162,6 +1148,7 @@ int mmc_getcd(struct mmc *mmc) } #endif +#if !CONFIG_IS_ENABLED(MMC_TINY) static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) { struct mmc_cmd cmd; @@ -1182,7 +1169,6 @@ static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) return mmc_send_cmd(mmc, &cmd, &data); } - static int sd_get_capabilities(struct mmc *mmc) { int err; @@ -1303,12 +1289,21 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) ALLOC_CACHE_ALIGN_BUFFER(uint, switch_status, 16); int speed; + /* SD version 1.00 and 1.01 does not support CMD 6 */ + if (mmc->version == SD_VERSION_1_0) + return 0; + switch (mode) { case SD_LEGACY: - case UHS_SDR12: 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; @@ -1321,6 +1316,7 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) case UHS_SDR104: speed = UHS_SDR104_BUS_SPEED; break; +#endif default: return -EINVAL; } @@ -1329,13 +1325,13 @@ static int sd_set_card_speed(struct mmc *mmc, enum bus_mode mode) if (err) return err; - if ((__be32_to_cpu(switch_status[4]) >> 24) != speed) + if (((__be32_to_cpu(switch_status[4]) >> 24) & 0xF) != speed) return -ENOTSUPP; return 0; } -int sd_select_bus_width(struct mmc *mmc, int w) +static int sd_select_bus_width(struct mmc *mmc, int w) { int err; struct mmc_cmd cmd; @@ -1363,9 +1359,19 @@ int sd_select_bus_width(struct mmc *mmc, int w) return 0; } +#endif +#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); @@ -1414,12 +1420,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[] = { @@ -1488,15 +1494,19 @@ static int mmc_set_ios(struct mmc *mmc) 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; + debug("clock is %s (%dHz)\n", disable ? "disabled" : "enabled", clock); + return mmc_set_ios(mmc); } @@ -1517,18 +1527,18 @@ 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 @@ -1562,7 +1572,7 @@ static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) mmc->signal_voltage = signal_voltage; err = mmc_set_ios(mmc); if (err) - debug("unable to set voltage (err %d)\n", err); + pr_debug("unable to set voltage (err %d)\n", err); return err; } @@ -1573,6 +1583,7 @@ static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) } #endif +#if !CONFIG_IS_ENABLED(MMC_TINY) static const struct mode_width_tuning sd_modes_by_pref[] = { #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) #ifdef MMC_SUPPORTS_TUNING @@ -1645,10 +1656,10 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) for (w = widths; w < widths + ARRAY_SIZE(widths); w++) { if (*w & 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); + 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)); @@ -1663,7 +1674,8 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) /* configure the bus mode (host) */ mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed, false); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); #ifdef MMC_SUPPORTS_TUNING /* execute tuning if needed */ @@ -1671,27 +1683,30 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) err = mmc_execute_tuning(mmc, mwt->tuning); if (err) { - debug("tuning failed\n"); + 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; - pr_warn("bad ssr\n"); - error: /* revert to a safer bus speed */ mmc_select_mode(mmc, SD_LEGACY); - mmc_set_clock(mmc, mmc->tran_speed, false); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); } } } - printf("unable to select a mode\n"); + pr_err("unable to select a mode\n"); return -ENOTSUPP; } @@ -1736,10 +1751,13 @@ static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, u32 card_mask = 0; switch (mode) { + case MMC_HS_400: case MMC_HS_200: - if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V) + if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_8V | + EXT_CSD_CARD_TYPE_HS400_1_8V)) card_mask |= MMC_SIGNAL_VOLTAGE_180; - if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V) + if (mmc->cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | + EXT_CSD_CARD_TYPE_HS400_1_2V)) card_mask |= MMC_SIGNAL_VOLTAGE_120; break; case MMC_DDR_52: @@ -1775,6 +1793,13 @@ static inline int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, #endif static const struct mode_width_tuning mmc_modes_by_pref[] = { +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + { + .mode = MMC_HS_400, + .widths = MMC_MODE_8BIT, + .tuning = MMC_CMD_SEND_TUNING_BLOCK_HS200 + }, +#endif #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) { .mode = MMC_HS_200, @@ -1818,6 +1843,54 @@ static const struct ext_csd_bus_width { {MMC_MODE_1BIT, false, EXT_CSD_BUS_WIDTH_1}, }; +#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) +static int mmc_select_hs400(struct mmc *mmc) +{ + int err; + + /* Set timing to HS200 for tuning */ + err = mmc_set_card_speed(mmc, MMC_HS_200); + if (err) + return err; + + /* configure the bus mode (host) */ + mmc_select_mode(mmc, MMC_HS_200); + mmc_set_clock(mmc, mmc->tran_speed, false); + + /* execute tuning if needed */ + err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200); + if (err) { + debug("tuning failed\n"); + return err; + } + + /* Set back to HS */ + mmc_set_card_speed(mmc, MMC_HS); + mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false); + + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, + EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG); + if (err) + return err; + + err = mmc_set_card_speed(mmc, MMC_HS_400); + if (err) + return err; + + mmc_select_mode(mmc, MMC_HS_400); + err = mmc_set_clock(mmc, mmc->tran_speed, false); + if (err) + return err; + + return 0; +} +#else +static int mmc_select_hs400(struct mmc *mmc) +{ + return -ENOTSUPP; +} +#endif + #define for_each_supported_width(caps, ddr, ecbv) \ for (ecbv = ext_csd_bus_width;\ ecbv < ext_csd_bus_width + ARRAY_SIZE(ext_csd_bus_width);\ @@ -1843,20 +1916,20 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) 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; } - mmc_set_clock(mmc, mmc->legacy_speed, false); + mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE); 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); + 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); @@ -1871,37 +1944,49 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) goto error; mmc_set_bus_width(mmc, bus_width(ecbw->cap)); - /* configure the bus speed (card) */ - err = mmc_set_card_speed(mmc, mwt->mode); - if (err) - goto error; - - /* - * configure the bus width AND the ddr mode (card) - * The host side will be taken care of in the next step - */ - if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) { - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - ecbw->ext_csd_bits); + if (mwt->mode == MMC_HS_400) { + err = mmc_select_hs400(mmc); + if (err) { + printf("Select HS400 failed %d\n", err); + goto error; + } + } else { + /* configure the bus speed (card) */ + err = mmc_set_card_speed(mmc, mwt->mode); if (err) goto error; - } - /* configure the bus mode (host) */ - mmc_select_mode(mmc, mwt->mode); - mmc_set_clock(mmc, mmc->tran_speed, false); + /* + * configure the bus width AND the ddr mode + * (card). The host side will be taken care + * of in the next step + */ + if (ecbw->ext_csd_bits & EXT_CSD_DDR_FLAG) { + err = mmc_switch(mmc, + EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BUS_WIDTH, + ecbw->ext_csd_bits); + if (err) + goto error; + } + + /* configure the bus mode (host) */ + mmc_select_mode(mmc, mwt->mode); + mmc_set_clock(mmc, mmc->tran_speed, + MMC_CLK_ENABLE); #ifdef MMC_SUPPORTS_TUNING - /* execute tuning if needed */ - if (mwt->tuning) { - err = mmc_execute_tuning(mmc, mwt->tuning); - if (err) { - debug("tuning failed\n"); - goto error; + /* 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); @@ -1921,6 +2006,11 @@ error: return -ENOTSUPP; } +#endif + +#if CONFIG_IS_ENABLED(MMC_TINY) +DEFINE_CACHE_ALIGN_BUFFER(u8, ext_csd_bkup, MMC_MAX_BLOCK_LEN); +#endif static int mmc_startup_v4(struct mmc *mmc) { @@ -1928,6 +2018,35 @@ static int mmc_startup_v4(struct mmc *mmc) u64 capacity; bool has_parts = false; bool part_completed; + 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 + }; + +#if CONFIG_IS_ENABLED(MMC_TINY) + u8 *ext_csd = ext_csd_bkup; + + if (IS_SD(mmc) || mmc->version < MMC_VERSION_4) + return 0; + + if (!mmc->ext_csd) + memset(ext_csd_bkup, 0, sizeof(ext_csd_bkup)); + + err = mmc_send_ext_csd(mmc, ext_csd); + if (err) + goto error; + + /* store the ext csd for future reference */ + if (!mmc->ext_csd) + mmc->ext_csd = ext_csd; +#else ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); if (IS_SD(mmc) || (mmc->version < MMC_VERSION_4)) @@ -1944,8 +2063,13 @@ static int mmc_startup_v4(struct mmc *mmc) if (!mmc->ext_csd) return -ENOMEM; memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN); +#endif + if (ext_csd[EXT_CSD_REV] >= ARRAY_SIZE(mmc_versions)) + return -EINVAL; - if (ext_csd[EXT_CSD_REV] >= 2) { + 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 @@ -1960,30 +2084,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, @@ -2021,6 +2121,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) + @@ -2037,6 +2138,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 @@ -2059,9 +2161,11 @@ static int mmc_startup_v4(struct mmc *mmc) } 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 @@ -2075,7 +2179,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; @@ -2084,17 +2190,21 @@ 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) { +#if !CONFIG_IS_ENABLED(MMC_TINY) free(mmc->ext_csd); +#endif mmc->ext_csd = NULL; } return err; @@ -2215,11 +2325,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 @@ -2241,8 +2353,10 @@ 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; @@ -2266,7 +2380,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); @@ -2277,6 +2393,11 @@ static int mmc_startup(struct mmc *mmc) if (err) return err; +#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_set_bus_width(mmc, 1); +#else if (IS_SD(mmc)) { err = sd_get_capabilities(mmc); if (err) @@ -2288,7 +2409,7 @@ static int mmc_startup(struct mmc *mmc) return err; mmc_select_mode_and_width(mmc, mmc->card_caps); } - +#endif if (err) return err; @@ -2297,7 +2418,9 @@ static int mmc_startup(struct mmc *mmc) /* 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 */ @@ -2325,9 +2448,6 @@ static int mmc_startup(struct mmc *mmc) bdesc->product[0] = 0; bdesc->revision[0] = 0; #endif -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT) - part_init(bdesc); -#endif return 0; } @@ -2371,12 +2491,12 @@ 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 */ /* @@ -2406,7 +2526,7 @@ static void mmc_set_initial_state(struct mmc *mmc) mmc_select_mode(mmc, MMC_LEGACY); mmc_set_bus_width(mmc, 1); - mmc_set_clock(mmc, 0, false); + mmc_set_clock(mmc, 0, MMC_CLK_ENABLE); } static int mmc_power_on(struct mmc *mmc) @@ -2426,13 +2546,13 @@ static int mmc_power_on(struct mmc *mmc) static int mmc_power_off(struct mmc *mmc) { - mmc_set_clock(mmc, 1, true); + mmc_set_clock(mmc, 0, MMC_CLK_DISABLE); #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) { - debug("Error disabling VMMC supply\n"); + pr_debug("Error disabling VMMC supply\n"); return ret; } } @@ -2455,32 +2575,11 @@ static int mmc_power_cycle(struct mmc *mmc) return mmc_power_on(mmc); } -int mmc_start_init(struct mmc *mmc) +int mmc_get_op_cond(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; - - /* we pretend there's no card when init is NULL */ - no_card = mmc_getcd(mmc) == 0; -#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"); -#endif - return -ENOMEDIUM; - } - if (mmc->has_init) return 0; @@ -2503,7 +2602,7 @@ int mmc_start_init(struct mmc *mmc) * 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"); + 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); @@ -2557,6 +2656,40 @@ retry: } } + return err; +} + +int mmc_start_init(struct mmc *mmc) +{ + bool no_card; + int err = 0; + + /* + * 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) + pr_err("MMC: no card present\n"); +#endif + return -ENOMEDIUM; + } + + err = mmc_get_op_cond(mmc); + if (!err) mmc->init_in_progress = 1; @@ -2583,7 +2716,7 @@ static int mmc_complete_init(struct mmc *mmc) int mmc_init(struct mmc *mmc) { int err = 0; - __maybe_unused unsigned start; + __maybe_unused ulong start; #if CONFIG_IS_ENABLED(DM_MMC) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(mmc->dev); @@ -2600,7 +2733,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; } @@ -2628,12 +2761,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;