From: Torsten Duwe <[email protected]>

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 <[email protected]>
---
 .../mach-bcm283x/include/mach/acpi/bcm2711.h  |  1 +
 drivers/pci/pcie_brcmstb.c                    | 64 ++++++++++++++++++-
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h 
b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
index 6eb5389b858..869482eaffe 100644
--- a/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
+++ b/arch/arm/mach-bcm283x/include/mach/acpi/bcm2711.h
@@ -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
diff --git a/drivers/pci/pcie_brcmstb.c b/drivers/pci/pcie_brcmstb.c
index e5c848c9e8e..bd1dd17e690 100644
--- a/drivers/pci/pcie_brcmstb.c
+++ b/drivers/pci/pcie_brcmstb.c
@@ -521,6 +521,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);
@@ -562,18 +586,56 @@ 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);
 
        /* Enable 32GB memory to be accessed from PCIe in the SCB0 */
        tmp = readl(base + PCIE_MISC_MISC_CTRL);
        u32p_replace_bits(&tmp, 20, MISC_CTRL_SCB0_SIZE_MASK);
        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);
-- 
2.51.0

Reply via email to