|
|
@@ -0,0 +1,131 @@
|
|
|
+From 980136d1c2b95644b96df6c7ec00ca5d7c87f37f Mon Sep 17 00:00:00 2001
|
|
|
+From: Krishna chaitanya chundru <[email protected]>
|
|
|
+Date: Wed, 19 Jun 2024 20:41:10 +0530
|
|
|
+Subject: [PATCH] PCI: qcom: Add ICC bandwidth vote for CPU to PCIe path
|
|
|
+MIME-Version: 1.0
|
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
|
+Content-Transfer-Encoding: 8bit
|
|
|
+
|
|
|
+To access the host controller registers of the host controller and the
|
|
|
+endpoint BAR/config space, the CPU-PCIe ICC (interconnect) path should
|
|
|
+be voted otherwise it may lead to NoC (Network on chip) timeout.
|
|
|
+We are surviving because of other driver voting for this path.
|
|
|
+
|
|
|
+As there is less access on this path compared to PCIe to mem path
|
|
|
+add minimum vote i.e 1KBps bandwidth always which is sufficient enough
|
|
|
+to keep the path active and is recommended by HW team.
|
|
|
+
|
|
|
+During S2RAM (Suspend-to-RAM), the DBI access can happen very late (while
|
|
|
+disabling the boot CPU). So do not disable the CPU-PCIe interconnect path
|
|
|
+during S2RAM as that may lead to NoC error.
|
|
|
+
|
|
|
+Link: https://lore.kernel.org/linux-pci/[email protected]
|
|
|
+Signed-off-by: Krishna chaitanya chundru <[email protected]>
|
|
|
+Signed-off-by: Krzysztof Wilczyński <[email protected]>
|
|
|
+Signed-off-by: Bjorn Helgaas <[email protected]>
|
|
|
+Reviewed-by: Bryan O'Donoghue <[email protected]>
|
|
|
+Reviewed-by: Manivannan Sadhasivam <[email protected]>
|
|
|
+---
|
|
|
+ drivers/pci/controller/dwc/pcie-qcom.c | 45 +++++++++++++++++++++++++++++++---
|
|
|
+ 1 file changed, 41 insertions(+), 4 deletions(-)
|
|
|
+
|
|
|
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
|
|
|
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
|
|
|
+@@ -245,6 +245,7 @@ struct qcom_pcie {
|
|
|
+ struct phy *phy;
|
|
|
+ struct gpio_desc *reset;
|
|
|
+ struct icc_path *icc_mem;
|
|
|
++ struct icc_path *icc_cpu;
|
|
|
+ const struct qcom_pcie_cfg *cfg;
|
|
|
+ struct dentry *debugfs;
|
|
|
+ bool suspended;
|
|
|
+@@ -1357,6 +1358,9 @@ static int qcom_pcie_icc_init(struct qco
|
|
|
+ if (IS_ERR(pcie->icc_mem))
|
|
|
+ return PTR_ERR(pcie->icc_mem);
|
|
|
+
|
|
|
++ pcie->icc_cpu = devm_of_icc_get(pci->dev, "cpu-pcie");
|
|
|
++ if (IS_ERR(pcie->icc_cpu))
|
|
|
++ return PTR_ERR(pcie->icc_cpu);
|
|
|
+ /*
|
|
|
+ * Some Qualcomm platforms require interconnect bandwidth constraints
|
|
|
+ * to be set before enabling interconnect clocks.
|
|
|
+@@ -1366,11 +1370,25 @@ static int qcom_pcie_icc_init(struct qco
|
|
|
+ */
|
|
|
+ ret = icc_set_bw(pcie->icc_mem, 0, MBps_to_icc(250));
|
|
|
+ if (ret) {
|
|
|
+- dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
|
|
|
++ dev_err(pci->dev, "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n",
|
|
|
+ ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
++ /*
|
|
|
++ * Since the CPU-PCIe path is only used for activities like register
|
|
|
++ * access of the host controller and endpoint Config/BAR space access,
|
|
|
++ * HW team has recommended to use a minimal bandwidth of 1KBps just to
|
|
|
++ * keep the path active.
|
|
|
++ */
|
|
|
++ ret = icc_set_bw(pcie->icc_cpu, 0, kBps_to_icc(1));
|
|
|
++ if (ret) {
|
|
|
++ dev_err(pci->dev, "Failed to set bandwidth for CPU-PCIe interconnect path: %d\n",
|
|
|
++ ret);
|
|
|
++ icc_set_bw(pcie->icc_mem, 0, 0);
|
|
|
++ return ret;
|
|
|
++ }
|
|
|
++
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -1411,7 +1429,7 @@ static void qcom_pcie_icc_update(struct
|
|
|
+
|
|
|
+ ret = icc_set_bw(pcie->icc_mem, 0, width * bw);
|
|
|
+ if (ret) {
|
|
|
+- dev_err(pci->dev, "failed to set interconnect bandwidth: %d\n",
|
|
|
++ dev_err(pci->dev, "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n",
|
|
|
+ ret);
|
|
|
+ }
|
|
|
+ }
|
|
|
+@@ -1573,7 +1591,7 @@ static int qcom_pcie_suspend_noirq(struc
|
|
|
+ */
|
|
|
+ ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1));
|
|
|
+ if (ret) {
|
|
|
+- dev_err(dev, "Failed to set interconnect bandwidth: %d\n", ret);
|
|
|
++ dev_err(dev, "Failed to set bandwidth for PCIe-MEM interconnect path: %d\n", ret);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -1597,7 +1615,18 @@ static int qcom_pcie_suspend_noirq(struc
|
|
|
+ pcie->suspended = true;
|
|
|
+ }
|
|
|
+
|
|
|
+- return 0;
|
|
|
++ /*
|
|
|
++ * Only disable CPU-PCIe interconnect path if the suspend is non-S2RAM.
|
|
|
++ * Because on some platforms, DBI access can happen very late during the
|
|
|
++ * S2RAM and a non-active CPU-PCIe interconnect path may lead to NoC
|
|
|
++ * error.
|
|
|
++ */
|
|
|
++ if (pm_suspend_target_state != PM_SUSPEND_MEM) {
|
|
|
++ ret = icc_disable(pcie->icc_cpu);
|
|
|
++ if (ret)
|
|
|
++ dev_err(dev, "Failed to disable CPU-PCIe interconnect path: %d\n", ret);
|
|
|
++ }
|
|
|
++ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ static int qcom_pcie_resume_noirq(struct device *dev)
|
|
|
+@@ -1605,6 +1634,14 @@ static int qcom_pcie_resume_noirq(struct
|
|
|
+ struct qcom_pcie *pcie = dev_get_drvdata(dev);
|
|
|
+ int ret;
|
|
|
+
|
|
|
++ if (pm_suspend_target_state != PM_SUSPEND_MEM) {
|
|
|
++ ret = icc_enable(pcie->icc_cpu);
|
|
|
++ if (ret) {
|
|
|
++ dev_err(dev, "Failed to enable CPU-PCIe interconnect path: %d\n", ret);
|
|
|
++ return ret;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
+ if (pcie->suspended) {
|
|
|
+ ret = qcom_pcie_host_init(&pcie->pci->pp);
|
|
|
+ if (ret)
|