ahci_platform manages all 3 clocks now, so enabling / disabling them from
ahci_imx just results in the sata_ref clock getting enabled / disabled twice.

Note untested, I've ordered a wandboard to be able to test these changes.

Signed-off-by: Hans de Goede <[email protected]>
---
 .../devicetree/bindings/ata/ahci-platform.txt      |  8 ++-
 drivers/ata/ahci_imx.c                             | 82 +++++++++-------------
 2 files changed, 40 insertions(+), 50 deletions(-)

diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt 
b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index f036e786..ee3a127 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -5,8 +5,8 @@ Each SATA controller should have its own node.
 
 Required properties:
 - compatible        : compatible list, one of "snps,spear-ahci",
-                      "snps,exynos5440-ahci", "ibm,476gtr-ahci", or
-                      "allwinner,sun4i-a10-ahci"
+                      "snps,exynos5440-ahci", "ibm,476gtr-ahci",
+                      "allwinner,sun4i-a10-ahci" or "fsl,imx6q-ahci"
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
@@ -18,6 +18,10 @@ Optional properties:
 allwinner,sun4i-a10-ahci required properties:
 - clocks            : index 0 must point to the sata_ref clk, 1 to the ahb clk
 
+fsl,imx6q-ahci required properties:
+- clocks            : index 0 must point to the sataf clk, 1 to the sata_ref
+                     clk and 2 to the ahb clk
+
 Examples:
         sata@ffe08000 {
                compatible = "snps,spear-ahci";
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 0051f29..8eb24a3 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -34,12 +34,15 @@ enum {
        HOST_TIMER1MS = 0xe0,                   /* Timer 1-ms */
 };
 
+enum {
+       CLK_SATA,
+       CLK_SATA_REF,
+       CLK_AHB
+};
+
 struct imx_ahci_priv {
        struct platform_device *ahci_pdev;
-       struct clk *sata_ref_clk;
-       struct clk *ahb_clk;
        struct regmap *gpr;
-       bool no_device;
        bool first_time;
 };
 
@@ -55,6 +58,7 @@ static void ahci_imx_error_handler(struct ata_port *ap)
        struct ahci_host_priv *hpriv = host->private_data;
        void __iomem *mmio = hpriv->mmio;
        struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
+       int i;
 
        ahci_error_handler(ap);
 
@@ -75,8 +79,13 @@ static void ahci_imx_error_handler(struct ata_port *ap)
        regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
                        IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                        !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-       clk_disable_unprepare(imxpriv->sata_ref_clk);
-       imxpriv->no_device = true;
+
+       for (i = CLK_AHB; i >= 0; i--) {
+               clk_disable_unprepare(hpriv->clks[i]);
+               /* Stop ahci_platform.c from trying to use the clks */
+               clk_put(hpriv->clks[i]);
+               hpriv->clks[i] = NULL;
+       }
 }
 
 static struct ata_port_operations ahci_imx_ops = {
@@ -94,7 +103,6 @@ static const struct ata_port_info ahci_imx_port_info = {
 static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv,
                           void __iomem *mmio)
 {
-       int ret = 0;
        unsigned int reg_val;
        struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
@@ -105,12 +113,6 @@ static int imx6q_sata_init(struct device *dev, struct 
ahci_host_priv *hpriv,
                return PTR_ERR(imxpriv->gpr);
        }
 
-       ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-       if (ret < 0) {
-               dev_err(dev, "prepare-enable sata_ref clock err:%d\n", ret);
-               return ret;
-       }
-
        /*
         * set PHY Paremeters, two steps to configure the GPR13,
         * one write for rest of parameters, mask of first write
@@ -157,7 +159,11 @@ static int imx6q_sata_init(struct device *dev, struct 
ahci_host_priv *hpriv,
                writel(reg_val, mmio + HOST_PORTS_IMPL);
        }
 
-       reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
+       if (!hpriv->clks[CLK_AHB]) {
+               dev_err(dev, "no ahb clk, need sata, sata_ref and ahb clks\n");
+               return -ENOENT;
+       }
+       reg_val = clk_get_rate(hpriv->clks[CLK_AHB]) / 1000;
        writel(reg_val, mmio + HOST_TIMER1MS);
 
        return 0;
@@ -165,41 +171,36 @@ static int imx6q_sata_init(struct device *dev, struct 
ahci_host_priv *hpriv,
 
 static void imx6q_sata_exit(struct device *dev)
 {
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
-       regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
+       if (hpriv->clks[CLK_SATA])
+               regmap_update_bits(imxpriv->gpr, 0x34,
+                       IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                        !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-       clk_disable_unprepare(imxpriv->sata_ref_clk);
 }
 
 static void imx_ahci_suspend(struct device *dev)
 {
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
-       /*
-        * If no_device is set, The CLKs had been gated off in the
-        * initialization so don't do it again here.
-        */
-       if (!imxpriv->no_device) {
+       /* Check the CLKs have not been gated off in the initialization. */
+       if (hpriv->clks[CLK_SATA])
                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
                                IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                                !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
-               clk_disable_unprepare(imxpriv->sata_ref_clk);
-       }
 }
 
 static int imx_ahci_resume(struct device *dev)
 {
-       struct imx_ahci_priv *imxpriv =  dev_get_drvdata(dev->parent);
-       int ret;
-
-       if (!imxpriv->no_device) {
-               ret = clk_prepare_enable(imxpriv->sata_ref_clk);
-               if (ret < 0) {
-                       dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret);
-                       return ret;
-               }
+       struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
+       struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
 
+       if (hpriv->clks[CLK_SATA]) {
                regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
                                IMX6Q_GPR13_SATA_MPLL_CLK_EN,
                                IMX6Q_GPR13_SATA_MPLL_CLK_EN);
@@ -247,22 +248,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
        ahci_dev = &ahci_pdev->dev;
        ahci_dev->parent = dev;
 
-       imxpriv->no_device = false;
        imxpriv->first_time = true;
-       imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
-       if (IS_ERR(imxpriv->ahb_clk)) {
-               dev_err(dev, "can't get ahb clock.\n");
-               ret = PTR_ERR(imxpriv->ahb_clk);
-               goto err_out;
-       }
-
-       imxpriv->sata_ref_clk = devm_clk_get(dev, "sata_ref");
-       if (IS_ERR(imxpriv->sata_ref_clk)) {
-               dev_err(dev, "can't get sata_ref clock.\n");
-               ret = PTR_ERR(imxpriv->sata_ref_clk);
-               goto err_out;
-       }
-
        imxpriv->ahci_pdev = ahci_pdev;
        platform_set_drvdata(pdev, imxpriv);
 
-- 
1.8.4.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to