diff options
author | Victor Shih <victor.shih@genesyslogic.com.tw> | 2024-10-18 18:53:22 +0800 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2024-10-24 14:36:56 +0200 |
commit | 9b1c779d86f5cb01d5e2626add3dc322bd4625c7 (patch) | |
tree | ec7807a5cbdfd69def88eb6709fbe62141cb924d | |
parent | 0f8186f146427137c11dc5c0498bdcf3d74dd072 (diff) |
mmc: sdhci-uhs2: add reset function
Sdhci_uhs2_reset() does a UHS-II specific reset operation.
Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Victor Shih <victor.shih@genesyslogic.com.tw>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Message-ID: <20241018105333.4569-6-victorshihgli@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sdhci-uhs2.c | 37 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-uhs2.h | 1 |
2 files changed, 38 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-uhs2.c b/drivers/mmc/host/sdhci-uhs2.c index 14514710e763..71c60952a40a 100644 --- a/drivers/mmc/host/sdhci-uhs2.c +++ b/drivers/mmc/host/sdhci-uhs2.c @@ -10,7 +10,9 @@ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org> */ +#include <linux/delay.h> #include <linux/module.h> +#include <linux/iopoll.h> #include "sdhci.h" #include "sdhci-uhs2.h" @@ -21,6 +23,8 @@ #define SDHCI_UHS2_DUMP(f, x...) \ pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x) +#define UHS2_RESET_TIMEOUT_100MS 100000 + void sdhci_uhs2_dump_regs(struct sdhci_host *host) { if (!(mmc_card_uhs2(host->mmc))) @@ -51,6 +55,39 @@ EXPORT_SYMBOL_GPL(sdhci_uhs2_dump_regs); /*****************************************************************************\ * * + * Low level functions * + * * +\*****************************************************************************/ + +/** + * 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) +{ + u32 val; + + sdhci_writew(host, mask, SDHCI_UHS2_SW_RESET); + + if (mask & SDHCI_UHS2_SW_RESET_FULL) + host->clock = 0; + + /* hw clears the bit when it's done */ + if (read_poll_timeout_atomic(sdhci_readw, val, !(val & mask), 10, + UHS2_RESET_TIMEOUT_100MS, true, host, SDHCI_UHS2_SW_RESET)) { + pr_warn("%s: %s: Reset 0x%x never completed. %s: clean reset bit.\n", __func__, + mmc_hostname(host->mmc), (int)mask, mmc_hostname(host->mmc)); + 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 04d75160b684..bc8395a9abda 100644 --- a/drivers/mmc/host/sdhci-uhs2.h +++ b/drivers/mmc/host/sdhci-uhs2.h @@ -175,5 +175,6 @@ struct sdhci_host; void sdhci_uhs2_dump_regs(struct sdhci_host *host); +void sdhci_uhs2_reset(struct sdhci_host *host, u16 mask); #endif /* __SDHCI_UHS2_H */ |