summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2023-04-18 11:30:39 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2023-04-21 08:29:45 +0200
commit3a3cd967288055777a692fabba7c94cf9259e500 (patch)
treefa05223ae5cd3d32b95ba71f6fecd07c8da7f18f /drivers
parentcf0f1454dae5d9fbebc0e212cdf0a2090f2e64a5 (diff)
downloadbarebox-3a3cd967288055777a692fabba7c94cf9259e500.tar.gz
barebox-3a3cd967288055777a692fabba7c94cf9259e500.tar.xz
mci: add eMMC DDR52 support
The maximum card frequency that can be configured by barebox currently is 50MHz for SD and 52MHz for eMMC. Higher speed modes require runtime voltage switching or tuning sequences, which are not yet implemented. Only exception is eMMC's DDR52: This mode was first introduced with MMC 4.4 and can be used even at 3.3V. This commit adds DDR52 support to the core. This introduces no functional change, because host controllers must opt-in by setting the appropriate host capabilities. In cases where it's enabled, bus width determination happens as usual and then if possible, the resulting bus width will be attempted with DDR. If that fails, we revert back to SDR. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20230418093040.1865982-4-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mci/mci-core.c60
1 files changed, 51 insertions, 9 deletions
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index bd5299e7a4..6d0d647377 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -135,6 +135,9 @@ static int mci_set_blocklen(struct mci *mci, unsigned len)
{
struct mci_cmd cmd;
+ if (mci->host->timing == MMC_TIMING_MMC_DDR52)
+ return 0;
+
mci_setup_cmd(&cmd, MMC_CMD_SET_BLOCKLEN, len, MMC_RSP_R1);
return mci_send_cmd(mci, &cmd, NULL);
}
@@ -649,11 +652,15 @@ static int mmc_change_freq(struct mci *mci)
return 0;
}
- /* High Speed is set, there are two types: 52MHz and 26MHz */
- if (cardtype & EXT_CSD_CARD_TYPE_52)
- mci->card_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED;
- else
- mci->card_caps |= MMC_CAP_MMC_HIGHSPEED;
+ mci->card_caps |= MMC_CAP_MMC_HIGHSPEED;
+
+ /* High Speed is set, there are three types: 26MHz, 52MHz, 52MHz DDR */
+ if (cardtype & EXT_CSD_CARD_TYPE_52) {
+ mci->card_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ;
+
+ if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V)
+ mci->card_caps |= MMC_CAP_MMC_3_3V_DDR | MMC_CAP_MMC_1_8V_DDR;
+ }
if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) &&
mci->ext_csd[EXT_CSD_REV] >= 3 && mci->ext_csd[EXT_CSD_BOOT_SIZE_MULT]) {
@@ -1180,17 +1187,25 @@ static u32 mci_bus_width_ext_csd_bits(enum mci_bus_width bus_width)
}
}
-static int mci_mmc_try_bus_width(struct mci *mci, enum mci_bus_width bus_width)
+static int mci_mmc_try_bus_width(struct mci *mci, enum mci_bus_width bus_width,
+ enum mci_timing timing)
{
u32 ext_csd_bits;
int err;
+ dev_dbg(&mci->dev, "attempting buswidth %u%s\n", 1 << bus_width,
+ mci_timing_is_ddr(timing) ? " (DDR)" : "");
+
ext_csd_bits = mci_bus_width_ext_csd_bits(bus_width);
+ if (mci_timing_is_ddr(timing))
+ ext_csd_bits |= EXT_CSD_DDR_FLAG;
+
err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits);
if (err < 0)
return err;
+ mci->host->timing = timing;
mci_set_bus_width(mci, bus_width);
err = mmc_compare_ext_csds(mci, bus_width);
@@ -1230,7 +1245,7 @@ static int mci_mmc_select_bus_width(struct mci *mci)
* 4bit transfer mode. On success set the corresponding
* bus width on the host.
*/
- ret = mci_mmc_try_bus_width(mci, bus_widths[idx]);
+ ret = mci_mmc_try_bus_width(mci, bus_widths[idx], host->timing);
if (ret > 0)
break;
}
@@ -1238,6 +1253,24 @@ static int mci_mmc_select_bus_width(struct mci *mci)
return ret;
}
+static int mci_mmc_select_hs_ddr(struct mci *mci)
+{
+ struct mci_host *host = mci->host;
+ int ret;
+
+ if (!(mci_caps(mci) & MMC_CAP_MMC_1_8V_DDR))
+ return 0;
+
+ ret = mci_mmc_try_bus_width(mci, host->bus_width, MMC_TIMING_MMC_DDR52);
+ if (ret < 0)
+ return mci_mmc_try_bus_width(mci, host->bus_width, MMC_TIMING_MMC_HS);
+
+ mci->read_bl_len = SECTOR_SIZE;
+ mci->write_bl_len = SECTOR_SIZE;
+
+ return 0;
+}
+
static int mci_startup_mmc(struct mci *mci)
{
struct mci_host *host = mci->host;
@@ -1255,7 +1288,11 @@ static int mci_startup_mmc(struct mci *mci)
mci_set_clock(mci, mci->tran_speed);
+ /* find out maximum bus width and then try DDR if supported */
ret = mci_mmc_select_bus_width(mci);
+ if (ret > MMC_BUS_WIDTH_1 && mci->tran_speed == 52000000)
+ ret = mci_mmc_select_hs_ddr(mci);
+
if (ret < 0) {
dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", ret);
return ret;
@@ -1687,6 +1724,8 @@ static const char *mci_timing_tostr(unsigned timing)
return "MMC HS";
case MMC_TIMING_SD_HS:
return "SD HS";
+ case MMC_TIMING_MMC_DDR52:
+ return "MMC DDR52";
default:
return "unknown"; /* shouldn't happen */
}
@@ -1694,12 +1733,15 @@ static const char *mci_timing_tostr(unsigned timing)
static void mci_print_caps(unsigned caps)
{
- printf(" capabilities: %s%s%s%s%s\n",
+ printf(" capabilities: %s%s%s%s%s%s%s%s\n",
caps & MMC_CAP_4_BIT_DATA ? "4bit " : "",
caps & MMC_CAP_8_BIT_DATA ? "8bit " : "",
caps & MMC_CAP_SD_HIGHSPEED ? "sd-hs " : "",
caps & MMC_CAP_MMC_HIGHSPEED ? "mmc-hs " : "",
- caps & MMC_CAP_MMC_HIGHSPEED_52MHZ ? "mmc-52MHz " : "");
+ caps & MMC_CAP_MMC_HIGHSPEED_52MHZ ? "mmc-52MHz " : "",
+ caps & MMC_CAP_MMC_3_3V_DDR ? "ddr-3.3v " : "",
+ caps & MMC_CAP_MMC_1_8V_DDR ? "ddr-1.8v " : "",
+ caps & MMC_CAP_MMC_1_2V_DDR ? "ddr-1.2v " : "");
}
/**