diff mbox series

[v2,06/11] mmc: add a mmc_hs400_prepare_ddr() interface

Message ID 20200717085024.19385-7-yangbo.lu@nxp.com
State Superseded
Delegated to: Peng Fan
Headers show
Series mmc: fsl_esdhc: support eMMC HS200/HS400 modes | expand

Commit Message

Yangbo Lu July 17, 2020, 8:50 a.m. UTC
Add a mmc_hs400_prepare_ddr() interface for controllers
which needs preparation before switching to DDR mode for
HS400 mode.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
Changes for v2:
	- None.
---
 drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
 drivers/mmc/mmc.c        |  2 ++
 include/mmc.h            | 15 ++++++++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

Comments

Peng Fan July 20, 2020, 1:40 a.m. UTC | #1
> Subject: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> 
> Add a mmc_hs400_prepare_ddr() interface for controllers which needs
> preparation before switching to DDR mode for
> HS400 mode.

This is LSx specific? If yes, could this be done in fsl_esdhc.c?

Thanks,
Peng.

> 
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> ---
> Changes for v2:
> 	- None.
> ---
>  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
>  drivers/mmc/mmc.c        |  2 ++
>  include/mmc.h            | 15 ++++++++++++++-
>  3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> b9f0880..240b205 100644
> --- a/drivers/mmc/mmc-uclass.c
> +++ b/drivers/mmc/mmc-uclass.c
> @@ -141,6 +141,21 @@ int mmc_set_enhanced_strobe(struct mmc
> *mmc)  }  #endif
> 
> +int dm_mmc_hs400_prepare_ddr(struct udevice *dev) {
> +	struct dm_mmc_ops *ops = mmc_get_ops(dev);
> +
> +	if (ops->hs400_prepare_ddr)
> +		return ops->hs400_prepare_ddr(dev);
> +
> +	return 0;
> +}
> +
> +int mmc_hs400_prepare_ddr(struct mmc *mmc) {
> +	return dm_mmc_hs400_prepare_ddr(mmc->dev);
> +}
> +
>  int dm_mmc_host_power_cycle(struct udevice *dev)  {
>  	struct dm_mmc_ops *ops = mmc_get_ops(dev); diff --git
> a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a18e75d..e396207
> 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -1987,6 +1987,8 @@ static int mmc_select_hs400(struct mmc *mmc)
>  	/* Set back to HS */
>  	mmc_set_card_speed(mmc, MMC_HS, true);
> 
> +	mmc_hs400_prepare_ddr(mmc);
> +
>  	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> EXT_CSD_BUS_WIDTH,
>  			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
>  	if (err)
> diff --git a/include/mmc.h b/include/mmc.h index 2399cc2..659df75 100644
> --- a/include/mmc.h
> +++ b/include/mmc.h
> @@ -513,6 +513,14 @@ struct dm_mmc_ops {
>  	 * @return maximum number of blocks for this transfer
>  	 */
>  	int (*get_b_max)(struct udevice *dev, void *dst, lbaint_t blkcnt);
> +
> +	/**
> +	 * hs400_prepare_ddr - prepare to switch to DDR mode
> +	 *
> +	 * @dev:	Device to check
> +	 * @return 0 if success, -ve on error
> +	 */
> +	int (*hs400_prepare_ddr)(struct udevice *dev);
>  };
> 
>  #define mmc_get_ops(dev)        ((struct dm_mmc_ops
> *)(dev)->driver->ops)
> @@ -540,7 +548,7 @@ int mmc_host_power_cycle(struct mmc *mmc);  int
> mmc_deferred_probe(struct mmc *mmc);  int mmc_reinit(struct mmc
> *mmc);  int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
> -
> +int mmc_hs400_prepare_ddr(struct mmc *mmc);
>  #else
>  struct mmc_ops {
>  	int (*send_cmd)(struct mmc *mmc,
> @@ -552,6 +560,11 @@ struct mmc_ops {
>  	int (*host_power_cycle)(struct mmc *mmc);
>  	int (*get_b_max)(struct mmc *mmc, void *dst, lbaint_t blkcnt);  };
> +
> +static inline int mmc_hs400_prepare_ddr(struct mmc *mmc) {
> +	return 0;
> +}
>  #endif
> 
>  struct mmc_config {
> --
> 2.7.4
Yangbo Lu July 20, 2020, 7:46 a.m. UTC | #2
Hi Peng,

> -----Original Message-----
> From: Peng Fan <peng.fan@nxp.com>
> Sent: Monday, July 20, 2020 9:40 AM
> To: Y.b. Lu <yangbo.lu@nxp.com>; u-boot@lists.denx.de; Priyanka Jain
> <priyanka.jain@nxp.com>; 'Jaehoon Chung' <jh80.chung@samsung.com>
> Cc: Y.b. Lu <yangbo.lu@nxp.com>
> Subject: RE: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> 
> > Subject: [v2, 06/11] mmc: add a mmc_hs400_prepare_ddr() interface
> >
> > Add a mmc_hs400_prepare_ddr() interface for controllers which needs
> > preparation before switching to DDR mode for
> > HS400 mode.
> 
> This is LSx specific? If yes, could this be done in fsl_esdhc.c?

Yes. Actually I desire to put these esdhc specific setting in its own driver too.
However the HS400 procedure of esdhc indeed break the standard process.
As you see in my patch #7 commit message, the tuning block has to be disabled after switching to HS and before switching to DDR.

> 3. Switch to High Speed mode and then set the card clock frequency to
>    a value not greater than 52Mhz
> 4. Clear TBCTL[TB_EN],tuning block enable bit.
> 5. Change to 8 bit DDR Mode

I have to make code changed as below expecting some controllers drivers may utilize mmc_hs400_prepare_ddr() too.
We had done same thing in linux too. (cc14eec mmc: core: Add ->hs400_prepare_ddr() callback)
Do you have any suggestion?

mmc_set_card_speed(mmc, MMC_HS, true);

+	mmc_hs400_prepare_ddr(mmc);
+
err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
               EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);

Thanks.

> 
> Thanks,
> Peng.
> 
> >
> > Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
> > ---
> > Changes for v2:
> > 	- None.
> > ---
> >  drivers/mmc/mmc-uclass.c | 15 +++++++++++++++
> >  drivers/mmc/mmc.c        |  2 ++
> >  include/mmc.h            | 15 ++++++++++++++-
> >  3 files changed, 31 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index
> > b9f0880..240b205 100644
> > --- a/drivers/mmc/mmc-uclass.c
> > +++ b/drivers/mmc/mmc-uclass.c
> > @@ -141,6 +141,21 @@ int mmc_set_enhanced_strobe(struct mmc
> > *mmc)  }  #endif
> >
> > +int dm_mmc_hs400_prepare_ddr(struct udevice *dev) {
> > +	struct dm_mmc_ops *ops = mmc_get_ops(dev);
> > +
> > +	if (ops->hs400_prepare_ddr)
> > +		return ops->hs400_prepare_ddr(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +int mmc_hs400_prepare_ddr(struct mmc *mmc) {
> > +	return dm_mmc_hs400_prepare_ddr(mmc->dev);
> > +}
> > +
> >  int dm_mmc_host_power_cycle(struct udevice *dev)  {
> >  	struct dm_mmc_ops *ops = mmc_get_ops(dev); diff --git
> > a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a18e75d..e396207
> > 100644
> > --- a/drivers/mmc/mmc.c
> > +++ b/drivers/mmc/mmc.c
> > @@ -1987,6 +1987,8 @@ static int mmc_select_hs400(struct mmc *mmc)
> >  	/* Set back to HS */
> >  	mmc_set_card_speed(mmc, MMC_HS, true);
> >
> > +	mmc_hs400_prepare_ddr(mmc);
> > +
> >  	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
> > EXT_CSD_BUS_WIDTH,
> >  			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
> >  	if (err)
> > diff --git a/include/mmc.h b/include/mmc.h index 2399cc2..659df75 100644
> > --- a/include/mmc.h
> > +++ b/include/mmc.h
> > @@ -513,6 +513,14 @@ struct dm_mmc_ops {
> >  	 * @return maximum number of blocks for this transfer
> >  	 */
> >  	int (*get_b_max)(struct udevice *dev, void *dst, lbaint_t blkcnt);
> > +
> > +	/**
> > +	 * hs400_prepare_ddr - prepare to switch to DDR mode
> > +	 *
> > +	 * @dev:	Device to check
> > +	 * @return 0 if success, -ve on error
> > +	 */
> > +	int (*hs400_prepare_ddr)(struct udevice *dev);
> >  };
> >
> >  #define mmc_get_ops(dev)        ((struct dm_mmc_ops
> > *)(dev)->driver->ops)
> > @@ -540,7 +548,7 @@ int mmc_host_power_cycle(struct mmc *mmc);
> int
> > mmc_deferred_probe(struct mmc *mmc);  int mmc_reinit(struct mmc
> > *mmc);  int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
> > -
> > +int mmc_hs400_prepare_ddr(struct mmc *mmc);
> >  #else
> >  struct mmc_ops {
> >  	int (*send_cmd)(struct mmc *mmc,
> > @@ -552,6 +560,11 @@ struct mmc_ops {
> >  	int (*host_power_cycle)(struct mmc *mmc);
> >  	int (*get_b_max)(struct mmc *mmc, void *dst, lbaint_t blkcnt);  };
> > +
> > +static inline int mmc_hs400_prepare_ddr(struct mmc *mmc) {
> > +	return 0;
> > +}
> >  #endif
> >
> >  struct mmc_config {
> > --
> > 2.7.4
diff mbox series

Patch

diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index b9f0880..240b205 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -141,6 +141,21 @@  int mmc_set_enhanced_strobe(struct mmc *mmc)
 }
 #endif
 
+int dm_mmc_hs400_prepare_ddr(struct udevice *dev)
+{
+	struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+	if (ops->hs400_prepare_ddr)
+		return ops->hs400_prepare_ddr(dev);
+
+	return 0;
+}
+
+int mmc_hs400_prepare_ddr(struct mmc *mmc)
+{
+	return dm_mmc_hs400_prepare_ddr(mmc->dev);
+}
+
 int dm_mmc_host_power_cycle(struct udevice *dev)
 {
 	struct dm_mmc_ops *ops = mmc_get_ops(dev);
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index a18e75d..e396207 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1987,6 +1987,8 @@  static int mmc_select_hs400(struct mmc *mmc)
 	/* Set back to HS */
 	mmc_set_card_speed(mmc, MMC_HS, true);
 
+	mmc_hs400_prepare_ddr(mmc);
+
 	err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			 EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
 	if (err)
diff --git a/include/mmc.h b/include/mmc.h
index 2399cc2..659df75 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -513,6 +513,14 @@  struct dm_mmc_ops {
 	 * @return maximum number of blocks for this transfer
 	 */
 	int (*get_b_max)(struct udevice *dev, void *dst, lbaint_t blkcnt);
+
+	/**
+	 * hs400_prepare_ddr - prepare to switch to DDR mode
+	 *
+	 * @dev:	Device to check
+	 * @return 0 if success, -ve on error
+	 */
+	int (*hs400_prepare_ddr)(struct udevice *dev);
 };
 
 #define mmc_get_ops(dev)        ((struct dm_mmc_ops *)(dev)->driver->ops)
@@ -540,7 +548,7 @@  int mmc_host_power_cycle(struct mmc *mmc);
 int mmc_deferred_probe(struct mmc *mmc);
 int mmc_reinit(struct mmc *mmc);
 int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt);
-
+int mmc_hs400_prepare_ddr(struct mmc *mmc);
 #else
 struct mmc_ops {
 	int (*send_cmd)(struct mmc *mmc,
@@ -552,6 +560,11 @@  struct mmc_ops {
 	int (*host_power_cycle)(struct mmc *mmc);
 	int (*get_b_max)(struct mmc *mmc, void *dst, lbaint_t blkcnt);
 };
+
+static inline int mmc_hs400_prepare_ddr(struct mmc *mmc)
+{
+	return 0;
+}
 #endif
 
 struct mmc_config {