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 <[email protected]> --- drivers/phy/mediatek/phy-mtk-dp.c | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c index ce33f6812bae..586e72795633 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; }; @@ -193,6 +218,17 @@ static int mtk_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) regmap_write(dp_phy->regmap, pdata->off_dig_glb + reg_bit_rate, val); } + if (opts->dp.set_lanes) { + const u32 reg_dig_tx_ctl = pdata->regs_dig_glb[DP_PHYD_TX_CTL_0]; + + val = 0; + for (i = 0; i < opts->dp.lanes; i++) + val |= FIELD_PREP(PHYD_TX_LN_EN, i); + + regmap_update_bits(dp_phy->regmap, pdata->off_dig_glb + reg_dig_tx_ctl, + PHYD_TX_LN_EN, val); + } + regmap_update_bits(dp_phy->regmap, pdata->off_dig_glb + pdata->regs_dig_glb[DP_PHYD_PLL_CTL_1], TPLL_SSC_EN, opts->dp.ssc ? TPLL_SSC_EN : 0); @@ -200,6 +236,53 @@ 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 = pdata->regs_dig_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[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[DP_PHYA_GLB_FORCE_CTRL_1], + CKM_CKTX0_EN_FORCE_MODE); + if (ret) + 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 = pdata->regs_dig_glb; + int ret; + + ret = regmap_set_bits(dp_phy->regmap, + pdata->off_ana_glb + regs[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[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 +303,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, @@ -305,8 +390,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
