diff mbox

PCI: imx6: remove LTSSM disable workaround

Message ID 20170120155837.2874-1-l.stach@pengutronix.de
State Accepted
Headers show

Commit Message

Lucas Stach Jan. 20, 2017, 3:58 p.m. UTC
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>
---
 drivers/pci/host/pci-imx6.c | 30 ------------------------------
 1 file changed, 30 deletions(-)

Comments

Bjorn Helgaas Jan. 30, 2017, 11:02 p.m. UTC | #1
On Fri, Jan 20, 2017 at 04:58:37PM +0100, Lucas Stach wrote:
> 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>

Applied to pci/host-imx6 for v4.11, thanks!

I don't really like the idea that we depend on a particular state from the
bootloader, but if there's no way around it, maybe this is the best we can
do.

> ---
>  drivers/pci/host/pci-imx6.c | 30 ------------------------------
>  1 file changed, 30 deletions(-)
> 
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index c8cefb078218..42c1987ffb3d 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -247,9 +247,6 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
>  
>  static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
>  {
> -	struct pcie_port *pp = &imx6_pcie->pp;
> -	u32 val, gpr1, gpr12;
> -
>  	switch (imx6_pcie->variant) {
>  	case IMX6SX:
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> @@ -266,33 +263,6 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
>  				   IMX6Q_GPR1_PCIE_SW_RST);
>  		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.
> -		 */
> -		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
> -		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &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;
> -			dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val);
> -
> -			regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
> -					   IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
> -		}
> -
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
>  				   IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
>  		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
> -- 
> 2.11.0
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Tim Harvey May 9, 2017, 4:24 p.m. UTC | #2
On Fri, Jan 20, 2017 at 7:58 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> 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.
>

Lucas,

I missed this patch when it came through.

Can you give some details about what you consider a 'safe state' for
the bootloader to bring PCI to before passing control to the kernel
(with respect to PERST#, PCI CLK, and the various host controller
registers)? I would like to investigate making PCI available in the
bootloader as well as the kernel reliable on IMX6.

Regards,

Tim
Lucas Stach May 9, 2017, 4:32 p.m. UTC | #3
Am Dienstag, den 09.05.2017, 09:24 -0700 schrieb Tim Harvey:
> On Fri, Jan 20, 2017 at 7:58 AM, Lucas Stach <l.stach@pengutronix.de> wrote:
> > 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.
> >
> 
> Lucas,
> 
> I missed this patch when it came through.
> 
> Can you give some details about what you consider a 'safe state' for
> the bootloader to bring PCI to before passing control to the kernel
> (with respect to PERST#, PCI CLK, and the various host controller
> registers)? I would like to investigate making PCI available in the
> bootloader as well as the kernel reliable on IMX6.

The bootloader needs to reset the LTSSM state, disable LTSSM and disable
the PCIe core and PHY clocks before jumping to the kernel image. This is
already done in Barebox [1] (where it works well with PCIe used both in
the BL and kernel) and I gave advance warning to multiple people using
U-Boot that they need to implement a similar shutdown hook there. Sadly
it seems that nothing has emerged yet.

Regards,
Lucas

[1]
https://git.pengutronix.de/cgit/barebox/commit/?id=f1da98da2760c21487bbba8f7fb957c843a22896
diff mbox

Patch

diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index c8cefb078218..42c1987ffb3d 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -247,9 +247,6 @@  static int imx6q_pcie_abort_handler(unsigned long addr,
 
 static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
 {
-	struct pcie_port *pp = &imx6_pcie->pp;
-	u32 val, gpr1, gpr12;
-
 	switch (imx6_pcie->variant) {
 	case IMX6SX:
 		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
@@ -266,33 +263,6 @@  static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
 				   IMX6Q_GPR1_PCIE_SW_RST);
 		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.
-		 */
-		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
-		regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &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;
-			dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val);
-
-			regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-					   IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
-		}
-
 		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
 				   IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
 		regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,