* [PATCH v2 2/5] mci: introduce new dedicated enum mmc_bus_width type
2023-04-18 9:30 [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Ahmad Fatoum
@ 2023-04-18 9:30 ` Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 3/5] mci: core: factor out MMC bus width selection for reuse Ahmad Fatoum
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2023-04-18 9:30 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
To make it clearer that a bus width of 8 is not equal to integer 8,
let's give it a dedicated type. No functional change.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- new patch
---
drivers/mci/mci-core.c | 6 +++---
include/mci.h | 20 ++++++++++----------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index f647cae8203b..2abed0011722 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -864,7 +864,7 @@ static void mci_set_clock(struct mci *mci, unsigned clock)
* @param mci MCI instance
* @param width New interface bit width (1, 4 or 8)
*/
-static void mci_set_bus_width(struct mci *mci, unsigned width)
+static void mci_set_bus_width(struct mci *mci, enum mci_bus_width width)
{
struct mci_host *host = mci->host;
@@ -1055,7 +1055,7 @@ static void mci_extract_card_dsr_imp_from_csd(struct mci *mci)
mci->dsr_imp = UNSTUFF_BITS(mci->csd, 76, 1);
}
-static int mmc_compare_ext_csds(struct mci *mci, unsigned bus_width)
+static int mmc_compare_ext_csds(struct mci *mci, enum mci_bus_width bus_width)
{
u8 *bw_ext_csd;
int err;
@@ -1176,7 +1176,7 @@ static int mci_startup_mmc(struct mci *mci)
EXT_CSD_BUS_WIDTH_4,
EXT_CSD_BUS_WIDTH_8,
};
- static unsigned bus_widths[] = {
+ static enum mci_bus_width bus_widths[] = {
MMC_BUS_WIDTH_4,
MMC_BUS_WIDTH_8,
};
diff --git a/include/mci.h b/include/mci.h
index c38567303241..a3f6d619b361 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -410,16 +410,16 @@ enum mci_timing {
MMC_TIMING_MMC_HS400 = 8,
};
-struct mci_ios {
- unsigned int clock; /* clock rate */
-
- unsigned char bus_width; /* data bus width */
-
-#define MMC_BUS_WIDTH_1 0
-#define MMC_BUS_WIDTH_4 2
-#define MMC_BUS_WIDTH_8 3
+enum mci_bus_width {
+ MMC_BUS_WIDTH_1 = 0,
+ MMC_BUS_WIDTH_4 = 2,
+ MMC_BUS_WIDTH_8 = 3,
+};
- enum mci_timing timing; /* timing specification used */
+struct mci_ios {
+ unsigned int clock; /* clock rate */
+ enum mci_bus_width bus_width; /* data bus width */
+ enum mci_timing timing; /* timing specification used */
};
struct mci;
@@ -434,7 +434,7 @@ struct mci_host {
unsigned f_min; /**< host interface lower limit */
unsigned f_max; /**< host interface upper limit */
unsigned clock; /**< Current clock used to talk to the card */
- unsigned bus_width; /**< used data bus width to the card */
+ enum mci_bus_width bus_width; /**< used data bus width to the card */
enum mci_timing timing; /**< used timing specification to the card */
unsigned max_req_size;
unsigned dsr_val; /**< optional dsr value */
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 3/5] mci: core: factor out MMC bus width selection for reuse
2023-04-18 9:30 [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 2/5] mci: introduce new dedicated enum mmc_bus_width type Ahmad Fatoum
@ 2023-04-18 9:30 ` Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 4/5] mci: add eMMC DDR52 support Ahmad Fatoum
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2023-04-18 9:30 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Higher speed modes like DDR52 and HS200 can operate at both 8-bit and
4-bit bus widths. To make it easier to support these, split up
mci_startup_mmc, so the refactored parts can be called with different
timings later on.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- new patch
---
drivers/mci/mci-core.c | 95 ++++++++++++++++++++++++++++--------------
1 file changed, 64 insertions(+), 31 deletions(-)
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 2abed0011722..bd5299e7a4f8 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -1167,34 +1167,51 @@ static int mci_startup_sd(struct mci *mci)
return 0;
}
-static int mci_startup_mmc(struct mci *mci)
+static u32 mci_bus_width_ext_csd_bits(enum mci_bus_width bus_width)
+{
+ switch (bus_width) {
+ case MMC_BUS_WIDTH_8:
+ return EXT_CSD_BUS_WIDTH_8;
+ case MMC_BUS_WIDTH_4:
+ return EXT_CSD_BUS_WIDTH_4;
+ case MMC_BUS_WIDTH_1:
+ default:
+ return EXT_CSD_BUS_WIDTH_1;
+ }
+}
+
+static int mci_mmc_try_bus_width(struct mci *mci, enum mci_bus_width bus_width)
{
- struct mci_host *host = mci->host;
+ u32 ext_csd_bits;
int err;
+
+ ext_csd_bits = mci_bus_width_ext_csd_bits(bus_width);
+
+ err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits);
+ if (err < 0)
+ return err;
+
+ mci_set_bus_width(mci, bus_width);
+
+ err = mmc_compare_ext_csds(mci, bus_width);
+ if (err < 0)
+ return err;
+
+ return bus_width;
+}
+
+static int mci_mmc_select_bus_width(struct mci *mci)
+{
+ struct mci_host *host = mci->host;
+ int ret;
int idx = 0;
- static unsigned ext_csd_bits[] = {
- EXT_CSD_BUS_WIDTH_4,
- EXT_CSD_BUS_WIDTH_8,
- };
static enum mci_bus_width bus_widths[] = {
MMC_BUS_WIDTH_4,
MMC_BUS_WIDTH_8,
};
- /* if possible, speed up the transfer */
- if (mci_caps(mci) & MMC_CAP_MMC_HIGHSPEED) {
- if (mci->card_caps & MMC_CAP_MMC_HIGHSPEED_52MHZ)
- mci->tran_speed = 52000000;
- else
- mci->tran_speed = 26000000;
-
- host->timing = MMC_TIMING_MMC_HS;
- }
-
- mci_set_clock(mci, mci->tran_speed);
-
if (!(host->host_caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
- return 0;
+ return MMC_BUS_WIDTH_1;
/*
* Unlike SD, MMC cards dont have a configuration register to notify
@@ -1206,7 +1223,6 @@ static int mci_startup_mmc(struct mci *mci)
idx = 1;
for (; idx >= 0; idx--) {
-
/*
* Host is capable of 8bit transfer, then switch
* the device to work in 8bit transfer mode. If the
@@ -1214,21 +1230,38 @@ static int mci_startup_mmc(struct mci *mci)
* 4bit transfer mode. On success set the corresponding
* bus width on the host.
*/
- err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]);
- if (err) {
- if (idx == 0)
- dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", err);
- continue;
- }
+ ret = mci_mmc_try_bus_width(mci, bus_widths[idx]);
+ if (ret > 0)
+ break;
+ }
- mci_set_bus_width(mci, bus_widths[idx]);
+ return ret;
+}
- err = mmc_compare_ext_csds(mci, bus_widths[idx]);
- if (!err)
- break;
+static int mci_startup_mmc(struct mci *mci)
+{
+ struct mci_host *host = mci->host;
+ int ret;
+
+ /* if possible, speed up the transfer */
+ if (mci_caps(mci) & MMC_CAP_MMC_HIGHSPEED) {
+ if (mci->card_caps & MMC_CAP_MMC_HIGHSPEED_52MHZ)
+ mci->tran_speed = 52000000;
+ else
+ mci->tran_speed = 26000000;
+
+ host->timing = MMC_TIMING_MMC_HS;
}
- return err;
+ mci_set_clock(mci, mci->tran_speed);
+
+ ret = mci_mmc_select_bus_width(mci);
+ if (ret < 0) {
+ dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
}
/**
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 4/5] mci: add eMMC DDR52 support
2023-04-18 9:30 [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 2/5] mci: introduce new dedicated enum mmc_bus_width type Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 3/5] mci: core: factor out MMC bus width selection for reuse Ahmad Fatoum
@ 2023-04-18 9:30 ` Ahmad Fatoum
2023-04-18 9:30 ` [PATCH v2 5/5] mci: imx-esdhc: add uSDHC " Ahmad Fatoum
2023-04-21 6:29 ` [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2023-04-18 9:30 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
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>
---
v1 -> v2:
- don't attempt 8-bit DDR if 8-bit SDR is not supported
- try SDR speed modes first before going DDR
- refactor a bit, so extension for HS200/HS400 is easier
---
drivers/mci/mci-core.c | 60 +++++++++++++++++++++++++++++++++++-------
include/mci.h | 19 +++++++++++++
2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index bd5299e7a4f8..6d0d6473770c 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 " : "");
}
/**
diff --git a/include/mci.h b/include/mci.h
index a3f6d619b361..3e93f378e4a3 100644
--- a/include/mci.h
+++ b/include/mci.h
@@ -51,6 +51,11 @@
#define MMC_CAP_SD_HIGHSPEED (1 << 3)
#define MMC_CAP_MMC_HIGHSPEED (1 << 4)
#define MMC_CAP_MMC_HIGHSPEED_52MHZ (1 << 5)
+#define MMC_CAP_MMC_3_3V_DDR (1 << 7) /* Host supports eMMC DDR 3.3V */
+#define MMC_CAP_MMC_1_8V_DDR (1 << 8) /* Host supports eMMC DDR 1.8V */
+#define MMC_CAP_MMC_1_2V_DDR (1 << 9) /* Host supports eMMC DDR 1.2V */
+#define MMC_CAP_DDR (MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR | \
+ MMC_CAP_1_2V_DDR)
/* Mask of all caps for bus width */
#define MMC_CAP_BIT_DATA_MASK (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)
@@ -308,6 +313,7 @@
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
+#define EXT_CSD_DDR_FLAG BIT(2) /* Flag for DDR mode */
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_STATUS(x) (x & 0xFFF9A000)
@@ -410,6 +416,19 @@ enum mci_timing {
MMC_TIMING_MMC_HS400 = 8,
};
+static inline bool mci_timing_is_ddr(enum mci_timing timing)
+{
+ switch (timing) {
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_MMC_HS200:
+ case MMC_TIMING_MMC_DDR52:
+ case MMC_TIMING_MMC_HS400:
+ return true;
+ default:
+ return false;
+ }
+}
+
enum mci_bus_width {
MMC_BUS_WIDTH_1 = 0,
MMC_BUS_WIDTH_4 = 2,
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 5/5] mci: imx-esdhc: add uSDHC eMMC DDR52 support
2023-04-18 9:30 [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Ahmad Fatoum
` (2 preceding siblings ...)
2023-04-18 9:30 ` [PATCH v2 4/5] mci: add eMMC DDR52 support Ahmad Fatoum
@ 2023-04-18 9:30 ` Ahmad Fatoum
2023-04-21 6:29 ` [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Ahmad Fatoum @ 2023-04-18 9:30 UTC (permalink / raw)
To: barebox; +Cc: Marco Felsch, Ahmad Fatoum
The uSDHC available with the i.MX6/7/8 SoCs has support for DDR
clock operation. This is enabled by flipping a bit in
IMX_SDHCI_MIXCTRL and adjusting the clock divider calculation to
account for the automatic internal halving of the clock.
Let's do that to speed up boot from eMMC. How much effect this has
in practice is not constant. Comparing two Kingston eMMCs: DDR on the
older v4.5 connected to an i.MX6 did not yield any difference. On the
newer v5.1 one connected to an i.MX8MM, I observe a 70% improvement in
sequential read throughput: from 40MiB/s to 69.5 MiB/s.
Reviewed-by: Marco Felsch <m.felsch@pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- added Marco's Reviewed-by
---
drivers/mci/imx-esdhc-common.c | 1 +
drivers/mci/imx-esdhc.c | 45 +++++++++++++++++++++++++++++-----
drivers/mci/imx-esdhc.h | 14 +++++++++++
3 files changed, 54 insertions(+), 6 deletions(-)
diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c
index 27293e44b724..3c1ff9882432 100644
--- a/drivers/mci/imx-esdhc-common.c
+++ b/drivers/mci/imx-esdhc-common.c
@@ -160,6 +160,7 @@ int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd,
mixctrl = xfertyp;
/* Keep the bits 22-25 of the register as is */
mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22));
+ mixctrl |= mci_timing_is_ddr(host->sdhci.timing) ? MIX_CTRL_DDREN : 0;
sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
}
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 2e2bc14ef95c..94f18fe2b3cf 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -43,9 +43,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
return __esdhc_send_cmd(host, cmd, data);
}
-static void set_sysctl(struct mci_host *mci, u32 clock)
+static void set_sysctl(struct mci_host *mci, u32 clock, bool ddr)
{
- int div, pre_div;
+ int div, pre_div, ddr_pre_div = ddr ? 2 : 1;
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
int sdhc_clk = clk_get_rate(host->clk);
u32 clk;
@@ -65,11 +65,11 @@ static void set_sysctl(struct mci_host *mci, u32 clock)
pre_div = 1;
else if (sdhc_clk / 16 > clock)
for (; pre_div < 256; pre_div *= 2)
- if ((sdhc_clk / pre_div) <= (clock * 16))
+ if ((sdhc_clk / (pre_div * ddr_pre_div)) <= (clock * 16))
break;
for (div = 1; div <= 16; div++)
- if ((sdhc_clk / (div * pre_div)) <= clock)
+ if ((sdhc_clk / (div * pre_div * ddr_pre_div)) <= clock)
break;
cur_clock = sdhc_clk / pre_div / div;
@@ -103,12 +103,42 @@ static void set_sysctl(struct mci_host *mci, u32 clock)
10 * MSECOND);
}
+static void esdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing)
+{
+ u32 mixctrl;
+
+ mixctrl = sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL);
+ mixctrl &= ~MIX_CTRL_DDREN;
+
+ switch (timing) {
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_MMC_DDR52:
+ mixctrl |= MIX_CTRL_DDREN;
+ sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
+ break;
+ default:
+ sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl);
+ }
+
+ host->sdhci.timing = timing;
+}
+
static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios)
{
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ /*
+ * call esdhc_set_timing() before update the clock rate,
+ * This is because current we support DDR and SDR timing,
+ * Once the DDR_EN bit is set, the card clock will be
+ * divide by 2 automatically. So need to do this before
+ * setting clock rate.
+ */
+ if (esdhc_is_usdhc(host) && host->sdhci.timing != ios->timing)
+ esdhc_set_timing(host, ios->timing);
+
/* Set the clock speed */
- set_sysctl(mci, ios->clock);
+ set_sysctl(mci, ios->clock, mci_timing_is_ddr(ios->timing));
/* Set the bus width */
esdhc_clrbits32(host, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL,
@@ -206,7 +236,7 @@ static int esdhc_init(struct mci_host *mci, struct device *dev)
esdhc_setbits32(host, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP);
/* Set the initial clock speed */
- set_sysctl(mci, 400000);
+ set_sysctl(mci, 400000, false);
sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, SDHCI_INT_CMD_COMPLETE |
SDHCI_INT_XFER_COMPLETE | SDHCI_INT_CARD_INT |
@@ -285,6 +315,9 @@ static int fsl_esdhc_probe(struct device *dev)
if (ret)
goto err_clk_disable;
+ if (esdhc_is_usdhc(host))
+ mci->host_caps |= MMC_CAP_MMC_3_3V_DDR | MMC_CAP_MMC_1_8V_DDR;
+
rate = clk_get_rate(host->clk);
host->mci.f_min = rate >> 12;
if (host->mci.f_min < 200000)
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index 0d8f157a7615..b14039757a7a 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -41,6 +41,20 @@
#define IMX_SDHCI_WML 0x44
#define IMX_SDHCI_MIXCTRL 0x48
+/* Imported from Linux Kernel drivers/mmc/host/sdhci-esdhc-imx.c */
+#define MIX_CTRL_DDREN BIT(3)
+#define MIX_CTRL_DTDSEL_READ BIT(4)
+#define MIX_CTRL_AC23EN BIT(7)
+#define MIX_CTRL_EXE_TUNE BIT(22)
+#define MIX_CTRL_SMPCLK_SEL BIT(23)
+#define MIX_CTRL_AUTO_TUNE_EN BIT(24)
+#define MIX_CTRL_FBCLK_SEL BIT(25)
+#define MIX_CTRL_HS400_EN BIT(26)
+#define MIX_CTRL_HS400_ES BIT(27)
+/* Bits 3 and 6 are not SDHCI standard definitions */
+#define MIX_CTRL_SDHCI_MASK 0xb7
+/* Tuning bits */
+#define MIX_CTRL_TUNING_MASK 0x03c00000
#define IMX_SDHCI_DLL_CTRL 0x60
#define IMX_SDHCI_MIX_CTRL_FBCLK_SEL BIT(25)
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants
2023-04-18 9:30 [PATCH v2 1/5] mci: core: drop unused DDR/SDR constants Ahmad Fatoum
` (3 preceding siblings ...)
2023-04-18 9:30 ` [PATCH v2 5/5] mci: imx-esdhc: add uSDHC " Ahmad Fatoum
@ 2023-04-21 6:29 ` Sascha Hauer
4 siblings, 0 replies; 6+ messages in thread
From: Sascha Hauer @ 2023-04-21 6:29 UTC (permalink / raw)
To: Ahmad Fatoum; +Cc: barebox
On Tue, Apr 18, 2023 at 11:30:36AM +0200, Ahmad Fatoum wrote:
> These macros are unused and will be replaced by their Linux counterparts
> in a follow up patch, so drop them.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> ---
> v1 -> v2:
> - new patch
> ---
> include/mci.h | 6 ------
> 1 file changed, 6 deletions(-)
Applied, thanks
Sascha
>
> diff --git a/include/mci.h b/include/mci.h
> index d356f071f7f2..c38567303241 100644
> --- a/include/mci.h
> +++ b/include/mci.h
> @@ -420,12 +420,6 @@ struct mci_ios {
> #define MMC_BUS_WIDTH_8 3
>
> enum mci_timing timing; /* timing specification used */
> -
> -#define MMC_SDR_MODE 0
> -#define MMC_1_2V_DDR_MODE 1
> -#define MMC_1_8V_DDR_MODE 2
> -#define MMC_1_2V_SDR_MODE 3
> -#define MMC_1_8V_SDR_MODE 4
> };
>
> struct mci;
> --
> 2.39.2
>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply [flat|nested] 6+ messages in thread