diff options
-rw-r--r-- | drivers/mmc/core/host.c | 32 | ||||
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 14 | ||||
-rw-r--r-- | drivers/mmc/host/mmci.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 2 | ||||
-rw-r--r-- | include/linux/mmc/slot-gpio.h | 4 |
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 | */ |
292 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | 294 | int 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 | */ |
340 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | 347 | int 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 | ||
25 | int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, | 25 | int 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); |
28 | int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, | 28 | int 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); |
31 | void mmc_gpiod_free_cd(struct mmc_host *host); | 31 | void mmc_gpiod_free_cd(struct mmc_host *host); |
32 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); | 32 | void mmc_gpiod_request_cd_irq(struct mmc_host *host); |
33 | 33 | ||