diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-02 08:03:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-10-02 08:03:04 -0400 |
commit | 36f8dafe52b0d0726edd5102900e37192f1d3c65 (patch) | |
tree | 275620178300956525d5f01f70f6dd5cf2ce91ee | |
parent | 8c25ab8b5a04a7c559aa8fd4cabe5fc4463b8ada (diff) | |
parent | 031277d4d33d33f0174fbb569ca8f68238175617 (diff) |
Merge tag 'mmc-v4.3-rc3' of git://git.linaro.org/people/ulf.hansson/mmc
Pull MMC fixes from Ulf Hansson:
"Here are some mmc fixes intended for v4.3 rc4:
MMC core:
- Allow users of mmc_of_parse() to succeed when CONFIG_GPIOLIB is
unset
- Prevent infinite loop of re-tuning for CRC-errors for CMD19 and
CMD21
MMC host:
- pxamci: Fix issues with card detect
- sunxi: Fix clk-delay settings"
* tag 'mmc-v4.3-rc3' of git://git.linaro.org/people/ulf.hansson/mmc:
mmc: core: fix dead loop of mmc_retune
mmc: pxamci: fix card detect with slot-gpio API
mmc: sunxi: Fix clk-delay settings
mmc: core: Don't return an error for CD/WP GPIOs when GPIOLIB is unset
-rw-r--r-- | drivers/mmc/core/core.c | 6 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/pxamci.c | 66 | ||||
-rw-r--r-- | drivers/mmc/host/sunxi-mmc.c | 53 |
4 files changed, 67 insertions, 62 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0520064dc33b..a3eb20bdcd97 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -134,9 +134,11 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) | |||
134 | int err = cmd->error; | 134 | int err = cmd->error; |
135 | 135 | ||
136 | /* Flag re-tuning needed on CRC errors */ | 136 | /* Flag re-tuning needed on CRC errors */ |
137 | if (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || | 137 | if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && |
138 | cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && | ||
139 | (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || | ||
138 | (mrq->data && mrq->data->error == -EILSEQ) || | 140 | (mrq->data && mrq->data->error == -EILSEQ) || |
139 | (mrq->stop && mrq->stop->error == -EILSEQ)) | 141 | (mrq->stop && mrq->stop->error == -EILSEQ))) |
140 | mmc_retune_needed(host); | 142 | mmc_retune_needed(host); |
141 | 143 | ||
142 | if (err && cmd->retries && mmc_host_is_spi(host)) { | 144 | if (err && cmd->retries && mmc_host_is_spi(host)) { |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index abd933b7029b..5466f25f0281 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
@@ -457,7 +457,7 @@ int mmc_of_parse(struct mmc_host *host) | |||
457 | 0, &cd_gpio_invert); | 457 | 0, &cd_gpio_invert); |
458 | if (!ret) | 458 | if (!ret) |
459 | dev_info(host->parent, "Got CD GPIO\n"); | 459 | dev_info(host->parent, "Got CD GPIO\n"); |
460 | else if (ret != -ENOENT) | 460 | else if (ret != -ENOENT && ret != -ENOSYS) |
461 | return ret; | 461 | return ret; |
462 | 462 | ||
463 | /* | 463 | /* |
@@ -481,7 +481,7 @@ int mmc_of_parse(struct mmc_host *host) | |||
481 | ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); | 481 | ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &ro_gpio_invert); |
482 | if (!ret) | 482 | if (!ret) |
483 | dev_info(host->parent, "Got WP GPIO\n"); | 483 | dev_info(host->parent, "Got WP GPIO\n"); |
484 | else if (ret != -ENOENT) | 484 | else if (ret != -ENOENT && ret != -ENOSYS) |
485 | return ret; | 485 | return ret; |
486 | 486 | ||
487 | if (of_property_read_bool(np, "disable-wp")) | 487 | if (of_property_read_bool(np, "disable-wp")) |
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 | ||
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index a7b7a6771598..b981b8552e43 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c | |||
@@ -210,6 +210,16 @@ | |||
210 | #define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ | 210 | #define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ |
211 | #define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ | 211 | #define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ |
212 | 212 | ||
213 | #define SDXC_CLK_400K 0 | ||
214 | #define SDXC_CLK_25M 1 | ||
215 | #define SDXC_CLK_50M 2 | ||
216 | #define SDXC_CLK_50M_DDR 3 | ||
217 | |||
218 | struct sunxi_mmc_clk_delay { | ||
219 | u32 output; | ||
220 | u32 sample; | ||
221 | }; | ||
222 | |||
213 | struct sunxi_idma_des { | 223 | struct sunxi_idma_des { |
214 | u32 config; | 224 | u32 config; |
215 | u32 buf_size; | 225 | u32 buf_size; |
@@ -229,6 +239,7 @@ struct sunxi_mmc_host { | |||
229 | struct clk *clk_mmc; | 239 | struct clk *clk_mmc; |
230 | struct clk *clk_sample; | 240 | struct clk *clk_sample; |
231 | struct clk *clk_output; | 241 | struct clk *clk_output; |
242 | const struct sunxi_mmc_clk_delay *clk_delays; | ||
232 | 243 | ||
233 | /* irq */ | 244 | /* irq */ |
234 | spinlock_t lock; | 245 | spinlock_t lock; |
@@ -654,25 +665,19 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, | |||
654 | 665 | ||
655 | /* determine delays */ | 666 | /* determine delays */ |
656 | if (rate <= 400000) { | 667 | if (rate <= 400000) { |
657 | oclk_dly = 180; | 668 | oclk_dly = host->clk_delays[SDXC_CLK_400K].output; |
658 | sclk_dly = 42; | 669 | sclk_dly = host->clk_delays[SDXC_CLK_400K].sample; |
659 | } else if (rate <= 25000000) { | 670 | } else if (rate <= 25000000) { |
660 | oclk_dly = 180; | 671 | oclk_dly = host->clk_delays[SDXC_CLK_25M].output; |
661 | sclk_dly = 75; | 672 | sclk_dly = host->clk_delays[SDXC_CLK_25M].sample; |
662 | } else if (rate <= 50000000) { | 673 | } else if (rate <= 50000000) { |
663 | if (ios->timing == MMC_TIMING_UHS_DDR50) { | 674 | if (ios->timing == MMC_TIMING_UHS_DDR50) { |
664 | oclk_dly = 60; | 675 | oclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].output; |
665 | sclk_dly = 120; | 676 | sclk_dly = host->clk_delays[SDXC_CLK_50M_DDR].sample; |
666 | } else { | 677 | } else { |
667 | oclk_dly = 90; | 678 | oclk_dly = host->clk_delays[SDXC_CLK_50M].output; |
668 | sclk_dly = 150; | 679 | sclk_dly = host->clk_delays[SDXC_CLK_50M].sample; |
669 | } | 680 | } |
670 | } else if (rate <= 100000000) { | ||
671 | oclk_dly = 6; | ||
672 | sclk_dly = 24; | ||
673 | } else if (rate <= 200000000) { | ||
674 | oclk_dly = 3; | ||
675 | sclk_dly = 12; | ||
676 | } else { | 681 | } else { |
677 | return -EINVAL; | 682 | return -EINVAL; |
678 | } | 683 | } |
@@ -871,6 +876,7 @@ static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
871 | static const struct of_device_id sunxi_mmc_of_match[] = { | 876 | static const struct of_device_id sunxi_mmc_of_match[] = { |
872 | { .compatible = "allwinner,sun4i-a10-mmc", }, | 877 | { .compatible = "allwinner,sun4i-a10-mmc", }, |
873 | { .compatible = "allwinner,sun5i-a13-mmc", }, | 878 | { .compatible = "allwinner,sun5i-a13-mmc", }, |
879 | { .compatible = "allwinner,sun9i-a80-mmc", }, | ||
874 | { /* sentinel */ } | 880 | { /* sentinel */ } |
875 | }; | 881 | }; |
876 | MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); | 882 | MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); |
@@ -884,6 +890,20 @@ static struct mmc_host_ops sunxi_mmc_ops = { | |||
884 | .hw_reset = sunxi_mmc_hw_reset, | 890 | .hw_reset = sunxi_mmc_hw_reset, |
885 | }; | 891 | }; |
886 | 892 | ||
893 | static const struct sunxi_mmc_clk_delay sunxi_mmc_clk_delays[] = { | ||
894 | [SDXC_CLK_400K] = { .output = 180, .sample = 180 }, | ||
895 | [SDXC_CLK_25M] = { .output = 180, .sample = 75 }, | ||
896 | [SDXC_CLK_50M] = { .output = 90, .sample = 120 }, | ||
897 | [SDXC_CLK_50M_DDR] = { .output = 60, .sample = 120 }, | ||
898 | }; | ||
899 | |||
900 | static const struct sunxi_mmc_clk_delay sun9i_mmc_clk_delays[] = { | ||
901 | [SDXC_CLK_400K] = { .output = 180, .sample = 180 }, | ||
902 | [SDXC_CLK_25M] = { .output = 180, .sample = 75 }, | ||
903 | [SDXC_CLK_50M] = { .output = 150, .sample = 120 }, | ||
904 | [SDXC_CLK_50M_DDR] = { .output = 90, .sample = 120 }, | ||
905 | }; | ||
906 | |||
887 | static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | 907 | static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, |
888 | struct platform_device *pdev) | 908 | struct platform_device *pdev) |
889 | { | 909 | { |
@@ -895,6 +915,11 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host, | |||
895 | else | 915 | else |
896 | host->idma_des_size_bits = 16; | 916 | host->idma_des_size_bits = 16; |
897 | 917 | ||
918 | if (of_device_is_compatible(np, "allwinner,sun9i-a80-mmc")) | ||
919 | host->clk_delays = sun9i_mmc_clk_delays; | ||
920 | else | ||
921 | host->clk_delays = sunxi_mmc_clk_delays; | ||
922 | |||
898 | ret = mmc_regulator_get_supply(host->mmc); | 923 | ret = mmc_regulator_get_supply(host->mmc); |
899 | if (ret) { | 924 | if (ret) { |
900 | if (ret != -EPROBE_DEFER) | 925 | if (ret != -EPROBE_DEFER) |