Skip to content

Commit 7b86e0a

Browse files
committed
Merge branch 'pci/controller/imx6'
- Fix suspend/resume support on i.MX6QDL, which has a hardware erratum that prevents use of L2 (Stefan Eichenberger) * pci/controller/imx6: PCI: imx6: Fix suspend/resume support on i.MX6QDL
2 parents 2b4049d + 0a726f5 commit 7b86e0a

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

drivers/pci/controller/dwc/pci-imx6.c

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ enum imx_pcie_variants {
8282
#define IMX_PCIE_FLAG_HAS_SERDES BIT(6)
8383
#define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7)
8484
#define IMX_PCIE_FLAG_CPU_ADDR_FIXUP BIT(8)
85+
/*
86+
* Because of ERR005723 (PCIe does not support L2 power down) we need to
87+
* workaround suspend resume on some devices which are affected by this errata.
88+
*/
89+
#define IMX_PCIE_FLAG_BROKEN_SUSPEND BIT(9)
8590

8691
#define imx_check_flag(pci, val) (pci->drvdata->flags & val)
8792

@@ -1237,9 +1242,19 @@ static int imx_pcie_suspend_noirq(struct device *dev)
12371242
return 0;
12381243

12391244
imx_pcie_msi_save_restore(imx_pcie, true);
1240-
imx_pcie_pm_turnoff(imx_pcie);
1241-
imx_pcie_stop_link(imx_pcie->pci);
1242-
imx_pcie_host_exit(pp);
1245+
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
1246+
/*
1247+
* The minimum for a workaround would be to set PERST# and to
1248+
* set the PCIE_TEST_PD flag. However, we can also disable the
1249+
* clock which saves some power.
1250+
*/
1251+
imx_pcie_assert_core_reset(imx_pcie);
1252+
imx_pcie->drvdata->enable_ref_clk(imx_pcie, false);
1253+
} else {
1254+
imx_pcie_pm_turnoff(imx_pcie);
1255+
imx_pcie_stop_link(imx_pcie->pci);
1256+
imx_pcie_host_exit(pp);
1257+
}
12431258

12441259
return 0;
12451260
}
@@ -1253,14 +1268,32 @@ static int imx_pcie_resume_noirq(struct device *dev)
12531268
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
12541269
return 0;
12551270

1256-
ret = imx_pcie_host_init(pp);
1257-
if (ret)
1258-
return ret;
1259-
imx_pcie_msi_save_restore(imx_pcie, false);
1260-
dw_pcie_setup_rc(pp);
1271+
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_BROKEN_SUSPEND)) {
1272+
ret = imx_pcie->drvdata->enable_ref_clk(imx_pcie, true);
1273+
if (ret)
1274+
return ret;
1275+
ret = imx_pcie_deassert_core_reset(imx_pcie);
1276+
if (ret)
1277+
return ret;
1278+
/*
1279+
* Using PCIE_TEST_PD seems to disable MSI and powers down the
1280+
* root complex. This is why we have to setup the rc again and
1281+
* why we have to restore the MSI register.
1282+
*/
1283+
ret = dw_pcie_setup_rc(&imx_pcie->pci->pp);
1284+
if (ret)
1285+
return ret;
1286+
imx_pcie_msi_save_restore(imx_pcie, false);
1287+
} else {
1288+
ret = imx_pcie_host_init(pp);
1289+
if (ret)
1290+
return ret;
1291+
imx_pcie_msi_save_restore(imx_pcie, false);
1292+
dw_pcie_setup_rc(pp);
12611293

1262-
if (imx_pcie->link_is_up)
1263-
imx_pcie_start_link(imx_pcie->pci);
1294+
if (imx_pcie->link_is_up)
1295+
imx_pcie_start_link(imx_pcie->pci);
1296+
}
12641297

12651298
return 0;
12661299
}
@@ -1485,7 +1518,9 @@ static const struct imx_pcie_drvdata drvdata[] = {
14851518
[IMX6Q] = {
14861519
.variant = IMX6Q,
14871520
.flags = IMX_PCIE_FLAG_IMX_PHY |
1488-
IMX_PCIE_FLAG_IMX_SPEED_CHANGE,
1521+
IMX_PCIE_FLAG_IMX_SPEED_CHANGE |
1522+
IMX_PCIE_FLAG_BROKEN_SUSPEND |
1523+
IMX_PCIE_FLAG_SUPPORTS_SUSPEND,
14891524
.dbi_length = 0x200,
14901525
.gpr = "fsl,imx6q-iomuxc-gpr",
14911526
.clk_names = imx6q_clks,

0 commit comments

Comments
 (0)