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 |
> 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
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 --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 {
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(-)