mmc: make UHS and HS200 optional
Supporting USH and HS200 increases the code size as it brings in IO voltage
control, tuning and fatter data structures.
Use Kconfig configuration to select which of those features should be
built in.
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c34ab21..2fcdadd 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -51,6 +51,52 @@
are enabled by default, other may require additionnal flags or are
enabled by the host driver.
+config MMC_IO_VOLTAGE
+ bool "Support IO voltage configuration"
+ help
+ IO voltage configuration allows selecting the voltage level of the IO
+ lines (not the level of main supply). This is required for UHS
+ support. For eMMC this not mandatory, but not enabling this option may
+ prevent the driver of using the faster modes.
+
+config SPL_MMC_IO_VOLTAGE
+ bool "Support IO voltage configuration in SPL"
+ default n
+ help
+ IO voltage configuration allows selecting the voltage level of the IO
+ lines (not the level of main supply). This is required for UHS
+ support. For eMMC this not mandatory, but not enabling this option may
+ prevent the driver of using the faster modes.
+
+config MMC_UHS_SUPPORT
+ bool "enable UHS support"
+ depends on MMC_IO_VOLTAGE
+ help
+ The Ultra High Speed (UHS) bus is available on some SDHC and SDXC
+ cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
+ frequency can go up to 208MHz (SDR104)
+
+config SPL_MMC_UHS_SUPPORT
+ bool "enable UHS support in SPL"
+ depends on SPL_MMC_IO_VOLTAGE
+ help
+ The Ultra High Speed (UHS) bus is available on some SDHC and SDXC
+ cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus
+ frequency can go up to 208MHz (SDR104)
+
+config MMC_HS200_SUPPORT
+ bool "enable HS200 support"
+ help
+ The HS200 mode is support by some eMMC. The bus frequency is up to
+ 200MHz. This mode requires tuning the IO.
+
+
+config SPL_MMC_HS200_SUPPORT
+ bool "enable HS200 support in SPL"
+ help
+ The HS200 mode is support by some eMMC. The bus frequency is up to
+ 200MHz. This mode requires tuning the IO.
+
config MMC_VERBOSE
bool "Output more information about the MMC"
default y
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index bfda942..793196b 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -63,6 +63,7 @@
dm_mmc_send_init_stream(mmc->dev);
}
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
@@ -76,6 +77,7 @@
{
return dm_mmc_wait_dat0(mmc->dev, state, timeout);
}
+#endif
int dm_mmc_get_wp(struct udevice *dev)
{
@@ -105,6 +107,7 @@
return dm_mmc_get_cd(mmc->dev);
}
+#ifdef MMC_SUPPORTS_TUNING
int dm_mmc_execute_tuning(struct udevice *dev, uint opcode)
{
struct dm_mmc_ops *ops = mmc_get_ops(dev);
@@ -118,6 +121,7 @@
{
return dm_mmc_execute_tuning(mmc->dev, opcode);
}
+#endif
int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)
{
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index 3fb82d9..400e163 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -59,10 +59,12 @@
#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)
{
@@ -190,14 +192,20 @@
[SD_LEGACY] = 25000000,
[MMC_HS] = 26000000,
[SD_HS] = 50000000,
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
[UHS_SDR12] = 25000000,
[UHS_SDR25] = 50000000,
[UHS_SDR50] = 100000000,
- [UHS_SDR104] = 208000000,
[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
};
if (mode == MMC_LEGACY)
@@ -308,6 +316,7 @@
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,
@@ -375,6 +384,7 @@
return 0;
}
+#endif
static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
lbaint_t blkcnt)
@@ -495,6 +505,7 @@
return 0;
}
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
{
struct mmc_cmd cmd;
@@ -554,6 +565,7 @@
return 0;
}
+#endif
static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
{
@@ -620,12 +632,14 @@
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;
@@ -880,6 +894,7 @@
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;
@@ -903,6 +918,13 @@
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)
{
@@ -1169,7 +1191,9 @@
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_CAP(SD_LEGACY);
@@ -1251,6 +1275,7 @@
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;
@@ -1266,6 +1291,7 @@
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;
}
@@ -1438,10 +1464,12 @@
}
#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)
{
@@ -1507,9 +1535,12 @@
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) {
@@ -1535,13 +1566,22 @@
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,
@@ -1554,14 +1594,17 @@
.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,
@@ -1579,7 +1622,11 @@
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
@@ -1618,6 +1665,7 @@
mmc_select_mode(mmc, mwt->mode);
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,
@@ -1627,6 +1675,7 @@
goto error;
}
}
+#endif
err = sd_read_ssr(mmc);
if (!err)
@@ -1680,6 +1729,7 @@
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)
{
@@ -1716,13 +1766,22 @@
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,
@@ -1832,6 +1891,7 @@
/* configure the bus mode (host) */
mmc_select_mode(mmc, mwt->mode);
mmc_set_clock(mmc, mmc->tran_speed, false);
+#ifdef MMC_SUPPORTS_TUNING
/* execute tuning if needed */
if (mwt->tuning) {
@@ -1841,6 +1901,7 @@
goto error;
}
}
+#endif
/* do a transfer to check the configuration */
err = mmc_read_and_compare_ext_csd(mmc);