summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2017-10-02 10:58:52 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2017-10-04 04:50:36 -0400
commitbb16ea1742c8f35a9349b7508dc45d3a922db5f5 (patch)
tree87416834df3b15a64f7d7a9d7d53878cac7602cb
parent0a44697627d17a66d7dc98f17aeca07ca79c5c20 (diff)
mmc: sdhci-xenon: Fix clock resource by adding an optional bus clock
On Armada 7K/8K we need to explicitly enable the bus clock. The bus clock is optional because not all the SoCs need them but at least for Armada 7K/8K it is actually mandatory. The binding documentation is updating accordingly. Without this patch the kernel hand during boot if the mvpp2.2 network driver was not present in the kernel. Indeed the clock needed by the xenon controller was set by the network driver. Fixes: 3a3748dba881 ("mmc: sdhci-xenon: Add Marvell Xenon SDHC core functionality)" CC: Stable <stable@vger.kernel.org> Tested-by: Zhoujie Wu <zjwu@marvell.com> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt12
-rw-r--r--drivers/mmc/host/sdhci-xenon.c24
-rw-r--r--drivers/mmc/host/sdhci-xenon.h1
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);
543err_clk_axi:
544 clk_disable_unprepare(priv->axi_clk);
530err_clk: 545err_clk:
531 clk_disable_unprepare(pltfm_host->clk); 546 clk_disable_unprepare(pltfm_host->clk);
532free_pltfm: 547free_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 /*