[PATCH 3/5] mmc: uniphier-sd: Add control to switch UHS speed

Kunihiko Hayashi hayashi.kunihiko at socionext.com
Tue Jan 24 17:01:59 PST 2023


SD interface logic has the register to switch UHS speed.
The default is up to SDR25 and to support SDR50 or faster,
add uniphier_sd_speed_switch() function to switch the speed mode.

Signed-off-by: Kunihiko Hayashi <hayashi.kunihiko at socionext.com>
---
 drivers/mmc/host/uniphier-sd.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index c9766d6a690f..61acd69fac0e 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -54,6 +54,7 @@
 #define UNIPHIER_SDCTRL_CHOFFSET	0x200
 #define UNIPHIER_SDCTRL_MODE		0x30
 #define   UNIPHIER_SDCTRL_MODE_UHS1MOD		BIT(15)
+#define   UNIPHIER_SDCTRL_MODE_SDRSEL		BIT(14)
 
 /*
  * IP is extended to support various features: built-in DMA engine,
@@ -429,6 +430,25 @@ static void uniphier_sd_hw_reset(struct mmc_host *mmc)
 	usleep_range(300, 1000);
 }
 
+static void uniphier_sd_speed_switch(struct tmio_mmc_host *host)
+{
+	struct uniphier_sd_priv *priv = uniphier_sd_priv(host);
+	unsigned int offset;
+	u32 val = 0;
+
+	if (!(host->mmc->caps & MMC_CAP_UHS))
+		return;
+
+	if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR50 ||
+	    host->mmc->ios.timing == MMC_TIMING_UHS_SDR104)
+		val = UNIPHIER_SDCTRL_MODE_SDRSEL;
+
+	offset = UNIPHIER_SDCTRL_CHOFFSET * priv->sdctrl_ch
+		+ UNIPHIER_SDCTRL_MODE;
+	regmap_write_bits(priv->sdctrl_regmap, offset,
+			  UNIPHIER_SDCTRL_MODE_SDRSEL, val);
+}
+
 static void uniphier_sd_uhs_enable(struct tmio_mmc_host *host, bool uhs_en)
 {
 	struct uniphier_sd_priv *priv = uniphier_sd_priv(host);
@@ -459,6 +479,8 @@ static void uniphier_sd_set_clock(struct tmio_mmc_host *host,
 	tmp &= ~CLK_CTL_SCLKEN;
 	writel(tmp, host->ctl + (CTL_SD_CARD_CLK_CTL << 1));
 
+	uniphier_sd_speed_switch(host);
+
 	if (clock == 0)
 		return;
 
-- 
2.25.1




More information about the linux-arm-kernel mailing list