Skip to content

Commit d93fefa

Browse files
committed
Merge branch 'pci/host/fu740'
- Drop redundant '-gpios' from DT GPIO lookup (Ben Dooks) - Force 2.5GT/s for initial device probe to workaround enumeration issue on SiFive Unmatched board (Ben Dooks) * pci/host/fu740: PCI: fu740: Force 2.5GT/s for initial device probe PCI: fu740: Drop redundant '-gpios' from DT GPIO lookup
2 parents a69e89b + a382c75 commit d93fefa

1 file changed

Lines changed: 52 additions & 3 deletions

File tree

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

Lines changed: 52 additions & 3 deletions
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)
@@ -259,11 +308,11 @@ static int fu740_pcie_probe(struct platform_device *pdev)
259308
return PTR_ERR(afp->mgmt_base);
260309

261310
/* Fetch GPIOs */
262-
afp->reset = devm_gpiod_get_optional(dev, "reset-gpios", GPIOD_OUT_LOW);
311+
afp->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
263312
if (IS_ERR(afp->reset))
264313
return dev_err_probe(dev, PTR_ERR(afp->reset), "unable to get reset-gpios\n");
265314

266-
afp->pwren = devm_gpiod_get_optional(dev, "pwren-gpios", GPIOD_OUT_LOW);
315+
afp->pwren = devm_gpiod_get_optional(dev, "pwren", GPIOD_OUT_LOW);
267316
if (IS_ERR(afp->pwren))
268317
return dev_err_probe(dev, PTR_ERR(afp->pwren), "unable to get pwren-gpios\n");
269318

0 commit comments

Comments
 (0)