Skip to content

Commit a382c75

Browse files
bjdooks-ctbjorn-helgaas
authored andcommitted
PCI: fu740: Force 2.5GT/s for initial device probe
The fu740 PCIe core does not probe any devices on the SiFive Unmatched board without this fix (or having U-Boot explicitly start the PCIe via either boot-script or user command). The fix is to start the link at 2.5GT/s speeds and once the link is up then change the maximum speed back to the default. The U-Boot driver claims to set the link-speed to 2.5GT/s to get the probe to work (and U-Boot does print link up at 2.5GT/s) in the following code: https://source.denx.de/u-boot/u-boot/-/blob/master/drivers/pci/pcie_dw_sifive.c?id=v2022.01#L271 Link: https://lore.kernel.org/r/20220318152430.526320-1-ben.dooks@codethink.co.uk Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent cf18fce commit a382c75

1 file changed

Lines changed: 50 additions & 1 deletion

File tree

drivers/pci/controller/dwc/pcie-fu740.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,59 @@ static int fu740_pcie_start_link(struct dw_pcie *pci)
181181
{
182182
struct device *dev = pci->dev;
183183
struct fu740_pcie *afp = dev_get_drvdata(dev);
184+
u8 cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
185+
int ret;
186+
u32 orig, tmp;
187+
188+
/*
189+
* Force 2.5GT/s when starting the link, due to some devices not
190+
* probing at higher speeds. This happens with the PCIe switch
191+
* on the Unmatched board when U-Boot has not initialised the PCIe.
192+
* The fix in U-Boot is to force 2.5GT/s, which then gets cleared
193+
* by the soft reset done by this driver.
194+
*/
195+
dev_dbg(dev, "cap_exp at %x\n", cap_exp);
196+
dw_pcie_dbi_ro_wr_en(pci);
197+
198+
tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
199+
orig = tmp & PCI_EXP_LNKCAP_SLS;
200+
tmp &= ~PCI_EXP_LNKCAP_SLS;
201+
tmp |= PCI_EXP_LNKCAP_SLS_2_5GB;
202+
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
184203

185204
/* Enable LTSSM */
186205
writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
187-
return 0;
206+
207+
ret = dw_pcie_wait_for_link(pci);
208+
if (ret) {
209+
dev_err(dev, "error: link did not start\n");
210+
goto err;
211+
}
212+
213+
tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
214+
if ((tmp & PCI_EXP_LNKCAP_SLS) != orig) {
215+
dev_dbg(dev, "changing speed back to original\n");
216+
217+
tmp &= ~PCI_EXP_LNKCAP_SLS;
218+
tmp |= orig;
219+
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
220+
221+
tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
222+
tmp |= PORT_LOGIC_SPEED_CHANGE;
223+
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
224+
225+
ret = dw_pcie_wait_for_link(pci);
226+
if (ret) {
227+
dev_err(dev, "error: link did not start at new speed\n");
228+
goto err;
229+
}
230+
}
231+
232+
ret = 0;
233+
err:
234+
WARN_ON(ret); /* we assume that errors will be very rare */
235+
dw_pcie_dbi_ro_wr_dis(pci);
236+
return ret;
188237
}
189238

190239
static int fu740_pcie_host_init(struct pcie_port *pp)

0 commit comments

Comments
 (0)