diff options
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-tegra194.c')
-rw-r--r-- | drivers/pci/controller/dwc/pcie-tegra194.c | 129 |
1 files changed, 49 insertions, 80 deletions
diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index f920e7efe118..5597b2a49598 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -765,8 +765,6 @@ static void tegra_pcie_enable_msi_interrupts(struct pcie_port *pp) struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); u32 val; - dw_pcie_msi_init(pp); - /* Enable MSI interrupt generation */ val = appl_readl(pcie, APPL_INTR_EN_L0_0); val |= APPL_INTR_EN_L0_0_SYS_MSI_INTR_EN; @@ -861,6 +859,10 @@ static void tegra_pcie_prepare_host(struct pcie_port *pp) struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); u32 val; + if (!pcie->pcie_cap_base) + pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci, + PCI_CAP_ID_EXP); + val = dw_pcie_readl_dbi(pci, PCI_IO_BASE); val &= ~(IO_BASE_IO_DECODE | IO_BASE_IO_DECODE_BIT8); dw_pcie_writel_dbi(pci, PCI_IO_BASE, val); @@ -889,6 +891,12 @@ static void tegra_pcie_prepare_host(struct pcie_port *pp) init_host_aspm(pcie); + /* Disable ASPM-L1SS advertisement if there is no CLKREQ routing */ + if (!pcie->supports_clkreq) { + disable_aspm_l11(pcie); + disable_aspm_l12(pcie); + } + val = dw_pcie_readl_dbi(pci, GEN3_RELATED_OFF); val &= ~GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL; dw_pcie_writel_dbi(pci, GEN3_RELATED_OFF, val); @@ -990,11 +998,6 @@ static int tegra_pcie_dw_link_up(struct dw_pcie *pci) return !!(val & PCI_EXP_LNKSTA_DLLLA); } -static void tegra_pcie_set_msi_vec_num(struct pcie_port *pp) -{ - pp->num_vectors = MAX_MSI_IRQS; -} - static int tegra_pcie_dw_start_link(struct dw_pcie *pci) { struct tegra_pcie_dw *pcie = to_tegra_pcie(pci); @@ -1019,7 +1022,6 @@ static const struct dw_pcie_ops tegra_dw_pcie_ops = { static struct dw_pcie_host_ops tegra_pcie_dw_host_ops = { .host_init = tegra_pcie_dw_host_init, - .set_num_vectors = tegra_pcie_set_msi_vec_num, }; static void tegra_pcie_disable_phy(struct tegra_pcie_dw *pcie) @@ -1061,9 +1063,16 @@ phy_exit: static int tegra_pcie_dw_parse_dt(struct tegra_pcie_dw *pcie) { + struct platform_device *pdev = to_platform_device(pcie->dev); struct device_node *np = pcie->dev->of_node; int ret; + pcie->dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); + if (!pcie->dbi_res) { + dev_err(pcie->dev, "Failed to find \"dbi\" region\n"); + return -ENODEV; + } + ret = of_property_read_u32(np, "nvidia,aspm-cmrt-us", &pcie->aspm_cmrt); if (ret < 0) { dev_info(pcie->dev, "Failed to read ASPM T_cmrt: %d\n", ret); @@ -1390,15 +1399,6 @@ static int tegra_pcie_config_controller(struct tegra_pcie_dw *pcie, reset_control_deassert(pcie->core_rst); - pcie->pcie_cap_base = dw_pcie_find_capability(&pcie->pci, - PCI_CAP_ID_EXP); - - /* Disable ASPM-L1SS advertisement as there is no CLKREQ routing */ - if (!pcie->supports_clkreq) { - disable_aspm_l11(pcie); - disable_aspm_l12(pcie); - } - return ret; fail_phy: @@ -1415,43 +1415,32 @@ fail_slot_reg_en: return ret; } -static int __deinit_controller(struct tegra_pcie_dw *pcie) +static void tegra_pcie_unconfig_controller(struct tegra_pcie_dw *pcie) { int ret; ret = reset_control_assert(pcie->core_rst); - if (ret) { - dev_err(pcie->dev, "Failed to assert \"core\" reset: %d\n", - ret); - return ret; - } + if (ret) + dev_err(pcie->dev, "Failed to assert \"core\" reset: %d\n", ret); tegra_pcie_disable_phy(pcie); ret = reset_control_assert(pcie->core_apb_rst); - if (ret) { + if (ret) dev_err(pcie->dev, "Failed to assert APB reset: %d\n", ret); - return ret; - } clk_disable_unprepare(pcie->core_clk); ret = regulator_disable(pcie->pex_ctl_supply); - if (ret) { + if (ret) dev_err(pcie->dev, "Failed to disable regulator: %d\n", ret); - return ret; - } tegra_pcie_disable_slot_regulators(pcie); ret = tegra_pcie_bpmp_set_ctrl_state(pcie, false); - if (ret) { + if (ret) dev_err(pcie->dev, "Failed to disable controller %d: %d\n", pcie->cid, ret); - return ret; - } - - return ret; } static int tegra_pcie_init_controller(struct tegra_pcie_dw *pcie) @@ -1475,7 +1464,8 @@ static int tegra_pcie_init_controller(struct tegra_pcie_dw *pcie) return 0; fail_host_init: - return __deinit_controller(pcie); + tegra_pcie_unconfig_controller(pcie); + return ret; } static int tegra_pcie_try_link_l2(struct tegra_pcie_dw *pcie) @@ -1516,6 +1506,14 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie) data &= ~APPL_PINMUX_PEX_RST; appl_writel(pcie, data, APPL_PINMUX); + /* + * Some cards do not go to detect state even after de-asserting + * PERST#. So, de-assert LTSSM to bring link to detect state. + */ + data = readl(pcie->appl_base + APPL_CTRL); + data &= ~APPL_CTRL_LTSSM_EN; + writel(data, pcie->appl_base + APPL_CTRL); + err = readl_poll_timeout_atomic(pcie->appl_base + APPL_DEBUG, data, ((data & @@ -1523,14 +1521,8 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie) APPL_DEBUG_LTSSM_STATE_SHIFT) == LTSSM_STATE_PRE_DETECT, 1, LTSSM_TIMEOUT); - if (err) { + if (err) dev_info(pcie->dev, "Link didn't go to detect state\n"); - } else { - /* Disable LTSSM after link is in detect state */ - data = appl_readl(pcie, APPL_CTRL); - data &= ~APPL_CTRL_LTSSM_EN; - appl_writel(pcie, data, APPL_CTRL); - } } /* * DBI registers may not be accessible after this as PLL-E would be @@ -1544,30 +1536,20 @@ static void tegra_pcie_dw_pme_turnoff(struct tegra_pcie_dw *pcie) appl_writel(pcie, data, APPL_PINMUX); } -static int tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie) +static void tegra_pcie_deinit_controller(struct tegra_pcie_dw *pcie) { tegra_pcie_downstream_dev_to_D0(pcie); dw_pcie_host_deinit(&pcie->pci.pp); tegra_pcie_dw_pme_turnoff(pcie); - - return __deinit_controller(pcie); + tegra_pcie_unconfig_controller(pcie); } static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) { - struct pcie_port *pp = &pcie->pci.pp; struct device *dev = pcie->dev; char *name; int ret; - if (IS_ENABLED(CONFIG_PCI_MSI)) { - pp->msi_irq = of_irq_get_byname(dev->of_node, "msi"); - if (!pp->msi_irq) { - dev_err(dev, "Failed to get MSI interrupt\n"); - return -ENODEV; - } - } - pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); @@ -1583,7 +1565,11 @@ static int tegra_pcie_config_rp(struct tegra_pcie_dw *pcie) goto fail_pm_get_sync; } - tegra_pcie_init_controller(pcie); + ret = tegra_pcie_init_controller(pcie); + if (ret < 0) { + dev_err(dev, "Failed to initialize controller: %d\n", ret); + goto fail_pm_get_sync; + } pcie->link_state = tegra_pcie_dw_link_up(&pcie->pci); if (!pcie->link_state) { @@ -1907,19 +1893,12 @@ static int tegra_pcie_config_ep(struct tegra_pcie_dw *pcie, struct dw_pcie *pci = &pcie->pci; struct device *dev = pcie->dev; struct dw_pcie_ep *ep; - struct resource *res; char *name; int ret; ep = &pci->ep; ep->ops = &pcie_ep_ops; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); - if (!res) - return -EINVAL; - - ep->phys_base = res->start; - ep->addr_size = resource_size(res); ep->page_size = SZ_64K; ret = gpiod_set_debounce(pcie->pex_rst_gpiod, PERST_DEBOUNCE_TIME); @@ -1982,7 +1961,6 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *atu_dma_res; struct tegra_pcie_dw *pcie; - struct resource *dbi_res; struct pcie_port *pp; struct dw_pcie *pci; struct phy **phys; @@ -2001,8 +1979,10 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) pci->ops = &tegra_dw_pcie_ops; pci->n_fts[0] = N_FTS_VAL; pci->n_fts[1] = FTS_VAL; + pci->version = 0x490A; pp = &pci->pp; + pp->num_vectors = MAX_MSI_IRQS; pcie->dev = &pdev->dev; pcie->mode = (enum dw_pcie_device_mode)data->mode; @@ -2091,20 +2071,6 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) pcie->phys = phys; - dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); - if (!dbi_res) { - dev_err(dev, "Failed to find \"dbi\" region\n"); - return -ENODEV; - } - pcie->dbi_res = dbi_res; - - pci->dbi_base = devm_ioremap_resource(dev, dbi_res); - if (IS_ERR(pci->dbi_base)) - return PTR_ERR(pci->dbi_base); - - /* Tegra HW locates DBI2 at a fixed offset from DBI */ - pci->dbi_base2 = pci->dbi_base + 0x1000; - atu_dma_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "atu_dma"); if (!atu_dma_res) { @@ -2113,6 +2079,7 @@ static int tegra_pcie_dw_probe(struct platform_device *pdev) } pcie->atu_dma_res = atu_dma_res; + pci->atu_size = resource_size(atu_dma_res); pci->atu_base = devm_ioremap_resource(dev, atu_dma_res); if (IS_ERR(pci->atu_base)) return PTR_ERR(pci->atu_base); @@ -2225,8 +2192,9 @@ static int tegra_pcie_dw_suspend_noirq(struct device *dev) PORT_LOGIC_MSI_CTRL_INT_0_EN); tegra_pcie_downstream_dev_to_D0(pcie); tegra_pcie_dw_pme_turnoff(pcie); + tegra_pcie_unconfig_controller(pcie); - return __deinit_controller(pcie); + return 0; } static int tegra_pcie_dw_resume_noirq(struct device *dev) @@ -2254,7 +2222,8 @@ static int tegra_pcie_dw_resume_noirq(struct device *dev) return 0; fail_host_init: - return __deinit_controller(pcie); + tegra_pcie_unconfig_controller(pcie); + return ret; } static int tegra_pcie_dw_resume_early(struct device *dev) @@ -2292,7 +2261,7 @@ static void tegra_pcie_dw_shutdown(struct platform_device *pdev) disable_irq(pcie->pci.pp.msi_irq); tegra_pcie_dw_pme_turnoff(pcie); - __deinit_controller(pcie); + tegra_pcie_unconfig_controller(pcie); } static const struct tegra_pcie_dw_of_data tegra_pcie_dw_rc_of_data = { |