Skip to content

Commit 99f7b80

Browse files
committed
Merge branch 'pci/controller/dwc'
- Wait for link to come up only if we've initiated link training (Ajay Agarwal) - Save and restore imx6 Root Port MSI control to work around hardware defect (Richard Zhu) * pci/controller/dwc: PCI: imx6: Save and restore root port MSI control in suspend and resume PCI: dwc: Wait for link up only if link is started
2 parents 375328f + 3bbc3c7 commit 99f7b80

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct imx6_pcie {
8080
struct clk *pcie;
8181
struct clk *pcie_aux;
8282
struct regmap *iomuxc_gpr;
83+
u16 msi_ctrl;
8384
u32 controller_id;
8485
struct reset_control *pciephy_reset;
8586
struct reset_control *apps_reset;
@@ -1178,6 +1179,26 @@ static void imx6_pcie_pm_turnoff(struct imx6_pcie *imx6_pcie)
11781179
usleep_range(1000, 10000);
11791180
}
11801181

1182+
static void imx6_pcie_msi_save_restore(struct imx6_pcie *imx6_pcie, bool save)
1183+
{
1184+
u8 offset;
1185+
u16 val;
1186+
struct dw_pcie *pci = imx6_pcie->pci;
1187+
1188+
if (pci_msi_enabled()) {
1189+
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI);
1190+
if (save) {
1191+
val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS);
1192+
imx6_pcie->msi_ctrl = val;
1193+
} else {
1194+
dw_pcie_dbi_ro_wr_en(pci);
1195+
val = imx6_pcie->msi_ctrl;
1196+
dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
1197+
dw_pcie_dbi_ro_wr_dis(pci);
1198+
}
1199+
}
1200+
}
1201+
11811202
static int imx6_pcie_suspend_noirq(struct device *dev)
11821203
{
11831204
struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
@@ -1186,6 +1207,7 @@ static int imx6_pcie_suspend_noirq(struct device *dev)
11861207
if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_SUPPORTS_SUSPEND))
11871208
return 0;
11881209

1210+
imx6_pcie_msi_save_restore(imx6_pcie, true);
11891211
imx6_pcie_pm_turnoff(imx6_pcie);
11901212
imx6_pcie_stop_link(imx6_pcie->pci);
11911213
imx6_pcie_host_exit(pp);
@@ -1205,6 +1227,7 @@ static int imx6_pcie_resume_noirq(struct device *dev)
12051227
ret = imx6_pcie_host_init(pp);
12061228
if (ret)
12071229
return ret;
1230+
imx6_pcie_msi_save_restore(imx6_pcie, false);
12081231
dw_pcie_setup_rc(pp);
12091232

12101233
if (imx6_pcie->link_is_up)

drivers/pci/controller/dwc/pcie-designware-host.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,14 +485,19 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
485485
if (ret)
486486
goto err_remove_edma;
487487

488-
if (!dw_pcie_link_up(pci)) {
488+
if (dw_pcie_link_up(pci)) {
489+
dw_pcie_print_link_status(pci);
490+
} else {
489491
ret = dw_pcie_start_link(pci);
490492
if (ret)
491493
goto err_remove_edma;
492-
}
493494

494-
/* Ignore errors, the link may come up later */
495-
dw_pcie_wait_for_link(pci);
495+
if (pci->ops && pci->ops->start_link) {
496+
ret = dw_pcie_wait_for_link(pci);
497+
if (ret)
498+
goto err_stop_link;
499+
}
500+
}
496501

497502
bridge->sysdata = pp;
498503

drivers/pci/controller/dwc/pcie-designware.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,9 +644,20 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index)
644644
dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0);
645645
}
646646

647-
int dw_pcie_wait_for_link(struct dw_pcie *pci)
647+
void dw_pcie_print_link_status(struct dw_pcie *pci)
648648
{
649649
u32 offset, val;
650+
651+
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
652+
val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
653+
654+
dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
655+
FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
656+
FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
657+
}
658+
659+
int dw_pcie_wait_for_link(struct dw_pcie *pci)
660+
{
650661
int retries;
651662

652663
/* Check if the link is up or not */
@@ -662,12 +673,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
662673
return -ETIMEDOUT;
663674
}
664675

665-
offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
666-
val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
667-
668-
dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
669-
FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
670-
FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
676+
dw_pcie_print_link_status(pci);
671677

672678
return 0;
673679
}

drivers/pci/controller/dwc/pcie-designware.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ void dw_pcie_setup(struct dw_pcie *pci);
429429
void dw_pcie_iatu_detect(struct dw_pcie *pci);
430430
int dw_pcie_edma_detect(struct dw_pcie *pci);
431431
void dw_pcie_edma_remove(struct dw_pcie *pci);
432+
void dw_pcie_print_link_status(struct dw_pcie *pci);
432433

433434
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
434435
{

0 commit comments

Comments
 (0)