From 9aa9049cfd999c4a885f214c4d6dfb5eb4bc7bf7 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:36:59 -0700 Subject: PCI: imx6: Simplify imx6_pcie_remove() Instead of manualy flipping the bits call imx6_pcie_assert_core_reset() to give the code, executing after BB, a clean slate. This also makes the function match similar code in Linux kernel driver. Signed-off-by: Andrey Smirnov Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 46483b4cc8..241df3ff8d 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -618,25 +618,8 @@ static int __init imx6_pcie_probe(struct device_d *dev) static void imx6_pcie_remove(struct device_d *dev) { struct imx6_pcie *imx6_pcie = dev->priv; - u32 val; - - val = readl(imx6_pcie->pp.dbi_base + PCIE_PL_PFLR); - val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; - val |= PCIE_PL_PFLR_FORCE_LINK; - data_abort_mask(); - writel(val, imx6_pcie->pp.dbi_base + PCIE_PL_PFLR); - data_abort_unmask(); - - val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); - val &= ~IMX6Q_GPR12_PCIE_CTL_2; - writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); - - val = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); - val |= IMX6Q_GPR1_PCIE_TEST_PD; - writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); - val &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN; - writel(val, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + imx6_pcie_assert_core_reset(&imx6_pcie->pp); } static struct of_device_id imx6_pcie_of_match[] = { -- cgit v1.2.3 From bd55401e972d630338d3326373f8aef9d204faaf Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:00 -0700 Subject: OF: Port of_match_device() and of_device_get_match_data() Port of_match_device() and of_device_get_match_data() from Linux kernel code. Signed-off-by: Andrey Smirnov Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/of/Makefile | 2 +- drivers/of/device.c | 33 +++++++++++++++++++++++++++++++++ include/of_device.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 drivers/of/device.c create mode 100644 include/of_device.h diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 0dc2f8d63e..f31bb293fb 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,4 +1,4 @@ -obj-y += address.o base.o fdt.o platform.o +obj-y += address.o base.o fdt.o platform.o device.o obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o obj-$(CONFIG_OF_GPIO) += of_gpio.o obj-$(CONFIG_OF_PCI) += of_pci.o diff --git a/drivers/of/device.c b/drivers/of/device.c new file mode 100644 index 0000000000..e2c3c02d27 --- /dev/null +++ b/drivers/of/device.c @@ -0,0 +1,33 @@ +#include +#include + + +/** + * of_match_device - Tell if a struct device matches an of_device_id list + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an platform_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct device_d *dev) +{ + if ((!matches) || (!dev->device_node)) + return NULL; + + return of_match_node(matches, dev->device_node); +} +EXPORT_SYMBOL(of_match_device); + +const void *of_device_get_match_data(const struct device_d *dev) +{ + const struct of_device_id *match; + + match = of_match_device(dev->driver->of_compatible, dev); + if (!match) + return NULL; + + return match->data; +} +EXPORT_SYMBOL(of_device_get_match_data); diff --git a/include/of_device.h b/include/of_device.h new file mode 100644 index 0000000000..e84fc9c377 --- /dev/null +++ b/include/of_device.h @@ -0,0 +1,48 @@ +#ifndef __OF_DEVICE_H +#define __OF_DEVICE_H + +#include +#include + + +#ifdef CONFIG_OFTREE +extern const struct of_device_id *of_match_device( + const struct of_device_id *matches, const struct device_d *dev); + +/** + * of_driver_match_device - Tell if a driver's of_match_table matches a device. + * @drv: the device_driver structure to test + * @dev: the device structure to match against + */ +static inline int of_driver_match_device(struct device_d *dev, + const struct driver_d *drv) +{ + return of_match_device(drv->of_compatible, dev) != NULL; +} + +extern const void *of_device_get_match_data(const struct device_d *dev); + +#else /* CONFIG_OF */ + +static inline int of_driver_match_device(struct device_d *dev, + const struct device_d *drv) +{ + return 0; +} + +static inline const void *of_device_get_match_data(const struct device_d *dev) +{ + return NULL; +} + +static inline const struct of_device_id *__of_match_device( + const struct of_device_id *matches, const struct device_d *dev) +{ + return NULL; +} +#define of_match_device(matches, dev) \ + __of_match_device(of_match_ptr(matches), (dev)) + +#endif /* CONFIG_OF */ + +#endif /* _LINUX_OF_DEVICE_H */ -- cgit v1.2.3 From 015ec0a52858e4b1b3c1ecdef4a02cf258fa26d7 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:01 -0700 Subject: PCI: imx6: Add proper i.MX6+ reset sequence I.MX6+ version of the silicon exposed PCIe core's reset signal as a bit in one of the control registers. As a result using old, pre-i.MX6+, reset sequence on i.MX6+ leads to Barebox hanging during startup. Using exposed reset bit instead solves the problem. This commit is based on portions of commit c34068d48273e24d392d9a49a38be807954420ed in http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git Signed-off-by: Andrey Smirnov Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 94 +++++++++++++++++++++++++++++------------- include/mfd/imx6q-iomuxc-gpr.h | 1 + 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 241df3ff8d..13a8b2262e 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,11 @@ #define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) +enum imx6_pcie_variants { + IMX6Q, + IMX6QP, +}; + struct imx6_pcie { int reset_gpio; struct clk *pcie_bus; @@ -43,6 +49,7 @@ struct imx6_pcie { struct clk *pcie; struct pcie_port pp; void __iomem *iomuxc_gpr; + enum imx6_pcie_variants variant; void __iomem *mem_base; }; @@ -219,39 +226,48 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); u32 val, gpr1, gpr12; - /* - * If the bootloader already enabled the link we need some special - * handling to get the core back into a state where it is safe to - * touch it for configuration. As there is no dedicated reset signal - * wired up for MX6QDL, we need to manually force LTSSM into "detect" - * state before completely disabling LTSSM, which is a prerequisite - * for core configuration. - * - * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong - * indication that the bootloader activated the link. - */ - gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); - gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + switch (imx6_pcie->variant) { + case IMX6QP: + gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + gpr1 |= IMX6Q_GPR1_PCIE_SW_RST; + writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + break; + case IMX6Q: + /* + * If the bootloader already enabled the link we need some special + * handling to get the core back into a state where it is safe to + * touch it for configuration. As there is no dedicated reset signal + * wired up for MX6QDL, we need to manually force LTSSM into "detect" + * state before completely disabling LTSSM, which is a prerequisite + * for core configuration. + * + * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we have a strong + * indication that the bootloader activated the link. + */ + gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); - if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) && - (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) { - val = readl(pp->dbi_base + PCIE_PL_PFLR); - val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; - val |= PCIE_PL_PFLR_FORCE_LINK; + if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) && + (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) { + val = readl(pp->dbi_base + PCIE_PL_PFLR); + val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; + val |= PCIE_PL_PFLR_FORCE_LINK; - data_abort_mask(); - writel(val, pp->dbi_base + PCIE_PL_PFLR); - data_abort_unmask(); + data_abort_mask(); + writel(val, pp->dbi_base + PCIE_PL_PFLR); + data_abort_unmask(); - gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2; - writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); - } + gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2; + writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + } - gpr1 |= IMX6Q_GPR1_PCIE_TEST_PD; - writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + gpr1 |= IMX6Q_GPR1_PCIE_TEST_PD; + writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); - gpr1 &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN; - writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + gpr1 &= ~IMX6Q_GPR1_PCIE_REF_CLK_EN; + writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + break; + } return 0; } @@ -298,6 +314,22 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) mdelay(100); gpio_set_value(imx6_pcie->reset_gpio, 1); } + + /* + * Release the PCIe PHY reset here + */ + switch (imx6_pcie->variant) { + case IMX6QP: + gpr1 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + gpr1 &= ~IMX6Q_GPR1_PCIE_SW_RST; + writel(gpr1, imx6_pcie->iomuxc_gpr + IOMUXC_GPR1); + + udelay(200); + break; + case IMX6Q: /* Nothing to do */ + break; + } + return 0; err_pcie: @@ -568,6 +600,9 @@ static int __init imx6_pcie_probe(struct device_d *dev) pp = &imx6_pcie->pp; pp->dev = dev; + imx6_pcie->variant = + (enum imx6_pcie_variants)of_device_get_match_data(dev); + iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); @@ -623,7 +658,8 @@ static void imx6_pcie_remove(struct device_d *dev) } static struct of_device_id imx6_pcie_of_match[] = { - { .compatible = "fsl,imx6q-pcie", }, + { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, }, + { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, }, {}, }; diff --git a/include/mfd/imx6q-iomuxc-gpr.h b/include/mfd/imx6q-iomuxc-gpr.h index a7ef1c8915..b2c9da6579 100644 --- a/include/mfd/imx6q-iomuxc-gpr.h +++ b/include/mfd/imx6q-iomuxc-gpr.h @@ -95,6 +95,7 @@ #define IMX6Q_GPR0_DMAREQ_MUX_SEL0_IOMUX BIT(0) #define IMX6Q_GPR1_PCIE_REQ_MASK (0x3 << 30) +#define IMX6Q_GPR1_PCIE_SW_RST BIT(29) #define IMX6Q_GPR1_PCIE_EXIT_L1 BIT(28) #define IMX6Q_GPR1_PCIE_RDY_L23 BIT(27) #define IMX6Q_GPR1_PCIE_ENTER_L1 BIT(26) -- cgit v1.2.3 From ea13b82ae3c60562ad1d56dc637e42fe51539c7c Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:02 -0700 Subject: PCI: imx6: Rename imx6_pcie_start_link() to imx6_pcie_establish_link() Rename imx6_pcie_start_link() to imx6_pcie_establish_link() to follow the convention of other DesignWare-based host drivers. No functional change. [Andrey Smirnov: port to BB codebase] Signed-off-by: Andrey Smirnov Signed-off-by: Bjorn Helgaas Acked-by: Pratyush Anand Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 13a8b2262e..30bc4fe0ed 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -415,7 +415,7 @@ static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp) } -static int imx6_pcie_start_link(struct pcie_port *pp) +static int imx6_pcie_establish_link(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); uint32_t tmp; @@ -483,7 +483,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_setup_rc(pp); - imx6_pcie_start_link(pp); + imx6_pcie_establish_link(pp); } static void imx6_pcie_reset_phy(struct pcie_port *pp) -- cgit v1.2.3 From 7ed3258eabc3aec4eea0747e66d3a5abe3e2cb56 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 25 Apr 2016 22:37:03 -0700 Subject: PCI: imx6: Simplify a trivial if-return sequence Simplify a trivial if-return sequence by combining it with a preceding function call. The semantic patch that makes this change is available in scripts/coccinelle/misc/simple_return.cocci. Signed-off-by: Fabio Estevam Signed-off-by: Bjorn Helgaas Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 30bc4fe0ed..2ccf80a74d 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -129,11 +129,7 @@ static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr) val = addr << PCIE_PHY_CTRL_DATA_LOC; writel(val, dbi_base + PCIE_PHY_CTRL); - ret = pcie_phy_poll_ack(dbi_base, 0); - if (ret) - return ret; - - return 0; + return pcie_phy_poll_ack(dbi_base, 0); } /* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ @@ -160,11 +156,7 @@ static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data) /* deassert Read signal */ writel(0x00, dbi_base + PCIE_PHY_CTRL); - ret = pcie_phy_poll_ack(dbi_base, 0); - if (ret) - return ret; - - return 0; + return pcie_phy_poll_ack(dbi_base, 0); } static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) -- cgit v1.2.3 From 69919d895a379949dce58292a749f6a10e22a3de Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:04 -0700 Subject: PCI: imx6: Move imx6_pcie_reset_phy() near other PHY handling functions Move imx6_pcie_reset_phy() near the other PHY related functions in the file. This is a cosmetic change, but also allows to do the following changes without introducing needless forward declarations. [Andrey Smirnov: port to Barebox codebase] Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 2ccf80a74d..fd53d360ea 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -213,6 +213,23 @@ static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) return 0; } +static void imx6_pcie_reset_phy(struct pcie_port *pp) +{ + uint32_t temp; + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); + temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); + + udelay(2000); + + pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); + temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | + PHY_RX_OVRD_IN_LO_RX_PLL_EN); + pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); +} + static int imx6_pcie_assert_core_reset(struct pcie_port *pp) { struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); @@ -478,23 +495,6 @@ static void imx6_pcie_host_init(struct pcie_port *pp) imx6_pcie_establish_link(pp); } -static void imx6_pcie_reset_phy(struct pcie_port *pp) -{ - uint32_t temp; - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); - temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); - - udelay(2000); - - pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); - temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | - PHY_RX_OVRD_IN_LO_RX_PLL_EN); - pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); -} - static int imx6_pcie_link_up(struct pcie_port *pp) { u32 rc, debug_r0, rx_valid; -- cgit v1.2.3 From 003f55844df33e99da4a3eac607618d62318bb57 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:05 -0700 Subject: PCI: imx6: Move PHY reset into imx6_pcie_establish_link() This adds the PHY reset into a common error path of imx6_pcie_establish_link(), deduplicating some of the debug prints. Also reduce the severity of the "no-link" message in the one place where it is expected to be hit when no peripheral is attached. [Andrey Smirnov: port to Barebox codebase] Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index fd53d360ea..a29e117ee3 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -399,10 +399,6 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp) if (!is_timeout(start, SECOND)) continue; - dev_err(pp->dev, "phy link never came up\n"); - dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", - readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), - readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); return -EINVAL; } } @@ -447,8 +443,10 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); ret = imx6_pcie_wait_for_link(pp); - if (ret) - return ret; + if (ret) { + dev_info(pp->dev, "Link never came up\n"); + goto err_reset_phy; + } /* Allow Gen2 mode after the link is up. */ tmp = readl(pp->dbi_base + PCIE_RC_LCR); @@ -467,19 +465,28 @@ static int imx6_pcie_establish_link(struct pcie_port *pp) ret = imx6_pcie_wait_for_speed_change(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } /* Make sure link training is finished as well! */ ret = imx6_pcie_wait_for_link(pp); if (ret) { dev_err(pp->dev, "Failed to bring link up!\n"); - return ret; + goto err_reset_phy; } tmp = readl(pp->dbi_base + PCIE_RC_LCSR); dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); + return 0; + +err_reset_phy: + dev_dbg(pp->dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", + readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), + readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); + imx6_pcie_reset_phy(pp); + + return ret; } static void imx6_pcie_host_init(struct pcie_port *pp) @@ -547,11 +554,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) if ((debug_r0 & 0x3f) != 0x0d) return 0; - dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); - dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc); - - imx6_pcie_reset_phy(pp); - return 0; } -- cgit v1.2.3 From a9fe885685d83d7866ceca913b361000c79c64bc Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:06 -0700 Subject: PCI: imx6: Remove broken Gen2 workaround Remove the remnants of the workaround for erratum ERR005184 which was never completely implemented. The checks alone don't carry any value as we don't act properly on the result. A workaround should be added to the lane speed change in establish_link later. [Andrey Smirnov: port to Barebox codebase] Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index a29e117ee3..833e5b768b 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -504,7 +504,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct pcie_port *pp) { - u32 rc, debug_r0, rx_valid; + u32 rc; int count = 5; /* @@ -538,21 +538,6 @@ static int imx6_pcie_link_up(struct pcie_port *pp) */ udelay(1000); } - /* - * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. - * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). - * If (MAC/LTSSM.state == Recovery.RcvrLock) - * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition - * to gen2 is stuck - */ - pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); - debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); - - if (rx_valid & 0x01) - return 0; - - if ((debug_r0 & 0x3f) != 0x0d) - return 0; return 0; } -- cgit v1.2.3 From d34b5ffc7f3972e91c9411e48b45b17b846fd555 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 25 Apr 2016 22:37:07 -0700 Subject: PCI: imx6: Add DT bindings to configure PHY Tx driver settings The settings in GPR8 are dependent upon the particular layout of the hardware platform. As such, they should be configurable via the device tree. Look up PHY Tx driver settings from the device tree. Fall back to the original hard-coded values if they are not specified in the device tree. [Andrey Smirnov: port to Barebox codebase] Signed-off-by: Justin Waters Signed-off-by: Bjorn Helgaas Signed-off-by: Andrey Smirnov Acked-by: Lucas Stach Signed-off-by: Sascha Hauer --- drivers/pci/pci-imx6.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 833e5b768b..affc705d0a 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -51,6 +51,11 @@ struct imx6_pcie { void __iomem *iomuxc_gpr; enum imx6_pcie_variants variant; void __iomem *mem_base; + u32 tx_deemph_gen1; + u32 tx_deemph_gen2_3p5db; + u32 tx_deemph_gen2_6db; + u32 tx_swing_full; + u32 tx_swing_low; }; /* PCIe Root Complex registers (memory-mapped) */ @@ -370,21 +375,23 @@ static void imx6_pcie_init_phy(struct pcie_port *pp) gpr8 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN1; + gpr8 |= imx6_pcie->tx_deemph_gen1 << 0; writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB; + gpr8 |= imx6_pcie->tx_deemph_gen2_3p5db << 6; writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); gpr8 &= ~IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB; - gpr8 |= 20 << 12; + gpr8 |= imx6_pcie->tx_deemph_gen2_6db << 12; writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); gpr8 &= ~IMX6Q_GPR8_TX_SWING_FULL; - gpr8 |= 127 << 18; + gpr8 |= imx6_pcie->tx_swing_full << 18; writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); gpr8 &= ~IMX6Q_GPR8_TX_SWING_LOW; - gpr8 |= 127 << 25; + gpr8 |= imx6_pcie->tx_swing_low << 25; writel(gpr8, imx6_pcie->iomuxc_gpr + IOMUXC_GPR8); } @@ -620,6 +627,27 @@ static int __init imx6_pcie_probe(struct device_d *dev) /* Grab GPR config register range */ imx6_pcie->iomuxc_gpr = IOMEM(MX6_IOMUXC_BASE_ADDR); + /* Grab PCIe PHY Tx Settings */ + if (of_property_read_u32(np, "fsl,tx-deemph-gen1", + &imx6_pcie->tx_deemph_gen1)) + imx6_pcie->tx_deemph_gen1 = 0; + + if (of_property_read_u32(np, "fsl,tx-deemph-gen2-3p5db", + &imx6_pcie->tx_deemph_gen2_3p5db)) + imx6_pcie->tx_deemph_gen2_3p5db = 0; + + if (of_property_read_u32(np, "fsl,tx-deemph-gen2-6db", + &imx6_pcie->tx_deemph_gen2_6db)) + imx6_pcie->tx_deemph_gen2_6db = 20; + + if (of_property_read_u32(np, "fsl,tx-swing-full", + &imx6_pcie->tx_swing_full)) + imx6_pcie->tx_swing_full = 127; + + if (of_property_read_u32(np, "fsl,tx-swing-low", + &imx6_pcie->tx_swing_low)) + imx6_pcie->tx_swing_low = 127; + ret = imx6_add_pcie_port(pp, dev); if (ret < 0) return ret; -- cgit v1.2.3