On Sat, Oct 3, 2026 at 5:31 AM Dave Klotz <[email protected]> wrote:
>
> The driver never reads the standard "num-lanes" property, so a board
> cannot set the width of a port: the OrangePi RV2's M.2 slot on port B
> is wired for two lanes, and other boards may use only one of the two.
>
> Linux's DesignWare core reads "num-lanes" and, when it is set,
> programs the port link mode, the link width and speed control register
> and the Maximum Link Width in Link Capabilities from it, leaving the
> hardware default otherwise. dw_pcie_link_set_max_link_width() in
> pcie_dw_common does exactly that; call it before link training.
>
> Signed-off-by: Dave Klotz <[email protected]>
> ---
> drivers/pci/pcie_dw_spacemit.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/pci/pcie_dw_spacemit.c b/drivers/pci/pcie_dw_spacemit.c
> index 3b5c2dc4e0..9b299ca17a 100644
> --- a/drivers/pci/pcie_dw_spacemit.c
> +++ b/drivers/pci/pcie_dw_spacemit.c
> @@ -41,6 +41,7 @@ struct pcie_dw_spacemit {
> struct reset_ctl_bulk rsts;
> struct udevice *vpcie3v3; /* slot supply, if described
> */
> u32 max_link_speed; /* 0: hardware default */
> + u32 num_lanes; /* 0: hardware default */
> };
>
> static inline u32 spacemit_pcie_readl(struct pcie_dw_spacemit *pcie, u32
> offset)
> @@ -93,6 +94,9 @@ static void pcie_dw_configure(struct pcie_dw_spacemit *pci)
> writew(lnkctl2, cap + PCI_EXP_LNKCTL2);
> }
>
> + /* Link width from "num-lanes"; without it, keep the hardware's */
> + dw_pcie_link_set_max_link_width(&pci->dw, pci->num_lanes);
> +
> dw_pcie_dbi_write_enable(&pci->dw, false);
> }
>
> @@ -406,6 +410,8 @@ static int pcie_dw_spacemit_of_to_plat(struct udevice
> *dev)
> pcie->max_link_speed = 0;
> }
>
> + pcie->num_lanes = dev_read_u32_default(dev, "num-lanes", 0);
> +
> /* Derive port ID from DBI base address */
> pcie->port_id = (dbi_addr - SPACEMIT_PCIE_DBI_BASE) /
> SPACEMIT_PCIE_DBI_STRIDE;
>
> --
> 2.55.0
>
>
Reviewed-by: Eric Chung <[email protected]>