[PATCH V3 2/5] ahci: imx: Add i.MX53 support

Richard Zhu Hong-Xing.Zhu at freescale.com
Wed Nov 20 02:34:49 EST 2013


Hi Marek:

> -----Original Message-----
> From: Shawn Guo [mailto:shawn.guo at linaro.org]
> Sent: Tuesday, November 19, 2013 4:48 PM
> To: Marek Vasut
> Cc: linux-arm-kernel at lists.infradead.org; Zhu Richard-R65037; Tejun Heo;
> Linux-IDE
> Subject: Re: [PATCH V3 2/5] ahci: imx: Add i.MX53 support
> 
> On Mon, Nov 18, 2013 at 03:30:40PM +0100, Marek Vasut wrote:
> > 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 <marex at denx.de>
> > Cc: Shawn Guo <shawn.guo at linaro.org>
> > Cc: Richard Zhu <r65037 at freescale.com>
> > Cc: Tejun Heo <tj at kernel.org>
> > Cc: Linux-IDE <linux-ide at vger.kernel.org>
> > ---
> >  drivers/ata/ahci_imx.c | 191
> > +++++++++++++++++++++++++++++++------------------
> >  1 file changed, 121 insertions(+), 70 deletions(-)
> >
> > V2: Rebase this patch to be coherent with formating change in 1/5 .
> > V3: Rebase this patch to be coherent with change in 1/5 .
> >
> > diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c index
> > b36f96c..8e4b4a9 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;
> 
> I think sata_ref_clk on imx6q and sata_phy_clk on imx53 are both the clock for
> SATA PHY, so they are the same clock?
> 
> Shawn
[Richard] They are the same clock used by sata phy.
> 
> > +	/* Common clock */
> >  	struct clk *ahb_clk;
> > +
> >  	struct regmap *gpr;
> >  	bool no_device;
> >  	bool first_time;
> > @@ -52,20 +65,32 @@ static int imx_sata_clock_enable(struct device *dev)
> >  	struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
> >  	int 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;
> > -	}
> > +	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;
> > +		}
> >
> > -	regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
> > -			   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
> > -			   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
> > +		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) {
> > +		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;
> > +		regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
> > +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN,
> > +				   IMX6Q_GPR13_SATA_MPLL_CLK_EN);
> >  	}
> >
> >  	return 0;
> > @@ -75,10 +100,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) @@ -122,7
> > +152,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;
> > @@ -158,7 +188,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);
> >  }
> > @@ -193,16 +223,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); @@ -212,12 +244,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"); @@ -233,6 +273,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"); @@ -240,24 +282,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) {
> > @@ -273,40 +323,41 @@ static int imx_ahci_probe(struct platform_device *pdev)
> >  	ahci_dev->dma_mask = &ahci_dev->coherent_dma_mask;
> >  	ahci_dev->of_node = dev->of_node;
> >
> > -	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");
> > -		ret = PTR_ERR(imxpriv->gpr);
> > -		goto err_out;
> > +	if (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);
> > +		}
> > +
> > +		/*
> > +		 * 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 happens in imx_sata_clock_enable().
> > +		 */
> > +		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);
> >  	}
> >
> > -	/*
> > -	 * 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 happens in imx_sata_clock_enable().
> > -	 */
> > -	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);
> > -
> >  	ret = platform_device_add_resources(ahci_pdev, res, 2);
> >  	if (ret)
> >  		goto err_out;
> > --
> > 1.8.4.2
> >

Best Regards
Richard Zhu





More information about the linux-arm-kernel mailing list