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
This commit is contained in:
Коммит
d93fefad20
|
@ -181,10 +181,59 @@ static int fu740_pcie_start_link(struct dw_pcie *pci)
|
||||||
{
|
{
|
||||||
struct device *dev = pci->dev;
|
struct device *dev = pci->dev;
|
||||||
struct fu740_pcie *afp = dev_get_drvdata(dev);
|
struct fu740_pcie *afp = dev_get_drvdata(dev);
|
||||||
|
u8 cap_exp = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
|
||||||
|
int ret;
|
||||||
|
u32 orig, tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force 2.5GT/s when starting the link, due to some devices not
|
||||||
|
* probing at higher speeds. This happens with the PCIe switch
|
||||||
|
* on the Unmatched board when U-Boot has not initialised the PCIe.
|
||||||
|
* The fix in U-Boot is to force 2.5GT/s, which then gets cleared
|
||||||
|
* by the soft reset done by this driver.
|
||||||
|
*/
|
||||||
|
dev_dbg(dev, "cap_exp at %x\n", cap_exp);
|
||||||
|
dw_pcie_dbi_ro_wr_en(pci);
|
||||||
|
|
||||||
|
tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
|
||||||
|
orig = tmp & PCI_EXP_LNKCAP_SLS;
|
||||||
|
tmp &= ~PCI_EXP_LNKCAP_SLS;
|
||||||
|
tmp |= PCI_EXP_LNKCAP_SLS_2_5GB;
|
||||||
|
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
|
||||||
|
|
||||||
/* Enable LTSSM */
|
/* Enable LTSSM */
|
||||||
writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
|
writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
|
||||||
return 0;
|
|
||||||
|
ret = dw_pcie_wait_for_link(pci);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "error: link did not start\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = dw_pcie_readl_dbi(pci, cap_exp + PCI_EXP_LNKCAP);
|
||||||
|
if ((tmp & PCI_EXP_LNKCAP_SLS) != orig) {
|
||||||
|
dev_dbg(dev, "changing speed back to original\n");
|
||||||
|
|
||||||
|
tmp &= ~PCI_EXP_LNKCAP_SLS;
|
||||||
|
tmp |= orig;
|
||||||
|
dw_pcie_writel_dbi(pci, cap_exp + PCI_EXP_LNKCAP, tmp);
|
||||||
|
|
||||||
|
tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
|
||||||
|
tmp |= PORT_LOGIC_SPEED_CHANGE;
|
||||||
|
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
|
||||||
|
|
||||||
|
ret = dw_pcie_wait_for_link(pci);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "error: link did not start at new speed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
err:
|
||||||
|
WARN_ON(ret); /* we assume that errors will be very rare */
|
||||||
|
dw_pcie_dbi_ro_wr_dis(pci);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fu740_pcie_host_init(struct pcie_port *pp)
|
static int fu740_pcie_host_init(struct pcie_port *pp)
|
||||||
|
@ -259,11 +308,11 @@ static int fu740_pcie_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(afp->mgmt_base);
|
return PTR_ERR(afp->mgmt_base);
|
||||||
|
|
||||||
/* Fetch GPIOs */
|
/* Fetch GPIOs */
|
||||||
afp->reset = devm_gpiod_get_optional(dev, "reset-gpios", GPIOD_OUT_LOW);
|
afp->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||||
if (IS_ERR(afp->reset))
|
if (IS_ERR(afp->reset))
|
||||||
return dev_err_probe(dev, PTR_ERR(afp->reset), "unable to get reset-gpios\n");
|
return dev_err_probe(dev, PTR_ERR(afp->reset), "unable to get reset-gpios\n");
|
||||||
|
|
||||||
afp->pwren = devm_gpiod_get_optional(dev, "pwren-gpios", GPIOD_OUT_LOW);
|
afp->pwren = devm_gpiod_get_optional(dev, "pwren", GPIOD_OUT_LOW);
|
||||||
if (IS_ERR(afp->pwren))
|
if (IS_ERR(afp->pwren))
|
||||||
return dev_err_probe(dev, PTR_ERR(afp->pwren), "unable to get pwren-gpios\n");
|
return dev_err_probe(dev, PTR_ERR(afp->pwren), "unable to get pwren-gpios\n");
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче