[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