diff options
author | Andrey Smirnov <andrew.smirnov@gmail.com> | 2018-12-16 21:19:07 -0800 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-01-08 16:28:48 +0100 |
commit | e93ea04d5f0776a445071dccf4135e10878ea4c3 (patch) | |
tree | ac165dadd00c58bb20e2dd2559984efce3331360 | |
parent | c6e81bac2b4c75c9c4ba769d4a9e26e7e1b18440 (diff) | |
download | barebox-e93ea04d5f0776a445071dccf4135e10878ea4c3.tar.gz barebox-e93ea04d5f0776a445071dccf4135e10878ea4c3.tar.xz |
PCI: imx6: Remove LTSSM disable workaround
Port of a Linux commit a71280722eeba8f1afa51ad6656028dcb96e110b
This causes CPU hangs when the system is reset by the watchdog, as the GPRs
aren't cleared, but the clocks are back to disabled state.
If the bootloader uses PCIe, it must take care to bring it down into a safe
state, before passing control to the Linux kernel. This is the only way to
get a properly operating system at all times and circumstances.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
LTSSM disable workaround still needs to be performed before passing
control to Linux. However, in order to avoid the hang described above,
we move it to imx6_pcie_remove() and apply it without relying on
values in GPR.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r-- | drivers/pci/pci-imx6.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index a9a4be927b..023e6f07fd 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -239,8 +239,7 @@ static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie) static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - u32 val, gpr1, gpr12; + u32 gpr1; switch (imx6_pcie->variant) { case IMX6QP: @@ -249,34 +248,7 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) 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 = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); - val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; - val |= PCIE_PL_PFLR_FORCE_LINK; - - data_abort_mask(); - dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val); - data_abort_unmask(); - - 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); @@ -642,6 +614,33 @@ static void imx6_pcie_remove(struct device_d *dev) { struct imx6_pcie *imx6_pcie = dev->priv; + if (imx6_pcie->variant == 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. + */ + struct pcie_port *pp = &imx6_pcie->pp; + u32 gpr12, val; + + val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); + val &= ~PCIE_PL_PFLR_LINK_STATE_MASK; + val |= PCIE_PL_PFLR_FORCE_LINK; + + data_abort_mask(); + dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val); + data_abort_unmask(); + + gpr12 = readl(imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + gpr12 &= ~IMX6Q_GPR12_PCIE_CTL_2; + writel(gpr12, imx6_pcie->iomuxc_gpr + IOMUXC_GPR12); + } + imx6_pcie_assert_core_reset(imx6_pcie); } |