Unverified Commit 3244b551 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!14977 PCI: imx6: Fix suspend/resume support on i.MX6QDL

parents a25007b6 8f6c0e0a
Loading
Loading
Loading
Loading
+48 −11
Original line number Diff line number Diff line
@@ -60,6 +60,13 @@ enum imx6_pcie_variants {
#define IMX6_PCIE_FLAG_IMX6_PHY			BIT(0)
#define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE	BIT(1)
#define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND		BIT(2)
/*
 * Because of ERR005723 (PCIe does not support L2 power down) we need to
 * workaround suspend resume on some devices which are affected by this errata.
 */
#define IMX6_PCIE_FLAG_BROKEN_SUSPEND		BIT(9)

#define imx6_check_flag(pci, val)	(pci->drvdata->flags & val)

struct imx6_pcie_drvdata {
	enum imx6_pcie_variants variant;
@@ -1210,9 +1217,19 @@ static int imx6_pcie_suspend_noirq(struct device *dev)
		return 0;

	imx6_pcie_msi_save_restore(imx6_pcie, true);
	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_BROKEN_SUSPEND)) {
		/*
		 * The minimum for a workaround would be to set PERST# and to
		 * set the PCIE_TEST_PD flag. However, we can also disable the
		 * clock which saves some power.
		 */
		imx6_pcie_assert_core_reset(imx6_pcie);
		imx6_pcie_enable_ref_clk(imx6_pcie);
	} else {
		imx6_pcie_pm_turnoff(imx6_pcie);
		imx6_pcie_stop_link(imx6_pcie->pci);
		imx6_pcie_host_exit(pp);
	}

	return 0;
}
@@ -1226,6 +1243,23 @@ static int imx6_pcie_resume_noirq(struct device *dev)
	if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))
		return 0;

	if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_BROKEN_SUSPEND)) {
		ret = imx6_pcie_enable_ref_clk(imx6_pcie);
		if (ret)
			return ret;
		ret = imx6_pcie_deassert_core_reset(imx6_pcie);
		if (ret)
			return ret;
		/*
		 * Using PCIE_TEST_PD seems to disable MSI and powers down the
		 * root complex. This is why we have to setup the rc again and
		 * why we have to restore the MSI register.
		 */
		ret = dw_pcie_setup_rc(&imx6_pcie->pci->pp);
		if (ret)
			return ret;
		imx6_pcie_msi_save_restore(imx6_pcie, false);
	} else {
		ret = imx6_pcie_host_init(pp);
		if (ret)
			return ret;
@@ -1234,6 +1268,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)

		if (imx6_pcie->link_is_up)
			imx6_pcie_start_link(imx6_pcie->pci);
	}

	return 0;
}
@@ -1475,7 +1510,9 @@ static const struct imx6_pcie_drvdata drvdata[] = {
	[IMX6Q] = {
		.variant = IMX6Q,
		.flags = IMX6_PCIE_FLAG_IMX6_PHY |
			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
			 IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |
			 IMX6_PCIE_FLAG_BROKEN_SUSPEND |
			 IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
		.dbi_length = 0x200,
		.gpr = "fsl,imx6q-iomuxc-gpr",
	},