summaryrefslogtreecommitdiff
path: root/drivers/pci/controller/dwc/pcie-qcom.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-03-25 13:02:05 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-03-25 13:02:05 -0700
commit148a650476955705482dd57e7ffcf105d8b65440 (patch)
tree8fa098f2b1e3e2d452eff8f2f050a7292ec3698b /drivers/pci/controller/dwc/pcie-qcom.c
parent636f64db07f33a18630248b4c57e182cd315b0da (diff)
parent611f841830aa5723ea67682628bd214cbc18df41 (diff)
Merge tag 'pci-v5.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull pci updates from Bjorn Helgaas: "Enumeration: - Move the VGA arbiter from drivers/gpu to drivers/pci because it's PCI-specific, not GPU-specific (Bjorn Helgaas) - Select the default VGA device consistently whether it's enumerated before or after VGA arbiter init, which fixes arches that enumerate PCI devices late (Huacai Chen) Resource management: - Support BAR sizes up to 8TB (Dongdong Liu) PCIe native device hotplug: - Fix "Command Completed" tracking to avoid spurious timouts when powering off empty slots (Liguang Zhang) - Quirk Qualcomm devices that don't implement Command Completed correctly, again to avoid spurious timeouts (Manivannan Sadhasivam) Peer-to-peer DMA: - Add Intel 3rd Gen Intel Xeon Scalable Processors to whitelist (Michael J. Ruhl) APM X-Gene PCIe controller driver: - Revert generic DT parsing changes that broke some machines in the field (Marc Zyngier) Freescale i.MX6 PCIe controller driver: - Allow controller probe to succeed even when no devices currently present to allow hot-add later (Fabio Estevam) - Enable power management on i.MX6QP (Richard Zhu) - Assert CLKREQ# on i.MX8MM so enumeration doesn't hang when no device is connected (Richard Zhu) Marvell Aardvark PCIe controller driver: - Fix MSI and MSI-X support (Marek Behún, Pali Rohár) - Add support for ERR and PME interrupts (Pali Rohár) Marvell MVEBU PCIe controller driver: - Add DT binding and support for "num-lanes" (Pali Rohár) - Add support for INTx interrupts (Pali Rohár) Microsoft Hyper-V host bridge driver: - Avoid unnecessary hypercalls when unmasking IRQs on ARM64 (Boqun Feng) Qualcomm PCIe controller driver: - Add SM8450 DT binding and driver support (Dmitry Baryshkov) Renesas R-Car PCIe controller driver: - Help the controller get to the L1 state since the hardware can't do it on its own (Marek Vasut) - Return PCI_ERROR_RESPONSE (~0) for reads that fail on PCIe (Marek Vasut) SiFive FU740 PCIe controller driver: - Drop redundant '-gpios' from DT GPIO lookup (Ben Dooks) - Force 2.5GT/s for initial device probe (Ben Dooks) Socionext UniPhier Pro5 controller driver: - Add NX1 DT binding and driver support (Kunihiko Hayashi) Synopsys DesignWare PCIe controller driver: - Restore MSI configuration so MSI works after resume (Jisheng Zhang)" * tag 'pci-v5.18-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (94 commits) x86/PCI: Add #includes to asm/pci_x86.h PCI: ibmphp: Remove unused assignments PCI: cpqphp: Remove unused assignments PCI: fu740: Remove unused assignments PCI: kirin: Remove unused assignments PCI: Remove unused assignments PCI: Declare pci_filp_private only when HAVE_PCI_MMAP PCI: Avoid broken MSI on SB600 USB devices PCI: fu740: Force 2.5GT/s for initial device probe PCI: xgene: Revert "PCI: xgene: Fix IB window setup" PCI: xgene: Revert "PCI: xgene: Use inbound resources for setup" PCI: imx6: Assert i.MX8MM CLKREQ# even if no device present PCI: imx6: Invoke the PHY exit function after PHY power off PCI: rcar: Use PCI_SET_ERROR_RESPONSE after read which triggered an exception PCI: rcar: Finish transition to L1 state in rcar_pcie_config_access() PCI: dwc: Restore MSI Receiver mask during resume PCI: fu740: Drop redundant '-gpios' from DT GPIO lookup PCI/VGA: Replace full MIT license text with SPDX identifier PCI/VGA: Use unsigned format string to print lock counts PCI/VGA: Log bridge control messages when adding devices ...
Diffstat (limited to 'drivers/pci/controller/dwc/pcie-qcom.c')
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c95
1 files changed, 63 insertions, 32 deletions
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index c19cd506ed3f..6ab90891801d 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -161,7 +161,7 @@ struct qcom_pcie_resources_2_3_3 {
/* 6 clocks typically, 7 for sm8250 */
struct qcom_pcie_resources_2_7_0 {
- struct clk_bulk_data clks[7];
+ struct clk_bulk_data clks[9];
int num_clks;
struct regulator_bulk_data supplies[2];
struct reset_control *pci_reset;
@@ -195,6 +195,10 @@ struct qcom_pcie_ops {
struct qcom_pcie_cfg {
const struct qcom_pcie_ops *ops;
unsigned int pipe_clk_need_muxing:1;
+ unsigned int has_tbu_clk:1;
+ unsigned int has_ddrss_sf_tbu_clk:1;
+ unsigned int has_aggre0_clk:1;
+ unsigned int has_aggre1_clk:1;
};
struct qcom_pcie {
@@ -204,8 +208,7 @@ struct qcom_pcie {
union qcom_pcie_resources res;
struct phy *phy;
struct gpio_desc *reset;
- const struct qcom_pcie_ops *ops;
- unsigned int pipe_clk_need_muxing:1;
+ const struct qcom_pcie_cfg *cfg;
};
#define to_qcom_pcie(x) dev_get_drvdata((x)->dev)
@@ -229,8 +232,8 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
struct qcom_pcie *pcie = to_qcom_pcie(pci);
/* Enable Link Training state machine */
- if (pcie->ops->ltssm_enable)
- pcie->ops->ltssm_enable(pcie);
+ if (pcie->cfg->ops->ltssm_enable)
+ pcie->cfg->ops->ltssm_enable(pcie);
return 0;
}
@@ -1146,6 +1149,7 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
+ unsigned int idx;
int ret;
res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
@@ -1159,24 +1163,28 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie)
if (ret)
return ret;
- res->clks[0].id = "aux";
- res->clks[1].id = "cfg";
- res->clks[2].id = "bus_master";
- res->clks[3].id = "bus_slave";
- res->clks[4].id = "slave_q2a";
- res->clks[5].id = "tbu";
- if (of_device_is_compatible(dev->of_node, "qcom,pcie-sm8250")) {
- res->clks[6].id = "ddrss_sf_tbu";
- res->num_clks = 7;
- } else {
- res->num_clks = 6;
- }
+ idx = 0;
+ res->clks[idx++].id = "aux";
+ res->clks[idx++].id = "cfg";
+ res->clks[idx++].id = "bus_master";
+ res->clks[idx++].id = "bus_slave";
+ res->clks[idx++].id = "slave_q2a";
+ if (pcie->cfg->has_tbu_clk)
+ res->clks[idx++].id = "tbu";
+ if (pcie->cfg->has_ddrss_sf_tbu_clk)
+ res->clks[idx++].id = "ddrss_sf_tbu";
+ if (pcie->cfg->has_aggre0_clk)
+ res->clks[idx++].id = "aggre0";
+ if (pcie->cfg->has_aggre1_clk)
+ res->clks[idx++].id = "aggre1";
+
+ res->num_clks = idx;
ret = devm_clk_bulk_get(dev, res->num_clks, res->clks);
if (ret < 0)
return ret;
- if (pcie->pipe_clk_need_muxing) {
+ if (pcie->cfg->pipe_clk_need_muxing) {
res->pipe_clk_src = devm_clk_get(dev, "pipe_mux");
if (IS_ERR(res->pipe_clk_src))
return PTR_ERR(res->pipe_clk_src);
@@ -1209,7 +1217,7 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
}
/* Set TCXO as clock source for pcie_pipe_clk_src */
- if (pcie->pipe_clk_need_muxing)
+ if (pcie->cfg->pipe_clk_need_muxing)
clk_set_parent(res->pipe_clk_src, res->ref_clk_src);
ret = clk_bulk_prepare_enable(res->num_clks, res->clks);
@@ -1236,6 +1244,9 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
goto err_disable_clocks;
}
+ /* Wait for reset to complete, required on SM8450 */
+ usleep_range(1000, 1500);
+
/* configure PCIe to RC mode */
writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE);
@@ -1284,7 +1295,7 @@ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0;
/* Set pipe clock as clock source for pcie_pipe_clk_src */
- if (pcie->pipe_clk_need_muxing)
+ if (pcie->cfg->pipe_clk_need_muxing)
clk_set_parent(res->pipe_clk_src, res->phy_pipe_clk);
return clk_prepare_enable(res->pipe_clk);
@@ -1384,7 +1395,7 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
qcom_ep_reset_assert(pcie);
- ret = pcie->ops->init(pcie);
+ ret = pcie->cfg->ops->init(pcie);
if (ret)
return ret;
@@ -1392,16 +1403,16 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
if (ret)
goto err_deinit;
- if (pcie->ops->post_init) {
- ret = pcie->ops->post_init(pcie);
+ if (pcie->cfg->ops->post_init) {
+ ret = pcie->cfg->ops->post_init(pcie);
if (ret)
goto err_disable_phy;
}
qcom_ep_reset_deassert(pcie);
- if (pcie->ops->config_sid) {
- ret = pcie->ops->config_sid(pcie);
+ if (pcie->cfg->ops->config_sid) {
+ ret = pcie->cfg->ops->config_sid(pcie);
if (ret)
goto err;
}
@@ -1410,12 +1421,12 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
err:
qcom_ep_reset_assert(pcie);
- if (pcie->ops->post_deinit)
- pcie->ops->post_deinit(pcie);
+ if (pcie->cfg->ops->post_deinit)
+ pcie->cfg->ops->post_deinit(pcie);
err_disable_phy:
phy_power_off(pcie->phy);
err_deinit:
- pcie->ops->deinit(pcie);
+ pcie->cfg->ops->deinit(pcie);
return ret;
}
@@ -1509,14 +1520,33 @@ static const struct qcom_pcie_cfg ipq4019_cfg = {
static const struct qcom_pcie_cfg sdm845_cfg = {
.ops = &ops_2_7_0,
+ .has_tbu_clk = true,
};
static const struct qcom_pcie_cfg sm8250_cfg = {
.ops = &ops_1_9_0,
+ .has_tbu_clk = true,
+ .has_ddrss_sf_tbu_clk = true,
+};
+
+static const struct qcom_pcie_cfg sm8450_pcie0_cfg = {
+ .ops = &ops_1_9_0,
+ .has_ddrss_sf_tbu_clk = true,
+ .pipe_clk_need_muxing = true,
+ .has_aggre0_clk = true,
+ .has_aggre1_clk = true,
+};
+
+static const struct qcom_pcie_cfg sm8450_pcie1_cfg = {
+ .ops = &ops_1_9_0,
+ .has_ddrss_sf_tbu_clk = true,
+ .pipe_clk_need_muxing = true,
+ .has_aggre1_clk = true,
};
static const struct qcom_pcie_cfg sc7280_cfg = {
.ops = &ops_1_9_0,
+ .has_tbu_clk = true,
.pipe_clk_need_muxing = true,
};
@@ -1559,8 +1589,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
pcie->pci = pci;
- pcie->ops = pcie_cfg->ops;
- pcie->pipe_clk_need_muxing = pcie_cfg->pipe_clk_need_muxing;
+ pcie->cfg = pcie_cfg;
pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_HIGH);
if (IS_ERR(pcie->reset)) {
@@ -1586,7 +1615,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
goto err_pm_runtime_put;
}
- ret = pcie->ops->get_resources(pcie);
+ ret = pcie->cfg->ops->get_resources(pcie);
if (ret)
goto err_pm_runtime_put;
@@ -1628,13 +1657,15 @@ static const struct of_device_id qcom_pcie_match[] = {
{ .compatible = "qcom,pcie-sdm845", .data = &sdm845_cfg },
{ .compatible = "qcom,pcie-sm8250", .data = &sm8250_cfg },
{ .compatible = "qcom,pcie-sc8180x", .data = &sm8250_cfg },
+ { .compatible = "qcom,pcie-sm8450-pcie0", .data = &sm8450_pcie0_cfg },
+ { .compatible = "qcom,pcie-sm8450-pcie1", .data = &sm8450_pcie1_cfg },
{ .compatible = "qcom,pcie-sc7280", .data = &sc7280_cfg },
{ }
};
static void qcom_fixup_class(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+ dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL;
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class);