Skip to content

Commit

Permalink
mmc: sdhci-xenon: Fix clock resource by adding an optional bus clock
Browse files Browse the repository at this point in the history
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: 3a3748d ("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>
  • Loading branch information
Gregory CLEMENT authored and Ulf Hansson committed Oct 4, 2017
1 parent 0a44697 commit bb16ea1
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
12 changes: 7 additions & 5 deletions Documentation/devicetree/bindings/mmc/marvell,xenon-sdhci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ Required Properties:

- clocks:
Array of clocks required for SDHC.
Require at least input clock for Xenon IP core.
Require at least input clock for Xenon IP core. For Armada AP806 and
CP110, the AXI clock is also mandatory.

- clock-names:
Array of names corresponding to clocks property.
The input clock for Xenon IP core should be named as "core".
The input clock for the AXI bus must be named as "axi".

- reg:
* For "marvell,armada-3700-sdhci", two register areas.
Expand Down Expand Up @@ -106,8 +108,8 @@ Example:
compatible = "marvell,armada-ap806-sdhci";
reg = <0xaa0000 0x1000>;
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>
clocks = <&emmc_clk>;
clock-names = "core";
clocks = <&emmc_clk>,<&axi_clk>;
clock-names = "core", "axi";
bus-width = <4>;
marvell,xenon-phy-slow-mode;
marvell,xenon-tun-count = <11>;
Expand All @@ -126,8 +128,8 @@ Example:
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>
vqmmc-supply = <&sd_vqmmc_regulator>;
vmmc-supply = <&sd_vmmc_regulator>;
clocks = <&sdclk>;
clock-names = "core";
clocks = <&sdclk>, <&axi_clk>;
clock-names = "core", "axi";
bus-width = <4>;
marvell,xenon-tun-count = <9>;
};
Expand Down
24 changes: 20 additions & 4 deletions drivers/mmc/host/sdhci-xenon.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ static int xenon_probe(struct platform_device *pdev)
{
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
struct xenon_priv *priv;
int err;

host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
Expand All @@ -474,6 +475,7 @@ static int xenon_probe(struct platform_device *pdev)
return PTR_ERR(host);

pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);

/*
* Link Xenon specific mmc_host_ops function,
Expand All @@ -491,9 +493,20 @@ static int xenon_probe(struct platform_device *pdev)
if (err)
goto free_pltfm;

priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
if (IS_ERR(priv->axi_clk)) {
err = PTR_ERR(priv->axi_clk);
if (err == -EPROBE_DEFER)
goto err_clk;
} else {
err = clk_prepare_enable(priv->axi_clk);
if (err)
goto err_clk;
}

err = mmc_of_parse(host->mmc);
if (err)
goto err_clk;
goto err_clk_axi;

sdhci_get_of_property(pdev);

Expand All @@ -502,11 +515,11 @@ static int xenon_probe(struct platform_device *pdev)
/* Xenon specific dt parse */
err = xenon_probe_dt(pdev);
if (err)
goto err_clk;
goto err_clk_axi;

err = xenon_sdhc_prepare(host);
if (err)
goto err_clk;
goto err_clk_axi;

pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
Expand All @@ -527,6 +540,8 @@ static int xenon_probe(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
xenon_sdhc_unprepare(host);
err_clk_axi:
clk_disable_unprepare(priv->axi_clk);
err_clk:
clk_disable_unprepare(pltfm_host->clk);
free_pltfm:
Expand All @@ -538,6 +553,7 @@ static int xenon_remove(struct platform_device *pdev)
{
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);

pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
Expand All @@ -546,7 +562,7 @@ static int xenon_remove(struct platform_device *pdev)
sdhci_remove_host(host, 0);

xenon_sdhc_unprepare(host);

clk_disable_unprepare(priv->axi_clk);
clk_disable_unprepare(pltfm_host->clk);

sdhci_pltfm_free(pdev);
Expand Down
1 change: 1 addition & 0 deletions drivers/mmc/host/sdhci-xenon.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ struct xenon_priv {
unsigned char bus_width;
unsigned char timing;
unsigned int clock;
struct clk *axi_clk;

int phy_type;
/*
Expand Down

0 comments on commit bb16ea1

Please sign in to comment.