> -----Original Message----- > From: Josua Mayer <josua@xxxxxxxxxxxxx> > Sent: 2024年11月1日 19:42 > To: Adrian Hunter <adrian.hunter@xxxxxxxxx>; Bough Chen > <haibo.chen@xxxxxxx>; Ulf Hansson <ulf.hansson@xxxxxxxxxx>; Shawn Guo > <shawnguo@xxxxxxxxxx>; Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>; > Pengutronix Kernel Team <kernel@xxxxxxxxxxxxxx>; Fabio Estevam > <festevam@xxxxxxxxx> > Cc: Mikhail Anikin <mikhail.anikin@xxxxxxxxxxxxx>; Jon Nettleton > <jon@xxxxxxxxxxxxx>; yazan.shhady <yazan.shhady@xxxxxxxxxxxxx>; Rabeeh > Khoury <rabeeh@xxxxxxxxxxxxx>; imx@xxxxxxxxxxxxxxx; > linux-mmc@xxxxxxxxxxxxxxx; dl-S32 <S32@xxxxxxx>; > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; Josua > Mayer <josua@xxxxxxxxxxxxx> > Subject: [PATCH v3 1/2] mmc: host: sdhci-esdhc-imx: implement emmc > hardware reset > > NXP ESDHC supports control of native emmc reset signal when pinmux is set > accordingly, using uSDHCx_SYS_CTRL register IPP_RST_N bit. > Documentation is available in NXP i.MX6Q Reference Manual. > > Implement the hw_reset function in sdhci_ops asserting reset for at least 1us > and waiting at least 200us after deassertion. > Lower bounds are based on: > JEDEC Standard No. 84-B51, 6.15.10 H/W Reset Operation, page 159. > Upper bounds are chosen allowing flexibility to the scheduler. > > Tested on SolidRun i.MX8DXL SoM with a scope, and confirmed that eMMC is > still accessible after boot: > - eMMC extcsd has RST_N_FUNCTION=0x01 > - sdhc node has cap-mmc-hw-reset > - pinmux set for EMMC0_RESET_B > - Linux v5.15 Reviewed-by: Haibo Chen <haibo.chen@xxxxxxx> Best Regards Haibo Chen > > Signed-off-by: Josua Mayer <josua@xxxxxxxxxxxxx> > --- > drivers/mmc/host/sdhci-esdhc-imx.c | 13 +++++++++++++ > 1 file changed, 13 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c > b/drivers/mmc/host/sdhci-esdhc-imx.c > index > 8f0bc6dca2b0402fd2a0695903cf261a5b4e19dc..f106e291c276d0c8063e9ac59 > a126acf5e9e239e 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -31,6 +31,7 @@ > #include "cqhci.h" > > #define ESDHC_SYS_CTRL_DTOCV_MASK 0x0f > +#define ESDHC_SYS_CTRL_IPP_RST_N BIT(23) > #define ESDHC_CTRL_D3CD 0x08 > #define ESDHC_BURST_LEN_EN_INCR (1 << 27) > /* VENDOR SPEC register */ > @@ -1402,6 +1403,17 @@ static u32 esdhc_cqhci_irq(struct sdhci_host *host, > u32 intmask) > return 0; > } > > +static void esdhc_hw_reset(struct sdhci_host *host) { > + esdhc_clrset_le(host, ESDHC_SYS_CTRL_IPP_RST_N, 0, > ESDHC_SYSTEM_CONTROL); > + /* eMMC spec requires minimum 1us, here delay between 1-10us */ > + usleep_range(1, 10); > + esdhc_clrset_le(host, ESDHC_SYS_CTRL_IPP_RST_N, > + ESDHC_SYS_CTRL_IPP_RST_N, ESDHC_SYSTEM_CONTROL); > + /* eMMC spec requires minimum 200us, here delay between 200-300us */ > + usleep_range(200, 300); > +} > + > static struct sdhci_ops sdhci_esdhc_ops = { > .read_l = esdhc_readl_le, > .read_w = esdhc_readw_le, > @@ -1420,6 +1432,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { > .reset = esdhc_reset, > .irq = esdhc_cqhci_irq, > .dump_vendor_regs = esdhc_dump_debug_regs, > + .hw_reset = esdhc_hw_reset, > }; > > static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = { > > -- > 2.43.0