mmc: Add support for disabling write-protect detection
authorLars-Peter Clausen <lars@metafoo.de>
Wed, 6 May 2015 18:31:19 +0000 (20:31 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Mon, 1 Jun 2015 07:06:59 +0000 (09:06 +0200)
It is not uncommon to see systems where there is no physical write-protect
signal (e.g. when using eMMC or microSD card slots). For some controllers,
which have a dedicated write-protection detection logic (like SDHCI
controllers), the get_ro() callback can return bogus data in such a case.

Instead of handling this on a per controller basis this patch adds a new
capability flag to the MMC core that can be set to specify that the result
of get_ro() is invalid. When the flag is set the core will not call
get_ro() and assume that the card is always read-write.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/core/sd.c
include/linux/mmc/host.h

index 31a9ef256d0652d5b2ce64623d3a161bbcfcd6b7..8f6864a2a05504757375232696cf0ecb51b1a10d 100644 (file)
@@ -804,6 +804,28 @@ int mmc_sd_get_csd(struct mmc_host *host, struct mmc_card *card)
        return 0;
 }
 
+static int mmc_sd_get_ro(struct mmc_host *host)
+{
+       int ro;
+
+       /*
+        * Some systems don't feature a write-protect pin and don't need one.
+        * E.g. because they only have micro-SD card slot. For those systems
+        * assume that the SD card is always read-write.
+        */
+       if (host->caps2 & MMC_CAP2_NO_WRITE_PROTECT)
+               return 0;
+
+       if (!host->ops->get_ro)
+               return -1;
+
+       mmc_host_clk_hold(host);
+       ro = host->ops->get_ro(host);
+       mmc_host_clk_release(host);
+
+       return ro;
+}
+
 int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
        bool reinit)
 {
@@ -855,13 +877,7 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
         * Check if read-only switch is active.
         */
        if (!reinit) {
-               int ro = -1;
-
-               if (host->ops->get_ro) {
-                       mmc_host_clk_hold(card->host);
-                       ro = host->ops->get_ro(host);
-                       mmc_host_clk_release(card->host);
-               }
+               int ro = mmc_sd_get_ro(host);
 
                if (ro < 0) {
                        pr_warn("%s: host does not support reading read-only switch, assuming write-enable\n",
index f471193ef6d637a4569f0d5a9962e4604d18b485..433eccb50838e9c2b20510e062313932a4d50fc7 100644 (file)
@@ -286,6 +286,7 @@ struct mmc_host {
                                 MMC_CAP2_HS400_1_2V)
 #define MMC_CAP2_HSX00_1_2V    (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V)
 #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
+#define MMC_CAP2_NO_WRITE_PROTECT (1 << 18)    /* No physical write protect pin, assume that card is always read-write */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */