[PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON to control card clock output
ZHIZHIKIN Andrey
andrey.zhizhikin at leica-geosystems.com
Mon Feb 1 10:52:06 CET 2021
Hello Haibo,
> -----Original Message-----
> From: haibo.chen at nxp.com <haibo.chen at nxp.com>
> Sent: Wednesday, January 27, 2021 11:47 AM
> To: peng.fan at nxp.com; u-boot at lists.denx.de
> Cc: haibo.chen at nxp.com; uboot-imx at nxp.com; tharvey at gateworks.com;
> ZHIZHIKIN Andrey <andrey.zhizhikin at leica-geosystems.com>
> Subject: [PATCH] mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON to
> control card clock output
>
> This email is not from Hexagon’s Office 365 instance. Please be careful while
> clicking links, opening attachments, or replying to this email.
>
>
> From: Haibo Chen <haibo.chen at nxp.com>
>
> For FSL_USDHC, it do not implement VENDORSPEC_CKEN/PEREN/HCKEN/IPGEN,
> these are reserved bits. Instead, use VENDORSPEC_FRC_SDCLK_ON to gate
> on/off the card clock output.
>
> After commit b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0() support"),
> we meet SD3.0 card can't work at UHS mode, mmc_switch_voltage() fail because
> the second mmc_wait_dat0 return -ETIMEDOUT. According to SD spec, during
> voltage switch, need to gate off/on the card clock. If not set the FRC_SDCLK_ON,
> after CMD11, hardware will gate off the card clock automatically, so card do not
> detect the clock off/on behavior, so will draw the data0 line low until next
> command.
>
> Fixes: b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0() support")
This patch does not fix the switch of uSDHC to 1v8...
I've applied it locally on the imx8mmevk, and had following log during the boot when tried
to query SD Card info:
-----------------------------------------------
U-Boot SPL 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)
Normal Boot
WDT: Started with servicing (60s timeout)
Trying to boot from MMC1
NOTICE: BL31: v2.2(release):rel_imx_5.4.70_2.3.0-0-gf1d7187f2
NOTICE: BL31: Built : 22:29:05, Jan 17 2021
U-Boot 2021.01-01004-gb852007333 (Feb 01 2021 - 09:45:42 +0100)
CPU: Freescale i.MX8MMQ rev1.0 at 1200 MHz
Reset cause: POR
Model: FSL i.MX8MM EVK board
DRAM: 2 GiB
WDT: Started with servicing (60s timeout)
MMC: FSL_SDHC: 1, FSL_SDHC: 2
Loading Environment from MMC... Run CMD11 1.8V switch
Card did not respond to voltage select! : -110
*** Warning - No block device, using default environment
In: serial
Out: serial
Err: serial
Net: eth0: ethernet at 30be0000
Hit any key to stop autoboot: 0
u-boot=> mmc dev 1
Card did not respond to voltage select! : -110
u-boot=> mmc info
MMC Device 0 not found
no mmc device at slot 0
u-boot=> mmc dev 2
switch to partitions #0, OK
mmc2(part 0) is current device
u-boot=> mmc info
Device: FSL_SDHC
Manufacturer ID: 45
OEM: 100
Name: DG401
Bus Speed: 200000000
Mode: HS400ES (200MHz)
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 14.7 GiB
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 14.7 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
Boot area 0 is not write protected
Boot area 1 is not write protected
-----------------------------------------------
Note, that eMMC is not affected and is operating in HS400ES mode without any issues.
Reverting patch b5874b552ffa ("mmc: fsl_esdhc_imx: add wait_dat0() support") with this
patch applied in tree does switch the SD Card to high-speed mode, following log is produced:
-----------------------------------------------
U-Boot SPL 2021.01-01005-gb8aeb689a2 (Feb 01 2021 - 10:38:01 +0100)
Normal Boot
WDT: Started with servicing (60s timeout)
Trying to boot from MMC1
NOTICE: BL31: v2.2(release):rel_imx_5.4.70_2.3.0-0-gf1d7187f2
NOTICE: BL31: Built : 22:29:05, Jan 17 2021
U-Boot 2021.01-01005-gb8aeb689a2 (Feb 01 2021 - 10:38:01 +0100)
CPU: Freescale i.MX8MMQ rev1.0 at 1200 MHz
Reset cause: POR
Model: FSL i.MX8MM EVK board
DRAM: 2 GiB
WDT: Started with servicing (60s timeout)
MMC: FSL_SDHC: 1, FSL_SDHC: 2
Loading Environment from MMC... Run CMD11 1.8V switch
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: eth0: ethernet at 30be0000
Hit any key to stop autoboot: 0
u-boot=> mmc dev 1
Run CMD11 1.8V switch
switch to partitions #0, OK
mmc1 is current device
u-boot=> mmc info
Device: FSL_SDHC
Manufacturer ID: 41
OEM: 3432
Name: SD32G
Bus Speed: 200000000
Mode: UHS SDR104 (208MHz)
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 29.3 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
u-boot=> mmc dev 2
switch to partitions #0, OK
mmc2(part 0) is current device
u-boot=> mmc info
Device: FSL_SDHC
Manufacturer ID: 45
OEM: 100
Name: DG401
Bus Speed: 200000000
Mode: HS400ES (200MHz)
Rd Block Len: 512
MMC version 5.1
High Capacity: Yes
Capacity: 14.7 GiB
Bus Width: 8-bit DDR
Erase Group Size: 512 KiB
HC WP Group Size: 8 MiB
User Capacity: 14.7 GiB WRREL
Boot Capacity: 4 MiB ENH
RPMB Capacity: 4 MiB ENH
Boot area 0 is not write protected
Boot area 1 is not write protected
-----------------------------------------------
I guess high-level modifications are also required, since the uSDHC does not follow the SD
Specification in regards to voltage switching, which is currently implemented in U-Boot,
this patch alone does not solve the mode switch.
> Signed-off-by: Haibo Chen <haibo.chen at nxp.com>
> ---
> drivers/mmc/fsl_esdhc_imx.c | 29 +++++++++++++++++++++--------
> include/fsl_esdhc_imx.h | 2 ++
> 2 files changed, 23 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index
> 8ac859797f..da33ee8253 100644
> --- a/drivers/mmc/fsl_esdhc_imx.c
> +++ b/drivers/mmc/fsl_esdhc_imx.c
> @@ -653,7 +653,10 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct
> mmc *mmc, uint clock)
> clk = (pre_div << 8) | (div << 4);
>
> #ifdef CONFIG_FSL_USDHC
> - esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN);
> + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp &
> PRSSTAT_SDOFF, 100);
> + if (ret)
> + pr_warn("fsl_esdhc_imx: Internal clock never gate
> + off.\n");
> #else
> esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); #endif @@ -665,7 +668,7 @@
> static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
> pr_warn("fsl_esdhc_imx: Internal clock never stabilised.\n");
>
> #ifdef CONFIG_FSL_USDHC
> - esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN |
> VENDORSPEC_CKEN);
> + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> #else
> esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); #endif @@ -
> 720,8 +723,14 @@ static void esdhc_set_strobe_dll(struct mmc *mmc)
> struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
> struct fsl_esdhc *regs = priv->esdhc_regs;
> u32 val;
> + u32 tmp;
> + int ret;
>
> if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) {
> + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp &
> PRSSTAT_SDOFF, 100);
> + if (ret)
> + pr_warn("fsl_esdhc_imx: Internal clock never
> + gate off.\n");
> esdhc_write32(®s->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET);
>
> /*
> @@ -739,6 +748,7 @@ static void esdhc_set_strobe_dll(struct mmc *mmc)
> pr_warn("HS400 strobe DLL status REF not lock!\n");
> if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK))
> pr_warn("HS400 strobe DLL status SLV not lock!\n");
> + esdhc_setbits32(®s->vendorspec,
> + VENDORSPEC_FRC_SDCLK_ON);
> }
> }
>
> @@ -962,14 +972,18 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv
> *priv, struct mmc *mmc) #ifdef MMC_SUPPORTS_TUNING
> if (mmc->clk_disable) {
> #ifdef CONFIG_FSL_USDHC
> - esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN);
> + u32 tmp;
> +
> + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp &
> PRSSTAT_SDOFF, 100);
> + if (ret)
> + pr_warn("fsl_esdhc_imx: Internal clock never
> + gate off.\n");
> #else
> esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); #endif
> } else {
> #ifdef CONFIG_FSL_USDHC
> - esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN |
> - VENDORSPEC_CKEN);
> + esdhc_setbits32(®s->vendorspec,
> + VENDORSPEC_FRC_SDCLK_ON);
> #else
> esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); #endif
> @@ -1045,7 +1059,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv
> *priv, struct mmc *mmc) #ifndef CONFIG_FSL_USDHC
> esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); #else
> - esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN |
> VENDORSPEC_IPGEN);
> + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> #endif
>
> /* Set the initial clock speed */ @@ -1183,8 +1197,7 @@ static int
> fsl_esdhc_init(struct fsl_esdhc_priv *priv,
> esdhc_write32(®s->autoc12err, 0);
> esdhc_write32(®s->clktunectrlstatus, 0); #else
> - esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN |
> - VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
> + esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON);
> #endif
>
> if (priv->vs18_enable)
> diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h index
> 45ed635a77..b092034464 100644
> --- a/include/fsl_esdhc_imx.h
> +++ b/include/fsl_esdhc_imx.h
> @@ -39,6 +39,7 @@
> #define VENDORSPEC_HCKEN 0x00001000
> #define VENDORSPEC_IPGEN 0x00000800
> #define VENDORSPEC_INIT 0x20007809
> +#define VENDORSPEC_FRC_SDCLK_ON 0x00000100
>
> #define IRQSTAT 0x0002e030
> #define IRQSTAT_DMAE (0x10000000)
> @@ -96,6 +97,7 @@
> #define PRSSTAT_CINS (0x00010000)
> #define PRSSTAT_BREN (0x00000800)
> #define PRSSTAT_BWEN (0x00000400)
> +#define PRSSTAT_SDOFF (0x00000080)
> #define PRSSTAT_SDSTB (0X00000008)
> #define PRSSTAT_DLA (0x00000004)
> #define PRSSTAT_CICHB (0x00000002)
> --
> 2.17.1
More information about the U-Boot
mailing list