mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-06-11 10:42:04 +08:00
132 lines
4.5 KiB
Diff
132 lines
4.5 KiB
Diff
From 980136d1c2b95644b96df6c7ec00ca5d7c87f37f Mon Sep 17 00:00:00 2001
|
|
From: Krishna chaitanya chundru <quic_krichai@quicinc.com>
|
|
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/20240619-opp_support-v15-1-aa769a2173a3@quicinc.com
|
|
Signed-off-by: Krishna chaitanya chundru <quic_krichai@quicinc.com>
|
|
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
|
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
|
|
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
|
|
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
|
---
|
|
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)
|