Skip to content

Commit 7a1e3f1

Browse files
ldesrochesstorulf
authored andcommitted
mmc: sdhci-of-at91: force card detect value for non removable devices
When the device is non removable, the card detect signal is often used for another purpose i.e. muxed to another SoC peripheral or used as a GPIO. It could lead to wrong behaviors depending the default value of this signal if not muxed to the SDHCI controller. Fixes: bb5f8ea ("mmc: sdhci-of-at91: introduce driver for the Atmel SDMMC") Signed-off-by: Ludovic Desroches <[email protected]> Acked-by: Adrian Hunter <[email protected]> Cc: <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent 16f73eb commit 7a1e3f1

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

drivers/mmc/host/sdhci-of-at91.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#define SDMMC_MC1R 0x204
3333
#define SDMMC_MC1R_DDR BIT(3)
34+
#define SDMMC_MC1R_FCD BIT(7)
3435
#define SDMMC_CACR 0x230
3536
#define SDMMC_CACR_CAPWREN BIT(0)
3637
#define SDMMC_CACR_KEY (0x46 << 8)
@@ -43,6 +44,15 @@ struct sdhci_at91_priv {
4344
struct clk *mainck;
4445
};
4546

47+
static void sdhci_at91_set_force_card_detect(struct sdhci_host *host)
48+
{
49+
u8 mc1r;
50+
51+
mc1r = readb(host->ioaddr + SDMMC_MC1R);
52+
mc1r |= SDMMC_MC1R_FCD;
53+
writeb(mc1r, host->ioaddr + SDMMC_MC1R);
54+
}
55+
4656
static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
4757
{
4858
u16 clk;
@@ -110,10 +120,18 @@ void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, unsigned int timing)
110120
sdhci_set_uhs_signaling(host, timing);
111121
}
112122

123+
static void sdhci_at91_reset(struct sdhci_host *host, u8 mask)
124+
{
125+
sdhci_reset(host, mask);
126+
127+
if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
128+
sdhci_at91_set_force_card_detect(host);
129+
}
130+
113131
static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
114132
.set_clock = sdhci_at91_set_clock,
115133
.set_bus_width = sdhci_set_bus_width,
116-
.reset = sdhci_reset,
134+
.reset = sdhci_at91_reset,
117135
.set_uhs_signaling = sdhci_at91_set_uhs_signaling,
118136
.set_power = sdhci_at91_set_power,
119137
};
@@ -324,6 +342,21 @@ static int sdhci_at91_probe(struct platform_device *pdev)
324342
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
325343
}
326344

345+
/*
346+
* If the device attached to the MMC bus is not removable, it is safer
347+
* to set the Force Card Detect bit. People often don't connect the
348+
* card detect signal and use this pin for another purpose. If the card
349+
* detect pin is not muxed to SDHCI controller, a default value is
350+
* used. This value can be different from a SoC revision to another
351+
* one. Problems come when this default value is not card present. To
352+
* avoid this case, if the device is non removable then the card
353+
* detection procedure using the SDMCC_CD signal is bypassed.
354+
* This bit is reset when a software reset for all command is performed
355+
* so we need to implement our own reset function to set back this bit.
356+
*/
357+
if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
358+
sdhci_at91_set_force_card_detect(host);
359+
327360
pm_runtime_put_autosuspend(&pdev->dev);
328361

329362
return 0;

0 commit comments

Comments
 (0)