[PATCH v5 3/3] PCI: imx6: Add support for i.MX6 PCIe controller
Sascha Hauer
s.hauer at pengutronix.de
Mon Sep 16 03:40:45 EDT 2013
On Mon, Sep 16, 2013 at 05:48:17AM +0000, Sean Cross wrote:
> Add support for the PCIe port present on the i.MX6 family of controllers.
> These use the Synopsis Designware core tied to their own PHY.
>
> diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
> index 971356b..d30ff63 100644
> --- a/arch/arm/mach-imx/clk-imx6q.c
> +++ b/arch/arm/mach-imx/clk-imx6q.c
> @@ -623,6 +623,18 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
> if (ret)
> pr_warn("failed to set up CLKO: %d\n", ret);
>
> + /*
> + * All existing boards with PCIe use LVDS1
> + */
> + if (IS_ENABLED(CONFIG_PCI_IMX6)) {
> + clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
This is fine,
> + clk_prepare_enable(clk[lvds1_gate]);
> + clk_prepare_enable(clk[pcie_ref_125m]);
> + clk_prepare_enable(clk[sata_ref_100m]);
> + clk_prepare_enable(clk[pcie_axi]);
but the clocks should be really enabled in the driver that needs them.
> +static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val)
> +{
> + u32 val;
> + u32 max_iterations = 10;
> + u32 wait_counter = 0;
> +
> + do {
> + val = readl(dbi_base + PCIE_PHY_STAT);
> + val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
> + wait_counter++;
if (val == exp_val)
return 0;
> + udelay(1);
Avoids the udelay when the value is correct during the first iteration.
> + } while ((wait_counter < max_iterations) && (val != exp_val));
> +
> + if (val != exp_val)
> + return -ETIMEDOUT;
> +
> + return 0;
> +}
> +
...
> +/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
> +static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data)
> +{
> + u32 val, phy_ctl;
> + int ret;
> +
> + ret = pcie_phy_wait_ack(dbi_base, addr);
> + if (ret)
> + return ret;
> +
> + /* assert Read signal */
> + phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
> + writel(phy_ctl, dbi_base + PCIE_PHY_CTRL);
> +
> + ret = pcie_phy_poll_ack(dbi_base, 1);
> + if (ret)
> + return ret;
> +
> + val = readl(dbi_base + PCIE_PHY_STAT);
> + *data = (val & (0xffff << PCIE_PHY_STAT_DATA_LOC));
This works because PCIE_PHY_STAT_DATA_LOC is 0. Otherwise you would have
to do:
*data = (val >> PCIE_PHY_STAT_DATA_LOC) & 0xfff;
I suggest to simply drop the bogus zero bit shift.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the linux-arm-kernel
mailing list