diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-24 11:21:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-24 11:21:56 -0400 |
commit | 590d4b333d12cbf85dae37257d81960a280232df (patch) | |
tree | ae87599e93d935a96acf88e95df601524af47735 | |
parent | 56fff1bb0f31358bf81a3c64a8dcd6da0dc44263 (diff) | |
parent | f5f968f2371ccdebb8a365487649673c9af68d09 (diff) |
Merge tag 'mmc-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC fixes from Ulf Hansson:
"A couple of MMC host fixes intended for v4.12 rc3:
- sdhci-xenon: Don't free data for phy allocated by devm*
- sdhci-iproc: Suppress spurious interrupts
- cavium: Fix probing race with regulator
- cavium: Prevent crash with incomplete DT
- cavium-octeon: Use proper GPIO name for power control
- cavium-octeon: Fix interrupt enable code"
* tag 'mmc-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
mmc: sdhci-iproc: suppress spurious interrupt with Multiblock read
mmc: cavium: Fix probing race with regulator
of/platform: Make of_platform_device_destroy globally visible
mmc: cavium: Prevent crash with incomplete DT
mmc: cavium-octeon: Use proper GPIO name for power control
mmc: cavium-octeon: Fix interrupt enable code
mmc: sdhci-xenon: kill xenon_clean_phy()
-rw-r--r-- | drivers/mmc/host/cavium-octeon.c | 15 | ||||
-rw-r--r-- | drivers/mmc/host/cavium-thunderx.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/cavium.c | 25 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-iproc.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-xenon-phy.c | 14 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-xenon.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-xenon.h | 1 | ||||
-rw-r--r-- | drivers/of/platform.c | 3 | ||||
-rw-r--r-- | include/linux/of_platform.h | 1 |
9 files changed, 35 insertions, 39 deletions
diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index 772d0900026d..951d2cdd7888 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c | |||
@@ -108,7 +108,7 @@ static void octeon_mmc_release_bus(struct cvm_mmc_host *host) | |||
108 | static void octeon_mmc_int_enable(struct cvm_mmc_host *host, u64 val) | 108 | static void octeon_mmc_int_enable(struct cvm_mmc_host *host, u64 val) |
109 | { | 109 | { |
110 | writeq(val, host->base + MIO_EMM_INT(host)); | 110 | writeq(val, host->base + MIO_EMM_INT(host)); |
111 | if (!host->dma_active || (host->dma_active && !host->has_ciu3)) | 111 | if (!host->has_ciu3) |
112 | writeq(val, host->base + MIO_EMM_INT_EN(host)); | 112 | writeq(val, host->base + MIO_EMM_INT_EN(host)); |
113 | } | 113 | } |
114 | 114 | ||
@@ -267,7 +267,7 @@ static int octeon_mmc_probe(struct platform_device *pdev) | |||
267 | } | 267 | } |
268 | 268 | ||
269 | host->global_pwr_gpiod = devm_gpiod_get_optional(&pdev->dev, | 269 | host->global_pwr_gpiod = devm_gpiod_get_optional(&pdev->dev, |
270 | "power-gpios", | 270 | "power", |
271 | GPIOD_OUT_HIGH); | 271 | GPIOD_OUT_HIGH); |
272 | if (IS_ERR(host->global_pwr_gpiod)) { | 272 | if (IS_ERR(host->global_pwr_gpiod)) { |
273 | dev_err(&pdev->dev, "Invalid power GPIO\n"); | 273 | dev_err(&pdev->dev, "Invalid power GPIO\n"); |
@@ -288,11 +288,20 @@ static int octeon_mmc_probe(struct platform_device *pdev) | |||
288 | if (ret) { | 288 | if (ret) { |
289 | dev_err(&pdev->dev, "Error populating slots\n"); | 289 | dev_err(&pdev->dev, "Error populating slots\n"); |
290 | octeon_mmc_set_shared_power(host, 0); | 290 | octeon_mmc_set_shared_power(host, 0); |
291 | return ret; | 291 | goto error; |
292 | } | 292 | } |
293 | i++; | 293 | i++; |
294 | } | 294 | } |
295 | return 0; | 295 | return 0; |
296 | |||
297 | error: | ||
298 | for (i = 0; i < CAVIUM_MAX_MMC; i++) { | ||
299 | if (host->slot[i]) | ||
300 | cvm_mmc_of_slot_remove(host->slot[i]); | ||
301 | if (host->slot_pdev[i]) | ||
302 | of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL); | ||
303 | } | ||
304 | return ret; | ||
296 | } | 305 | } |
297 | 306 | ||
298 | static int octeon_mmc_remove(struct platform_device *pdev) | 307 | static int octeon_mmc_remove(struct platform_device *pdev) |
diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index fe3d77267cd6..b9cc95998799 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c | |||
@@ -146,6 +146,12 @@ static int thunder_mmc_probe(struct pci_dev *pdev, | |||
146 | return 0; | 146 | return 0; |
147 | 147 | ||
148 | error: | 148 | error: |
149 | for (i = 0; i < CAVIUM_MAX_MMC; i++) { | ||
150 | if (host->slot[i]) | ||
151 | cvm_mmc_of_slot_remove(host->slot[i]); | ||
152 | if (host->slot_pdev[i]) | ||
153 | of_platform_device_destroy(&host->slot_pdev[i]->dev, NULL); | ||
154 | } | ||
149 | clk_disable_unprepare(host->clk); | 155 | clk_disable_unprepare(host->clk); |
150 | return ret; | 156 | return ret; |
151 | } | 157 | } |
diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index 58b51ba6aabd..b8aaf0fdb77c 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c | |||
@@ -839,14 +839,14 @@ static void cvm_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
839 | cvm_mmc_reset_bus(slot); | 839 | cvm_mmc_reset_bus(slot); |
840 | if (host->global_pwr_gpiod) | 840 | if (host->global_pwr_gpiod) |
841 | host->set_shared_power(host, 0); | 841 | host->set_shared_power(host, 0); |
842 | else | 842 | else if (!IS_ERR(mmc->supply.vmmc)) |
843 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); | 843 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); |
844 | break; | 844 | break; |
845 | 845 | ||
846 | case MMC_POWER_UP: | 846 | case MMC_POWER_UP: |
847 | if (host->global_pwr_gpiod) | 847 | if (host->global_pwr_gpiod) |
848 | host->set_shared_power(host, 1); | 848 | host->set_shared_power(host, 1); |
849 | else | 849 | else if (!IS_ERR(mmc->supply.vmmc)) |
850 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); | 850 | mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); |
851 | break; | 851 | break; |
852 | } | 852 | } |
@@ -968,20 +968,15 @@ static int cvm_mmc_of_parse(struct device *dev, struct cvm_mmc_slot *slot) | |||
968 | return -EINVAL; | 968 | return -EINVAL; |
969 | } | 969 | } |
970 | 970 | ||
971 | mmc->supply.vmmc = devm_regulator_get_optional(dev, "vmmc"); | 971 | ret = mmc_regulator_get_supply(mmc); |
972 | if (IS_ERR(mmc->supply.vmmc)) { | 972 | if (ret == -EPROBE_DEFER) |
973 | if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER) | 973 | return ret; |
974 | return -EPROBE_DEFER; | 974 | /* |
975 | /* | 975 | * Legacy Octeon firmware has no regulator entry, fall-back to |
976 | * Legacy Octeon firmware has no regulator entry, fall-back to | 976 | * a hard-coded voltage to get a sane OCR. |
977 | * a hard-coded voltage to get a sane OCR. | 977 | */ |
978 | */ | 978 | if (IS_ERR(mmc->supply.vmmc)) |
979 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 979 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
980 | } else { | ||
981 | ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc); | ||
982 | if (ret > 0) | ||
983 | mmc->ocr_avail = ret; | ||
984 | } | ||
985 | 980 | ||
986 | /* Common MMC bindings */ | 981 | /* Common MMC bindings */ |
987 | ret = mmc_of_parse(mmc); | 982 | ret = mmc_of_parse(mmc); |
diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 3275d4995812..61666d269771 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c | |||
@@ -187,7 +187,8 @@ static const struct sdhci_iproc_data iproc_cygnus_data = { | |||
187 | }; | 187 | }; |
188 | 188 | ||
189 | static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = { | 189 | static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = { |
190 | .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, | 190 | .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | |
191 | SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, | ||
191 | .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN, | 192 | .quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN, |
192 | .ops = &sdhci_iproc_ops, | 193 | .ops = &sdhci_iproc_ops, |
193 | }; | 194 | }; |
diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index 6356781f1cca..f7e26b031e76 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c | |||
@@ -787,14 +787,6 @@ int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios) | |||
787 | return ret; | 787 | return ret; |
788 | } | 788 | } |
789 | 789 | ||
790 | void xenon_clean_phy(struct sdhci_host *host) | ||
791 | { | ||
792 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
793 | struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
794 | |||
795 | kfree(priv->phy_params); | ||
796 | } | ||
797 | |||
798 | static int xenon_add_phy(struct device_node *np, struct sdhci_host *host, | 790 | static int xenon_add_phy(struct device_node *np, struct sdhci_host *host, |
799 | const char *phy_name) | 791 | const char *phy_name) |
800 | { | 792 | { |
@@ -819,11 +811,7 @@ static int xenon_add_phy(struct device_node *np, struct sdhci_host *host, | |||
819 | if (ret) | 811 | if (ret) |
820 | return ret; | 812 | return ret; |
821 | 813 | ||
822 | ret = xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params); | 814 | return xenon_emmc_phy_parse_param_dt(host, np, priv->phy_params); |
823 | if (ret) | ||
824 | xenon_clean_phy(host); | ||
825 | |||
826 | return ret; | ||
827 | } | 815 | } |
828 | 816 | ||
829 | int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host) | 817 | int xenon_phy_parse_dt(struct device_node *np, struct sdhci_host *host) |
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 67246655315b..bc1781bb070b 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c | |||
@@ -486,7 +486,7 @@ static int xenon_probe(struct platform_device *pdev) | |||
486 | 486 | ||
487 | err = xenon_sdhc_prepare(host); | 487 | err = xenon_sdhc_prepare(host); |
488 | if (err) | 488 | if (err) |
489 | goto clean_phy_param; | 489 | goto err_clk; |
490 | 490 | ||
491 | err = sdhci_add_host(host); | 491 | err = sdhci_add_host(host); |
492 | if (err) | 492 | if (err) |
@@ -496,8 +496,6 @@ static int xenon_probe(struct platform_device *pdev) | |||
496 | 496 | ||
497 | remove_sdhc: | 497 | remove_sdhc: |
498 | xenon_sdhc_unprepare(host); | 498 | xenon_sdhc_unprepare(host); |
499 | clean_phy_param: | ||
500 | xenon_clean_phy(host); | ||
501 | err_clk: | 499 | err_clk: |
502 | clk_disable_unprepare(pltfm_host->clk); | 500 | clk_disable_unprepare(pltfm_host->clk); |
503 | free_pltfm: | 501 | free_pltfm: |
@@ -510,8 +508,6 @@ static int xenon_remove(struct platform_device *pdev) | |||
510 | struct sdhci_host *host = platform_get_drvdata(pdev); | 508 | struct sdhci_host *host = platform_get_drvdata(pdev); |
511 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 509 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
512 | 510 | ||
513 | xenon_clean_phy(host); | ||
514 | |||
515 | sdhci_remove_host(host, 0); | 511 | sdhci_remove_host(host, 0); |
516 | 512 | ||
517 | xenon_sdhc_unprepare(host); | 513 | xenon_sdhc_unprepare(host); |
diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h index 6e6523ea01ce..73debb42dc2f 100644 --- a/drivers/mmc/host/sdhci-xenon.h +++ b/drivers/mmc/host/sdhci-xenon.h | |||
@@ -93,7 +93,6 @@ struct xenon_priv { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios); | 95 | int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios); |
96 | void xenon_clean_phy(struct sdhci_host *host); | ||
97 | int xenon_phy_parse_dt(struct device_node *np, | 96 | int xenon_phy_parse_dt(struct device_node *np, |
98 | struct sdhci_host *host); | 97 | struct sdhci_host *host); |
99 | void xenon_soc_pad_ctrl(struct sdhci_host *host, | 98 | void xenon_soc_pad_ctrl(struct sdhci_host *host, |
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 71fecc2debfc..703a42118ffc 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -523,7 +523,7 @@ static int __init of_platform_default_populate_init(void) | |||
523 | arch_initcall_sync(of_platform_default_populate_init); | 523 | arch_initcall_sync(of_platform_default_populate_init); |
524 | #endif | 524 | #endif |
525 | 525 | ||
526 | static int of_platform_device_destroy(struct device *dev, void *data) | 526 | int of_platform_device_destroy(struct device *dev, void *data) |
527 | { | 527 | { |
528 | /* Do not touch devices not populated from the device tree */ | 528 | /* Do not touch devices not populated from the device tree */ |
529 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) | 529 | if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) |
@@ -544,6 +544,7 @@ static int of_platform_device_destroy(struct device *dev, void *data) | |||
544 | of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); | 544 | of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); |
545 | return 0; | 545 | return 0; |
546 | } | 546 | } |
547 | EXPORT_SYMBOL_GPL(of_platform_device_destroy); | ||
547 | 548 | ||
548 | /** | 549 | /** |
549 | * of_platform_depopulate() - Remove devices populated from device tree | 550 | * of_platform_depopulate() - Remove devices populated from device tree |
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index dc8224ae28d5..e0d1946270f3 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
@@ -64,6 +64,7 @@ extern struct platform_device *of_platform_device_create(struct device_node *np, | |||
64 | const char *bus_id, | 64 | const char *bus_id, |
65 | struct device *parent); | 65 | struct device *parent); |
66 | 66 | ||
67 | extern int of_platform_device_destroy(struct device *dev, void *data); | ||
67 | extern int of_platform_bus_probe(struct device_node *root, | 68 | extern int of_platform_bus_probe(struct device_node *root, |
68 | const struct of_device_id *matches, | 69 | const struct of_device_id *matches, |
69 | struct device *parent); | 70 | struct device *parent); |