[PATCH v2 9/9] pci: brcmstb: Adapt to AXI bridge
Neil Armstrong
neil.armstrong at linaro.org
Wed May 6 16:37:16 CEST 2026
On 4/28/26 18:39, Torsten Duwe wrote:
> From: Torsten Duwe <duwe at suse.de>
>
> 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 at suse.de>
> Co-authored-by: Oleksii Moisieiev <oleksii_moisieiev at epam.com>
> Tested-by: Pedro Falcato <pfalcato at suse.de>
>
> ---
> .../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 05b80a45b50..f0b0f1cc117 100644
> --- a/drivers/pci/pcie_brcmstb.c
> +++ b/drivers/pci/pcie_brcmstb.c
> @@ -551,6 +551,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);
> @@ -592,12 +616,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) {
> @@ -617,6 +656,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);
Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>
Thanks,
Neil
More information about the U-Boot
mailing list