Skip to content

Commit d12990f

Browse files
psr0kastorulf
authored andcommitted
mmc: sdhci-cadence: add HS400 enhanced strobe support
Add support for HS400ES mode to Cadence SDHCI driver. Signed-off-by: Piotr Sroka <piotrs@cadence.com> Reviewed-by: Masahiro Yamada <yamada.masahiro@socionext.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 4346b7c commit d12990f

File tree

1 file changed

+50
-7
lines changed

1 file changed

+50
-7
lines changed

drivers/mmc/host/sdhci-cadence.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3
4141
#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4
4242
#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5
43+
#define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6
4344

4445
/* SRS - Slot Register Set (SDHCI-compatible) */
4546
#define SDHCI_CDNS_SRS_BASE 0x200
@@ -64,6 +65,7 @@
6465

6566
struct sdhci_cdns_priv {
6667
void __iomem *hrs_addr;
68+
bool enhanced_strobe;
6769
};
6870

6971
static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
@@ -108,11 +110,30 @@ static unsigned int sdhci_cdns_get_timeout_clock(struct sdhci_host *host)
108110
return host->max_clk / 1000;
109111
}
110112

113+
static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
114+
{
115+
u32 tmp;
116+
117+
/* The speed mode for eMMC is selected by HRS06 register */
118+
tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
119+
tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
120+
tmp |= mode;
121+
writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
122+
}
123+
124+
static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv)
125+
{
126+
u32 tmp;
127+
128+
tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
129+
return tmp & SDHCI_CDNS_HRS06_MODE_MASK;
130+
}
131+
111132
static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
112133
unsigned int timing)
113134
{
114135
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
115-
u32 mode, tmp;
136+
u32 mode;
116137

117138
switch (timing) {
118139
case MMC_TIMING_MMC_HS:
@@ -125,18 +146,17 @@ static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
125146
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
126147
break;
127148
case MMC_TIMING_MMC_HS400:
128-
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
149+
if (priv->enhanced_strobe)
150+
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
151+
else
152+
mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
129153
break;
130154
default:
131155
mode = SDHCI_CDNS_HRS06_MODE_SD;
132156
break;
133157
}
134158

135-
/* The speed mode for eMMC is selected by HRS06 register */
136-
tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
137-
tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
138-
tmp |= mode;
139-
writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
159+
sdhci_cdns_set_emmc_mode(priv, mode);
140160

141161
/* For SD, fall back to the default handler */
142162
if (mode == SDHCI_CDNS_HRS06_MODE_SD)
@@ -213,6 +233,26 @@ static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
213233
return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
214234
}
215235

236+
static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
237+
struct mmc_ios *ios)
238+
{
239+
struct sdhci_host *host = mmc_priv(mmc);
240+
struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
241+
u32 mode;
242+
243+
priv->enhanced_strobe = ios->enhanced_strobe;
244+
245+
mode = sdhci_cdns_get_emmc_mode(priv);
246+
247+
if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400 && ios->enhanced_strobe)
248+
sdhci_cdns_set_emmc_mode(priv,
249+
SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
250+
251+
if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400ES && !ios->enhanced_strobe)
252+
sdhci_cdns_set_emmc_mode(priv,
253+
SDHCI_CDNS_HRS06_MODE_MMC_HS400);
254+
}
255+
216256
static int sdhci_cdns_probe(struct platform_device *pdev)
217257
{
218258
struct sdhci_host *host;
@@ -240,8 +280,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
240280

241281
priv = sdhci_cdns_priv(host);
242282
priv->hrs_addr = host->ioaddr;
283+
priv->enhanced_strobe = false;
243284
host->ioaddr += SDHCI_CDNS_SRS_BASE;
244285
host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
286+
host->mmc_host_ops.hs400_enhanced_strobe =
287+
sdhci_cdns_hs400_enhanced_strobe;
245288

246289
ret = mmc_of_parse(host->mmc);
247290
if (ret)

0 commit comments

Comments
 (0)