On Fri, 15 Sept 2023 at 11:44, Victor Shih <victorshihgli@xxxxxxxxx> wrote: > > From: Victor Shih <victor.shih@xxxxxxxxxxxxxxxxxxx> > > Sdhci_uhs2_reset() does a UHS-II specific reset operation. > > Signed-off-by: Ben Chuang <ben.chuang@xxxxxxxxxxxxxxxxxxx> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> > Signed-off-by: Victor Shih <victor.shih@xxxxxxxxxxxxxxxxxxx> > Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > --- > > Updates in V8: > - Adjust the position of matching brackets. > > Updates in V6: > - Remove unnecessary functions and simplify code. > > --- > > drivers/mmc/host/sdhci-uhs2.c | 45 +++++++++++++++++++++++++++++++++++ > drivers/mmc/host/sdhci-uhs2.h | 2 ++ > 2 files changed, 47 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c > index e339821d3504..dfc80a7f1bad 100644 > --- a/drivers/mmc/host/sdhci-uhs2.c > +++ b/drivers/mmc/host/sdhci-uhs2.c > @@ -10,7 +10,9 @@ > * Author: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> > */ > > +#include <linux/delay.h> > #include <linux/module.h> > +#include <linux/iopoll.h> > > #include "sdhci.h" > #include "sdhci-uhs2.h" > @@ -49,6 +51,49 @@ void sdhci_uhs2_dump_regs(struct sdhci_host *host) > } > EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs); > > +/*****************************************************************************\ > + * * > + * Low level functions * > + * * > +\*****************************************************************************/ > + > +bool sdhci_uhs2_mode(struct sdhci_host *host) > +{ > + return host->mmc->flags & MMC_UHS2_SUPPORT; The MMC_UHS2_SUPPORT bit looks redundant to me. Instead, I think we should be using mmc->ios.timings, which already indicates whether we are using UHS2 (MMC_TIMING_UHS2_SPEED_*). See patch2 where we added this. That said, I think we should drop the sdhci_uhs2_mode() function altogether and instead use mmc_card_uhs2(), which means we should move it to include/linux/mmc/host.h, so it becomes available for host drivers. > +} > + > +/** > + * sdhci_uhs2_reset - invoke SW reset > + * @host: SDHCI host > + * @mask: Control mask > + * > + * Invoke SW reset, depending on a bit in @mask and wait for completion. > + */ > +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask) > +{ > + unsigned long timeout; > + u32 val; > + > + sdhci_writew(host, mask, SDHCI_UHS2_SW_RESET); > + > + if (mask & SDHCI_UHS2_SW_RESET_FULL) > + host->clock = 0; > + > + /* Wait max 100 ms */ > + timeout = 100000; Please convert into using a define and use that directly, below instead. > + > + /* hw clears the bit when it's done */ > + if (read_poll_timeout_atomic(sdhci_readw, val, !(val & mask), 10, > + timeout, true, host, SDHCI_UHS2_SW_RESET)) { > + pr_err("%s: %s: Reset 0x%x never completed.\n", __func__, > + mmc_hostname(host->mmc), (int)mask); > + pr_err("%s: clean reset bit\n", mmc_hostname(host->mmc)); It looks silly to do two pr_err immediately after each other, please combine them into one. Moreover, I think we should probably convert into using a pr_warn() instead. > + sdhci_writeb(host, 0, SDHCI_UHS2_SW_RESET); > + return; > + } > +} > +EXPORT_SYMBOL_GPL(sdhci_uhs2_reset); > + > /*****************************************************************************\ > * * > * Driver init/exit * > diff --git a/drivers/mmc/host/sdhci-uhs2.h b/drivers/mmc/host/sdhci-uhs2.h > index 2bfe18d29bca..8253d50f7852 100644 > --- a/drivers/mmc/host/sdhci-uhs2.h > +++ b/drivers/mmc/host/sdhci-uhs2.h > @@ -177,5 +177,7 @@ > struct sdhci_host; > > void sdhci_uhs2_dump_regs(struct sdhci_host *host); > +bool sdhci_uhs2_mode(struct sdhci_host *host); > +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); > > #endif /* __SDHCI_UHS2_H */ > -- > 2.25.1 > Kind regards Uffe