* [PATCH 2/3] mci: imx-esdhc: Layerscape: fix clock setup
2023-11-22 10:53 [PATCH 1/3] mci: imx-esdhc: add layerscape flag Sascha Hauer
@ 2023-11-22 10:53 ` Sascha Hauer
2023-11-22 10:53 ` [PATCH 3/3] mci: imx-esdhc: Layerscape: add eMMC DDR52 support Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2023-11-22 10:53 UTC (permalink / raw)
To: Barebox List
Set the PCS bit in the ESDHCCTL register. With this Peripheral/2 clock
is used which is the clock we are actually calculating the dividers for.
As the input clock is only half of the expected clock we have to account
for this in set_sysctl().
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mci/imx-esdhc.c | 8 ++++++--
drivers/mci/imx-esdhc.h | 2 +-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 90a6c12439..92aea9ed9d 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -51,6 +51,9 @@ static void set_sysctl(struct mci_host *mci, u32 clock, bool ddr)
u32 clk;
unsigned long cur_clock;
+ if (esdhc_is_layerscape(host))
+ sdhc_clk >>= 1;
+
/*
* With eMMC and imx53 (sdhc_clk=200MHz) a pre_div of 1 results in
* pre_div=1,div=4 (=50MHz)
@@ -231,9 +234,10 @@ static int esdhc_init(struct mci_host *mci, struct device *dev)
/* RSTA doesn't reset MMC_BOOT register, so manually reset it */
sdhci_write32(&host->sdhci, SDHCI_MMC_BOOT, 0);
- /* Enable cache snooping */
if (esdhc_is_layerscape(host))
- esdhc_setbits32(host, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP);
+ esdhc_setbits32(host, ESDHC_DMA_SYSCTL,
+ ESDHC_SYSCTL_DMA_SNOOP | /* Enable cache snooping */
+ ESDHC_SYSCTL_PERIPHERAL_CLK_SEL);
/* Set the initial clock speed */
set_sysctl(mci, 400000, false);
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index 6810039a96..047c32615d 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -60,7 +60,7 @@
#define ESDHC_DMA_SYSCTL 0x40c /* Layerscape specific */
#define ESDHC_SYSCTL_DMA_SNOOP BIT(6)
-
+#define ESDHC_SYSCTL_PERIPHERAL_CLK_SEL BIT(19)
/*
* The CMDTYPE of the CMD register (offset 0xE) should be set to
--
2.39.2
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 3/3] mci: imx-esdhc: Layerscape: add eMMC DDR52 support
2023-11-22 10:53 [PATCH 1/3] mci: imx-esdhc: add layerscape flag Sascha Hauer
2023-11-22 10:53 ` [PATCH 2/3] mci: imx-esdhc: Layerscape: fix clock setup Sascha Hauer
@ 2023-11-22 10:53 ` Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2023-11-22 10:53 UTC (permalink / raw)
To: Barebox List
The Layerscape variant of the imx-esdhc also supports eMMC DDR52,
add support for this mode.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/mci/imx-esdhc.c | 41 ++++++++++++++++++++++++++++++++++++-----
drivers/mci/imx-esdhc.h | 2 ++
2 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 92aea9ed9d..e1d4e3c2d4 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -45,12 +45,15 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
static void set_sysctl(struct mci_host *mci, u32 clock, bool ddr)
{
- int div, pre_div, ddr_pre_div = ddr ? 2 : 1;
+ int div, pre_div, ddr_pre_div = 1;
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
int sdhc_clk = clk_get_rate(host->clk);
u32 clk;
unsigned long cur_clock;
+ if (esdhc_is_usdhc(host) && ddr)
+ ddr_pre_div = 2;
+
if (esdhc_is_layerscape(host))
sdhc_clk >>= 1;
@@ -106,7 +109,7 @@ static void set_sysctl(struct mci_host *mci, u32 clock, bool ddr)
10 * MSECOND);
}
-static void esdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing)
+static void usdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing)
{
u32 mixctrl;
@@ -126,6 +129,30 @@ static void esdhc_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing
host->sdhci.timing = timing;
}
+static void layerscape_set_timing(struct fsl_esdhc_host *host, enum mci_timing timing)
+{
+ esdhc_clrbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
+ SYSCTL_CKEN);
+
+ switch (timing) {
+ case MMC_TIMING_UHS_DDR50:
+ case MMC_TIMING_MMC_DDR52:
+ esdhc_clrsetbits32(host, SDHCI_ACMD12_ERR__HOST_CONTROL2,
+ SDHCI_ACMD12_ERR__HOST_CONTROL2_UHSM,
+ FIELD_PREP(SDHCI_ACMD12_ERR__HOST_CONTROL2_UHSM, 4));
+ break;
+ default:
+ esdhc_clrbits32(host, SDHCI_ACMD12_ERR__HOST_CONTROL2,
+ SDHCI_ACMD12_ERR__HOST_CONTROL2_UHSM);
+ break;
+ }
+
+ esdhc_setbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET,
+ SYSCTL_CKEN);
+
+ 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);
@@ -137,8 +164,12 @@ static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios)
* 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);
+ if (host->sdhci.timing != ios->timing) {
+ if (esdhc_is_usdhc(host))
+ usdhc_set_timing(host, ios->timing);
+ else if (esdhc_is_layerscape(host))
+ layerscape_set_timing(host, ios->timing);
+ }
/* Set the clock speed */
set_sysctl(mci, ios->clock, mci_timing_is_ddr(ios->timing));
@@ -319,7 +350,7 @@ static int fsl_esdhc_probe(struct device *dev)
if (ret)
goto err_clk_disable;
- if (esdhc_is_usdhc(host))
+ if (esdhc_is_usdhc(host) || esdhc_is_layerscape(host))
mci->host_caps |= MMC_CAP_MMC_3_3V_DDR | MMC_CAP_MMC_1_8V_DDR;
rate = clk_get_rate(host->clk);
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
index 047c32615d..eff556f2ff 100644
--- a/drivers/mci/imx-esdhc.h
+++ b/drivers/mci/imx-esdhc.h
@@ -39,6 +39,8 @@
#define PIO_TIMEOUT 100000
+#define SDHCI_ACMD12_ERR__HOST_CONTROL2_UHSM GENMASK(18, 16) /* Layerscape specific */
+
#define IMX_SDHCI_WML 0x44
#define IMX_SDHCI_MIXCTRL 0x48
/* Imported from Linux Kernel drivers/mmc/host/sdhci-esdhc-imx.c */
--
2.39.2
^ permalink raw reply [flat|nested] 3+ messages in thread