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


Reply via email to