From: Qiang Yu <qiang.yu@oss.qualcomm.com>
To: Vinod Koul <vkoul@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Philipp Zabel <p.zabel@pengutronix.de>,
Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konradybcio@kernel.org>
Cc: Qiang Yu <qiang.yu@oss.qualcomm.com>,
linux-arm-msm@vger.kernel.org, linux-phy@lists.infradead.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH RFC v4 4/9] phy: qcom: qmp-pcie: Support multiple nocsr resets
Date: Mon, 18 May 2026 22:47:15 -0700 [thread overview]
Message-ID: <20260518-link_mode_0519-v4-4-269cd73cc5d1@oss.qualcomm.com> (raw)
In-Reply-To: <20260518-link_mode_0519-v4-0-269cd73cc5d1@oss.qualcomm.com>
Refactor nocsr reset handling to support multiple nocsr resets required
for PHY configurations with bifurcated operation modes.
The Glymur SoC's 3rd PCIe instance supports 8-lane mode using two PHYs
in bifurcation, where each PHY requires its own nocsr reset to be
controlled simultaneously. The current implementation only supports a
single nocsr reset per PHY configuration.
Add num_nocsr and nocsr_list fields to struct qmp_phy_cfg to represent the
number and names of a group of nocsr reset names. Initialize these fields
for all PHYs that have nocsr resets, allowing the driver to correctly
acquire multiple nocsr resets during probe and control them as an array
by using reset_control_bulk APIs.
The refactoring maintains backward compatibility for existing single
nocsr reset configurations while enabling support for multi-PHY
scenarios like Glymur's 8-lane bifurcation mode.
Additionally, introduces x1e80100_qmp_gen3x2_pciephy_cfg as a separate
configuration from sm8550_qmp_gen3x2_pciephy_cfg since the x1e80100 Gen3x2
PHY requires nocsr reset support while the sm8550 Gen3x2 PHY does not.
Signed-off-by: Qiang Yu <qiang.yu@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 87 ++++++++++++++++++++++++++++----
1 file changed, 77 insertions(+), 10 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
index 832b5d93105b..1dee4733d4f2 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c
@@ -3281,6 +3281,11 @@ struct qmp_phy_cfg {
/* resets to be requested */
const char * const *reset_list;
int num_resets;
+
+ /* nocsr resets to be requested */
+ const char * const *nocsr_reset_list;
+ int num_nocsr_resets;
+
/* regulators to be requested */
const char * const *vreg_list;
int num_vregs;
@@ -3327,7 +3332,7 @@ struct qmp_pcie {
int num_pipe_clks;
struct reset_control_bulk_data *resets;
- struct reset_control *nocsr_reset;
+ struct reset_control_bulk_data *nocsr_reset;
struct regulator_bulk_data *vregs;
struct phy *phy;
@@ -3392,6 +3397,10 @@ static const char * const sdm845_pciephy_reset_l[] = {
"phy",
};
+static const char * const sm8550_pciephy_nocsr_reset_l[] = {
+ "phy_nocsr",
+};
+
static const struct qmp_pcie_offsets qmp_pcie_offsets_qhp = {
.serdes = 0,
.pcs = 0x1800,
@@ -4348,6 +4357,8 @@ static const struct qmp_phy_cfg sm8550_qmp_gen4x2_pciephy_cfg = {
},
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4380,6 +4391,8 @@ static const struct qmp_phy_cfg sm8650_qmp_gen4x2_pciephy_cfg = {
},
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = sm8550_qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4480,6 +4493,35 @@ static const struct qmp_phy_cfg sa8775p_qmp_gen4x4_pciephy_cfg = {
.phy_status = PHYSTATUS_4_20,
};
+static const struct qmp_phy_cfg x1e80100_qmp_gen3x2_pciephy_cfg = {
+ .lanes = 2,
+
+ .offsets = &qmp_pcie_offsets_v5,
+
+ .tbls = {
+ .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl,
+ .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl),
+ .tx = sm8550_qmp_gen3x2_pcie_tx_tbl,
+ .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl),
+ .rx = sm8550_qmp_gen3x2_pcie_rx_tbl,
+ .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl),
+ .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl,
+ .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl),
+ .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl,
+ .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl),
+ },
+ .reset_list = sdm845_pciephy_reset_l,
+ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
+ .vreg_list = qmp_phy_vreg_l,
+ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+ .regs = pciephy_v5_regs_layout,
+
+ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
+ .phy_status = PHYSTATUS,
+};
+
static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
.lanes = 2,
@@ -4502,6 +4544,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x2_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4535,6 +4579,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x4_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4566,6 +4612,8 @@ static const struct qmp_phy_cfg x1e80100_qmp_gen4x8_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4581,6 +4629,8 @@ static const struct qmp_phy_cfg qmp_v6_gen4x4_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v6_regs_layout,
@@ -4609,6 +4659,8 @@ static const struct qmp_phy_cfg qmp_v8_gen3x2_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
.regs = pciephy_v8_regs_layout,
@@ -4624,6 +4676,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen5x4_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
@@ -4640,6 +4694,8 @@ static const struct qmp_phy_cfg glymur_qmp_gen4x2_pciephy_cfg = {
.reset_list = sdm845_pciephy_reset_l,
.num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l),
+ .nocsr_reset_list = sm8550_pciephy_nocsr_reset_l,
+ .num_nocsr_resets = ARRAY_SIZE(sm8550_pciephy_nocsr_reset_l),
.vreg_list = qmp_phy_vreg_l,
.num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
@@ -4768,7 +4824,7 @@ static int qmp_pcie_init(struct phy *phy)
}
}
- ret = reset_control_assert(qmp->nocsr_reset);
+ ret = reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset assert failed\n");
goto err_assert_reset;
@@ -4805,7 +4861,7 @@ static int qmp_pcie_exit(struct phy *phy)
const struct qmp_phy_cfg *cfg = qmp->cfg;
if (qmp->nocsr_reset)
- reset_control_assert(qmp->nocsr_reset);
+ reset_control_bulk_assert(cfg->num_nocsr_resets, qmp->nocsr_reset);
else
reset_control_bulk_assert(cfg->num_resets, qmp->resets);
@@ -4849,7 +4905,7 @@ static int qmp_pcie_power_on(struct phy *phy)
if (ret)
return ret;
- ret = reset_control_deassert(qmp->nocsr_reset);
+ ret = reset_control_bulk_deassert(cfg->num_nocsr_resets, qmp->nocsr_reset);
if (ret) {
dev_err(qmp->dev, "no-csr reset deassert failed\n");
goto err_disable_pipe_clk;
@@ -4998,14 +5054,25 @@ static int qmp_pcie_reset_init(struct qmp_pcie *qmp)
for (i = 0; i < cfg->num_resets; i++)
qmp->resets[i].id = cfg->reset_list[i];
- ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets, qmp->resets);
+ ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_resets,
+ qmp->resets);
if (ret)
return dev_err_probe(dev, ret, "failed to get resets\n");
- qmp->nocsr_reset = devm_reset_control_get_optional_exclusive(dev, "phy_nocsr");
- if (IS_ERR(qmp->nocsr_reset))
- return dev_err_probe(dev, PTR_ERR(qmp->nocsr_reset),
- "failed to get no-csr reset\n");
+ if (!cfg->num_nocsr_resets)
+ return 0;
+ qmp->nocsr_reset = devm_kcalloc(dev, cfg->num_nocsr_resets,
+ sizeof(*qmp->nocsr_reset), GFP_KERNEL);
+ if (!qmp->nocsr_reset)
+ return -ENOMEM;
+
+ for (i = 0; i < cfg->num_nocsr_resets; i++)
+ qmp->nocsr_reset[i].id = cfg->nocsr_reset_list[i];
+
+ ret = devm_reset_control_bulk_get_exclusive(dev, cfg->num_nocsr_resets,
+ qmp->nocsr_reset);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get no-csr reset\n");
return 0;
}
@@ -5520,7 +5587,7 @@ static const struct of_device_id qmp_pcie_of_match_table[] = {
.data = &sm8750_qmp_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy",
- .data = &sm8550_qmp_gen3x2_pciephy_cfg,
+ .data = &x1e80100_qmp_gen3x2_pciephy_cfg,
}, {
.compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy",
.data = &x1e80100_qmp_gen4x2_pciephy_cfg,
--
2.34.1
next prev parent reply other threads:[~2026-05-19 5:47 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-19 5:47 [PATCH RFC v4 0/9] phy: qcom: qmp-pcie: Add link-mode based support for Glymur Gen5x8 PHY Qiang Yu
2026-05-19 5:47 ` [PATCH RFC v4 1/9] dt-bindings: phy: qcom,sc8280xp-qmp-pcie-phy: Add glymur-qmp-gen5x8-pcie-phy compatible Qiang Yu
2026-06-16 14:03 ` Konrad Dybcio
2026-06-29 5:14 ` Qiang Yu
2026-06-29 9:20 ` Konrad Dybcio
2026-05-19 5:47 ` [PATCH RFC v4 2/9] dt-bindings: phy: qcom-qmp: Add PHY selector and Glymur link-mode macros Qiang Yu
2026-06-16 14:07 ` Konrad Dybcio
2026-06-29 5:18 ` Qiang Yu
2026-06-29 9:21 ` Konrad Dybcio
2026-05-19 5:47 ` [PATCH RFC v4 3/9] phy: qcom: qmp-pcie: Add multiple power-domains support Qiang Yu
2026-05-19 5:47 ` Qiang Yu [this message]
2026-05-19 5:47 ` [PATCH RFC v4 5/9] phy: qcom: qmp-pcie: Refactor pipe clk register and parse_dt helpers Qiang Yu
2026-05-20 16:25 ` Dmitry Baryshkov
2026-05-22 10:57 ` Manivannan Sadhasivam
2026-05-28 13:15 ` Qiang Yu
2026-05-28 13:48 ` Dmitry Baryshkov
2026-05-29 7:02 ` Qiang Yu
2026-06-16 14:05 ` Konrad Dybcio
2026-06-29 5:56 ` Qiang Yu
2026-06-29 9:21 ` Konrad Dybcio
2026-05-19 5:47 ` [PATCH RFC v4 6/9] phy: qcom: qmp-pcie: Add clock and reset lists for secondary PHY selector Qiang Yu
2026-05-19 5:47 ` [PATCH RFC v4 7/9] phy: qcom: qmp-pcie: Add link-mode multi-PHY probe infrastructure Qiang Yu
2026-05-19 5:47 ` [PATCH RFC v4 8/9] phy: qcom: qmp-pcie: Add Glymur Gen5x8 PHY config and match data Qiang Yu
2026-05-19 5:47 ` [PATCH RFC v4 9/9] arm64: dts: qcom: glymur: Wire PCIe3a/3b to shared Gen5x8 PHY Qiang Yu
2026-06-17 11:19 ` Konrad Dybcio
2026-06-29 5:05 ` Qiang Yu
2026-06-29 9:20 ` Konrad Dybcio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260518-link_mode_0519-v4-4-269cd73cc5d1@oss.qualcomm.com \
--to=qiang.yu@oss.qualcomm.com \
--cc=andersson@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=konradybcio@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=neil.armstrong@linaro.org \
--cc=p.zabel@pengutronix.de \
--cc=robh@kernel.org \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox