021e210591d6e1c7a9d694d0d1f0e4f2341766a0
[openwrt/staging/blocktrron.git] /
1 From 4b0c6453808a662869a43c504913f3b7ed64486a Mon Sep 17 00:00:00 2001
2 From: Jonathan Bell <jonathan@raspberrypi.com>
3 Date: Wed, 20 Sep 2023 13:01:11 +0100
4 Subject: [PATCH] drivers: pci: brcmstb: optionally extend Tperst_clk time
5 during link-up
6
7 The RC has a feature that allows for manual control over the deassertion
8 of the PERST# output pin, which allows the time between refclk active
9 and reset deassert at the EP to be increased.
10
11 Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
12 ---
13 drivers/pci/controller/pcie-brcmstb.c | 24 +++++++++++++++++++++++-
14 1 file changed, 23 insertions(+), 1 deletion(-)
15
16 --- a/drivers/pci/controller/pcie-brcmstb.c
17 +++ b/drivers/pci/controller/pcie-brcmstb.c
18 @@ -138,6 +138,7 @@
19
20 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG pcie->reg_offsets[PCIE_HARD_DEBUG]
21 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_DEBUG_ENABLE_MASK 0x2
22 +#define PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK 0x8
23 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x08000000
24 #define PCIE_BMIPS_MISC_HARD_PCIE_HARD_DEBUG_SERDES_IDDQ_MASK 0x00800000
25 #define PCIE_MISC_HARD_PCIE_HARD_DEBUG_CLKREQ_L1SS_ENABLE_MASK 0x00200000
26 @@ -352,6 +353,7 @@ struct brcm_pcie {
27 bool (*rc_mode)(struct brcm_pcie *pcie);
28 struct subdev_regulators *sr;
29 bool ep_wakeup_capable;
30 + u32 tperst_clk_ms;
31 };
32
33 static inline bool is_bmips(const struct brcm_pcie *pcie)
34 @@ -1388,9 +1390,28 @@ static int brcm_pcie_start_link(struct b
35 u16 nlw, cls, lnksta;
36 bool ssc_good = false;
37 int ret, i;
38 + u32 tmp;
39
40 /* Unassert the fundamental reset */
41 - pcie->perst_set(pcie, 0);
42 + if (pcie->tperst_clk_ms) {
43 + /*
44 + * Increase Tperst_clk time by forcing PERST# output low while
45 + * the internal reset is released, so the PLL generates stable
46 + * refclk output further in advance of PERST# deassertion.
47 + */
48 + tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
49 + u32p_replace_bits(&tmp, 1, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
50 + writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
51 +
52 + pcie->perst_set(pcie, 0);
53 + msleep(pcie->tperst_clk_ms);
54 +
55 + tmp = readl(base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
56 + u32p_replace_bits(&tmp, 0, PCIE_MISC_HARD_PCIE_HARD_DEBUG_PERST_ASSERT_MASK);
57 + writel(tmp, base + PCIE_MISC_HARD_PCIE_HARD_DEBUG);
58 + } else {
59 + pcie->perst_set(pcie, 0);
60 + }
61
62 /*
63 * Wait for 100ms after PERST# deassertion; see PCIe CEM specification
64 @@ -1923,6 +1944,7 @@ static int brcm_pcie_probe(struct platfo
65 pcie->ssc = of_property_read_bool(np, "brcm,enable-ssc");
66 pcie->l1ss = of_property_read_bool(np, "brcm,enable-l1ss");
67 pcie->rcb_mps_mode = of_property_read_bool(np, "brcm,enable-mps-rcb");
68 + of_property_read_u32(np, "brcm,tperst-clk-ms", &pcie->tperst_clk_ms);
69
70 ret = clk_prepare_enable(pcie->clk);
71 if (ret) {