diff --git a/msm/dp/dp_pll.c b/msm/dp/dp_pll.c index 22ac57190c..2a727ec2e4 100644 --- a/msm/dp/dp_pll.c +++ b/msm/dp/dp_pll.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -55,6 +56,7 @@ static int dp_pll_clock_register(struct dp_pll *pll) rc = dp_pll_clock_register_5nm(pll); break; case DP_PLL_4NM_V1: + case DP_PLL_4NM_V1_1: rc = dp_pll_clock_register_4nm(pll); break; default: @@ -73,6 +75,7 @@ static void dp_pll_clock_unregister(struct dp_pll *pll) dp_pll_clock_unregister_5nm(pll); break; case DP_PLL_4NM_V1: + case DP_PLL_4NM_V1_1: dp_pll_clock_unregister_4nm(pll); break; default: @@ -139,6 +142,8 @@ struct dp_pll *dp_pll_get(struct dp_pll_in *in) pll->revision = DP_PLL_5NM_V2; } else if (!strcmp(label, "4nm-v1")) { pll->revision = DP_PLL_4NM_V1; + } else if (!strcmp(label, "4nm-v1.1")) { + pll->revision = DP_PLL_4NM_V1_1; } else { DP_ERR("Unsupported pll revision\n"); rc = -ENOTSUPP; diff --git a/msm/dp/dp_pll.h b/msm/dp/dp_pll.h index e0cd6f3482..bd4006688d 100644 --- a/msm/dp/dp_pll.h +++ b/msm/dp/dp_pll.h @@ -37,6 +37,15 @@ enum dp_pll_revision { DP_PLL_5NM_V1, DP_PLL_5NM_V2, DP_PLL_4NM_V1, + DP_PLL_4NM_V1_1, +}; + +enum hsclk_rate { + HSCLK_RATE_1620MHZ, + HSCLK_RATE_2700MHZ, + HSCLK_RATE_5400MHZ, + HSCLK_RATE_8100MHZ, + HSCLK_RATE_MAX, }; static inline const char *dp_pll_get_revision(enum dp_pll_revision rev) @@ -46,6 +55,7 @@ static inline const char *dp_pll_get_revision(enum dp_pll_revision rev) case DP_PLL_5NM_V1: return "DP_PLL_5NM_V1"; case DP_PLL_5NM_V2: return "DP_PLL_5NM_V2"; case DP_PLL_4NM_V1: return "DP_PLL_4NM_V1"; + case DP_PLL_4NM_V1_1: return "DP_PLL_4NM_V1_1"; default: return "???"; } } @@ -91,31 +101,40 @@ struct dp_pll { int (*pll_unprepare)(struct dp_pll *pll); }; -struct dp_pll_db { - struct dp_pll *pll; - - /* lane and orientation settings */ - u8 lane_cnt; - u8 orientation; - +struct dp_pll_params { /* COM PHY settings */ u32 hsclk_sel; + u32 integloop_gain0_mode0; + u32 integloop_gain1_mode0; + u32 lock_cmp_en; + /* PHY vco divider */ + u32 phy_vco_div; u32 dec_start_mode0; u32 div_frac_start1_mode0; u32 div_frac_start2_mode0; u32 div_frac_start3_mode0; - u32 integloop_gain0_mode0; - u32 integloop_gain1_mode0; u32 lock_cmp1_mode0; u32 lock_cmp2_mode0; - u32 lock_cmp_en; u32 ssc_step_size1_mode0; u32 ssc_step_size2_mode0; u32 ssc_per1; + u32 ssc_per2; u32 cmp_code1_mode0; u32 cmp_code2_mode0; - /* PHY vco divider */ - u32 phy_vco_div; + u32 pll_ivco; + u32 bg_timer; + u32 core_clk_en; + u32 lane_offset_tx; + u32 lane_offset_rx; +}; + +struct dp_pll_db { + struct dp_pll *pll; + /* lane and orientation settings */ + u8 lane_cnt; + u8 orientation; + u32 rate_idx; + const struct dp_pll_params *pll_params; }; static inline struct dp_pll_vco_clk *to_dp_vco_hw(struct clk_hw *hw) diff --git a/msm/dp/dp_pll_4nm.c b/msm/dp/dp_pll_4nm.c index 2851e83810..6ed1103bed 100644 --- a/msm/dp/dp_pll_4nm.c +++ b/msm/dp/dp_pll_4nm.c @@ -128,6 +128,29 @@ #define DP_4NM_PHY_READY BIT(1) #define DP_4NM_TSYNC_DONE BIT(0) +static const struct dp_pll_params pll_params_v1[HSCLK_RATE_MAX] = { + {0x05, 0x3f, 0x00, 0x04, 0x01, 0x69, 0x00, 0x80, 0x07, 0x6f, 0x08, 0x45, 0x06, 0x36, 0x01, + 0xe2, 0x18, 0x0f, 0x0e, 0x1f, 0x0a, 0x11}, + {0x03, 0x3f, 0x00, 0x08, 0x01, 0x69, 0x00, 0x80, 0x07, 0x0f, 0x0e, 0x13, 0x06, 0x40, 0x01, + 0xe2, 0x18, 0x0f, 0x0e, 0x1f, 0x0a, 0x11}, + {0x01, 0x3f, 0x00, 0x08, 0x02, 0x8c, 0x00, 0x00, 0x0a, 0x1f, 0x1c, 0x1a, 0x08, 0x40, 0x01, + 0x2e, 0x21, 0x0f, 0x0e, 0x1f, 0x0a, 0x11}, + {0x00, 0x3f, 0x00, 0x08, 0x00, 0x69, 0x00, 0x80, 0x07, 0x2f, 0x2a, 0x13, 0x06, 0x40, 0x01, + 0xe2, 0x18, 0x0f, 0x0e, 0x1f, 0x0a, 0x11}, +}; + +static const struct dp_pll_params pll_params_v1_1[HSCLK_RATE_MAX] = { + {0x05, 0x3f, 0x00, 0x04, 0x01, 0x34, 0x00, 0xc0, 0x0b, 0x37, 0x04, 0x92, 0x01, 0x6b, 0x02, + 0x71, 0x0c, 0x0f, 0x0a, 0x0f, 0x0c, 0x0c}, + {0x03, 0x3f, 0x00, 0x08, 0x01, 0x34, 0x00, 0xc0, 0x0b, 0x07, 0x07, 0x92, 0x01, 0x6b, 0x02, + 0x71, 0x0c, 0x0f, 0x0e, 0x0f, 0x0c, 0x0c}, + {0x01, 0x3f, 0x00, 0x08, 0x02, 0x46, 0x00, 0x00, 0x05, 0x0f, 0x0e, 0x18, 0x02, 0x6b, 0x02, + 0x97, 0x10, 0x0f, 0x0a, 0x0f, 0x0c, 0x0c}, + {0x00, 0x3f, 0x00, 0x08, 0x00, 0x34, 0x00, 0xc0, 0x0b, 0x17, 0x15, 0x92, 0x01, 0x6b, 0x02, + 0x71, 0x0c, 0x0f, 0x0a, 0x0f, 0x0c, 0x0c} + +}; + static int set_vco_div(struct dp_pll *pll, unsigned long rate) { u32 div, val; @@ -191,74 +214,22 @@ static int dp_vco_pll_init_db_4nm(struct dp_pll_db *pdb, DP_DEBUG("spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", spare_value, pdb->lane_cnt, pdb->orientation); - pdb->div_frac_start1_mode0 = 0x00; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - switch (rate) { case DP_VCO_HSCLK_RATE_1620MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_9720MHZDIV1000); - pdb->hsclk_sel = 0x05; - pdb->dec_start_mode0 = 0x34; - pdb->div_frac_start2_mode0 = 0xc0; - pdb->div_frac_start3_mode0 = 0x0b; - pdb->lock_cmp1_mode0 = 0x37; - pdb->lock_cmp2_mode0 = 0x04; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x04; - pdb->ssc_step_size1_mode0 = 0x92; - pdb->ssc_step_size2_mode0 = 0x01; - pdb->ssc_per1 = 0x6B; - pdb->cmp_code1_mode0 = 0x71; - pdb->cmp_code2_mode0 = 0x0c; + pdb->rate_idx = HSCLK_RATE_1620MHZ; break; case DP_VCO_HSCLK_RATE_2700MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x03; - pdb->dec_start_mode0 = 0x34; - pdb->div_frac_start2_mode0 = 0xc0; - pdb->div_frac_start3_mode0 = 0x0b; - pdb->lock_cmp1_mode0 = 0x07; - pdb->lock_cmp2_mode0 = 0x07; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x92; - pdb->ssc_step_size2_mode0 = 0x01; - pdb->ssc_per1 = 0x6B; - pdb->cmp_code1_mode0 = 0x71; - pdb->cmp_code2_mode0 = 0x0c; + pdb->rate_idx = HSCLK_RATE_2700MHZ; break; case DP_VCO_HSCLK_RATE_5400MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x01; - pdb->dec_start_mode0 = 0x46; - pdb->div_frac_start2_mode0 = 0x00; - pdb->div_frac_start3_mode0 = 0x05; - pdb->lock_cmp1_mode0 = 0x0f; - pdb->lock_cmp2_mode0 = 0x0e; - pdb->phy_vco_div = 0x2; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x18; - pdb->ssc_step_size2_mode0 = 0x02; - pdb->ssc_per1 = 0x6B; - pdb->cmp_code1_mode0 = 0x97; - pdb->cmp_code2_mode0 = 0x10; + pdb->rate_idx = HSCLK_RATE_5400MHZ; break; case DP_VCO_HSCLK_RATE_8100MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_8100MHZDIV1000); - pdb->hsclk_sel = 0x00; - pdb->dec_start_mode0 = 0x34; - pdb->div_frac_start2_mode0 = 0xc0; - pdb->div_frac_start3_mode0 = 0x0b; - pdb->lock_cmp1_mode0 = 0x17; - pdb->lock_cmp2_mode0 = 0x15; - pdb->phy_vco_div = 0x0; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x92; - pdb->ssc_step_size2_mode0 = 0x01; - pdb->ssc_per1 = 0x6B; - pdb->cmp_code1_mode0 = 0x71; - pdb->cmp_code2_mode0 = 0x0c; + pdb->rate_idx = HSCLK_RATE_8100MHZ; break; default: DP_ERR("unsupported rate %ld\n", rate); @@ -272,6 +243,7 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, { int rc = 0; struct dp_pll_db *pdb = (struct dp_pll_db *)pll->priv; + const struct dp_pll_params *params; rc = dp_vco_pll_init_db_4nm(pdb, rate); if (rc < 0) { @@ -290,6 +262,13 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, dp_pll_write(dp_phy, DP_PHY_PD_CTL, 0x7d); } + if (pdb->rate_idx < HSCLK_RATE_MAX) { + params = &pdb->pll_params[pdb->rate_idx]; + } else { + DP_ERR("link rate not set\n"); + return -EINVAL; + } + /* Make sure the PHY register writes are done */ wmb(); @@ -303,7 +282,7 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, wmb(); /* PLL Optimization */ - dp_pll_write(dp_pll, QSERDES_COM_PLL_IVCO, 0x07); + dp_pll_write(dp_pll, QSERDES_COM_PLL_IVCO, params->pll_ivco); dp_pll_write(dp_pll, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); dp_pll_write(dp_pll, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); dp_pll_write(dp_pll, QSERDES_COM_CP_CTRL_MODE0, 0x06); @@ -311,49 +290,56 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, wmb(); /* link rate dependent params */ - dp_pll_write(dp_pll, QSERDES_COM_HSCLK_SEL_1, pdb->hsclk_sel); - dp_pll_write(dp_pll, QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0); + dp_pll_write(dp_pll, QSERDES_COM_HSCLK_SEL_1, params->hsclk_sel); + dp_pll_write(dp_pll, QSERDES_COM_DEC_START_MODE0, params->dec_start_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0); + QSERDES_COM_DIV_FRAC_START1_MODE0, params->div_frac_start1_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0); + QSERDES_COM_DIV_FRAC_START2_MODE0, params->div_frac_start2_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP_EN, pdb->lock_cmp_en); - dp_pll_write(dp_phy, DP_PHY_VCO_DIV, pdb->phy_vco_div); + QSERDES_COM_DIV_FRAC_START3_MODE0, params->div_frac_start3_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP1_MODE0, params->lock_cmp1_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP2_MODE0, params->lock_cmp2_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP_EN, params->lock_cmp_en); + dp_pll_write(dp_phy, DP_PHY_VCO_DIV, params->phy_vco_div); /* Make sure the PLL register writes are done */ wmb(); dp_pll_write(dp_pll, QSERDES_COM_CMN_CONFIG_1, 0x12); - dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); - dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); + dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, + params->integloop_gain0_mode0); + dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, + params->integloop_gain1_mode0); dp_pll_write(dp_pll, QSERDES_COM_VCO_TUNE_MAP, 0x00); /* Make sure the PHY register writes are done */ wmb(); - dp_pll_write(dp_pll, QSERDES_COM_BG_TIMER, 0x0a); + dp_pll_write(dp_pll, QSERDES_COM_BG_TIMER, params->bg_timer); dp_pll_write(dp_pll, QSERDES_COM_CORECLK_DIV_MODE0, 0x14); dp_pll_write(dp_pll, QSERDES_COM_VCO_TUNE_CTRL, 0x00); - dp_pll_write(dp_pll, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1f); + if (pll->bonding_en) + dp_pll_write(dp_pll, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1f); + else + dp_pll_write(dp_pll, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x17); - dp_pll_write(dp_pll, QSERDES_COM_CORE_CLK_EN, 0x0f); - dp_pll_write(dp_pll, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, pdb->cmp_code1_mode0); - dp_pll_write(dp_pll, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, pdb->cmp_code2_mode0); + dp_pll_write(dp_pll, QSERDES_COM_CORE_CLK_EN, params->core_clk_en); + dp_pll_write(dp_pll, QSERDES_COM_BIN_VCOCAL_CMP_CODE1_MODE0, + params->cmp_code1_mode0); + dp_pll_write(dp_pll, QSERDES_COM_BIN_VCOCAL_CMP_CODE2_MODE0, + params->cmp_code2_mode0); /* Make sure the PHY register writes are done */ wmb(); if (pll->ssc_en) { dp_pll_write(dp_pll, QSERDES_COM_SSC_EN_CENTER, 0x01); dp_pll_write(dp_pll, QSERDES_COM_SSC_ADJ_PER1, 0x00); - dp_pll_write(dp_pll, QSERDES_COM_SSC_PER1, pdb->ssc_per1); - dp_pll_write(dp_pll, QSERDES_COM_SSC_PER2, 0x02); + dp_pll_write(dp_pll, QSERDES_COM_SSC_PER1, params->ssc_per1); + dp_pll_write(dp_pll, QSERDES_COM_SSC_PER2, params->ssc_per2); dp_pll_write(dp_pll, QSERDES_COM_SSC_STEP_SIZE1_MODE0, - pdb->ssc_step_size1_mode0); + params->ssc_step_size1_mode0); dp_pll_write(dp_pll, QSERDES_COM_SSC_STEP_SIZE2_MODE0, - pdb->ssc_step_size2_mode0); + params->ssc_step_size2_mode0); } if (pdb->orientation == ORIENTATION_CC2) @@ -376,8 +362,8 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, dp_pll_write(dp_ln_tx0, DP_TRAN_DRVR_EMP_EN, 0xf); dp_pll_write(dp_ln_tx0, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); dp_pll_write(dp_ln_tx0, DP_TX_INTERFACE_MODE, 0x00); - dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_TX, 0x0A); - dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); + dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_TX, params->lane_offset_tx); + dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_RX, params->lane_offset_rx); dp_pll_write(dp_ln_tx0, TXn_TX_BAND, 0x04); /* Make sure the PLL register writes are done */ wmb(); @@ -392,8 +378,8 @@ static int dp_config_vco_rate_4nm(struct dp_pll *pll, dp_pll_write(dp_ln_tx1, DP_TRAN_DRVR_EMP_EN, 0xf); dp_pll_write(dp_ln_tx1, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); dp_pll_write(dp_ln_tx1, DP_TX_INTERFACE_MODE, 0x00); - dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_TX, 0x11); - dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); + dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_TX, params->lane_offset_tx); + dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_RX, params->lane_offset_rx); dp_pll_write(dp_ln_tx1, TXn_TX_BAND, 0x04); /* Make sure the PHY register writes are done */ wmb(); @@ -629,7 +615,7 @@ static int dp_pll_prepare(struct dp_pll *pll) * link rate is 8.1Gbps. This will result in voting to place Mx rail in * turbo as required for V1 hardware PLL functionality. */ - if (pll->revision == DP_PLL_4NM_V1 && + if (pll->revision >= DP_PLL_4NM_V1 && pll->vco_rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) { rc = dp_regulator_enable_4nm(pll->parser, DP_PLL_PM, true); if (rc < 0) { @@ -654,7 +640,7 @@ static int dp_pll_unprepare(struct dp_pll *pll) return -EINVAL; } - if (pll->revision == DP_PLL_4NM_V1 && + if (pll->revision >= DP_PLL_4NM_V1 && pll->vco_rate == DP_VCO_HSCLK_RATE_8100MHZDIV1000) { rc = dp_regulator_enable_4nm(pll->parser, DP_PLL_PM, false); if (rc < 0) { @@ -878,6 +864,11 @@ int dp_pll_clock_register_4nm(struct dp_pll *pll) pll->priv = &dp_pdb; dp_pdb.pll = pll; + if (pll->revision == DP_PLL_4NM_V1_1) + dp_pdb.pll_params = pll_params_v1_1; + else + dp_pdb.pll_params = pll_params_v1; + pll->pll_cfg = dp_pll_configure; pll->pll_prepare = dp_pll_prepare; pll->pll_unprepare = dp_pll_unprepare; diff --git a/msm/dp/dp_pll_5nm.c b/msm/dp/dp_pll_5nm.c index 23591ef9ba..0af078d8e9 100644 --- a/msm/dp/dp_pll_5nm.c +++ b/msm/dp/dp_pll_5nm.c @@ -128,6 +128,17 @@ #define DP_5NM_PHY_READY BIT(1) #define DP_5NM_TSYNC_DONE BIT(0) +static const struct dp_pll_params pll_params[HSCLK_RATE_MAX] = { + {0x05, 0x3f, 0x00, 0x04, 0x01, 0x69, 0x00, 0x80, 0x07, 0x6f, 0x08, 0x45, 0x06, 0x36, 0x01, + 0x00, 0x00, 0x0f, 0x0a, 0x1f, 0x0a, 0x11}, + {0x03, 0x3f, 0x00, 0x08, 0x01, 0x69, 0x00, 0x80, 0x07, 0x0f, 0x0e, 0x45, 0x06, 0x36, 0x01, + 0x00, 0x00, 0x0f, 0x0a, 0x1f, 0x0a, 0x11}, + {0x01, 0x3f, 0x00, 0x08, 0x02, 0x8c, 0x00, 0x00, 0x0a, 0x1f, 0x1c, 0x5c, 0x08, 0x36, 0x01, + 0x00, 0x00, 0x0f, 0x0a, 0x1f, 0x0a, 0x11}, + {0x00, 0x3f, 0x00, 0x08, 0x00, 0x69, 0x00, 0x80, 0x07, 0x2f, 0x2a, 0x45, 0x06, 0x36, 0x01, + 0x00, 0x00, 0x0f, 0x0a, 0x1f, 0x0a, 0x11}, +}; + static int set_vco_div(struct dp_pll *pll, unsigned long rate) { u32 div, val; @@ -191,62 +202,22 @@ static int dp_vco_pll_init_db_5nm(struct dp_pll_db *pdb, DP_DEBUG("spare_value=0x%x, ln_cnt=0x%x, orientation=0x%x\n", spare_value, pdb->lane_cnt, pdb->orientation); - pdb->div_frac_start1_mode0 = 0x00; - pdb->integloop_gain0_mode0 = 0x3f; - pdb->integloop_gain1_mode0 = 0x00; - switch (rate) { case DP_VCO_HSCLK_RATE_1620MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_9720MHZDIV1000); - pdb->hsclk_sel = 0x05; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x6f; - pdb->lock_cmp2_mode0 = 0x08; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x04; - pdb->ssc_step_size1_mode0 = 0x45; - pdb->ssc_step_size2_mode0 = 0x06; + pdb->rate_idx = HSCLK_RATE_1620MHZ; break; case DP_VCO_HSCLK_RATE_2700MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x03; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x0f; - pdb->lock_cmp2_mode0 = 0x0e; - pdb->phy_vco_div = 0x1; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x45; - pdb->ssc_step_size2_mode0 = 0x06; + pdb->rate_idx = HSCLK_RATE_2700MHZ; break; case DP_VCO_HSCLK_RATE_5400MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_10800MHZDIV1000); - pdb->hsclk_sel = 0x01; - pdb->dec_start_mode0 = 0x8c; - pdb->div_frac_start2_mode0 = 0x00; - pdb->div_frac_start3_mode0 = 0x0a; - pdb->lock_cmp1_mode0 = 0x1f; - pdb->lock_cmp2_mode0 = 0x1c; - pdb->phy_vco_div = 0x2; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x5c; - pdb->ssc_step_size2_mode0 = 0x08; + pdb->rate_idx = HSCLK_RATE_5400MHZ; break; case DP_VCO_HSCLK_RATE_8100MHZDIV1000: DP_DEBUG("VCO rate: %ld\n", DP_VCO_RATE_8100MHZDIV1000); - pdb->hsclk_sel = 0x00; - pdb->dec_start_mode0 = 0x69; - pdb->div_frac_start2_mode0 = 0x80; - pdb->div_frac_start3_mode0 = 0x07; - pdb->lock_cmp1_mode0 = 0x2f; - pdb->lock_cmp2_mode0 = 0x2a; - pdb->phy_vco_div = 0x0; - pdb->lock_cmp_en = 0x08; - pdb->ssc_step_size1_mode0 = 0x45; - pdb->ssc_step_size2_mode0 = 0x06; + pdb->rate_idx = HSCLK_RATE_8100MHZ; break; default: DP_ERR("unsupported rate %ld\n", rate); @@ -260,6 +231,7 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, { int rc = 0; struct dp_pll_db *pdb = (struct dp_pll_db *)pll->priv; + const struct dp_pll_params *params; rc = dp_vco_pll_init_db_5nm(pdb, rate); if (rc < 0) { @@ -281,6 +253,13 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, /* Make sure the PHY register writes are done */ wmb(); + if (pdb->rate_idx < HSCLK_RATE_MAX) { + params = &pdb->pll_params[pdb->rate_idx]; + } else { + DP_ERR("link rate not set\n"); + return -EINVAL; + } + dp_pll_write(dp_pll, QSERDES_COM_SVS_MODE_CLK_SEL, 0x05); dp_pll_write(dp_pll, QSERDES_COM_SYSCLK_EN_SEL, 0x3b); dp_pll_write(dp_pll, QSERDES_COM_SYS_CLK_CTRL, 0x02); @@ -291,7 +270,7 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, wmb(); /* PLL Optimization */ - dp_pll_write(dp_pll, QSERDES_COM_PLL_IVCO, 0x0f); + dp_pll_write(dp_pll, QSERDES_COM_PLL_IVCO, params->pll_ivco); dp_pll_write(dp_pll, QSERDES_COM_PLL_CCTRL_MODE0, 0x36); dp_pll_write(dp_pll, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); dp_pll_write(dp_pll, QSERDES_COM_CP_CTRL_MODE0, 0x06); @@ -299,48 +278,50 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, wmb(); /* link rate dependent params */ - dp_pll_write(dp_pll, QSERDES_COM_HSCLK_SEL, pdb->hsclk_sel); - dp_pll_write(dp_pll, QSERDES_COM_DEC_START_MODE0, pdb->dec_start_mode0); + dp_pll_write(dp_pll, QSERDES_COM_HSCLK_SEL, params->hsclk_sel); + dp_pll_write(dp_pll, QSERDES_COM_DEC_START_MODE0, params->dec_start_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START1_MODE0, pdb->div_frac_start1_mode0); + QSERDES_COM_DIV_FRAC_START1_MODE0, params->div_frac_start1_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START2_MODE0, pdb->div_frac_start2_mode0); + QSERDES_COM_DIV_FRAC_START2_MODE0, params->div_frac_start2_mode0); dp_pll_write(dp_pll, - QSERDES_COM_DIV_FRAC_START3_MODE0, pdb->div_frac_start3_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP1_MODE0, pdb->lock_cmp1_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP2_MODE0, pdb->lock_cmp2_mode0); - dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP_EN, pdb->lock_cmp_en); - dp_pll_write(dp_phy, DP_PHY_VCO_DIV, pdb->phy_vco_div); + QSERDES_COM_DIV_FRAC_START3_MODE0, params->div_frac_start3_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP1_MODE0, params->lock_cmp1_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP2_MODE0, params->lock_cmp2_mode0); + dp_pll_write(dp_pll, QSERDES_COM_LOCK_CMP_EN, params->lock_cmp_en); + dp_pll_write(dp_phy, DP_PHY_VCO_DIV, params->phy_vco_div); /* Make sure the PLL register writes are done */ wmb(); dp_pll_write(dp_pll, QSERDES_COM_CMN_CONFIG, 0x02); - dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); - dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); + dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, + params->integloop_gain0_mode0); + dp_pll_write(dp_pll, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, + params->integloop_gain1_mode0); dp_pll_write(dp_pll, QSERDES_COM_VCO_TUNE_MAP, 0x00); /* Make sure the PHY register writes are done */ wmb(); - dp_pll_write(dp_pll, QSERDES_COM_BG_TIMER, 0x0a); + dp_pll_write(dp_pll, QSERDES_COM_BG_TIMER, params->bg_timer); dp_pll_write(dp_pll, QSERDES_COM_CORECLK_DIV_MODE0, 0x0a); dp_pll_write(dp_pll, QSERDES_COM_VCO_TUNE_CTRL, 0x00); if (pll->bonding_en) dp_pll_write(dp_pll, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1f); else dp_pll_write(dp_pll, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x17); - dp_pll_write(dp_pll, QSERDES_COM_CORE_CLK_EN, 0x1f); + dp_pll_write(dp_pll, QSERDES_COM_CORE_CLK_EN, params->core_clk_en); /* Make sure the PHY register writes are done */ wmb(); if (pll->ssc_en) { dp_pll_write(dp_pll, QSERDES_COM_SSC_EN_CENTER, 0x01); dp_pll_write(dp_pll, QSERDES_COM_SSC_ADJ_PER1, 0x00); - dp_pll_write(dp_pll, QSERDES_COM_SSC_PER1, 0x36); - dp_pll_write(dp_pll, QSERDES_COM_SSC_PER2, 0x01); + dp_pll_write(dp_pll, QSERDES_COM_SSC_PER1, params->ssc_per1); + dp_pll_write(dp_pll, QSERDES_COM_SSC_PER2, params->ssc_per1); dp_pll_write(dp_pll, QSERDES_COM_SSC_STEP_SIZE1_MODE0, - pdb->ssc_step_size1_mode0); + params->ssc_step_size1_mode0); dp_pll_write(dp_pll, QSERDES_COM_SSC_STEP_SIZE2_MODE0, - pdb->ssc_step_size2_mode0); + params->ssc_step_size2_mode0); } if (pdb->orientation == ORIENTATION_CC2) @@ -363,8 +344,8 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, dp_pll_write(dp_ln_tx0, DP_TRAN_DRVR_EMP_EN, 0xf); dp_pll_write(dp_ln_tx0, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); dp_pll_write(dp_ln_tx0, DP_TX_INTERFACE_MODE, 0x00); - dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_TX, 0x0A); - dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); + dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_TX, params->lane_offset_tx); + dp_pll_write(dp_ln_tx0, TXn_RES_CODE_LANE_OFFSET_RX, params->lane_offset_rx); dp_pll_write(dp_ln_tx0, TXn_TX_BAND, 0x04); /* Make sure the PLL register writes are done */ wmb(); @@ -379,8 +360,8 @@ static int dp_config_vco_rate_5nm(struct dp_pll *pll, dp_pll_write(dp_ln_tx1, DP_TRAN_DRVR_EMP_EN, 0xf); dp_pll_write(dp_ln_tx1, TXn_PARRATE_REC_DETECT_IDLE_EN, 0x00); dp_pll_write(dp_ln_tx1, DP_TX_INTERFACE_MODE, 0x00); - dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_TX, 0x0A); - dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_RX, 0x11); + dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_TX, params->lane_offset_tx); + dp_pll_write(dp_ln_tx1, TXn_RES_CODE_LANE_OFFSET_RX, params->lane_offset_rx); dp_pll_write(dp_ln_tx1, TXn_TX_BAND, 0x04); /* Make sure the PHY register writes are done */ wmb(); @@ -864,6 +845,7 @@ int dp_pll_clock_register_5nm(struct dp_pll *pll) pll->clk_data->clk_num = DP_PLL_NUM_CLKS; pll->priv = &dp_pdb; dp_pdb.pll = pll; + dp_pdb.pll_params = pll_params; pll->pll_cfg = dp_pll_configure; pll->pll_prepare = dp_pll_prepare;