From patchwork Sun Nov 17 01:20:48 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Vasut X-Patchwork-Id: 3193331 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 42904C045B for ; Sun, 17 Nov 2013 01:23:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C5C12088A for ; Sun, 17 Nov 2013 01:23:57 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id AB4BB20880 for ; Sun, 17 Nov 2013 01:23:55 +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 1Vhr49-0004JC-Fq; Sun, 17 Nov 2013 01:22:21 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vhr3s-0002hC-Ak; Sun, 17 Nov 2013 01:22:04 +0000 Received: from mail-out.m-online.net ([212.18.0.10]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Vhr3R-0002dt-Jc for linux-arm-kernel@lists.infradead.org; Sun, 17 Nov 2013 01:21:46 +0000 Received: from frontend1.mail.m-online.net (frontend1.mail.intern.m-online.net [192.168.8.180]) by mail-out.m-online.net (Postfix) with ESMTP id 3dMb915997z3hhxD; Sun, 17 Nov 2013 02:21:09 +0100 (CET) X-Auth-Info: A0AjFzFu8GVumH8Z9OOFVez82fiO0O/eh+8Jv8RtbpY= Received: from chi.lan (unknown [195.140.253.167]) by smtp-auth.mnet-online.de (Postfix) with ESMTPA id 3dMb913Pc9zbbhm; Sun, 17 Nov 2013 02:21:09 +0100 (CET) From: Marek Vasut To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/5] ahci: imx: Add i.MX53 support Date: Sun, 17 Nov 2013 02:20:48 +0100 Message-Id: <1384651251-5548-2-git-send-email-marex@denx.de> X-Mailer: git-send-email 1.8.4.2 In-Reply-To: <1384651251-5548-1-git-send-email-marex@denx.de> References: <1384651251-5548-1-git-send-email-marex@denx.de> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131116_202138_357207_763F280B X-CRM114-Status: GOOD ( 20.30 ) X-Spam-Score: -1.9 (-) Cc: Marek Vasut , Richard Zhu , Tejun Heo , Shawn Guo , Linux-IDE 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.2 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 Add minor adjustments to support i.MX53 SATA port as well as i.MX6Q one. The difference here is mostly the clock which need to be enabled and also the lack of need of programming IOMUXC registers on i.MX53. All of which is well handles in the clock enable/disable functions. Note that this patch also cleans up the names of the common functions, so they don't read imx6q_* but imx_* instead. Signed-off-by: Marek Vasut Cc: Shawn Guo Cc: Richard Zhu Cc: Tejun Heo Cc: Linux-IDE --- drivers/ata/ahci_imx.c | 198 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 70 deletions(-) diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index c7ee505..e6854593 100644 --- a/drivers/ata/ahci_imx.c +++ b/drivers/ata/ahci_imx.c @@ -34,10 +34,23 @@ enum { HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ }; +enum ahci_imx_type { + AHCI_IMX53, + AHCI_IMX6Q, +}; + struct imx_ahci_priv { struct platform_device *ahci_pdev; + enum ahci_imx_type type; + + /* i.MX53 clock */ + struct clk *sata_gate_clk; + struct clk *sata_phy_clk; + /* i.MX6Q clock */ struct clk *sata_ref_clk; + /* Common clock */ struct clk *ahb_clk; + struct regmap *gpr; bool no_device; bool first_time; @@ -52,53 +65,73 @@ static int imx_sata_clock_enable(struct device *dev, bool config) struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); int ret; - 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; - } + if (imxpriv->type == AHCI_IMX53) { + ret = clk_prepare_enable(imxpriv->sata_gate_clk); + if (ret < 0) { + dev_err(dev, "prepare-enable sata_gate 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 - * is 0x07fffffd, and the other one write for setting - * the mpll_clk_en. - */ - if (config) { + ret = clk_prepare_enable(imxpriv->sata_phy_clk); + if (ret < 0) { + clk_disable_unprepare(imxpriv->sata_gate_clk); + dev_err(dev, "prepare-enable sata_phy clock err:%d\n", + ret); + return ret; + } + } else if (imxpriv->type == AHCI_IMX6Q) { + 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; + } + + /* + * set PHY Paremeters, two steps to configure the GPR13, + * one write for rest of parameters, mask of first write + * is 0x07fffffd, and the other one write for setting + * the mpll_clk_en. + */ + if (config) { + regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, + IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK + | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK + | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK + | IMX6Q_GPR13_SATA_SPD_MODE_MASK + | IMX6Q_GPR13_SATA_MPLL_SS_EN + | IMX6Q_GPR13_SATA_TX_ATTEN_MASK + | IMX6Q_GPR13_SATA_TX_BOOST_MASK + | IMX6Q_GPR13_SATA_TX_LVL_MASK + | IMX6Q_GPR13_SATA_TX_EDGE_RATE + , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB + | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M + | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F + | IMX6Q_GPR13_SATA_SPD_MODE_3P0G + | IMX6Q_GPR13_SATA_MPLL_SS_EN + | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 + | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB + | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); + } regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_RX_EQ_VAL_MASK - | IMX6Q_GPR13_SATA_RX_LOS_LVL_MASK - | IMX6Q_GPR13_SATA_RX_DPLL_MODE_MASK - | IMX6Q_GPR13_SATA_SPD_MODE_MASK - | IMX6Q_GPR13_SATA_MPLL_SS_EN - | IMX6Q_GPR13_SATA_TX_ATTEN_MASK - | IMX6Q_GPR13_SATA_TX_BOOST_MASK - | IMX6Q_GPR13_SATA_TX_LVL_MASK - | IMX6Q_GPR13_SATA_TX_EDGE_RATE - , IMX6Q_GPR13_SATA_RX_EQ_VAL_3_0_DB - | IMX6Q_GPR13_SATA_RX_LOS_LVL_SATA2M - | IMX6Q_GPR13_SATA_RX_DPLL_MODE_2P_4F - | IMX6Q_GPR13_SATA_SPD_MODE_3P0G - | IMX6Q_GPR13_SATA_MPLL_SS_EN - | IMX6Q_GPR13_SATA_TX_ATTEN_9_16 - | IMX6Q_GPR13_SATA_TX_BOOST_3_33_DB - | IMX6Q_GPR13_SATA_TX_LVL_1_025_V); - } - regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, - IMX6Q_GPR13_SATA_MPLL_CLK_EN, - IMX6Q_GPR13_SATA_MPLL_CLK_EN); + IMX6Q_GPR13_SATA_MPLL_CLK_EN, + IMX6Q_GPR13_SATA_MPLL_CLK_EN); - 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; + 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; + } } return 0; @@ -108,10 +141,15 @@ static void imx_sata_clock_disable(struct device *dev) { struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent); - 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); + if (imxpriv->type == AHCI_IMX53) { + clk_disable_unprepare(imxpriv->sata_phy_clk); + clk_disable_unprepare(imxpriv->sata_gate_clk); + } else if (imxpriv->type == AHCI_IMX6Q) { + 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 void ahci_imx_error_handler(struct ata_port *ap) @@ -155,7 +193,7 @@ static const struct ata_port_info ahci_imx_port_info = { .port_ops = &ahci_imx_ops, }; -static int imx6q_sata_init(struct device *dev, void __iomem *mmio) +static int imx_sata_init(struct device *dev, void __iomem *mmio) { int ret = 0; unsigned int reg_val; @@ -191,7 +229,7 @@ static int imx6q_sata_init(struct device *dev, void __iomem *mmio) return 0; } -static void imx6q_sata_exit(struct device *dev) +static void imx_sata_exit(struct device *dev) { imx_sata_clock_disable(dev); } @@ -226,16 +264,18 @@ static int imx_ahci_resume(struct device *dev) return 0; } -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 struct ahci_platform_data imx_sata_pdata = { + .init = imx_sata_init, + .exit = imx_sata_exit, + .ata_port_info = &ahci_imx_port_info, + .suspend = imx_ahci_suspend, + .resume = imx_ahci_resume, + }; static const struct of_device_id imx_ahci_of_match[] = { - { .compatible = "fsl,imx6q-ahci", .data = &imx6q_sata_pdata}, + { .compatible = "fsl,imx53-ahci", .data = (void *)AHCI_IMX53 }, + { .compatible = "fsl,imx6q-ahci", .data = (void *)AHCI_IMX6Q }, {}, }; MODULE_DEVICE_TABLE(of, imx_ahci_of_match); @@ -245,12 +285,20 @@ 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; + enum ahci_imx_type type; const struct ahci_platform_data *pdata = NULL; struct imx_ahci_priv *imxpriv; struct device *ahci_dev; struct platform_device *ahci_pdev; int ret; + of_id = of_match_device(imx_ahci_of_match, dev); + if (!of_id) + return -EINVAL; + + type = (enum ahci_imx_type)of_id->data; + pdata = &imx_sata_pdata; + imxpriv = devm_kzalloc(dev, sizeof(*imxpriv), GFP_KERNEL); if (!imxpriv) { dev_err(dev, "can't alloc ahci_host_priv\n"); @@ -266,6 +314,8 @@ static int imx_ahci_probe(struct platform_device *pdev) imxpriv->no_device = false; imxpriv->first_time = true; + imxpriv->type = type; + imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); if (IS_ERR(imxpriv->ahb_clk)) { dev_err(dev, "can't get ahb clock.\n"); @@ -273,24 +323,32 @@ static int imx_ahci_probe(struct platform_device *pdev) 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; + if (type == AHCI_IMX53) { + imxpriv->sata_gate_clk = devm_clk_get(dev, "sata_gate"); + if (IS_ERR(imxpriv->sata_gate_clk)) { + dev_err(dev, "can't get sata_gate clock.\n"); + ret = PTR_ERR(imxpriv->sata_gate_clk); + goto err_out; + } + + imxpriv->sata_phy_clk = devm_clk_get(dev, "sata_phy"); + if (IS_ERR(imxpriv->sata_phy_clk)) { + dev_err(dev, "can't get sata_phy clock.\n"); + ret = PTR_ERR(imxpriv->sata_phy_clk); + goto err_out; + } + } else if (type == AHCI_IMX6Q) { + 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) {