diff options
author | Robert Jarzmik <robert.jarzmik@free.fr> | 2015-09-26 15:41:01 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-09-29 06:17:05 -0400 |
commit | fd546ee6a7dc4b71ebc6d1205bf72ea3c1c7030a (patch) | |
tree | b145c9e9bea9a40a4c0b37e0cd864555e957345e | |
parent | 51424b2860670ec20e1dd5177fe70ab4b6fd7a5b (diff) |
mmc: pxamci: fix card detect with slot-gpio API
Move pxamci to mmc slot-gpio API to fix interrupt request.
It fixes the case where the card detection is on a gpio expander, on I2C
for example on zylonite board. In this case, the card detect netsted
interrupt is called from a threaded interrupt. The request_irq() fails,
because a hard irq cannot be a nested interrupt from a threaded
interrupt (set __setup_irq()).
This was tested on zylonite and mioa701 boards.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
Cc: Petr Cvek <petr.cvek@tul.cz>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/pxamci.c | 66 |
1 files changed, 22 insertions, 44 deletions
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 1420f29628c7..8cadd74e8407 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/err.h> | 29 | #include <linux/err.h> |
30 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
31 | #include <linux/mmc/slot-gpio.h> | ||
31 | #include <linux/io.h> | 32 | #include <linux/io.h> |
32 | #include <linux/regulator/consumer.h> | 33 | #include <linux/regulator/consumer.h> |
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
@@ -454,12 +455,8 @@ static int pxamci_get_ro(struct mmc_host *mmc) | |||
454 | { | 455 | { |
455 | struct pxamci_host *host = mmc_priv(mmc); | 456 | struct pxamci_host *host = mmc_priv(mmc); |
456 | 457 | ||
457 | if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) { | 458 | if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) |
458 | if (host->pdata->gpio_card_ro_invert) | 459 | return mmc_gpio_get_ro(mmc); |
459 | return !gpio_get_value(host->pdata->gpio_card_ro); | ||
460 | else | ||
461 | return gpio_get_value(host->pdata->gpio_card_ro); | ||
462 | } | ||
463 | if (host->pdata && host->pdata->get_ro) | 460 | if (host->pdata && host->pdata->get_ro) |
464 | return !!host->pdata->get_ro(mmc_dev(mmc)); | 461 | return !!host->pdata->get_ro(mmc_dev(mmc)); |
465 | /* | 462 | /* |
@@ -551,6 +548,7 @@ static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) | |||
551 | 548 | ||
552 | static const struct mmc_host_ops pxamci_ops = { | 549 | static const struct mmc_host_ops pxamci_ops = { |
553 | .request = pxamci_request, | 550 | .request = pxamci_request, |
551 | .get_cd = mmc_gpio_get_cd, | ||
554 | .get_ro = pxamci_get_ro, | 552 | .get_ro = pxamci_get_ro, |
555 | .set_ios = pxamci_set_ios, | 553 | .set_ios = pxamci_set_ios, |
556 | .enable_sdio_irq = pxamci_enable_sdio_irq, | 554 | .enable_sdio_irq = pxamci_enable_sdio_irq, |
@@ -790,37 +788,31 @@ static int pxamci_probe(struct platform_device *pdev) | |||
790 | gpio_power = host->pdata->gpio_power; | 788 | gpio_power = host->pdata->gpio_power; |
791 | } | 789 | } |
792 | if (gpio_is_valid(gpio_power)) { | 790 | if (gpio_is_valid(gpio_power)) { |
793 | ret = gpio_request(gpio_power, "mmc card power"); | 791 | ret = devm_gpio_request(&pdev->dev, gpio_power, |
792 | "mmc card power"); | ||
794 | if (ret) { | 793 | if (ret) { |
795 | dev_err(&pdev->dev, "Failed requesting gpio_power %d\n", gpio_power); | 794 | dev_err(&pdev->dev, "Failed requesting gpio_power %d\n", |
795 | gpio_power); | ||
796 | goto out; | 796 | goto out; |
797 | } | 797 | } |
798 | gpio_direction_output(gpio_power, | 798 | gpio_direction_output(gpio_power, |
799 | host->pdata->gpio_power_invert); | 799 | host->pdata->gpio_power_invert); |
800 | } | 800 | } |
801 | if (gpio_is_valid(gpio_ro)) { | 801 | if (gpio_is_valid(gpio_ro)) |
802 | ret = gpio_request(gpio_ro, "mmc card read only"); | 802 | ret = mmc_gpio_request_ro(mmc, gpio_ro); |
803 | if (ret) { | 803 | if (ret) { |
804 | dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro); | 804 | dev_err(&pdev->dev, "Failed requesting gpio_ro %d\n", gpio_ro); |
805 | goto err_gpio_ro; | 805 | goto out; |
806 | } | 806 | } else { |
807 | gpio_direction_input(gpio_ro); | 807 | mmc->caps |= host->pdata->gpio_card_ro_invert ? |
808 | MMC_CAP2_RO_ACTIVE_HIGH : 0; | ||
808 | } | 809 | } |
809 | if (gpio_is_valid(gpio_cd)) { | ||
810 | ret = gpio_request(gpio_cd, "mmc card detect"); | ||
811 | if (ret) { | ||
812 | dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd); | ||
813 | goto err_gpio_cd; | ||
814 | } | ||
815 | gpio_direction_input(gpio_cd); | ||
816 | 810 | ||
817 | ret = request_irq(gpio_to_irq(gpio_cd), pxamci_detect_irq, | 811 | if (gpio_is_valid(gpio_cd)) |
818 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | 812 | ret = mmc_gpio_request_cd(mmc, gpio_cd, 0); |
819 | "mmc card detect", mmc); | 813 | if (ret) { |
820 | if (ret) { | 814 | dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", gpio_cd); |
821 | dev_err(&pdev->dev, "failed to request card detect IRQ\n"); | 815 | goto out; |
822 | goto err_request_irq; | ||
823 | } | ||
824 | } | 816 | } |
825 | 817 | ||
826 | if (host->pdata && host->pdata->init) | 818 | if (host->pdata && host->pdata->init) |
@@ -835,13 +827,7 @@ static int pxamci_probe(struct platform_device *pdev) | |||
835 | 827 | ||
836 | return 0; | 828 | return 0; |
837 | 829 | ||
838 | err_request_irq: | 830 | out: |
839 | gpio_free(gpio_cd); | ||
840 | err_gpio_cd: | ||
841 | gpio_free(gpio_ro); | ||
842 | err_gpio_ro: | ||
843 | gpio_free(gpio_power); | ||
844 | out: | ||
845 | if (host) { | 831 | if (host) { |
846 | if (host->dma_chan_rx) | 832 | if (host->dma_chan_rx) |
847 | dma_release_channel(host->dma_chan_rx); | 833 | dma_release_channel(host->dma_chan_rx); |
@@ -873,14 +859,6 @@ static int pxamci_remove(struct platform_device *pdev) | |||
873 | gpio_ro = host->pdata->gpio_card_ro; | 859 | gpio_ro = host->pdata->gpio_card_ro; |
874 | gpio_power = host->pdata->gpio_power; | 860 | gpio_power = host->pdata->gpio_power; |
875 | } | 861 | } |
876 | if (gpio_is_valid(gpio_cd)) { | ||
877 | free_irq(gpio_to_irq(gpio_cd), mmc); | ||
878 | gpio_free(gpio_cd); | ||
879 | } | ||
880 | if (gpio_is_valid(gpio_ro)) | ||
881 | gpio_free(gpio_ro); | ||
882 | if (gpio_is_valid(gpio_power)) | ||
883 | gpio_free(gpio_power); | ||
884 | if (host->vcc) | 862 | if (host->vcc) |
885 | regulator_put(host->vcc); | 863 | regulator_put(host->vcc); |
886 | 864 | ||