From patchwork Mon Jan 20 16:45:03 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 3513831 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 70FA29F2D6 for ; Mon, 20 Jan 2014 17:43:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4F24820122 for ; Mon, 20 Jan 2014 17:43:19 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D2C022010E for ; Mon, 20 Jan 2014 17:43:17 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1W5I1G-0003V6-Fq; Mon, 20 Jan 2014 16:48:17 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1W5I0R-0005jV-5S; Mon, 20 Jan 2014 16:47:23 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1W5Hz4-0005Yc-Ni for linux-arm-kernel@lists.infradead.org; Mon, 20 Jan 2014 16:46:11 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s0KGjYZc031206 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 20 Jan 2014 11:45:34 -0500 Received: from shalem.localdomain.com (vpn1-5-170.ams2.redhat.com [10.36.5.170]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s0KGj4eq011144; Mon, 20 Jan 2014 11:45:32 -0500 From: Hans de Goede To: Tejun Heo Subject: [PATCH RFC v4 10/10] ahci_imx: Port to library-ised ahci_platform Date: Mon, 20 Jan 2014 17:45:03 +0100 Message-Id: <1390236303-22538-11-git-send-email-hdegoede@redhat.com> In-Reply-To: <1390236303-22538-1-git-send-email-hdegoede@redhat.com> References: <1390236303-22538-1-git-send-email-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140120_114559_112976_09507965 X-CRM114-Status: GOOD ( 23.37 ) X-Spam-Score: -7.5 (-------) Cc: devicetree , Hans de Goede , linux-ide@vger.kernel.org, Oliver Schinagl , Richard Zhu , linux-sunxi@googlegroups.com, Maxime Ripard , linux-arm-kernel@lists.infradead.org, Roger Quadros X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This avoids the ugliness of creating a nested platform device from probe. Note untested, I've ordered a wandboard to be able to test these changes. Signed-off-by: Hans de Goede --- .../devicetree/bindings/ata/ahci-platform.txt | 8 +- drivers/ata/ahci_imx.c | 199 ++++++++------------- 2 files changed, 80 insertions(+), 127 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 : - reg : @@ -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 49fa0ca..3454b18 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -34,10 +34,14 @@ 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; @@ -47,6 +51,8 @@ static int ahci_imx_hotplug; module_param_named(hotplug, ahci_imx_hotplug, int, 0644); MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)"); +static void ahci_imx_host_stop(struct ata_host *host); + static void ahci_imx_error_handler(struct ata_port *ap) { u32 reg_val; @@ -54,7 +60,7 @@ static void ahci_imx_error_handler(struct ata_port *ap) struct ata_host *host = dev_get_drvdata(ap->dev); struct ahci_host_priv *hpriv = host->private_data; void __iomem *mmio = hpriv->mmio; - struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent); + struct imx_ahci_priv *imxpriv = hpriv->plat_data; ahci_error_handler(ap); @@ -75,12 +81,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); + ahci_platform_disable_clks(hpriv); imxpriv->no_device = true; } static struct ata_port_operations ahci_imx_ops = { - .inherits = &ahci_platform_ops, + .inherits = &ahci_ops, + .host_stop = ahci_imx_host_stop, .error_handler = ahci_imx_error_handler, }; @@ -91,23 +98,38 @@ static const struct ata_port_info ahci_imx_port_info = { .port_ops = &ahci_imx_ops, }; -static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv) +static int imx_ahci_probe(struct platform_device *pdev) { - int ret = 0; + struct device *dev = &pdev->dev; + struct ahci_host_priv *hpriv; + struct imx_ahci_priv *imxpriv; unsigned int reg_val; - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + int rc; + + imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); + if (!imxpriv) + return -ENOMEM; + + hpriv = ahci_platform_get_resources(pdev); + if (IS_ERR(hpriv)) + return PTR_ERR(hpriv); + if (!hpriv->clks[CLK_AHB]) { + dev_err(dev, "no ahb clk, need sata, sata_ref and ahb clks\n"); + rc = -ENOENT; + goto put_resources; + } + hpriv->plat_data = imxpriv; + + rc = ahci_platform_enable_resources(hpriv); + if (rc) + goto put_resources; imxpriv->gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); if (IS_ERR(imxpriv->gpr)) { dev_err(dev, "failed to find fsl,imx6q-iomux-gpr regmap\n"); - 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; + rc = PTR_ERR(imxpriv->gpr); + goto disable_resources; } /* @@ -156,24 +178,45 @@ static int imx6q_sata_init(struct device *dev, struct ahci_host_priv *hpriv) writel(reg_val, hpriv->mmio + HOST_PORTS_IMPL); } - reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; + reg_val = clk_get_rate(hpriv->clks[CLK_AHB]) / 1000; writel(reg_val, hpriv->mmio + HOST_TIMER1MS); + rc = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0); + if (rc) + goto disable_resources; + return 0; + +disable_resources: + ahci_platform_disable_resources(hpriv); +put_resources: + ahci_platform_put_resources(hpriv); + return rc; } -static void imx6q_sata_exit(struct device *dev) +static void ahci_imx_host_stop(struct ata_host *host) { - struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); + struct ahci_host_priv *hpriv = host->private_data; + struct imx_ahci_priv *imxpriv = hpriv->plat_data; - regmap_update_bits(imxpriv->gpr, 0x34, IMX6Q_GPR13_SATA_MPLL_CLK_EN, + if (!imxpriv->no_device) { + 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); + ahci_platform_disable_clks(hpriv); + } } static int 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 = hpriv->plat_data; + int rc; + + rc = ahci_platform_suspend_host(dev); + if (rc) + return rc; /* * If no_device is set, The CLKs had been gated off in the @@ -183,7 +226,7 @@ static int imx_ahci_suspend(struct device *dev) 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); + ahci_platform_disable_clks(hpriv); } return 0; @@ -191,11 +234,13 @@ static int imx_ahci_suspend(struct device *dev) static int imx_ahci_resume(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 = hpriv->plat_data; int ret; if (!imxpriv->no_device) { - ret = clk_prepare_enable(imxpriv->sata_ref_clk); + ret = ahci_platform_enable_clks(hpriv); if (ret < 0) { dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret); return ret; @@ -207,123 +252,27 @@ static int imx_ahci_resume(struct device *dev) usleep_range(1000, 2000); } - return 0; + return ahci_platform_resume_host(dev); } -static struct ahci_platform_data imx6q_sata_pdata = { - .init = imx6q_sata_init, - .exit = imx6q_sata_exit, - .ata_port_info = &ahci_imx_port_info, - .suspend = imx_ahci_suspend, - .resume = imx_ahci_resume, -}; +static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume); static const struct of_device_id imx_ahci_of_match[] = { - { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata}, + { .compatible = "fsl,imx6q-ahci", }, {}, }; MODULE_DEVICE_TABLE(of, imx_ahci_of_match); -static int imx_ahci_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct resource *mem, *irq, res[2]; - const struct of_device_id *of_id; - const struct ahci_platform_data *pdata = NULL; - struct imx_ahci_priv *imxpriv; - struct device *ahci_dev; - struct platform_device *ahci_pdev; - int ret; - - imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); - if (!imxpriv) { - dev_err(dev, "can't alloc ahci_host_priv\n"); - return -ENOMEM; - } - - ahci_pdev = platform_device_alloc("ahci", -1); - if (!ahci_pdev) - return -ENODEV; - - 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); - - of_id = of_match_device(imx_ahci_of_match, dev); - if (of_id) { - pdata = of_id->data; - } else { - ret = -EINVAL; - goto err_out; - } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!mem || !irq) { - dev_err(dev, "no mmio/irq resource\n"); - ret = -ENOMEM; - goto err_out; - } - - res[0] = *mem; - res[1] = *irq; - - ahci_dev->coherent_dma_mask = DMA_BIT_MASK(32); - ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask; - ahci_dev->of_node = dev->of_node; - - ret = platform_device_add_resources(ahci_pdev, res, 2); - if (ret) - goto err_out; - - ret = platform_device_add_data(ahci_pdev, pdata, sizeof(*pdata)); - if (ret) - goto err_out; - - ret = platform_device_add(ahci_pdev); - if (ret) { -err_out: - platform_device_put(ahci_pdev); - return ret; - } - - return 0; -} - -static int imx_ahci_remove(struct platform_device *pdev) -{ - struct imx_ahci_priv *imxpriv = platform_get_drvdata(pdev); - struct platform_device *ahci_pdev = imxpriv->ahci_pdev; - - platform_device_unregister(ahci_pdev); - return 0; -} static struct platform_driver imx_ahci_driver = { .probe = imx_ahci_probe, - .remove = imx_ahci_remove, + .remove = ata_platform_remove_one, .driver = { .name = "ahci-imx", .owner = THIS_MODULE, .of_match_table = imx_ahci_of_match, + .pm = &ahci_imx_pm_ops, }, }; module_platform_driver(imx_ahci_driver);