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 | 88 +++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/drivers/phy/mediatek/phy-mtk-dp.c b/drivers/phy/mediatek/phy-mtk-dp.c index 20974650d940..f6b0e83d4833 100644 --- a/drivers/phy/mediatek/phy-mtk-dp.c +++ b/drivers/phy/mediatek/phy-mtk-dp.c @@ -21,6 +21,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) @@ -38,6 +41,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 DRIVING_PARAM_0_DEFAULT 0x0 #define DRIVING_PARAM_1_DEFAULT 0x0 #define DRIVING_PARAM_2_DEFAULT 0x0 @@ -88,6 +96,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 @@ -98,9 +112,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, }; @@ -110,21 +130,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; }; @@ -208,6 +233,65 @@ 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_cktx, ret_aux; + + ret_cktx = regmap_set_bits(dp_phy->regmap, + pdata->off_ana_glb + regs_ana[DP_PHYA_GLB_FORCE_CTRL_1], + CKM_CKTX0_EN_FORCE_MODE); + + /* Disable RX unconditionally */ + ret_aux = regmap_write(dp_phy->regmap, + pdata->off_dig_glb + regs_dig[DP_PHYD_AUX_RX_CTL], 0); + if (ret_aux) { + dev_err(&phy->dev, "Could not disable AUX RX: %d\n", ret_aux); + return ret_aux; + } + + /* Still fail if CKTX0_EN was not disabled, but at least AUX is off */ + if (ret_cktx) { + dev_err(&phy->dev, "Could not disable CKTX0: %d\n", ret_cktx); + return ret_cktx; + } + + return 0; +} + static int mtk_dp_phy_reset(struct phy *phy) { struct mtk_dp_phy *dp_phy = phy_get_drvdata(phy); @@ -228,6 +312,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, @@ -330,8 +416,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
