aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/host.c32
-rw-r--r--drivers/mmc/core/slot-gpio.c14
-rw-r--r--drivers/mmc/host/mmci.c4
-rw-r--r--drivers/mmc/host/sdhci-acpi.c2
-rw-r--r--include/linux/mmc/slot-gpio.h4
5 files changed, 45 insertions, 11 deletions
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 31969436d77c..03c53b72a2d6 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -311,6 +311,7 @@ int mmc_of_parse(struct mmc_host *host)
311 struct device_node *np; 311 struct device_node *np;
312 u32 bus_width; 312 u32 bus_width;
313 int len, ret; 313 int len, ret;
314 bool cap_invert, gpio_invert;
314 315
315 if (!host->parent || !host->parent->of_node) 316 if (!host->parent || !host->parent->of_node)
316 return 0; 317 return 0;
@@ -359,12 +360,15 @@ int mmc_of_parse(struct mmc_host *host)
359 host->caps |= MMC_CAP_NONREMOVABLE; 360 host->caps |= MMC_CAP_NONREMOVABLE;
360 } else { 361 } else {
361 if (of_property_read_bool(np, "cd-inverted")) 362 if (of_property_read_bool(np, "cd-inverted"))
362 host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; 363 cap_invert = true;
364 else
365 cap_invert = false;
363 366
364 if (of_find_property(np, "broken-cd", &len)) 367 if (of_find_property(np, "broken-cd", &len))
365 host->caps |= MMC_CAP_NEEDS_POLL; 368 host->caps |= MMC_CAP_NEEDS_POLL;
366 369
367 ret = mmc_gpiod_request_cd(host, "cd", 0, false, 0); 370 ret = mmc_gpiod_request_cd(host, "cd", 0, true,
371 0, &gpio_invert);
368 if (ret) { 372 if (ret) {
369 if (ret == -EPROBE_DEFER) 373 if (ret == -EPROBE_DEFER)
370 return ret; 374 return ret;
@@ -375,13 +379,29 @@ int mmc_of_parse(struct mmc_host *host)
375 } 379 }
376 } else 380 } else
377 dev_info(host->parent, "Got CD GPIO\n"); 381 dev_info(host->parent, "Got CD GPIO\n");
382
383 /*
384 * There are two ways to flag that the CD line is inverted:
385 * through the cd-inverted flag and by the GPIO line itself
386 * being inverted from the GPIO subsystem. This is a leftover
387 * from the times when the GPIO subsystem did not make it
388 * possible to flag a line as inverted.
389 *
390 * If the capability on the host AND the GPIO line are
391 * both inverted, the end result is that the CD line is
392 * not inverted.
393 */
394 if (cap_invert ^ gpio_invert)
395 host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
378 } 396 }
379 397
380 /* Parse Write Protection */ 398 /* Parse Write Protection */
381 if (of_property_read_bool(np, "wp-inverted")) 399 if (of_property_read_bool(np, "wp-inverted"))
382 host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; 400 cap_invert = true;
401 else
402 cap_invert = false;
383 403
384 ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0); 404 ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &gpio_invert);
385 if (ret) { 405 if (ret) {
386 if (ret == -EPROBE_DEFER) 406 if (ret == -EPROBE_DEFER)
387 goto out; 407 goto out;
@@ -393,6 +413,10 @@ int mmc_of_parse(struct mmc_host *host)
393 } else 413 } else
394 dev_info(host->parent, "Got WP GPIO\n"); 414 dev_info(host->parent, "Got WP GPIO\n");
395 415
416 /* See the comment on CD inversion above */
417 if (cap_invert ^ gpio_invert)
418 host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
419
396 if (of_find_property(np, "cap-sd-highspeed", &len)) 420 if (of_find_property(np, "cap-sd-highspeed", &len))
397 host->caps |= MMC_CAP_SD_HIGHSPEED; 421 host->caps |= MMC_CAP_SD_HIGHSPEED;
398 if (of_find_property(np, "cap-mmc-highspeed", &len)) 422 if (of_find_property(np, "cap-mmc-highspeed", &len))
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 38f76555d4bf..69bbf2adb329 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -281,6 +281,8 @@ EXPORT_SYMBOL(mmc_gpio_free_cd);
281 * @idx: index of the GPIO to obtain in the consumer 281 * @idx: index of the GPIO to obtain in the consumer
282 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag 282 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
283 * @debounce: debounce time in microseconds 283 * @debounce: debounce time in microseconds
284 * @gpio_invert: will return whether the GPIO line is inverted or not, set
285 * to NULL to ignore
284 * 286 *
285 * Use this function in place of mmc_gpio_request_cd() to use the GPIO 287 * Use this function in place of mmc_gpio_request_cd() to use the GPIO
286 * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not 288 * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not
@@ -291,7 +293,7 @@ EXPORT_SYMBOL(mmc_gpio_free_cd);
291 */ 293 */
292int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, 294int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
293 unsigned int idx, bool override_active_level, 295 unsigned int idx, bool override_active_level,
294 unsigned int debounce) 296 unsigned int debounce, bool *gpio_invert)
295{ 297{
296 struct mmc_gpio *ctx; 298 struct mmc_gpio *ctx;
297 struct gpio_desc *desc; 299 struct gpio_desc *desc;
@@ -316,6 +318,9 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
316 return ret; 318 return ret;
317 } 319 }
318 320
321 if (gpio_invert)
322 *gpio_invert = !gpiod_is_active_low(desc);
323
319 ctx->override_cd_active_level = override_active_level; 324 ctx->override_cd_active_level = override_active_level;
320 ctx->cd_gpio = desc; 325 ctx->cd_gpio = desc;
321 326
@@ -330,6 +335,8 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd);
330 * @idx: index of the GPIO to obtain in the consumer 335 * @idx: index of the GPIO to obtain in the consumer
331 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag 336 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag
332 * @debounce: debounce time in microseconds 337 * @debounce: debounce time in microseconds
338 * @gpio_invert: will return whether the GPIO line is inverted or not,
339 * set to NULL to ignore
333 * 340 *
334 * Use this function in place of mmc_gpio_request_ro() to use the GPIO 341 * Use this function in place of mmc_gpio_request_ro() to use the GPIO
335 * descriptor API. Note that it is paired with mmc_gpiod_free_ro() not 342 * descriptor API. Note that it is paired with mmc_gpiod_free_ro() not
@@ -339,7 +346,7 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd);
339 */ 346 */
340int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, 347int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
341 unsigned int idx, bool override_active_level, 348 unsigned int idx, bool override_active_level,
342 unsigned int debounce) 349 unsigned int debounce, bool *gpio_invert)
343{ 350{
344 struct mmc_gpio *ctx; 351 struct mmc_gpio *ctx;
345 struct gpio_desc *desc; 352 struct gpio_desc *desc;
@@ -364,6 +371,9 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
364 return ret; 371 return ret;
365 } 372 }
366 373
374 if (gpio_invert)
375 *gpio_invert = !gpiod_is_active_low(desc);
376
367 ctx->override_ro_active_level = override_active_level; 377 ctx->override_ro_active_level = override_active_level;
368 ctx->ro_gpio = desc; 378 ctx->ro_gpio = desc;
369 379
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index c9dafed550f2..43af791e2e45 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1682,7 +1682,7 @@ static int mmci_probe(struct amba_device *dev,
1682 * silently of these do not exist and proceed to try platform data 1682 * silently of these do not exist and proceed to try platform data
1683 */ 1683 */
1684 if (!np) { 1684 if (!np) {
1685 ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0); 1685 ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
1686 if (ret < 0) { 1686 if (ret < 0) {
1687 if (ret == -EPROBE_DEFER) 1687 if (ret == -EPROBE_DEFER)
1688 goto clk_disable; 1688 goto clk_disable;
@@ -1693,7 +1693,7 @@ static int mmci_probe(struct amba_device *dev,
1693 } 1693 }
1694 } 1694 }
1695 1695
1696 ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0); 1696 ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
1697 if (ret < 0) { 1697 if (ret < 0) {
1698 if (ret == -EPROBE_DEFER) 1698 if (ret == -EPROBE_DEFER)
1699 goto clk_disable; 1699 goto clk_disable;
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index 3483c089baa7..327bc24ec8ce 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -352,7 +352,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
352 if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { 352 if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
353 bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); 353 bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL);
354 354
355 if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) { 355 if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL)) {
356 dev_warn(dev, "failed to setup card detect gpio\n"); 356 dev_warn(dev, "failed to setup card detect gpio\n");
357 c->use_runtime_pm = false; 357 c->use_runtime_pm = false;
358 } 358 }
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
index a0d0442c15bf..e56fa24c9322 100644
--- a/include/linux/mmc/slot-gpio.h
+++ b/include/linux/mmc/slot-gpio.h
@@ -24,10 +24,10 @@ void mmc_gpio_free_cd(struct mmc_host *host);
24 24
25int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, 25int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id,
26 unsigned int idx, bool override_active_level, 26 unsigned int idx, bool override_active_level,
27 unsigned int debounce); 27 unsigned int debounce, bool *gpio_invert);
28int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, 28int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id,
29 unsigned int idx, bool override_active_level, 29 unsigned int idx, bool override_active_level,
30 unsigned int debounce); 30 unsigned int debounce, bool *gpio_invert);
31void mmc_gpiod_free_cd(struct mmc_host *host); 31void mmc_gpiod_free_cd(struct mmc_host *host);
32void mmc_gpiod_request_cd_irq(struct mmc_host *host); 32void mmc_gpiod_request_cd_irq(struct mmc_host *host);
33 33