[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20231117113149.9069-12-victorshihgli@gmail.com>
Date: Fri, 17 Nov 2023 19:31:39 +0800
From: Victor Shih <victorshihgli@...il.com>
To: ulf.hansson@...aro.org, adrian.hunter@...el.com
Cc: linux-mmc@...r.kernel.org, linux-kernel@...r.kernel.org,
benchuanggli@...il.com, HL.Liu@...esyslogic.com.tw,
Greg.tu@...esyslogic.com.tw, takahiro.akashi@...aro.org,
dlunev@...omium.org, Victor Shih <victor.shih@...esyslogic.com.tw>,
Ben Chuang <ben.chuang@...esyslogic.com.tw>
Subject: [PATCH V13 11/21] mmc: sdhci-uhs2: add reset function and uhs2_mode function
From: Victor Shih <victor.shih@...esyslogic.com.tw>
Sdhci_uhs2_reset() does a UHS-II specific reset operation.
Signed-off-by: Ben Chuang <ben.chuang@...esyslogic.com.tw>
Signed-off-by: AKASHI Takahiro <takahiro.akashi@...aro.org>
Signed-off-by: Victor Shih <victor.shih@...esyslogic.com.tw>
---
Updates in V13:
- Use ios timing to stead MMC_UHS2_SUPPORT for indicate the UHS2 mode.
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..ef6f02583d61 100644
--- a/drivers/mmc/host/sdhci-uhs2.c
+++ b/drivers/mmc/host/sdhci-uhs2.c
@@ -10,7 +10,9 @@
* Author: AKASHI Takahiro <takahiro.akashi@...aro.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 (!(sdhci_uhs2_mode(host)))
@@ -49,6 +53,47 @@ 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->ios.timing == MMC_TIMING_UHS2_SPEED_A ||
+ host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B ||
+ host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_A_HD ||
+ host->mmc->ios.timing == MMC_TIMING_UHS2_SPEED_B_HD;
+}
+
+/**
+ * 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 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
Powered by blists - more mailing lists