Hello Haibo, > -----Original Message----- > From: haibo.c...@nxp.com <haibo.c...@nxp.com> > Sent: Wednesday, January 27, 2021 11:47 AM > To: peng....@nxp.com; u-boot@lists.denx.de > Cc: haibo.c...@nxp.com; uboot-...@nxp.com; thar...@gateworks.com; > ZHIZHIKIN Andrey <andrey.zhizhi...@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.c...@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@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@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.c...@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