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

Shawn Guo shawn.guo at linaro.org
Tue Nov 19 03:48:16 EST 2013


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

> +	/* 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
> 




More information about the linux-arm-kernel mailing list