diff options
| -rw-r--r-- | Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt | 12 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-xenon.c | 24 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-xenon.h | 1 |
3 files changed, 28 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt index b878a1e305af..ed1456f5c94d 100644 --- a/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt +++ b/Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt | |||
| @@ -16,11 +16,13 @@ Required Properties: | |||
| 16 | 16 | ||
| 17 | - clocks: | 17 | - clocks: |
| 18 | Array of clocks required for SDHC. | 18 | Array of clocks required for SDHC. |
| 19 | Require at least input clock for Xenon IP core. | 19 | Require at least input clock for Xenon IP core. For Armada AP806 and |
| 20 | CP110, the AXI clock is also mandatory. | ||
| 20 | 21 | ||
| 21 | - clock-names: | 22 | - clock-names: |
| 22 | Array of names corresponding to clocks property. | 23 | Array of names corresponding to clocks property. |
| 23 | The input clock for Xenon IP core should be named as "core". | 24 | The input clock for Xenon IP core should be named as "core". |
| 25 | The input clock for the AXI bus must be named as "axi". | ||
| 24 | 26 | ||
| 25 | - reg: | 27 | - reg: |
| 26 | * For "marvell,armada-3700-sdhci", two register areas. | 28 | * For "marvell,armada-3700-sdhci", two register areas. |
| @@ -106,8 +108,8 @@ Example: | |||
| 106 | compatible = "marvell,armada-ap806-sdhci"; | 108 | compatible = "marvell,armada-ap806-sdhci"; |
| 107 | reg = <0xaa0000 0x1000>; | 109 | reg = <0xaa0000 0x1000>; |
| 108 | interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH> | 110 | interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH> |
| 109 | clocks = <&emmc_clk>; | 111 | clocks = <&emmc_clk>,<&axi_clk>; |
| 110 | clock-names = "core"; | 112 | clock-names = "core", "axi"; |
| 111 | bus-width = <4>; | 113 | bus-width = <4>; |
| 112 | marvell,xenon-phy-slow-mode; | 114 | marvell,xenon-phy-slow-mode; |
| 113 | marvell,xenon-tun-count = <11>; | 115 | marvell,xenon-tun-count = <11>; |
| @@ -126,8 +128,8 @@ Example: | |||
| 126 | interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH> | 128 | interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH> |
| 127 | vqmmc-supply = <&sd_vqmmc_regulator>; | 129 | vqmmc-supply = <&sd_vqmmc_regulator>; |
| 128 | vmmc-supply = <&sd_vmmc_regulator>; | 130 | vmmc-supply = <&sd_vmmc_regulator>; |
| 129 | clocks = <&sdclk>; | 131 | clocks = <&sdclk>, <&axi_clk>; |
| 130 | clock-names = "core"; | 132 | clock-names = "core", "axi"; |
| 131 | bus-width = <4>; | 133 | bus-width = <4>; |
| 132 | marvell,xenon-tun-count = <9>; | 134 | marvell,xenon-tun-count = <9>; |
| 133 | }; | 135 | }; |
diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 2eec2e652c53..0842bbc2d7ad 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c | |||
| @@ -466,6 +466,7 @@ static int xenon_probe(struct platform_device *pdev) | |||
| 466 | { | 466 | { |
| 467 | struct sdhci_pltfm_host *pltfm_host; | 467 | struct sdhci_pltfm_host *pltfm_host; |
| 468 | struct sdhci_host *host; | 468 | struct sdhci_host *host; |
| 469 | struct xenon_priv *priv; | ||
| 469 | int err; | 470 | int err; |
| 470 | 471 | ||
| 471 | host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata, | 472 | host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata, |
| @@ -474,6 +475,7 @@ static int xenon_probe(struct platform_device *pdev) | |||
| 474 | return PTR_ERR(host); | 475 | return PTR_ERR(host); |
| 475 | 476 | ||
| 476 | pltfm_host = sdhci_priv(host); | 477 | pltfm_host = sdhci_priv(host); |
| 478 | priv = sdhci_pltfm_priv(pltfm_host); | ||
| 477 | 479 | ||
| 478 | /* | 480 | /* |
| 479 | * Link Xenon specific mmc_host_ops function, | 481 | * Link Xenon specific mmc_host_ops function, |
| @@ -491,9 +493,20 @@ static int xenon_probe(struct platform_device *pdev) | |||
| 491 | if (err) | 493 | if (err) |
| 492 | goto free_pltfm; | 494 | goto free_pltfm; |
| 493 | 495 | ||
| 496 | priv->axi_clk = devm_clk_get(&pdev->dev, "axi"); | ||
| 497 | if (IS_ERR(priv->axi_clk)) { | ||
| 498 | err = PTR_ERR(priv->axi_clk); | ||
| 499 | if (err == -EPROBE_DEFER) | ||
| 500 | goto err_clk; | ||
| 501 | } else { | ||
| 502 | err = clk_prepare_enable(priv->axi_clk); | ||
| 503 | if (err) | ||
| 504 | goto err_clk; | ||
| 505 | } | ||
| 506 | |||
| 494 | err = mmc_of_parse(host->mmc); | 507 | err = mmc_of_parse(host->mmc); |
| 495 | if (err) | 508 | if (err) |
| 496 | goto err_clk; | 509 | goto err_clk_axi; |
| 497 | 510 | ||
| 498 | sdhci_get_of_property(pdev); | 511 | sdhci_get_of_property(pdev); |
| 499 | 512 | ||
| @@ -502,11 +515,11 @@ static int xenon_probe(struct platform_device *pdev) | |||
| 502 | /* Xenon specific dt parse */ | 515 | /* Xenon specific dt parse */ |
| 503 | err = xenon_probe_dt(pdev); | 516 | err = xenon_probe_dt(pdev); |
| 504 | if (err) | 517 | if (err) |
| 505 | goto err_clk; | 518 | goto err_clk_axi; |
| 506 | 519 | ||
| 507 | err = xenon_sdhc_prepare(host); | 520 | err = xenon_sdhc_prepare(host); |
| 508 | if (err) | 521 | if (err) |
| 509 | goto err_clk; | 522 | goto err_clk_axi; |
| 510 | 523 | ||
| 511 | pm_runtime_get_noresume(&pdev->dev); | 524 | pm_runtime_get_noresume(&pdev->dev); |
| 512 | pm_runtime_set_active(&pdev->dev); | 525 | pm_runtime_set_active(&pdev->dev); |
| @@ -527,6 +540,8 @@ remove_sdhc: | |||
| 527 | pm_runtime_disable(&pdev->dev); | 540 | pm_runtime_disable(&pdev->dev); |
| 528 | pm_runtime_put_noidle(&pdev->dev); | 541 | pm_runtime_put_noidle(&pdev->dev); |
| 529 | xenon_sdhc_unprepare(host); | 542 | xenon_sdhc_unprepare(host); |
| 543 | err_clk_axi: | ||
| 544 | clk_disable_unprepare(priv->axi_clk); | ||
| 530 | err_clk: | 545 | err_clk: |
| 531 | clk_disable_unprepare(pltfm_host->clk); | 546 | clk_disable_unprepare(pltfm_host->clk); |
| 532 | free_pltfm: | 547 | free_pltfm: |
| @@ -538,6 +553,7 @@ static int xenon_remove(struct platform_device *pdev) | |||
| 538 | { | 553 | { |
| 539 | struct sdhci_host *host = platform_get_drvdata(pdev); | 554 | struct sdhci_host *host = platform_get_drvdata(pdev); |
| 540 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 555 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
| 556 | struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); | ||
| 541 | 557 | ||
| 542 | pm_runtime_get_sync(&pdev->dev); | 558 | pm_runtime_get_sync(&pdev->dev); |
| 543 | pm_runtime_disable(&pdev->dev); | 559 | pm_runtime_disable(&pdev->dev); |
| @@ -546,7 +562,7 @@ static int xenon_remove(struct platform_device *pdev) | |||
| 546 | sdhci_remove_host(host, 0); | 562 | sdhci_remove_host(host, 0); |
| 547 | 563 | ||
| 548 | xenon_sdhc_unprepare(host); | 564 | xenon_sdhc_unprepare(host); |
| 549 | 565 | clk_disable_unprepare(priv->axi_clk); | |
| 550 | clk_disable_unprepare(pltfm_host->clk); | 566 | clk_disable_unprepare(pltfm_host->clk); |
| 551 | 567 | ||
| 552 | sdhci_pltfm_free(pdev); | 568 | sdhci_pltfm_free(pdev); |
diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h index 2bc0510c0769..9994995c7c56 100644 --- a/drivers/mmc/host/sdhci-xenon.h +++ b/drivers/mmc/host/sdhci-xenon.h | |||
| @@ -83,6 +83,7 @@ struct xenon_priv { | |||
| 83 | unsigned char bus_width; | 83 | unsigned char bus_width; |
| 84 | unsigned char timing; | 84 | unsigned char timing; |
| 85 | unsigned int clock; | 85 | unsigned int clock; |
| 86 | struct clk *axi_clk; | ||
| 86 | 87 | ||
| 87 | int phy_type; | 88 | int phy_type; |
| 88 | /* | 89 | /* |
