[PATCH RFC v4 5/9] phy: qcom: qmp-pcie: Refactor pipe clk register and parse_dt helpers
From: Qiang Yu
Date: Tue May 19 2026 - 01:50:54 EST
Some QMP PCIe PHY hardware blocks can be split into multiple sub-PHYs
under a single DT node, each requiring its own pipe clock registration and
DT resource mapping. The current helpers are tightly coupled to a single
qmp_pcie instance, which prevents reuse across sub-PHY instances.
Refactor __phy_pipe_clk_register() as a generic helper and reduce
phy_pipe_clk_register() to a thin wrapper around it. Similarly, extract
qmp_pcie_parse_dt_common() from qmp_pcie_parse_dt() to hold the register-
mapping and pipe-clock setup that will be shared between sub-PHY instances,
with pipe clock names parameterised per instance.
This is a preparatory step before adding multi-PHY support. No functional
change for existing platforms.
Signed-off-by: Qiang Yu <qiang.yu@xxxxxxxxxxxxxxxx>
---
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 76 ++++++++++++++++++--------------
1 file changed, 44 insertions(+), 32 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 1dee4733d4f2..6332f15f78ca 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -5116,32 +5116,34 @@ static void phy_clk_release_provider(void *res)
* clk | +-------+ | +-----+
* +---------------+
*/
-static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
+static int __phy_pipe_clk_register(struct device *dev, struct device_node *np,
+ int clk_name_index, struct clk_fixed_rate *fixed)
{
- struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed;
struct clk_init_data init = { };
int ret;
- ret = of_property_read_string_index(np, "clock-output-names", 0, &init.name);
+ ret = of_property_read_string_index(np, "clock-output-names", clk_name_index,
+ &init.name);
if (ret) {
- dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np);
+ dev_err(dev, "%pOFn: No clock-output-names\n", np);
return ret;
}
init.ops = &clk_fixed_rate_ops;
- /*
- * Controllers using QMP PHY-s use 125MHz pipe clock interface
- * unless other frequency is specified in the PHY config.
- */
- if (qmp->cfg->pipe_clock_rate)
- fixed->fixed_rate = qmp->cfg->pipe_clock_rate;
- else
+ /* Default to 125MHz if caller did not pre-populate a rate. */
+ if (!fixed->fixed_rate)
fixed->fixed_rate = 125000000;
fixed->hw.init = &init;
- return devm_clk_hw_register(qmp->dev, &fixed->hw);
+ return devm_clk_hw_register(dev, &fixed->hw);
+}
+
+static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np)
+{
+ qmp->pipe_clk_fixed.fixed_rate = qmp->cfg->pipe_clock_rate;
+ return __phy_pipe_clk_register(qmp->dev, np, 0, &qmp->pipe_clk_fixed);
}
/*
@@ -5336,26 +5338,18 @@ static int qmp_pcie_get_4ln_config(struct qmp_pcie *qmp)
return 0;
}
-static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
+static int qmp_pcie_parse_dt_common(struct qmp_pcie *qmp, void __iomem *base,
+ const char *pipe_clk_name,
+ const char *pipediv2_clk_name)
{
- struct platform_device *pdev = to_platform_device(qmp->dev);
const struct qmp_phy_cfg *cfg = qmp->cfg;
const struct qmp_pcie_offsets *offs = cfg->offsets;
struct device *dev = qmp->dev;
- void __iomem *base;
int ret;
if (!offs)
return -EINVAL;
- ret = qmp_pcie_get_4ln_config(qmp);
- if (ret)
- return ret;
-
- base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
qmp->serdes = base + offs->serdes;
qmp->pcs = base + offs->pcs;
qmp->pcs_misc = base + offs->pcs_misc;
@@ -5368,12 +5362,6 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
qmp->rx2 = base + offs->rx2;
}
- if (qmp->cfg->lanes >= 4 && qmp->tcsr_4ln_config) {
- qmp->port_b = devm_platform_ioremap_resource(pdev, 1);
- if (IS_ERR(qmp->port_b))
- return PTR_ERR(qmp->port_b);
- }
-
qmp->txz = base + offs->txz;
qmp->rxz = base + offs->rxz;
@@ -5381,17 +5369,41 @@ static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
qmp->ln_shrd = base + offs->ln_shrd;
qmp->num_pipe_clks = 2;
- qmp->pipe_clks[0].id = "pipe";
- qmp->pipe_clks[1].id = "pipediv2";
+ qmp->pipe_clks[0].id = pipe_clk_name;
+ qmp->pipe_clks[1].id = pipediv2_clk_name;
ret = devm_clk_bulk_get(dev, 1, qmp->pipe_clks);
if (ret)
return ret;
- ret = devm_clk_bulk_get_optional(dev, qmp->num_pipe_clks - 1, qmp->pipe_clks + 1);
+ return devm_clk_bulk_get_optional(dev, qmp->num_pipe_clks - 1,
+ qmp->pipe_clks + 1);
+}
+
+static int qmp_pcie_parse_dt(struct qmp_pcie *qmp)
+{
+ struct platform_device *pdev = to_platform_device(qmp->dev);
+ void __iomem *base;
+ int ret;
+
+ ret = qmp_pcie_get_4ln_config(qmp);
+ if (ret)
+ return ret;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ ret = qmp_pcie_parse_dt_common(qmp, base, "pipe", "pipediv2");
if (ret)
return ret;
+ if (qmp->cfg->lanes >= 4 && qmp->tcsr_4ln_config) {
+ qmp->port_b = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(qmp->port_b))
+ return PTR_ERR(qmp->port_b);
+ }
+
return 0;
}
--
2.34.1