/* * Baikal-T1 MMIO space must be read/written by the dword-aligned * instructions. Note the methods are optimized to have the dword operations * performed with minimum overhead as the most frequently used ones.
*/ staticint bt1_pcie_read_mmio(void __iomem *addr, int size, u32 *val)
{ unsignedint ofs = (uintptr_t)addr & 0x3;
if (!IS_ALIGNED((uintptr_t)addr, size)) return -EINVAL;
/* * Enable LTSSM and make sure it was able to establish both PHY and * data links. This procedure shall work fine to reach 2.5 GT/s speed.
*/
regmap_update_bits(btpci->sys_regs, BT1_CCU_PCIE_GENC,
BT1_CCU_PCIE_LTSSM_EN, BT1_CCU_PCIE_LTSSM_EN);
ret = regmap_read_poll_timeout(btpci->sys_regs, BT1_CCU_PCIE_PMSC, val,
(val & BT1_CCU_PCIE_SMLH_LINKUP),
BT1_PCIE_LNK_DELAY_US, BT1_PCIE_LNK_TIMEOUT_US); if (ret) {
dev_err(pci->dev, "LTSSM failed to set PHY link up\n"); return ret;
}
ret = regmap_read_poll_timeout(btpci->sys_regs, BT1_CCU_PCIE_PMSC, val,
(val & BT1_CCU_PCIE_RDLH_LINKUP),
BT1_PCIE_LNK_DELAY_US, BT1_PCIE_LNK_TIMEOUT_US); if (ret) {
dev_err(pci->dev, "LTSSM failed to set data link up\n"); return ret;
}
/* * Activate direct speed change after the link is established in an * attempt to reach a higher bus performance (up to Gen.3 - 8.0 GT/s). * This is required at least to get 8.0 GT/s speed.
*/
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
val |= PORT_LOGIC_SPEED_CHANGE;
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
ret = regmap_read_poll_timeout(btpci->sys_regs, BT1_CCU_PCIE_PMSC, val,
BT1_CCU_PCIE_LTSSM_LINKUP(val),
BT1_PCIE_LNK_DELAY_US, BT1_PCIE_LNK_TIMEOUT_US); if (ret)
dev_err(pci->dev, "LTSSM failed to get into L0 state\n");
/* DBI access is supposed to be performed by the dword-aligned IOs */
btpci->dw.pp.bridge->ops = &bt1_pci_ops;
/* These CSRs are in MMIO so we won't check the regmap-methods status */
btpci->sys_regs =
syscon_regmap_lookup_by_phandle(dev->of_node, "baikal,bt1-syscon"); if (IS_ERR(btpci->sys_regs)) return dev_err_probe(dev, PTR_ERR(btpci->sys_regs), "Failed to get syscon\n");
/* Make sure all the required resources have been specified */ for (i = 0; i < BT1_PCIE_NUM_APP_CLKS; i++) { if (!btpci->dw.app_clks[bt1_pcie_app_clks[i]].clk) {
dev_err(dev, "App clocks set is incomplete\n"); return -ENOENT;
}
}
for (i = 0; i < BT1_PCIE_NUM_CORE_CLKS; i++) { if (!btpci->dw.core_clks[bt1_pcie_core_clks[i]].clk) {
dev_err(dev, "Core clocks set is incomplete\n"); return -ENOENT;
}
}
for (i = 0; i < BT1_PCIE_NUM_APP_RSTS; i++) { if (!btpci->dw.app_rsts[bt1_pcie_app_rsts[i]].rstc) {
dev_err(dev, "App resets set is incomplete\n"); return -ENOENT;
}
}
for (i = 0; i < BT1_PCIE_NUM_CORE_RSTS; i++) { if (!btpci->dw.core_rsts[bt1_pcie_core_rsts[i]].rstc) {
dev_err(dev, "Core resets set is incomplete\n"); return -ENOENT;
}
}
/* Disable LTSSM for sure */
regmap_update_bits(btpci->sys_regs, BT1_CCU_PCIE_GENC,
BT1_CCU_PCIE_LTSSM_EN, 0);
/* * Application reset controls are trigger-based so assert the core * resets only.
*/
ret = reset_control_bulk_assert(DW_PCIE_NUM_CORE_RSTS, pci->core_rsts); if (ret)
dev_err(dev, "Failed to assert core resets\n");
/* * Clocks are disabled by default at least in accordance with the clk * enable counter value on init stage.
*/ if (!init) {
clk_bulk_disable_unprepare(DW_PCIE_NUM_CORE_CLKS, pci->core_clks);
/* The peripheral devices are unavailable anyway so reset them too */
gpiod_set_value_cansleep(pci->pe_rst, 1);
/* Make sure all the resets are settled */
msleep(BT1_PCIE_RST_DELAY_MS);
}
/* * Implements the cold reset procedure in accordance with the reference manual * and available PM signals.
*/ staticint bt1_pcie_cold_start_bus(struct bt1_pcie *btpci)
{ struct device *dev = btpci->dw.dev; struct dw_pcie *pci = &btpci->dw;
u32 val; int ret;
/* First get out of the Power/Hot reset state */
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_PWR_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert PHY reset\n"); return ret;
}
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_HOT_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert hot reset\n"); goto err_assert_pwr_rst;
}
/* Wait for the PM-core to stop requesting the PHY reset */
ret = regmap_read_poll_timeout(btpci->sys_regs, BT1_CCU_PCIE_RSTC, val,
!(val & BT1_CCU_PCIE_REQ_PHY_RST),
BT1_PCIE_REQ_DELAY_US, BT1_PCIE_REQ_TIMEOUT_US); if (ret) {
dev_err(dev, "Timed out waiting for PM to stop PHY resetting\n"); goto err_assert_hot_rst;
}
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_PHY_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert PHY reset\n"); goto err_assert_hot_rst;
}
/* Clocks can be now enabled, but the ref one is crucial at this stage */
ret = clk_bulk_prepare_enable(DW_PCIE_NUM_APP_CLKS, pci->app_clks); if (ret) {
dev_err(dev, "Failed to enable app clocks\n"); goto err_assert_phy_rst;
}
ret = clk_bulk_prepare_enable(DW_PCIE_NUM_CORE_CLKS, pci->core_clks); if (ret) {
dev_err(dev, "Failed to enable ref clocks\n"); goto err_disable_app_clk;
}
/* Wait for the PM to stop requesting the controller core reset */
ret = regmap_read_poll_timeout(btpci->sys_regs, BT1_CCU_PCIE_RSTC, val,
!(val & BT1_CCU_PCIE_REQ_CORE_RST),
BT1_PCIE_REQ_DELAY_US, BT1_PCIE_REQ_TIMEOUT_US); if (ret) {
dev_err(dev, "Timed out waiting for PM to stop core resetting\n"); goto err_disable_core_clk;
}
/* PCS-PIPE interface and controller core can be now activated */
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_PIPE_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert PIPE reset\n"); goto err_disable_core_clk;
}
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_CORE_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert core reset\n"); goto err_assert_pipe_rst;
}
/* It's recommended to reset the core and application logic together */
ret = reset_control_bulk_reset(DW_PCIE_NUM_APP_RSTS, pci->app_rsts); if (ret) {
dev_err(dev, "Failed to reset app domain\n"); goto err_assert_core_rst;
}
/* Sticky/Non-sticky CSR flags can be now unreset too */
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_STICKY_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert sticky reset\n"); goto err_assert_core_rst;
}
ret = reset_control_deassert(pci->core_rsts[DW_PCIE_NON_STICKY_RST].rstc); if (ret) {
dev_err(dev, "Failed to deassert non-sticky reset\n"); goto err_assert_sticky_rst;
}
/* Activate the PCIe bus peripheral devices */
gpiod_set_value_cansleep(pci->pe_rst, 0);
/* Make sure the state is settled (LTSSM is still disabled though) */
usleep_range(BT1_PCIE_RUN_DELAY_US, BT1_PCIE_RUN_DELAY_US + 100);
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.