]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
pci: brcmstb: Adapt to AXI bridge
authorTorsten Duwe <duwe@suse.de>
Mon, 1 Jun 2026 10:39:40 +0000 (12:39 +0200)
committerPeter Robinson <pbrobinson@gmail.com>
Thu, 4 Jun 2026 09:50:04 +0000 (10:50 +0100)
Fix-ups for the BCM root complex when it is located behind an AXI
bridge and clocked with 54MHz.  Some are from kernel commit
377bced88c326, some where picked by Oleksii off a now-stale older
branch. All reworked for the simpler setup code in U-Boot.

Signed-off-by: Torsten Duwe <duwe@suse.de>
Co-authored-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Tested-by: Pedro Falcato <pfalcato@suse.de>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
drivers/pci/pcie_brcmstb.c

index 5171c593c727abf4365706dcb4b39217107a7f3a..c72b47e1b103bc20942b5b49e35a00d600f3b770 100644 (file)
@@ -54,6 +54,7 @@
 #define  MISC_CTRL_CFG_READ_UR_MODE_MASK          0x2000
 #define  MISC_CTRL_MAX_BURST_SIZE_MASK            0x300000
 #define  MISC_CTRL_MAX_BURST_SIZE_128             0x0
+#define  MISC_CTRL_MAX_BURST_SIZE_128_2712             0x100000
 #define  MISC_CTRL_SCB0_SIZE_MASK                 0xf8000000
 
 #define PCIE_MISC_CPU_2_PCIE_MEM_WIN0_LO          0x400c
index 624376fe2351b04aff9ef1d0ea68658b339df2b6..1b03b0a7b05b0dfbad8c7b22bdff9c363c68e234 100644 (file)
@@ -555,6 +555,30 @@ static void brcm_pcie_set_inbound_windows(struct udevice *dev)
        }
 }
 
+static void brcm_pcie_munge_pll(struct brcm_pcie *pcie)
+{
+       u32 tmp;
+       int ret, i;
+       u8 regs[] =  { 0x16,   0x17,   0x18,   0x19,   0x1b,   0x1c,   0x1e };
+       u16 data[] = { 0x50b9, 0xbda1, 0x0094, 0x97b4, 0x5030, 0x5030, 0x0007 };
+
+       ret = brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, SET_ADDR_OFFSET,
+                                  0x1600);
+       for (i = 0; i < ARRAY_SIZE(regs); i++) {
+               brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
+               debug("PCIE MDIO pre_refclk 0x%02x = 0x%04x\n",
+                     regs[i], tmp);
+       }
+       for (i = 0; i < ARRAY_SIZE(regs); i++) {
+               brcm_pcie_mdio_write(pcie->base, MDIO_PORT0, regs[i], data[i]);
+               brcm_pcie_mdio_read(pcie->base, MDIO_PORT0, regs[i], &tmp);
+               debug("PCIE MDIO post_refclk 0x%02x = 0x%04x\n",
+                     regs[i], tmp);
+       }
+
+       udelay(200);
+}
+
 static int brcm_pcie_probe(struct udevice *dev)
 {
        struct udevice *ctlr = pci_get_controller(dev);
@@ -600,12 +624,27 @@ static int brcm_pcie_probe(struct udevice *dev)
        /* Wait for SerDes to be stable */
        udelay(100);
 
+       if (pcie->pcie_cfg->type == BCM2712) {
+               /* Allow a 54MHz (xosc) refclk source */
+               brcm_pcie_munge_pll(pcie);
+               /* Fix for L1SS errata */
+               tmp = readl(base + PCIE_RC_PL_PHY_CTL_15);
+               tmp &= ~PCIE_RC_PL_PHY_CTL_15_PM_CLK_PERIOD_MASK;
+               /* PM clock period is 18.52ns (round down) */
+               tmp |= 0x12;
+               writel(tmp, base + PCIE_RC_PL_PHY_CTL_15);
+       }
+
+       tmp = (pcie->pcie_cfg->type == BCM2712) ?
+                       MISC_CTRL_MAX_BURST_SIZE_128_2712 :
+                       MISC_CTRL_MAX_BURST_SIZE_128;
        /* Set SCB_MAX_BURST_SIZE, CFG_READ_UR_MODE, SCB_ACCESS_EN */
        clrsetbits_le32(base + PCIE_MISC_MISC_CTRL,
                        MISC_CTRL_MAX_BURST_SIZE_MASK,
                        MISC_CTRL_SCB_ACCESS_EN_MASK |
                        MISC_CTRL_CFG_READ_UR_MODE_MASK |
-                       MISC_CTRL_MAX_BURST_SIZE_128);
+                       MISC_CTRL_PCIE_RCB_MPS_MODE_MASK |
+                       tmp);
 
        tmp = readl(base + PCIE_MISC_MISC_CTRL);
        if (pcie->pcie_cfg->type == BCM2712) {
@@ -625,6 +664,29 @@ static int brcm_pcie_probe(struct udevice *dev)
        }
        writel(tmp, base + PCIE_MISC_MISC_CTRL);
 
+       if (pcie->pcie_cfg->type == BCM2712) {
+               /* Suppress AXI error responses and return 1s for read failures */
+               tmp = readl(base + PCIE_MISC_UBUS_CTRL);
+               u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_ERR_DIS_MASK);
+               u32p_replace_bits(&tmp, 1, PCIE_MISC_UBUS_CTRL_UBUS_PCIE_REPLY_DECERR_DIS_MASK);
+               writel(tmp, base + PCIE_MISC_UBUS_CTRL);
+               writel(0xffffffff, base + PCIE_MISC_AXI_READ_ERROR_DATA);
+
+               /*
+                * Adjust timeouts. The UBUS timeout also affects CRS
+                * completion retries, as the request will get terminated if
+                * either timeout expires, so both have to be a large value
+                * (in clocks of 750MHz).
+                * Set UBUS timeout to 250ms, then set RC config retry timeout
+                * to be ~240ms.
+                *
+                * Setting CRSVis=1 will stop the core from blocking on a CRS
+                * response, but does require the device to be well-behaved...
+                */
+               writel(0xB2D0000, base + PCIE_MISC_UBUS_TIMEOUT);
+               writel(0xABA0000, base + PCIE_MISC_RC_CONFIG_RETRY_TIMEOUT);
+       }
+
        /* Disable the PCIe->GISB memory window (RC_BAR1) */
        clrbits_le32(base + PCIE_MISC_RC_BAR1_CONFIG_LO,
                     RC_BAR1_CONFIG_LO_SIZE_MASK);