[PATCH 06/12] phy: phy-mtk-dp: Support set_lanes in configure and properly cleanup
AngeloGioacchino Del Regno
angelogioacchino.delregno at collabora.com
Wed Jul 1 05:20:02 PDT 2026
Add support for enabling a specifically requested number of lanes
in the .configure() callback and disable all lanes in power off
and reset callbacks for proper hardware cleanup.
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
---
drivers/phy/mediatek/phy-mtk-dp.c | 49 ++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
index 586e72795633..a2cd22b9da06 100644
--- a/drivers/phy/mediatek/phy-mtk-dp.c
+++ b/drivers/phy/mediatek/phy-mtk-dp.c
@@ -45,6 +45,9 @@
#define PHYD_DIG_XTP_GLB_CKDET_EN BIT(1)
#define PHYD_DIG_DPAUX_RX_DEGLITCH_EN BIT(2)
+/* DP_PHYD_TX_CTL_0 */
+#define PHYD_TX_LN_EN GENMASK(7, 4)
+
#define XTP_LN_TX_LCTXC0_SW0_PRE0_DEFAULT BIT(4)
#define XTP_LN_TX_LCTXC0_SW0_PRE1_DEFAULT (BIT(10) | BIT(12))
#define XTP_LN_TX_LCTXC0_SW0_PRE2_DEFAULT GENMASK(20, 19)
@@ -108,6 +111,7 @@ enum mtk_dp_phyd_dig_glb_regidx {
DP_PHYD_SW_RST,
DP_PHYD_BIT_RATE,
DP_PHYD_AUX_RX_CTL,
+ DP_PHYD_TX_CTL_0,
DP_PHYD_GLOBAL_MAX
};
@@ -126,6 +130,7 @@ static const u8 mt8195_phy_dig_glb_regs[DP_PHYD_GLOBAL_MAX] = {
[DP_PHYD_SW_RST] = 0x38,
[DP_PHYD_BIT_RATE] = 0x3c,
[DP_PHYD_AUX_RX_CTL] = 0x40,
+ [DP_PHYD_TX_CTL_0] = 0x44,
};
/**
@@ -192,6 +197,7 @@ static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata;
u32 val;
+ int i;
if (opts->dp.set_rate) {
const u32 reg_bit_rate = pdata->regs_dig_glb[DP_PHYD_BIT_RATE];
@@ -223,7 +229,7 @@ static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts)
val = 0;
for (i = 0; i < opts->dp.lanes; i++)
- val |= FIELD_PREP(PHYD_TX_LN_EN, i);
+ val |= FIELD_PREP(PHYD_TX_LN_EN, BIT(i));
regmap_update_bits(dp_phy->regmap, pdata->off_dig_glb + reg_dig_tx_ctl,
PHYD_TX_LN_EN, val);
@@ -261,6 +267,35 @@ static int mtk_dp_phy_power_on(struct phy *phy)
return 0;
}
+static int mtk_dp_phy_disable_all_lanes(struct mtk_dp_phy *dp_phy)
+{
+ const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata;
+ const u8 *regs = pdata->regs_dig_glb;
+ int ret;
+ u32 val;
+
+ ret = regmap_read(dp_phy->regmap, pdata->off_dig_glb + regs[DP_PHYD_TX_CTL_0], &val);
+ if (ret)
+ return ret;
+
+ /* Get mask of currently enabled lane */
+ val = FIELD_GET(PHYD_TX_LN_EN, val);
+
+ /* Disable all lanes (needs to be done one by one, from last to first) */
+ do {
+ u32 lane_num = fls(val) - 1;
+ val &= ~BIT(lane_num);
+
+ ret = regmap_clear_bits(dp_phy->regmap,
+ pdata->off_dig_glb + regs[DP_PHYD_TX_CTL_0],
+ FIELD_PREP(PHYD_TX_LN_EN, lane_num));
+ if (ret)
+ return ret;
+ } while (val);
+
+ return 0;
+}
+
static int mtk_dp_phy_power_off(struct phy *phy)
{
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
@@ -280,6 +315,12 @@ static int mtk_dp_phy_power_off(struct phy *phy)
if (ret)
return ret;
+ ret = mtk_dp_phy_disable_all_lanes(dp_phy);
+ if (ret) {
+ dev_err(dp_phy->dev, "Could not disable lanes for poweroff!\n");
+ return ret;
+ }
+
return 0;
}
@@ -288,6 +329,7 @@ static int mtk_dp_phy_reset(struct phy *phy)
struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata;
const u32 reg_rst = pdata->regs_dig_glb[DP_PHYD_SW_RST];
+ int ret;
/* Clearing bits sets reset state */
regmap_clear_bits(dp_phy->regmap, pdata->off_dig_glb + reg_rst, DP_GLB_SW_RST_PHYD);
@@ -298,6 +340,11 @@ static int mtk_dp_phy_reset(struct phy *phy)
/* Setting bits means go out of reset */
regmap_set_bits(dp_phy->regmap, pdata->off_dig_glb + reg_rst, DP_GLB_SW_RST_PHYD);
+ /* Disable all lanes and continue reset even if this fails, but notify */
+ ret = mtk_dp_phy_disable_all_lanes(dp_phy);
+ if (ret)
+ dev_err(dp_phy->dev, "Could not disable lanes during reset!\n");
+
return 0;
}
--
2.54.0
More information about the linux-arm-kernel
mailing list