These patches were generated from: https://github.com/raspberrypi/linux/commits/rpi-6.12.y With the following command: git format-patch -N v6.12.27..HEAD (HEAD -> 8d3206ee456a5ecdf9ddbfd8e5e231e4f0cd716e) Exceptions: - (def)configs patches - github workflows patches - applied & reverted patches - readme patches - wireless patches Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
89 lines
3.4 KiB
Diff
89 lines
3.4 KiB
Diff
From 693653f118c81b7338ed584bea0bc085b0e8c529 Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Bell <jonathan@raspberrypi.com>
|
|
Date: Thu, 13 Feb 2025 16:46:49 +0000
|
|
Subject: [PATCH] PCI: pcie-brcmstb: optionally extend Tperst_clk time
|
|
|
|
Some endpoints need longer than the minimum Tperst_clk time of 100us
|
|
that the PCIe specification allows for, as they may need to sequence
|
|
internal resets off the stable output of internal PLLs prior to removal
|
|
of fundamental reset. PCIe switches are an especially bad case, in some
|
|
cases requiring up to 100 milliseconds for stable downstream link
|
|
behaviour.
|
|
|
|
Parse the DT property brcm,tperst-clk-ms and use this to hold PERST# low
|
|
during brcm_pcie_start_link().
|
|
|
|
The BRCM RC typically outputs 200us of stable refclk before deasserting
|
|
PERST#. By masking/forcing the output signal while deasserting the
|
|
internal reset, the effect is to extend the length of time that the
|
|
refclk is active and stable before PERST# is released.
|
|
|
|
The TX lanes will enter the Polling state before PERST# is released, but
|
|
this appears to be harmless.
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
|
|
---
|
|
drivers/pci/controller/pcie-brcmstb.c | 25 ++++++++++++++++++++++++-
|
|
1 file changed, 24 insertions(+), 1 deletion(-)
|
|
|
|
--- a/drivers/pci/controller/pcie-brcmstb.c
|
|
+++ b/drivers/pci/controller/pcie-brcmstb.c
|
|
@@ -134,6 +134,7 @@
|
|
PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI + ((win) * 8)
|
|
|
|
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
|
|
+#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8
|
|
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_L1SS_ENABLE_MASK 0x200000
|
|
#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
|
|
#define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000
|
|
@@ -360,6 +361,7 @@ struct brcm_pcie {
|
|
struct subdev_regulators *sr;
|
|
bool ep_wakeup_capable;
|
|
const struct pcie_cfg_data *cfg;
|
|
+ u32 tperst_clk_ms;
|
|
};
|
|
|
|
static inline bool is_bmips(const struct brcm_pcie *pcie)
|
|
@@ -1487,13 +1489,32 @@ static int brcm_pcie_start_link(struct b
|
|
u16 nlw, cls, lnksta, tmp16;
|
|
bool ssc_good = false;
|
|
int ret, i;
|
|
+ u32 tmp;
|
|
|
|
/* Limit the generation if specified */
|
|
if (pcie->gen)
|
|
brcm_pcie_set_gen(pcie, pcie->gen);
|
|
|
|
/* Unassert the fundamental reset */
|
|
- ret = pcie->cfg->perst_set(pcie, 0);
|
|
+ if (pcie->tperst_clk_ms) {
|
|
+ /*
|
|
+ * Increase Tperst_clk time by forcing PERST# output low while
|
|
+ * the internal reset is released, so the PLL generates stable
|
|
+ * refclk output further in advance of PERST# deassertion.
|
|
+ */
|
|
+ tmp = readl(pcie->base + HARD_DEBUG(pcie));
|
|
+ u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
|
|
+ writel(tmp, pcie->base + HARD_DEBUG(pcie));
|
|
+
|
|
+ ret = pcie->cfg->perst_set(pcie, 0);
|
|
+ fsleep(pcie->tperst_clk_ms * USEC_PER_MSEC);
|
|
+
|
|
+ tmp = readl(pcie->base + HARD_DEBUG(pcie));
|
|
+ u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
|
|
+ writel(tmp, pcie->base + HARD_DEBUG(pcie));
|
|
+ } else {
|
|
+ ret = pcie->cfg->perst_set(pcie, 0);
|
|
+ }
|
|
if (ret)
|
|
return ret;
|
|
|
|
@@ -2057,6 +2078,8 @@ static int brcm_pcie_probe(struct platfo
|
|
pcie->ssc = !(pcie->cfg->quirks & CFG_QUIRK_NO_SSC) &&
|
|
of_property_read_bool(np, "brcm,enable-ssc");
|
|
|
|
+ of_property_read_u32(np, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms);
|
|
+
|
|
pcie->rescal = devm_reset_control_get_optional_shared(&pdev->dev, "rescal");
|
|
if (IS_ERR(pcie->rescal))
|
|
return PTR_ERR(pcie->rescal);
|