[PATCH 4.12 014/106] mmc: sdhci-of-at91: force card detect value for non removable devices

2017-08-09 Thread Greg Kroah-Hartman
4.12-stable review patch.  If anyone has any objections, please let me know.

--

From: Ludovic Desroches 

commit 7a1e3f143176e8ebdb2f5a9b3b47abc18b879d90 upstream.

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: bb5f8ea4d514 ("mmc: sdhci-of-at91: introduce driver for the Atmel SDMMC")
Signed-off-by: Ludovic Desroches 
Acked-by: Adrian Hunter 
Signed-off-by: Ulf Hansson 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/mmc/host/sdhci-of-at91.c |   35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -31,6 +31,7 @@
 
 #define SDMMC_MC1R 0x204
 #defineSDMMC_MC1R_DDR  BIT(3)
+#defineSDMMC_MC1R_FCD  BIT(7)
 #define SDMMC_CACR 0x230
 #defineSDMMC_CACR_CAPWREN  BIT(0)
 #defineSDMMC_CACR_KEY  (0x46 << 8)
@@ -43,6 +44,15 @@ struct sdhci_at91_priv {
struct clk *mainck;
 };
 
+static void sdhci_at91_set_force_card_detect(struct sdhci_host *host)
+{
+   u8 mc1r;
+
+   mc1r = readb(host->ioaddr + SDMMC_MC1R);
+   mc1r |= SDMMC_MC1R_FCD;
+   writeb(mc1r, host->ioaddr + SDMMC_MC1R);
+}
+
 static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
 {
u16 clk;
@@ -110,10 +120,18 @@ void sdhci_at91_set_uhs_signaling(struct
sdhci_set_uhs_signaling(host, timing);
 }
 
+static void sdhci_at91_reset(struct sdhci_host *host, u8 mask)
+{
+   sdhci_reset(host, mask);
+
+   if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+   sdhci_at91_set_force_card_detect(host);
+}
+
 static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
.set_clock  = sdhci_at91_set_clock,
.set_bus_width  = sdhci_set_bus_width,
-   .reset  = sdhci_reset,
+   .reset  = sdhci_at91_reset,
.set_uhs_signaling  = sdhci_at91_set_uhs_signaling,
.set_power  = sdhci_at91_set_power,
 };
@@ -324,6 +342,21 @@ static int sdhci_at91_probe(struct platf
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
 
+   /*
+* If the device attached to the MMC bus is not removable, it is safer
+* to set the Force Card Detect bit. People often don't connect the
+* card detect signal and use this pin for another purpose. If the card
+* detect pin is not muxed to SDHCI controller, a default value is
+* used. This value can be different from a SoC revision to another
+* one. Problems come when this default value is not card present. To
+* avoid this case, if the device is non removable then the card
+* detection procedure using the SDMCC_CD signal is bypassed.
+* This bit is reset when a software reset for all command is performed
+* so we need to implement our own reset function to set back this bit.
+*/
+   if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+   sdhci_at91_set_force_card_detect(host);
+
pm_runtime_put_autosuspend(>dev);
 
return 0;




[PATCH 4.12 014/106] mmc: sdhci-of-at91: force card detect value for non removable devices

2017-08-09 Thread Greg Kroah-Hartman
4.12-stable review patch.  If anyone has any objections, please let me know.

--

From: Ludovic Desroches 

commit 7a1e3f143176e8ebdb2f5a9b3b47abc18b879d90 upstream.

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: bb5f8ea4d514 ("mmc: sdhci-of-at91: introduce driver for the Atmel SDMMC")
Signed-off-by: Ludovic Desroches 
Acked-by: Adrian Hunter 
Signed-off-by: Ulf Hansson 
Signed-off-by: Greg Kroah-Hartman 

---
 drivers/mmc/host/sdhci-of-at91.c |   35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -31,6 +31,7 @@
 
 #define SDMMC_MC1R 0x204
 #defineSDMMC_MC1R_DDR  BIT(3)
+#defineSDMMC_MC1R_FCD  BIT(7)
 #define SDMMC_CACR 0x230
 #defineSDMMC_CACR_CAPWREN  BIT(0)
 #defineSDMMC_CACR_KEY  (0x46 << 8)
@@ -43,6 +44,15 @@ struct sdhci_at91_priv {
struct clk *mainck;
 };
 
+static void sdhci_at91_set_force_card_detect(struct sdhci_host *host)
+{
+   u8 mc1r;
+
+   mc1r = readb(host->ioaddr + SDMMC_MC1R);
+   mc1r |= SDMMC_MC1R_FCD;
+   writeb(mc1r, host->ioaddr + SDMMC_MC1R);
+}
+
 static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
 {
u16 clk;
@@ -110,10 +120,18 @@ void sdhci_at91_set_uhs_signaling(struct
sdhci_set_uhs_signaling(host, timing);
 }
 
+static void sdhci_at91_reset(struct sdhci_host *host, u8 mask)
+{
+   sdhci_reset(host, mask);
+
+   if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+   sdhci_at91_set_force_card_detect(host);
+}
+
 static const struct sdhci_ops sdhci_at91_sama5d2_ops = {
.set_clock  = sdhci_at91_set_clock,
.set_bus_width  = sdhci_set_bus_width,
-   .reset  = sdhci_reset,
+   .reset  = sdhci_at91_reset,
.set_uhs_signaling  = sdhci_at91_set_uhs_signaling,
.set_power  = sdhci_at91_set_power,
 };
@@ -324,6 +342,21 @@ static int sdhci_at91_probe(struct platf
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
 
+   /*
+* If the device attached to the MMC bus is not removable, it is safer
+* to set the Force Card Detect bit. People often don't connect the
+* card detect signal and use this pin for another purpose. If the card
+* detect pin is not muxed to SDHCI controller, a default value is
+* used. This value can be different from a SoC revision to another
+* one. Problems come when this default value is not card present. To
+* avoid this case, if the device is non removable then the card
+* detection procedure using the SDMCC_CD signal is bypassed.
+* This bit is reset when a software reset for all command is performed
+* so we need to implement our own reset function to set back this bit.
+*/
+   if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+   sdhci_at91_set_force_card_detect(host);
+
pm_runtime_put_autosuspend(>dev);
 
return 0;