Skip to content

Commit 491cb9c

Browse files
LorenzoBianconikwilczynski
authored andcommitted
PCI: mediatek-gen3: Avoid PCIe resetting via PERST# for Airoha EN7581 SoC
Airoha EN7581 has a hw bug asserting/releasing PERST# signal causing occasional PCIe link down issues. In order to overcome the problem, PERST# signal is not asserted/released during device probe or suspend/resume phase and the PCIe block is reset using en7523_reset_assert() and en7581_pci_enable(). Introduce flags field in the mtk_gen3_pcie_pdata struct in order to specify per-SoC capabilities. Link: https://lore.kernel.org/r/20250109-pcie-en7581-rst-fix-v4-1-4a45c89fb143@kernel.org Tested-by: Hui Ma <hui.ma@airoha.com> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
1 parent c98bee1 commit 491cb9c

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

drivers/pci/controller/pcie-mediatek-gen3.c

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,26 @@ struct mtk_gen3_pcie;
135135
#define PCIE_CONF_LINK2_CTL_STS (PCIE_CFG_OFFSET_ADDR + 0xb0)
136136
#define PCIE_CONF_LINK2_LCR2_LINK_SPEED GENMASK(3, 0)
137137

138+
enum mtk_gen3_pcie_flags {
139+
SKIP_PCIE_RSTB = BIT(0), /* Skip PERST# assertion during device
140+
* probing or suspend/resume phase to
141+
* avoid hw bugs/issues.
142+
*/
143+
};
144+
138145
/**
139146
* struct mtk_gen3_pcie_pdata - differentiate between host generations
140147
* @power_up: pcie power_up callback
141148
* @phy_resets: phy reset lines SoC data.
149+
* @flags: pcie device flags.
142150
*/
143151
struct mtk_gen3_pcie_pdata {
144152
int (*power_up)(struct mtk_gen3_pcie *pcie);
145153
struct {
146154
const char *id[MAX_NUM_PHY_RESETS];
147155
int num_resets;
148156
} phy_resets;
157+
u32 flags;
149158
};
150159

151160
/**
@@ -440,22 +449,33 @@ static int mtk_pcie_startup_port(struct mtk_gen3_pcie *pcie)
440449
val |= PCIE_DISABLE_DVFSRC_VLT_REQ;
441450
writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG);
442451

443-
/* Assert all reset signals */
444-
val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
445-
val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
446-
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
447-
448452
/*
449-
* Described in PCIe CEM specification sections 2.2 (PERST# Signal)
450-
* and 2.2.1 (Initial Power-Up (G3 to S0)).
451-
* The deassertion of PERST# should be delayed 100ms (TPVPERL)
452-
* for the power and clock to become stable.
453+
* Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
454+
* causing occasional PCIe link down. In order to overcome the issue,
455+
* PCIE_RSTB signals are not asserted/released at this stage and the
456+
* PCIe block is reset using en7523_reset_assert() and
457+
* en7581_pci_enable().
453458
*/
454-
msleep(100);
455-
456-
/* De-assert reset signals */
457-
val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB);
458-
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
459+
if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
460+
/* Assert all reset signals */
461+
val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
462+
val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
463+
PCIE_PE_RSTB;
464+
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
465+
466+
/*
467+
* Described in PCIe CEM specification revision 6.0.
468+
*
469+
* The deassertion of PERST# should be delayed 100ms (TPVPERL)
470+
* for the power and clock to become stable.
471+
*/
472+
msleep(PCIE_T_PVPERL_MS);
473+
474+
/* De-assert reset signals */
475+
val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
476+
PCIE_PE_RSTB);
477+
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
478+
}
459479

460480
/* Check if the link is up or not */
461481
err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val,
@@ -1242,10 +1262,12 @@ static int mtk_pcie_suspend_noirq(struct device *dev)
12421262
return err;
12431263
}
12441264

1245-
/* Pull down the PERST# pin */
1246-
val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
1247-
val |= PCIE_PE_RSTB;
1248-
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
1265+
if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
1266+
/* Assert the PERST# pin */
1267+
val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
1268+
val |= PCIE_PE_RSTB;
1269+
writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
1270+
}
12491271

12501272
dev_dbg(pcie->dev, "entered L2 states successfully");
12511273

@@ -1296,6 +1318,7 @@ static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
12961318
.id[2] = "phy-lane2",
12971319
.num_resets = 3,
12981320
},
1321+
.flags = SKIP_PCIE_RSTB,
12991322
};
13001323

13011324
static const struct of_device_id mtk_pcie_of_match[] = {

0 commit comments

Comments
 (0)