mmc: core: restore detect line inversion semantics
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / core / host.c
index 31969436d77c6529c24580b6ddada88e871c4646..03c53b72a2d6a34bafbea7e1a1bda90299772fa8 100644 (file)
@@ -311,6 +311,7 @@ int mmc_of_parse(struct mmc_host *host)
        struct device_node *np;
        u32 bus_width;
        int len, ret;
+       bool cap_invert, gpio_invert;
 
        if (!host->parent || !host->parent->of_node)
                return 0;
@@ -359,12 +360,15 @@ int mmc_of_parse(struct mmc_host *host)
                host->caps |= MMC_CAP_NONREMOVABLE;
        } else {
                if (of_property_read_bool(np, "cd-inverted"))
-                       host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+                       cap_invert = true;
+               else
+                       cap_invert = false;
 
                if (of_find_property(np, "broken-cd", &len))
                        host->caps |= MMC_CAP_NEEDS_POLL;
 
-               ret = mmc_gpiod_request_cd(host, "cd", 0, false, 0);
+               ret = mmc_gpiod_request_cd(host, "cd", 0, true,
+                                          0, &gpio_invert);
                if (ret) {
                        if (ret == -EPROBE_DEFER)
                                return ret;
@@ -375,13 +379,29 @@ int mmc_of_parse(struct mmc_host *host)
                        }
                } else
                        dev_info(host->parent, "Got CD GPIO\n");
+
+               /*
+                * There are two ways to flag that the CD line is inverted:
+                * through the cd-inverted flag and by the GPIO line itself
+                * being inverted from the GPIO subsystem. This is a leftover
+                * from the times when the GPIO subsystem did not make it
+                * possible to flag a line as inverted.
+                *
+                * If the capability on the host AND the GPIO line are
+                * both inverted, the end result is that the CD line is
+                * not inverted.
+                */
+               if (cap_invert ^ gpio_invert)
+                       host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
        }
 
        /* Parse Write Protection */
        if (of_property_read_bool(np, "wp-inverted"))
-               host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+               cap_invert = true;
+       else
+               cap_invert = false;
 
-       ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0);
+       ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &gpio_invert);
        if (ret) {
                if (ret == -EPROBE_DEFER)
                        goto out;
@@ -393,6 +413,10 @@ int mmc_of_parse(struct mmc_host *host)
        } else
                dev_info(host->parent, "Got WP GPIO\n");
 
+       /* See the comment on CD inversion above */
+       if (cap_invert ^ gpio_invert)
+               host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+
        if (of_find_property(np, "cap-sd-highspeed", &len))
                host->caps |= MMC_CAP_SD_HIGHSPEED;
        if (of_find_property(np, "cap-mmc-highspeed", &len))