// SPDX-License-Identifier: GPL-2.0 /* * FU740 DesignWare PCIe Controller integration * Copyright (C) 2019-2021 SiFive, Inc. * Paul Walmsley * Greentime Hu * * Based in part on the i.MX6 PCIe host controller shim which is: * * Copyright (C) 2013 Kosagi * https://www.kosagi.com
*/
staticvoid fu740_pcie_power_on(struct fu740_pcie *afp)
{
gpiod_set_value_cansleep(afp->pwren, 1); /* * Ensure that PERST has been asserted for at least 100 ms. * Section 2.2 of PCI Express Card Electromechanical Specification * Revision 3.0
*/
msleep(100);
}
/* Wait for wait_idle */
ret = readl_poll_timeout(phy_cr_para_ack, val, val, 10, 5000); if (ret)
dev_warn(dev, "Wait for wait_idle state failed!\n");
/* Clear */
writel_relaxed(0, phy_cr_para_wr_en);
/* Wait for ~wait_idle */
ret = readl_poll_timeout(phy_cr_para_ack, val, !val, 10, 5000); if (ret)
dev_warn(dev, "Wait for !wait_idle state failed!\n");
}
/* * 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);
/* Enable pcieauxclk */
ret = clk_prepare_enable(afp->pcie_aux); if (ret) {
dev_err(dev, "unable to enable pcie_aux clock\n"); return ret;
}
/* * Assert hold_phy_rst (hold the controller LTSSM in reset after * power_up_rst_n for register programming with cr_para)
*/
writel_relaxed(0x1, afp->mgmt_base + PCIEX8MGMT_APP_HOLD_PHY_RST);
/* Deassert power_up_rst_n */
ret = reset_control_deassert(afp->rst); if (ret) {
dev_err(dev, "unable to deassert pcie_power_up_rst_n\n"); return ret;
}
/* SiFive specific region: mgmt */
afp->mgmt_base = devm_platform_ioremap_resource_byname(pdev, "mgmt"); if (IS_ERR(afp->mgmt_base)) return PTR_ERR(afp->mgmt_base);
/* Fetch GPIOs */
afp->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(afp->reset)) return dev_err_probe(dev, PTR_ERR(afp->reset), "unable to get reset-gpios\n");
afp->pwren = devm_gpiod_get_optional(dev, "pwren", GPIOD_OUT_LOW); if (IS_ERR(afp->pwren)) return dev_err_probe(dev, PTR_ERR(afp->pwren), "unable to get pwren-gpios\n");
/* Fetch clocks */
afp->pcie_aux = devm_clk_get(dev, "pcie_aux"); if (IS_ERR(afp->pcie_aux)) return dev_err_probe(dev, PTR_ERR(afp->pcie_aux), "pcie_aux clock source missing or invalid\n");
/* Fetch reset */
afp->rst = devm_reset_control_get_exclusive(dev, NULL); if (IS_ERR(afp->rst)) return dev_err_probe(dev, PTR_ERR(afp->rst), "unable to get reset\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.