summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>2025-10-13 16:23:32 +0530
committerBjorn Helgaas <bhelgaas@google.com>2025-10-31 16:20:46 -0500
commit50433f6eeaed2117d5eee4a3dac4a3869a9c32ea (patch)
treedb534d2dab8e5b491ac796d9ae18b01e554a7a32
parent3a8660878839faadb4f1a6dd72c3179c1df56787 (diff)
PCI: qcom: Use frequency and level based OPP lookup
PCIe link configurations such as 8GT/s x2 and 16GT/s x1 may operate at the same frequency, but differ in other characteristics like RPMh votes. But the existing OPP selection which is solely based on frequency (the 'opp-hz' DT property) cannot distinguish between such cases. Hence, use the newly introduced dev_pm_opp_find_key_exact() API to match both frequency and level (the 'opp-level' property) when selecting an OPP, here level indicates PCIe data rate. To support older device trees where opp-level is not defined, check if opp-level is present or not using dev_pm_opp_find_level_exact(). If not present fallback to frequency only match. Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> [mani: zero initialize dev_pm_opp_key struct] Signed-off-by: Manivannan Sadhasivam <mani@kernel.org> [bhelgaas: add 'opp-hz' and 'opp-level' in commit log] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20251013-opp_pcie-v5-5-eb64db2b4bd3@oss.qualcomm.com
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index 805edbbfe7eb..5677416c0144 100644
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1565,6 +1565,7 @@ static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie)
{
u32 offset, status, width, speed;
struct dw_pcie *pci = pcie->pci;
+ struct dev_pm_opp_key key = {};
unsigned long freq_kbps;
struct dev_pm_opp *opp;
int ret, freq_mbps;
@@ -1592,8 +1593,20 @@ static void qcom_pcie_icc_opp_update(struct qcom_pcie *pcie)
return;
freq_kbps = freq_mbps * KILO;
- opp = dev_pm_opp_find_freq_exact(pci->dev, freq_kbps * width,
- true);
+ opp = dev_pm_opp_find_level_exact(pci->dev, speed);
+ if (IS_ERR(opp)) {
+ /* opp-level is not defined use only frequency */
+ opp = dev_pm_opp_find_freq_exact(pci->dev, freq_kbps * width,
+ true);
+ } else {
+ /* put opp-level OPP */
+ dev_pm_opp_put(opp);
+
+ key.freq = freq_kbps * width;
+ key.level = speed;
+ key.bw = 0;
+ opp = dev_pm_opp_find_key_exact(pci->dev, &key, true);
+ }
if (!IS_ERR(opp)) {
ret = dev_pm_opp_set_opp(pci->dev, opp);
if (ret)