[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250722-add-displayport-support-for-qcs615-platform-v2-5-42b4037171f8@oss.qualcomm.com>
Date: Tue, 22 Jul 2025 15:22:06 +0800
From: Xiangxu Yin <xiangxu.yin@....qualcomm.com>
To: Rob Clark <robin.clark@....qualcomm.com>,
Dmitry Baryshkov <lumag@...nel.org>,
Abhinav Kumar <abhinav.kumar@...ux.dev>,
Jessica Zhang <jessica.zhang@....qualcomm.com>,
Sean Paul <sean@...rly.run>,
Marijn Suijten <marijn.suijten@...ainline.org>,
Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>,
Maxime Ripard <mripard@...nel.org>,
Thomas Zimmermann <tzimmermann@...e.de>,
David Airlie <airlied@...il.com>, Simona Vetter <simona@...ll.ch>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
Kuogee Hsieh <quic_khsieh@...cinc.com>, Vinod Koul <vkoul@...nel.org>,
Kishon Vijay Abraham I <kishon@...nel.org>
Cc: linux-arm-msm@...r.kernel.org, dri-devel@...ts.freedesktop.org,
freedreno@...ts.freedesktop.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-phy@...ts.infradead.org,
dmitry.baryshkov@....qualcomm.com, konrad.dybcio@....qualcomm.com,
fange.zhang@....qualcomm.com, quic_lliu6@...cinc.com,
quic_yongmou@...cinc.com, Xiangxu Yin <xiangxu.yin@....qualcomm.com>
Subject: [PATCH v2 05/13] phy: qcom: qmp-usbc: Introduce PHY type enum for
USB/DP support
Add `qmp_phy_usbc_type` enum and a `type` field in `qmp_usbc` to
distinguish between USB and DP PHYs.
- Introduce `qmp_phy_usbc_type` enum with USB and DP types.
- Update device match table to associate compatible strings with type
and config.
- Wrap existing USB-specific logic with type checks to prepare for
future DP support.
No functional changes and serves as a preparatory step for adding DP PHY
support.
Signed-off-by: Xiangxu Yin <xiangxu.yin@....qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-usbc.c | 195 ++++++++++++++++++++-----------
1 file changed, 126 insertions(+), 69 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
index 078752dbc66f9b9844c003e7755fff6466ea1d6c..647e2f54b744bf099ea667e672c606dd7aef3bcf 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
@@ -286,6 +286,16 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
};
+enum qmp_phy_usbc_type {
+ QMP_PHY_USBC_USB,
+ QMP_PHY_USBC_DP,
+};
+
+struct qmp_phy_cfg {
+ int type;
+ const void *cfg;
+};
+
struct qmp_usbc_usb_offsets {
u16 serdes;
u16 pcs;
@@ -454,23 +464,40 @@ static const struct qmp_phy_usb_cfg sdm660_usb3phy_cfg = {
.regs = qmp_v3_usb3phy_regs_layout_qcm2290,
};
+static const struct qmp_phy_cfg msm8998_phy_usb3_cfg = {
+ .type = QMP_PHY_USBC_USB,
+ .cfg = &msm8998_usb3phy_cfg,
+};
+
+static const struct qmp_phy_cfg qcm2290_phy_usb3_cfg = {
+ .type = QMP_PHY_USBC_USB,
+ .cfg = &qcm2290_usb3phy_cfg,
+};
+
+static const struct qmp_phy_cfg sdm660_phy_usb3_cfg = {
+ .type = QMP_PHY_USBC_USB,
+ .cfg = &sdm660_usb3phy_cfg,
+};
+
#define to_usb_cfg(x) ((struct qmp_phy_usb_cfg *)((x)->cfg))
#define to_usb_layout(x) ((struct qmp_phy_usb_layout *)((x)->layout))
static int qmp_usbc_generic_init(struct phy *phy)
{
struct qmp_usbc *qmp = phy_get_drvdata(phy);
- struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
- struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
int num_vregs;
- unsigned int reg_pwr_dn;
u32 val;
int ret;
+ unsigned int reg_pwr_dn;
- num_vregs = cfg->num_vregs;
- reg_pwr_dn = cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL];
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
- ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
+ num_vregs = cfg->num_vregs;
+ reg_pwr_dn = cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL];
+ }
+
+ ret = regulator_bulk_enable(num_vregs, qmp->vregs);
if (ret) {
dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
return ret;
@@ -497,8 +524,12 @@ static int qmp_usbc_generic_init(struct phy *phy)
if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
val |= SW_PORTSELECT_VAL;
- qphy_setbits(layout->pcs, reg_pwr_dn, SW_PWRDN);
- writel(val, layout->pcs_misc);
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
+
+ qphy_setbits(layout->pcs, reg_pwr_dn, SW_PWRDN);
+ writel(val, layout->pcs_misc);
+ }
return 0;
@@ -513,13 +544,18 @@ static int qmp_usbc_generic_init(struct phy *phy)
static int qmp_usbc_generic_exit(struct phy *phy)
{
struct qmp_usbc *qmp = phy_get_drvdata(phy);
- struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
+ int num_vregs;
reset_control_bulk_assert(qmp->num_resets, qmp->resets);
clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
- regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
+
+ num_vregs = cfg->num_vregs;
+ }
+ regulator_bulk_disable(num_vregs, qmp->vregs);
return 0;
}
@@ -650,7 +686,7 @@ static const struct phy_ops qmp_usbc_usb_phy_ops = {
static void qmp_usbc_enable_autonomous_mode(struct qmp_usbc *qmp)
{
- const struct qmp_phy_usb_cfg *cfg = qmp->cfg;
+ const struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
void __iomem *pcs = layout->pcs;
u32 intr_mask;
@@ -698,18 +734,20 @@ static void qmp_usbc_disable_autonomous_mode(struct qmp_usbc *qmp)
static int __maybe_unused qmp_usbc_runtime_suspend(struct device *dev)
{
struct qmp_usbc *qmp = dev_get_drvdata(dev);
- struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
-
- dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", layout->mode);
if (!qmp->phy->init_count) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
- qmp_usbc_enable_autonomous_mode(qmp);
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
+
+ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", layout->mode);
+ qmp_usbc_enable_autonomous_mode(qmp);
+ clk_disable_unprepare(layout->pipe_clk);
+ }
- clk_disable_unprepare(layout->pipe_clk);
clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
return 0;
@@ -718,11 +756,8 @@ static int __maybe_unused qmp_usbc_runtime_suspend(struct device *dev)
static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev)
{
struct qmp_usbc *qmp = dev_get_drvdata(dev);
- struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
int ret = 0;
- dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", layout->mode);
-
if (!qmp->phy->init_count) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
@@ -732,14 +767,19 @@ static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev)
if (ret)
return ret;
- ret = clk_prepare_enable(layout->pipe_clk);
- if (ret) {
- dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
- clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
- return ret;
- }
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_layout *layout = to_usb_layout(qmp);
+
+ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", layout->mode);
+ ret = clk_prepare_enable(layout->pipe_clk);
+ if (ret) {
+ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
+ return ret;
+ }
- qmp_usbc_disable_autonomous_mode(qmp);
+ qmp_usbc_disable_autonomous_mode(qmp);
+ }
return 0;
}
@@ -751,20 +791,28 @@ static const struct dev_pm_ops qmp_usbc_pm_ops = {
static int qmp_usbc_vreg_init(struct qmp_usbc *qmp)
{
- struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
struct device *dev = qmp->dev;
- int i;
+ int ret, i;
- int num = cfg->num_vregs;
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ struct qmp_phy_usb_cfg *cfg = to_usb_cfg(qmp);
+ int num = cfg->num_vregs;
- qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
- if (!qmp->vregs)
- return -ENOMEM;
+ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
+ if (!qmp->vregs)
+ return -ENOMEM;
- for (i = 0; i < num; i++)
- qmp->vregs[i].supply = cfg->vreg_list[i];
+ for (i = 0; i < num; i++)
+ qmp->vregs[i].supply = cfg->vreg_list[i];
- return devm_regulator_bulk_get(dev, num, qmp->vregs);
+ ret = devm_regulator_bulk_get(dev, num, qmp->vregs);
+ if (ret) {
+ dev_err(dev, "failed at devm_regulator_bulk_get\n");
+ return ret;
+ }
+ }
+
+ return 0;
}
static int qmp_usbc_reset_init(struct qmp_usbc *qmp,
@@ -1061,6 +1109,7 @@ static int qmp_usbc_probe(struct platform_device *pdev)
struct phy_provider *phy_provider;
struct device_node *np;
struct qmp_usbc *qmp;
+ const struct qmp_phy_cfg *data_cfg;
int ret;
qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL);
@@ -1072,39 +1121,45 @@ static int qmp_usbc_probe(struct platform_device *pdev)
qmp->orientation = TYPEC_ORIENTATION_NORMAL;
- qmp->cfg = of_device_get_match_data(dev);
- if (!qmp->cfg)
+ data_cfg = of_device_get_match_data(dev);
+ if (!data_cfg)
return -EINVAL;
mutex_init(&qmp->phy_mutex);
+ qmp->type = data_cfg->type;
+ qmp->cfg = data_cfg->cfg;
+
ret = qmp_usbc_vreg_init(qmp);
if (ret)
return ret;
- qmp->layout = devm_kzalloc(dev, sizeof(struct qmp_phy_usb_layout), GFP_KERNEL);
- if (!qmp->layout)
- return -ENOMEM;
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ qmp->layout = devm_kzalloc(dev, sizeof(struct qmp_phy_usb_layout), GFP_KERNEL);
+ if (!qmp->layout)
+ return -ENOMEM;
+
+ ret = qmp_usbc_parse_vls_clamp(qmp);
+ if (ret)
+ return ret;
+
+ /* Check for legacy binding with child node. */
+ np = of_get_child_by_name(dev->of_node, "phy");
+ if (np) {
+ ret = qmp_usbc_parse_usb_dt_legacy(qmp, np);
+ } else {
+ np = of_node_get(dev->of_node);
+ ret = qmp_usbc_parse_usb_dt(qmp);
+ }
+
+ if (ret)
+ goto err_node_put;
+ }
ret = qmp_usbc_typec_switch_register(qmp);
if (ret)
return ret;
- ret = qmp_usbc_parse_vls_clamp(qmp);
- if (ret)
- return ret;
-
- /* Check for legacy binding with child node. */
- np = of_get_child_by_name(dev->of_node, "phy");
- if (np) {
- ret = qmp_usbc_parse_usb_dt_legacy(qmp, np);
- } else {
- np = of_node_get(dev->of_node);
- ret = qmp_usbc_parse_usb_dt(qmp);
- }
- if (ret)
- goto err_node_put;
-
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
@@ -1115,15 +1170,17 @@ static int qmp_usbc_probe(struct platform_device *pdev)
*/
pm_runtime_forbid(dev);
- ret = phy_pipe_clk_register(qmp, np);
- if (ret)
- goto err_node_put;
-
- qmp->phy = devm_phy_create(dev, np, &qmp_usbc_usb_phy_ops);
- if (IS_ERR(qmp->phy)) {
- ret = PTR_ERR(qmp->phy);
- dev_err(dev, "failed to create PHY: %d\n", ret);
- goto err_node_put;
+ if (qmp->type == QMP_PHY_USBC_USB) {
+ ret = phy_pipe_clk_register(qmp, np);
+ if (ret)
+ goto err_node_put;
+
+ qmp->phy = devm_phy_create(dev, np, &qmp_usbc_usb_phy_ops);
+ if (IS_ERR(qmp->phy)) {
+ ret = PTR_ERR(qmp->phy);
+ dev_err(dev, "failed to create PHY: %d\n", ret);
+ goto err_node_put;
+ }
}
phy_set_drvdata(qmp->phy, qmp);
@@ -1142,19 +1199,19 @@ static int qmp_usbc_probe(struct platform_device *pdev)
static const struct of_device_id qmp_usbc_of_match_table[] = {
{
.compatible = "qcom,msm8998-qmp-usb3-phy",
- .data = &msm8998_usb3phy_cfg,
+ .data = &msm8998_phy_usb3_cfg,
}, {
.compatible = "qcom,qcm2290-qmp-usb3-phy",
- .data = &qcm2290_usb3phy_cfg,
+ .data = &qcm2290_phy_usb3_cfg,
}, {
.compatible = "qcom,qcs615-qmp-usb3-phy",
- .data = &qcm2290_usb3phy_cfg,
+ .data = &qcm2290_phy_usb3_cfg,
}, {
.compatible = "qcom,sdm660-qmp-usb3-phy",
- .data = &sdm660_usb3phy_cfg,
+ .data = &sdm660_phy_usb3_cfg,
}, {
.compatible = "qcom,sm6115-qmp-usb3-phy",
- .data = &qcm2290_usb3phy_cfg,
+ .data = &qcm2290_phy_usb3_cfg,
},
{ },
};
--
2.34.1
Powered by blists - more mailing lists