[PATCH v2 05/12] phy: phy-mtk-dp: Implement power_on and power_off PHY callbacks
From: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Date: 2026-07-07 14:19:51
Also in:
dri-devel, linux-arm-kernel, linux-mediatek, linux-phy, lkml
Subsystem:
arm/mediatek usb3 phy driver, drm drivers for mediatek, generic phy framework, the rest · Maintainers:
Chunfeng Yun, Chun-Kuang Hu, Philipp Zabel, Vinod Koul, Linus Torvalds
Add .power_on() and .power_off() callbacks to mtk_dp_phy_dev_ops to be able to call those with phy_power_on() and phy_power_off() API in the DisplayPort driver to be able to stop using all of those hardcoded register writes in that external driver. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> --- drivers/phy/mediatek/phy-mtk-dp.c | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+)
diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c
index 915f148325c4..0c3f06791613 100644
--- a/drivers/phy/mediatek/phy-mtk-dp.c
+++ b/drivers/phy/mediatek/phy-mtk-dp.c@@ -20,6 +20,9 @@ #define MTK_DP_PHY_MAX_LANES 4 +/* DP_PHYA_GLB_FORCE_CTRL_1 */ +#define CKM_CKTX0_EN_FORCE_MODE BIT(10) + /* DP_PHYD_PLL_CTL_1 */ #define TPLL_SSC_EN BIT(3)
@@ -37,6 +40,11 @@ # define DP_GLB_SW_RST_XTAL_CLK BIT(2) # define DP_GLB_SW_RST_MAIN_LINK BIT(3) +/* DP_PHYD_AUX_RX_CTL */ +#define PHYD_DIG_DPAUX_RX_EN BIT(0) +#define PHYD_DIG_XTP_GLB_CKDET_EN BIT(1) +#define PHYD_DIG_DPAUX_RX_DEGLITCH_EN BIT(2) + #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)
@@ -83,6 +91,12 @@ #define DRIVING_PARAM_8_DEFAULT (XTP_LN_TX_LCTXCP1_SW2_PRE1_DEFAULT | \ XTP_LN_TX_LCTXCP1_SW3_PRE0_DEFAULT) +enum mtk_dp_phya_ana_glb_regidx { + DP_PHYA_GLB_FORCE_CTRL_0, + DP_PHYA_GLB_FORCE_CTRL_1, + DP_PHYA_GLOBAL_MAX +}; + enum mtk_dp_phyd_dig_lane_regidx { DP_PHYD_LAN_DRIVING_PARAM_0, DP_PHYD_LAN_MAX
@@ -93,9 +107,15 @@ enum mtk_dp_phyd_dig_glb_regidx { DP_PHYD_PLL_CTL_1, DP_PHYD_SW_RST, DP_PHYD_BIT_RATE, + DP_PHYD_AUX_RX_CTL, DP_PHYD_GLOBAL_MAX }; +static const u8 mt8195_phy_ana_glb_regs[DP_PHYA_GLOBAL_MAX] = { + [DP_PHYA_GLB_FORCE_CTRL_0] = 0x30, + [DP_PHYA_GLB_FORCE_CTRL_1] = 0x34, +}; + static const u8 mt8195_phy_dig_lane_regs[DP_PHYD_LAN_MAX] = { [DP_PHYD_LAN_DRIVING_PARAM_0] = 0x2c, };
@@ -105,21 +125,26 @@ static const u8 mt8195_phy_dig_glb_regs[DP_PHYD_GLOBAL_MAX] = { [DP_PHYD_PLL_CTL_1] = 0x14, [DP_PHYD_SW_RST] = 0x38, [DP_PHYD_BIT_RATE] = 0x3c, + [DP_PHYD_AUX_RX_CTL] = 0x40, }; /** * struct mtk_dp_phy_pdata - Platform data and defaults for MediaTek DP/eDP PHY + * @off_ana_glb: Base offset for dptx_phyd_sifslv_ana_glb * @off_dig_glb: Base offset for dptx_phyd_sifslv_dig_glb * @off_dig_lane: Base offsets for dptx_phyd_sifslv_dig_lan (for each lane) + * @regs_ana_glb: Register (layout) offsets for ana_glb * @regs_dig_glb: Register (layout) offsets for dig_glb * @regs_dig_lane: Register (layout) offsets for dig_lan */ struct mtk_dp_phy_pdata { /* Register offsets */ + u16 off_ana_glb; u16 off_dig_glb; u16 off_dig_lane[MTK_DP_PHY_MAX_LANES]; /* Register maps */ + const u8 *regs_ana_glb; const u8 *regs_dig_glb; const u8 *regs_dig_lane; };
@@ -200,6 +225,59 @@ static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) return 0; } +static int mtk_dp_phy_power_on(struct phy *phy) +{ + struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); + const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata; + const u8 *regs_dig = pdata->regs_dig_glb; + const u8 *regs_ana = pdata->regs_ana_glb; + int ret; + + /* Enable AUX Channel with RX De-Glitch and input clock detection */ + ret = regmap_write(dp_phy->regmap, + pdata->off_dig_glb + regs_dig[DP_PHYD_AUX_RX_CTL], + PHYD_DIG_DPAUX_RX_EN | + PHYD_DIG_XTP_GLB_CKDET_EN | + PHYD_DIG_DPAUX_RX_DEGLITCH_EN); + if (ret) + return ret; + + ret = regmap_clear_bits(dp_phy->regmap, + pdata->off_ana_glb + regs_ana[DP_PHYA_GLB_FORCE_CTRL_1], + CKM_CKTX0_EN_FORCE_MODE); + if (ret) { + /* Shut down AUX channel */ + regmap_write(dp_phy->regmap, + pdata->off_dig_glb + regs_dig[DP_PHYD_AUX_RX_CTL], 0); + return ret; + } + + return 0; +} + +static int mtk_dp_phy_power_off(struct phy *phy) +{ + struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); + const struct mtk_dp_phy_pdata *pdata = dp_phy->pdata; + const u8 *regs_dig = pdata->regs_dig_glb; + const u8 *regs_ana = pdata->regs_ana_glb; + int ret; + + ret = regmap_set_bits(dp_phy->regmap, + pdata->off_ana_glb + regs_ana[DP_PHYA_GLB_FORCE_CTRL_1], + CKM_CKTX0_EN_FORCE_MODE); + if (ret) + return ret; + + /* Disable RX */ + ret = regmap_write(dp_phy->regmap, + pdata->off_dig_glb + regs_dig[DP_PHYD_AUX_RX_CTL], 0); + if (ret) + return ret; + + return 0; +} + static int mtk_dp_phy_reset(struct phy *phy) { struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy);
@@ -220,6 +298,8 @@ static int mtk_dp_phy_reset(struct phy *phy) static const struct phy_ops mtk_dp_phy_dev_ops = { .init = mtk_dp_phy_init, + .power_on = mtk_dp_phy_power_on, + .power_off = mtk_dp_phy_power_off, .configure = mtk_dp_phy_configure, .reset = mtk_dp_phy_reset, .owner = THIS_MODULE,
@@ -319,8 +399,10 @@ static int mtk_dp_phy_probe(struct platform_device *pdev) } static const struct mtk_dp_phy_pdata mt8195_dp_phy_data = { + .off_ana_glb = 0x0, .off_dig_glb = 0x1000, .off_dig_lane = (const u16[]) { 0x1100, 0x1200, 0x1300, 0x1400 }, + .regs_ana_glb = mt8195_phy_ana_glb_regs, .regs_dig_glb = mt8195_phy_dig_glb_regs, .regs_dig_lane = mt8195_phy_dig_lane_regs, };
--
2.54.0