@@ -82,6 +82,11 @@ enum imx_pcie_variants {
82
82
#define IMX_PCIE_FLAG_HAS_SERDES BIT(6)
83
83
#define IMX_PCIE_FLAG_SUPPORT_64BIT BIT(7)
84
84
#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)
85
90
86
91
#define imx_check_flag (pci , val ) (pci->drvdata->flags & val)
87
92
@@ -1237,9 +1242,19 @@ static int imx_pcie_suspend_noirq(struct device *dev)
1237
1242
return 0 ;
1238
1243
1239
1244
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
+ }
1243
1258
1244
1259
return 0 ;
1245
1260
}
@@ -1253,14 +1268,32 @@ static int imx_pcie_resume_noirq(struct device *dev)
1253
1268
if (!(imx_pcie -> drvdata -> flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND ))
1254
1269
return 0 ;
1255
1270
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 );
1261
1293
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
+ }
1264
1297
1265
1298
return 0 ;
1266
1299
}
@@ -1485,7 +1518,9 @@ static const struct imx_pcie_drvdata drvdata[] = {
1485
1518
[IMX6Q ] = {
1486
1519
.variant = IMX6Q ,
1487
1520
.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 ,
1489
1524
.dbi_length = 0x200 ,
1490
1525
.gpr = "fsl,imx6q-iomuxc-gpr" ,
1491
1526
.clk_names = imx6q_clks ,
0 commit comments