#include <div64.h>
#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);
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;
cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f;
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 (cardtype & EXT_CSD_CARD_TYPE_52) {
if (cardtype & EXT_CSD_CARD_TYPE_DDR_52)
mmc->card_caps |= MMC_MODE_DDR_52MHz;
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)
return 0;
}
+#endif
#if !CONFIG_IS_ENABLED(DM_MMC)
int mmc_getcd(struct mmc *mmc)
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;
case UHS_SDR104:
speed = UHS_SDR104_BUS_SPEED;
break;
+#endif
default:
return -EINVAL;
}
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);
return 0;
}
-
+#endif
/* frequency bases */
/* divided by 10 to be nice to platforms without floating point */
static const int fbase[] = {
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;
}
#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);
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_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 -ENOMEM;
memcpy(mmc->ext_csd, ext_csd, MMC_MAX_BLOCK_LEN);
- if (ext_csd[EXT_CSD_REV] >= 2) {
+ 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
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,
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) +
if (mmc->high_capacity)
mmc->enh_user_start <<= 9;
}
+#endif
/*
* Host needs to enable ERASE_GRP_DEF bit if device is
}
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
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;
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];
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
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;
/*
* 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);
/* 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 */
static int mmc_power_off(struct mmc *mmc)
{
- mmc_set_clock(mmc, 1, true);
+ 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);
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