Loading drivers/clk/qcom/mdss/mdss-dp-pll-8998-util.c +209 −167 Original line number Diff line number Diff line Loading @@ -49,13 +49,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1 |= 0x4; /*configure DP PHY MODE */ phy_mode = 0x48; phy_mode = 0x58; if (div == 10) { link2xclk_div_tx0 |= 1; link2xclk_div_tx1 |= 1; phy_mode |= 1; } MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_BAND, link2xclk_div_tx0); Loading @@ -64,7 +59,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, phy_mode); /* Make sure the PHY register writes are done */ wmb(); pr_debug("%s: div=%d link2xclk_div_tx0=%x, link2xclk_div_tx1=%x\n", __func__, div, link2xclk_div_tx0, link2xclk_div_tx1); Loading Loading @@ -105,63 +101,6 @@ int link2xclk_divsel_get_div(struct div_clk *clk) return div; } int hsclk_divsel_set_div(struct div_clk *clk, int div) { int rc; u32 hsclk_div; struct mdss_pll_resources *dp_res = clk->priv; rc = mdss_pll_resource_enable(dp_res, true); if (rc) { pr_err("Failed to enable mdss DP PLL resources\n"); return rc; } hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); hsclk_div &= ~0x0f; /* bits 0 to 3 */ if (div == 3) hsclk_div |= 4; else hsclk_div |= 0; MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_HSCLK_SEL, hsclk_div); pr_debug("%s: div=%d hsclk_div=%x\n", __func__, div, hsclk_div); mdss_pll_resource_enable(dp_res, false); return rc; } int hsclk_divsel_get_div(struct div_clk *clk) { int rc; u32 hsclk_div, div; struct mdss_pll_resources *dp_res = clk->priv; rc = mdss_pll_resource_enable(dp_res, true); if (rc) { pr_err("Failed to enable dp_res resources\n"); return rc; } hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); hsclk_div &= 0x0f; if (hsclk_div == 4) div = 3; else div = 2; mdss_pll_resource_enable(dp_res, false); pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div); return div; } int vco_divided_clk_set_div(struct div_clk *clk, int div) { int rc; Loading @@ -174,18 +113,18 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div) return rc; } auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= ~0x03; /* bits 0 to 1 */ auxclk_div |= 1; /* Default divider */ if (div == 4) auxclk_div |= 2; else if (div == 2) auxclk_div |= 1; else auxclk_div |= 2; /* Default divider */ MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, auxclk_div); /* Make sure the PHY registers writes are done */ wmb(); pr_debug("%s: div=%d auxclk_div=%x\n", __func__, div, auxclk_div); mdss_pll_resource_enable(dp_res, false); Loading Loading @@ -215,15 +154,12 @@ int vco_divided_clk_get_div(struct div_clk *clk) return rc; } auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= 0x03; div = 2; /* Default divider */ if (auxclk_div == 2) div = 4; else if (auxclk_div == 1) div = 2; else div = 0; mdss_pll_resource_enable(dp_res, false); Loading @@ -239,14 +175,12 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3d); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_IVCO, 0x0f); /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); Loading @@ -255,16 +189,16 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_SEL, 0x30); /* Different for each clock rates */ if (rate == DP_VCO_HSCLK_RATE_1620MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_8100MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP_EN, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x34); QSERDES_COM_SYS_CLK_CTRL, 0x02); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); QSERDES_COM_HSCLK_SEL, 0x2c); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x08); /* Different for each clock rates */ if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_LOCK_CMP_EN, 0x04); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, Loading @@ -273,58 +207,88 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); } else if (rate == DP_VCO_RATE_9720MHz) { MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x7e); QSERDES_COM_CMN_CONFIG, 0x42); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); QSERDES_COM_LOCK_CMP1_MODE0, 0xbf); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); QSERDES_COM_LOCK_CMP2_MODE0, 0x21); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09); } else if (rate == DP_VCO_RATE_10800MHz) { QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else if (rate == DP_VCO_HSCLK_RATE_2700MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_8100MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x8c); QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); QSERDES_COM_HSCLK_SEL, 0x84); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); QSERDES_COM_LOCK_CMP_EN, 0x08); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a); } else { pr_err("%s: unsupported rate: %ld\n", __func__, rate); return -EINVAL; } QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x3f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x38); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else if (rate == DP_VCO_RATE_9720MHz) { } else if (rate == DP_VCO_HSCLK_RATE_5400MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_10800MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x43); QSERDES_COM_HSCLK_SEL, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else { QSERDES_COM_LOCK_CMP_EN, 0x08); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x8c); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x12); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x70); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else { pr_err("%s: unsupported rate: %ld\n", __func__, rate); return -EINVAL; } /* Make sure the PLL register writes are done */ wmb(); if ((rate == DP_VCO_HSCLK_RATE_1620MHz) || (rate == DP_VCO_HSCLK_RATE_2700MHz)) { MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, 0x1); } else { MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, 0x2); } /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BG_TIMER, 0x00); Loading @@ -335,58 +299,42 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37); QSERDES_COM_CP_CTRL_MODE0, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x0f); /* Different for each clock rate */ if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_PLL_CCTRL_MODE0, 0x36); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } else if (rate == DP_VCO_RATE_9720MHz) { QSERDES_COM_PLL_RCTRL_MODE0, 0x16); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } else { QSERDES_COM_PLL_IVCO, 0x07); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x0f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x00); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x00); /* Make sure the PLL register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x38); DP_PHY_MODE, 0x58); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x38); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2c); DP_PHY_TX0_TX1_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2c); DP_PHY_TX2_TX3_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX0_TX1_LANE_CTL, 0x05); QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX2_TX3_LANE_CTL, 0x05); QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30); Loading Loading @@ -429,6 +377,15 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, 0x00); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_BAND, 0x4); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_BAND, 0x4); /* Make sure the PHY register writes are done */ wmb(); return res; } Loading Loading @@ -479,9 +436,12 @@ static int dp_pll_enable(struct clk *c) DP_PHY_CFG, 0x01); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); /* Make sure the PLL register writes are done */ wmb(); /* poll for PLL ready status */ if (readl_poll_timeout_atomic((dp_res->pll_base + QSERDES_COM_C_READY_STATUS), Loading @@ -497,7 +457,8 @@ static int dp_pll_enable(struct clk *c) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); /* Make sure the PHY register writes are done */ wmb(); /* poll for PHY ready status */ if (readl_poll_timeout_atomic((dp_res->phy_base + DP_PHY_STATUS), Loading @@ -513,17 +474,17 @@ static int dp_pll_enable(struct clk *c) pr_debug("%s: PLL is locked\n", __func__); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_POL_INV, Loading @@ -533,6 +494,8 @@ static int dp_pll_enable(struct clk *c) 0x0a); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); udelay(2000); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); Loading @@ -542,6 +505,77 @@ static int dp_pll_enable(struct clk *c) */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_LANE_MODE_1, 0xf6); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_LANE_MODE_1, 0xf6); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x1f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x1f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); /* * Make sure all the register writes are completed before * doing any other operation */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); udelay(2000); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); udelay(2000); /* poll for PHY ready status */ if (readl_poll_timeout_atomic((dp_res->phy_base + DP_PHY_STATUS), status, ((status & BIT(1)) > 0), DP_PLL_POLL_SLEEP_US, DP_PLL_POLL_TIMEOUT_US)) { pr_err("%s: Lane_mode: Phy_ready is not high. Status=%x\n", __func__, status); rc = -EINVAL; goto lock_err; } MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x2a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x2a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x20); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x20); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x11); /* Make sure the PHY register writes are done */ wmb(); lock_err: return rc; } Loading @@ -554,7 +588,7 @@ static int dp_pll_disable(struct clk *c) /* Assert DP PHY power down */ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3c); DP_PHY_PD_CTL, 0x2); /* * Make sure all the register writes to disable PLL are * completed before doing any other operation Loading Loading @@ -655,14 +689,20 @@ unsigned long dp_vco_get_rate(struct clk *c) div = MDSS_PLL_REG_R(pll->pll_base, QSERDES_COM_HSCLK_SEL); div &= 0x0f; if (div == 4) if (div == 12) hsclk_div = 5; /* Default */ else if (div == 4) hsclk_div = 3; else else if (div == 0) hsclk_div = 2; else { pr_debug("unknown divider. forcing to default\n"); hsclk_div = 5; } div = MDSS_PLL_REG_R(pll->phy_base, DP_PHY_MODE); if (div & 0x48) if (div & 0x58) pr_err("%s: DP PAR Rate not correct\n", __func__); if ((div & 0x3) == 1) Loading @@ -673,12 +713,14 @@ unsigned long dp_vco_get_rate(struct clk *c) pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div); if (link2xclk_div == 10) { vco_rate = DP_VCO_RATE_9720MHz; vco_rate = DP_VCO_HSCLK_RATE_2700MHz; } else { if (hsclk_div == 3) vco_rate = DP_VCO_RATE_8100MHz; if (hsclk_div == 5) vco_rate = DP_VCO_HSCLK_RATE_1620MHz; else if (hsclk_div == 3) vco_rate = DP_VCO_HSCLK_RATE_2700MHz; else vco_rate = DP_VCO_RATE_10800MHz; vco_rate = DP_VCO_HSCLK_RATE_5400MHz; } pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); Loading @@ -695,8 +737,8 @@ long dp_vco_round_rate(struct clk *c, unsigned long rate) if (rate <= vco->min_rate) rrate = vco->min_rate; else if (rate <= DP_VCO_RATE_9720MHz) rrate = DP_VCO_RATE_9720MHz; else if (rate <= DP_VCO_HSCLK_RATE_2700MHz) rrate = DP_VCO_HSCLK_RATE_2700MHz; else rrate = vco->max_rate; Loading drivers/clk/qcom/mdss/mdss-dp-pll-8998.c +64 −89 Original line number Diff line number Diff line Loading @@ -16,40 +16,37 @@ ******** Display Port PLL driver block diagram for branch clocks ********** *************************************************************************** +-------------------+ | dp_vco_clk | | (DP PLL/VCO) | +---------+---------+ | | v +----------+-----------+ | hsclk_divsel_clk_src | +----------+-----------+ | +--------------------------+ | DP_VCO_CLK | | | | +-------------------+ | | | (DP PLL/VCO) | | | +---------+---------+ | | v | | +----------+-----------+ | | | hsclk_divsel_clk_src | | | +----------+-----------+ | +--------------------------+ | v +------------<------------|------------>-------------+ | | | | | | +----------v----------+ +----------v----------+ +----------v----------+ |vco_divided_clk_src | | dp_link_2x_clk | | dp_link_2x_clk | | (aux_clk_ops) | | | | | v----------+----------v | divsel_five | | divsel_ten | | dp_link_2x_clk | | vco_divided_clk_src | | vco_divided_clk_src | | divsel_five | | | | | v----------+----------v | divsel_two | | divsel_four | | +----------+----------+ +----------+----------+ | | | v v v | +--------------------+ | Input to MMSSCC block | | | | for DP pixel clock +--> dp_link_2x_clk_mux <--+ | | +----------+---------+ | +---------------------+ | Input to MMSSCC block | | (aux_clk_ops) | | for link clk, crypto clk +--> vco_divided_clk <-+ and interface clock | _src_mux | +----------+----------+ | v Input to MMSSCC block for link clk, crypto clk and interface clock for DP pixel clock ****************************************************************************** */ Loading @@ -68,14 +65,9 @@ v----------+----------v | divsel_five | | divsel_ten | #include "mdss-dp-pll.h" #include "mdss-dp-pll-8998.h" static const struct clk_ops clk_ops_hsclk_divsel_clk_src_c; static const struct clk_ops clk_ops_vco_divided_clk_src_c; static const struct clk_ops clk_ops_link_2x_clk_div_c; static struct clk_div_ops hsclk_divsel_ops = { .set_div = hsclk_divsel_set_div, .get_div = hsclk_divsel_get_div, }; static const struct clk_ops clk_ops_gen_mux_dp; static struct clk_div_ops link2xclk_divsel_ops = { .set_div = link2xclk_divsel_set_div, Loading @@ -101,8 +93,8 @@ static struct clk_mux_ops mdss_mux_ops = { }; static struct dp_pll_vco_clk dp_vco_clk = { .min_rate = DP_VCO_RATE_8100MHz, .max_rate = DP_VCO_RATE_10800MHz, .min_rate = DP_VCO_HSCLK_RATE_1620MHz, .max_rate = DP_VCO_HSCLK_RATE_5400MHz, .c = { .dbg_name = "dp_vco_clk", .ops = &dp_8998_vco_clk_ops, Loading @@ -111,21 +103,6 @@ static struct dp_pll_vco_clk dp_vco_clk = { }, }; static struct div_clk hsclk_divsel_clk_src = { .data = { .min_div = 2, .max_div = 3, }, .ops = &hsclk_divsel_ops, .c = { .parent = &dp_vco_clk.c, .dbg_name = "hsclk_divsel_clk_src", .ops = &clk_ops_hsclk_divsel_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(hsclk_divsel_clk_src.c), }, }; static struct div_clk dp_link_2x_clk_divsel_five = { .data = { .div = 5, Loading @@ -134,7 +111,7 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, .ops = &link2xclk_divsel_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .parent = &dp_vco_clk.c, .dbg_name = "dp_link_2x_clk_divsel_five", .ops = &clk_ops_link_2x_clk_div_c, .flags = CLKFLAG_NO_RATE_CACHE, Loading @@ -142,61 +119,60 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, }; static struct div_clk dp_link_2x_clk_divsel_ten = { static struct div_clk vco_divsel_four_clk_src = { .data = { .div = 10, .min_div = 10, .max_div = 10, .div = 4, .min_div = 4, .max_div = 4, }, .ops = &link2xclk_divsel_ops, .ops = &vco_divided_clk_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .dbg_name = "dp_link_2x_clk_divsel_ten", .ops = &clk_ops_link_2x_clk_div_c, .parent = &dp_vco_clk.c, .dbg_name = "vco_divsel_four_clk_src", .ops = &clk_ops_vco_divided_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(dp_link_2x_clk_divsel_ten.c), CLK_INIT(vco_divsel_four_clk_src.c), }, }; static struct mux_clk dp_link_2x_clk_mux = { .num_parents = 2, .parents = (struct clk_src[]) { {&dp_link_2x_clk_divsel_five.c, 0}, {&dp_link_2x_clk_divsel_ten.c, 1}, static struct div_clk vco_divsel_two_clk_src = { .data = { .div = 2, .min_div = 2, .max_div = 2, }, .ops = &mdss_mux_ops, .ops = &vco_divided_clk_ops, .c = { .parent = &dp_link_2x_clk_divsel_five.c, .dbg_name = "dp_link_2x_clk_mux", .ops = &clk_ops_gen_mux, .parent = &dp_vco_clk.c, .dbg_name = "vco_divsel_two_clk_src", .ops = &clk_ops_vco_divided_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(dp_link_2x_clk_mux.c), } CLK_INIT(vco_divsel_two_clk_src.c), }, }; static struct div_clk vco_divided_clk_src = { .data = { .div = 4, .min_div = 4, .max_div = 4, static struct mux_clk vco_divided_clk_src_mux = { .num_parents = 2, .parents = (struct clk_src[]) { {&vco_divsel_two_clk_src.c, 0}, {&vco_divsel_four_clk_src.c, 1}, }, .ops = &vco_divided_clk_ops, .ops = &mdss_mux_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .dbg_name = "vco_divided_clk", .ops = &clk_ops_vco_divided_clk_src_c, .parent = &vco_divsel_two_clk_src.c, .dbg_name = "vco_divided_clk_src_mux", .ops = &clk_ops_gen_mux_dp, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(vco_divided_clk_src.c), }, CLK_INIT(vco_divided_clk_src_mux.c), } }; static struct clk_lookup dp_pllcc_8998[] = { CLK_LIST(dp_vco_clk), CLK_LIST(hsclk_divsel_clk_src), CLK_LIST(dp_link_2x_clk_divsel_five), CLK_LIST(dp_link_2x_clk_divsel_ten), CLK_LIST(dp_link_2x_clk_mux), CLK_LIST(vco_divided_clk_src), CLK_LIST(vco_divsel_four_clk_src), CLK_LIST(vco_divsel_two_clk_src), CLK_LIST(vco_divided_clk_src_mux), }; int dp_pll_clock_register_8998(struct platform_device *pdev, Loading @@ -211,14 +187,10 @@ int dp_pll_clock_register_8998(struct platform_device *pdev, /* Set client data for vco, mux and div clocks */ dp_vco_clk.priv = pll_res; hsclk_divsel_clk_src.priv = pll_res; dp_link_2x_clk_mux.priv = pll_res; vco_divided_clk_src.priv = pll_res; vco_divided_clk_src_mux.priv = pll_res; vco_divsel_two_clk_src.priv = pll_res; vco_divsel_four_clk_src.priv = pll_res; dp_link_2x_clk_divsel_five.priv = pll_res; dp_link_2x_clk_divsel_ten.priv = pll_res; clk_ops_hsclk_divsel_clk_src_c = clk_ops_div; clk_ops_hsclk_divsel_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_link_2x_clk_div_c = clk_ops_div; clk_ops_link_2x_clk_div_c.prepare = mdss_pll_div_prepare; Loading @@ -233,6 +205,9 @@ int dp_pll_clock_register_8998(struct platform_device *pdev, clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_vco_divided_clk_src_c.handoff = vco_divided_clk_handoff; clk_ops_gen_mux_dp = clk_ops_gen_mux; clk_ops_gen_mux_dp.get_rate = parent_get_rate; /* We can select different clock ops for future versions */ dp_vco_clk.c.ops = &dp_8998_vco_clk_ops; Loading drivers/clk/qcom/mdss/mdss-dp-pll-8998.h +11 −1 Original line number Diff line number Diff line Loading @@ -59,12 +59,19 @@ #define TXn_SLEW_CNTL 0x0030 #define TXn_INTERFACE_SELECT 0x0034 #define TXn_RES_CODE_LANE_TX 0x003C #define TXn_RES_CODE_LANE_RX 0x0040 #define TXn_RES_CODE_LANE_OFFSET_TX 0x0044 #define TXn_RES_CODE_LANE_OFFSET_RX 0x0048 #define TXn_DEBUG_BUS_SEL 0x0058 #define TXn_TRANSCEIVER_BIAS_EN 0x005C #define TXn_HIGHZ_DRVR_EN 0x0060 #define TXn_TX_POL_INV 0x0064 #define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 #define TXn_LANE_MODE_1 0x008C #define TXn_TRAN_DRVR_EMP_EN 0x00C0 #define TXn_TX_INTERFACE_MODE 0x00C4 Loading Loading @@ -149,9 +156,12 @@ #define DP_PLL_POLL_TIMEOUT_US 10000 #define DP_VCO_RATE_8100MHz 8100000000ULL #define DP_VCO_RATE_9720MHz 9720000000ULL #define DP_VCO_RATE_10800MHz 10800000000ULL #define DP_VCO_HSCLK_RATE_1620MHz 1620000000ULL #define DP_VCO_HSCLK_RATE_2700MHz 2700000000ULL #define DP_VCO_HSCLK_RATE_5400MHz 5400000000ULL int dp_vco_set_rate(struct clk *c, unsigned long rate); unsigned long dp_vco_get_rate(struct clk *c); long dp_vco_round_rate(struct clk *c, unsigned long rate); Loading Loading
drivers/clk/qcom/mdss/mdss-dp-pll-8998-util.c +209 −167 Original line number Diff line number Diff line Loading @@ -49,13 +49,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1 |= 0x4; /*configure DP PHY MODE */ phy_mode = 0x48; phy_mode = 0x58; if (div == 10) { link2xclk_div_tx0 |= 1; link2xclk_div_tx1 |= 1; phy_mode |= 1; } MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_BAND, link2xclk_div_tx0); Loading @@ -64,7 +59,8 @@ int link2xclk_divsel_set_div(struct div_clk *clk, int div) link2xclk_div_tx1); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_MODE, phy_mode); /* Make sure the PHY register writes are done */ wmb(); pr_debug("%s: div=%d link2xclk_div_tx0=%x, link2xclk_div_tx1=%x\n", __func__, div, link2xclk_div_tx0, link2xclk_div_tx1); Loading Loading @@ -105,63 +101,6 @@ int link2xclk_divsel_get_div(struct div_clk *clk) return div; } int hsclk_divsel_set_div(struct div_clk *clk, int div) { int rc; u32 hsclk_div; struct mdss_pll_resources *dp_res = clk->priv; rc = mdss_pll_resource_enable(dp_res, true); if (rc) { pr_err("Failed to enable mdss DP PLL resources\n"); return rc; } hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); hsclk_div &= ~0x0f; /* bits 0 to 3 */ if (div == 3) hsclk_div |= 4; else hsclk_div |= 0; MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_HSCLK_SEL, hsclk_div); pr_debug("%s: div=%d hsclk_div=%x\n", __func__, div, hsclk_div); mdss_pll_resource_enable(dp_res, false); return rc; } int hsclk_divsel_get_div(struct div_clk *clk) { int rc; u32 hsclk_div, div; struct mdss_pll_resources *dp_res = clk->priv; rc = mdss_pll_resource_enable(dp_res, true); if (rc) { pr_err("Failed to enable dp_res resources\n"); return rc; } hsclk_div = MDSS_PLL_REG_R(dp_res->pll_base, QSERDES_COM_HSCLK_SEL); hsclk_div &= 0x0f; if (hsclk_div == 4) div = 3; else div = 2; mdss_pll_resource_enable(dp_res, false); pr_debug("%s: hsclk_div:%d, div=%d\n", __func__, hsclk_div, div); return div; } int vco_divided_clk_set_div(struct div_clk *clk, int div) { int rc; Loading @@ -174,18 +113,18 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div) return rc; } auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= ~0x03; /* bits 0 to 1 */ auxclk_div |= 1; /* Default divider */ if (div == 4) auxclk_div |= 2; else if (div == 2) auxclk_div |= 1; else auxclk_div |= 2; /* Default divider */ MDSS_PLL_REG_W(dp_res->pll_base, MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, auxclk_div); /* Make sure the PHY registers writes are done */ wmb(); pr_debug("%s: div=%d auxclk_div=%x\n", __func__, div, auxclk_div); mdss_pll_resource_enable(dp_res, false); Loading Loading @@ -215,15 +154,12 @@ int vco_divided_clk_get_div(struct div_clk *clk) return rc; } auxclk_div = MDSS_PLL_REG_R(dp_res->pll_base, DP_PHY_VCO_DIV); auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= 0x03; div = 2; /* Default divider */ if (auxclk_div == 2) div = 4; else if (auxclk_div == 1) div = 2; else div = 0; mdss_pll_resource_enable(dp_res, false); Loading @@ -239,14 +175,12 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3d); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_IVCO, 0x0f); /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL, 0x01); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0e); Loading @@ -255,16 +189,16 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CLK_SEL, 0x30); /* Different for each clock rates */ if (rate == DP_VCO_HSCLK_RATE_1620MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_8100MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP_EN, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_CCTRL_MODE0, 0x34); QSERDES_COM_SYS_CLK_CTRL, 0x02); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); QSERDES_COM_HSCLK_SEL, 0x2c); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CP_CTRL_MODE0, 0x08); /* Different for each clock rates */ if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_LOCK_CMP_EN, 0x04); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, Loading @@ -273,58 +207,88 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); } else if (rate == DP_VCO_RATE_9720MHz) { MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x7e); QSERDES_COM_CMN_CONFIG, 0x42); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); QSERDES_COM_LOCK_CMP1_MODE0, 0xbf); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); QSERDES_COM_LOCK_CMP2_MODE0, 0x21); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x09); } else if (rate == DP_VCO_RATE_10800MHz) { QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else if (rate == DP_VCO_HSCLK_RATE_2700MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_8100MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x8c); QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); QSERDES_COM_HSCLK_SEL, 0x84); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); QSERDES_COM_LOCK_CMP_EN, 0x08); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0x0a); } else { pr_err("%s: unsupported rate: %ld\n", __func__, rate); return -EINVAL; } QSERDES_COM_DEC_START_MODE0, 0x69); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); QSERDES_COM_DIV_FRAC_START2_MODE0, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_DIV_FRAC_START3_MODE0, 0x07); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x3f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x38); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else if (rate == DP_VCO_RATE_9720MHz) { } else if (rate == DP_VCO_HSCLK_RATE_5400MHz) { pr_debug("%s: VCO rate: %lld\n", __func__, DP_VCO_RATE_10800MHz); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); QSERDES_COM_SYS_CLK_CTRL, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x43); QSERDES_COM_HSCLK_SEL, 0x80); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else { QSERDES_COM_LOCK_CMP_EN, 0x08); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DEC_START_MODE0, 0x8c); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0, 0xa0); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x12); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP1_MODE0, 0x7f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP2_MODE0, 0x70); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_LOCK_CMP3_MODE0, 0x00); } else { pr_err("%s: unsupported rate: %ld\n", __func__, rate); return -EINVAL; } /* Make sure the PLL register writes are done */ wmb(); if ((rate == DP_VCO_HSCLK_RATE_1620MHz) || (rate == DP_VCO_HSCLK_RATE_2700MHz)) { MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, 0x1); } else { MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, 0x2); } /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3f); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BG_TIMER, 0x00); Loading @@ -335,58 +299,42 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_VCO_TUNE_CTRL, 0x00); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37); QSERDES_COM_CP_CTRL_MODE0, 0x06); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x0f); /* Different for each clock rate */ if (rate == DP_VCO_RATE_8100MHz) { QSERDES_COM_PLL_CCTRL_MODE0, 0x36); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } else if (rate == DP_VCO_RATE_9720MHz) { QSERDES_COM_PLL_RCTRL_MODE0, 0x16); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } else { QSERDES_COM_PLL_IVCO, 0x07); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CMN_CONFIG, 0x02); } QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x37); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_CORE_CLK_EN, 0x0f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x00); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x00); /* Make sure the PLL register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x38); DP_PHY_MODE, 0x58); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x38); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2c); DP_PHY_TX0_TX1_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x2c); DP_PHY_TX2_TX3_LANE_CTL, 0x05); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX0_TX1_LANE_CTL, 0x05); QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_TX2_TX3_LANE_CTL, 0x05); QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x1a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_VMODE_CTRL1, 0x40); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_PRE_STALL_LDO_BOOST_EN, 0x30); Loading Loading @@ -429,6 +377,15 @@ int dp_config_vco_rate(struct dp_pll_vco_clk *vco, unsigned long rate) MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_INTERFACE_MODE, 0x00); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_BAND, 0x4); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_BAND, 0x4); /* Make sure the PHY register writes are done */ wmb(); return res; } Loading Loading @@ -479,9 +436,12 @@ static int dp_pll_enable(struct clk *c) DP_PHY_CFG, 0x01); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); /* Make sure the PHY register writes are done */ wmb(); MDSS_PLL_REG_W(dp_res->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20); /* Make sure the PLL register writes are done */ wmb(); /* poll for PLL ready status */ if (readl_poll_timeout_atomic((dp_res->pll_base + QSERDES_COM_C_READY_STATUS), Loading @@ -497,7 +457,8 @@ static int dp_pll_enable(struct clk *c) MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); /* Make sure the PHY register writes are done */ wmb(); /* poll for PHY ready status */ if (readl_poll_timeout_atomic((dp_res->phy_base + DP_PHY_STATUS), Loading @@ -513,17 +474,17 @@ static int dp_pll_enable(struct clk *c) pr_debug("%s: PLL is locked\n", __func__); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_HIGHZ_DRVR_EN, QSERDES_TX0_OFFSET + TXn_TRANSCEIVER_BIAS_EN, 0x3f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_HIGHZ_DRVR_EN, 0x10); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_POL_INV, Loading @@ -533,6 +494,8 @@ static int dp_pll_enable(struct clk *c) 0x0a); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x18); udelay(2000); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); Loading @@ -542,6 +505,77 @@ static int dp_pll_enable(struct clk *c) */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_LANE_MODE_1, 0xf6); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_LANE_MODE_1, 0xf6); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x1f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x1f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_CLKBUF_ENABLE, 0x0f); /* * Make sure all the register writes are completed before * doing any other operation */ wmb(); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x09); udelay(2000); MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_CFG, 0x19); udelay(2000); /* poll for PHY ready status */ if (readl_poll_timeout_atomic((dp_res->phy_base + DP_PHY_STATUS), status, ((status & BIT(1)) > 0), DP_PLL_POLL_SLEEP_US, DP_PLL_POLL_TIMEOUT_US)) { pr_err("%s: Lane_mode: Phy_ready is not high. Status=%x\n", __func__, status); rc = -EINVAL; goto lock_err; } MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_DRV_LVL, 0x2a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_DRV_LVL, 0x2a); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_TX_EMP_POST1_LVL, 0x20); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_TX_EMP_POST1_LVL, 0x20); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_TX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX0_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x11); MDSS_PLL_REG_W(dp_res->phy_base, QSERDES_TX1_OFFSET + TXn_RES_CODE_LANE_OFFSET_RX, 0x11); /* Make sure the PHY register writes are done */ wmb(); lock_err: return rc; } Loading @@ -554,7 +588,7 @@ static int dp_pll_disable(struct clk *c) /* Assert DP PHY power down */ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_PD_CTL, 0x3c); DP_PHY_PD_CTL, 0x2); /* * Make sure all the register writes to disable PLL are * completed before doing any other operation Loading Loading @@ -655,14 +689,20 @@ unsigned long dp_vco_get_rate(struct clk *c) div = MDSS_PLL_REG_R(pll->pll_base, QSERDES_COM_HSCLK_SEL); div &= 0x0f; if (div == 4) if (div == 12) hsclk_div = 5; /* Default */ else if (div == 4) hsclk_div = 3; else else if (div == 0) hsclk_div = 2; else { pr_debug("unknown divider. forcing to default\n"); hsclk_div = 5; } div = MDSS_PLL_REG_R(pll->phy_base, DP_PHY_MODE); if (div & 0x48) if (div & 0x58) pr_err("%s: DP PAR Rate not correct\n", __func__); if ((div & 0x3) == 1) Loading @@ -673,12 +713,14 @@ unsigned long dp_vco_get_rate(struct clk *c) pr_err("%s: unsupported div. Phy_mode: %d\n", __func__, div); if (link2xclk_div == 10) { vco_rate = DP_VCO_RATE_9720MHz; vco_rate = DP_VCO_HSCLK_RATE_2700MHz; } else { if (hsclk_div == 3) vco_rate = DP_VCO_RATE_8100MHz; if (hsclk_div == 5) vco_rate = DP_VCO_HSCLK_RATE_1620MHz; else if (hsclk_div == 3) vco_rate = DP_VCO_HSCLK_RATE_2700MHz; else vco_rate = DP_VCO_RATE_10800MHz; vco_rate = DP_VCO_HSCLK_RATE_5400MHz; } pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate); Loading @@ -695,8 +737,8 @@ long dp_vco_round_rate(struct clk *c, unsigned long rate) if (rate <= vco->min_rate) rrate = vco->min_rate; else if (rate <= DP_VCO_RATE_9720MHz) rrate = DP_VCO_RATE_9720MHz; else if (rate <= DP_VCO_HSCLK_RATE_2700MHz) rrate = DP_VCO_HSCLK_RATE_2700MHz; else rrate = vco->max_rate; Loading
drivers/clk/qcom/mdss/mdss-dp-pll-8998.c +64 −89 Original line number Diff line number Diff line Loading @@ -16,40 +16,37 @@ ******** Display Port PLL driver block diagram for branch clocks ********** *************************************************************************** +-------------------+ | dp_vco_clk | | (DP PLL/VCO) | +---------+---------+ | | v +----------+-----------+ | hsclk_divsel_clk_src | +----------+-----------+ | +--------------------------+ | DP_VCO_CLK | | | | +-------------------+ | | | (DP PLL/VCO) | | | +---------+---------+ | | v | | +----------+-----------+ | | | hsclk_divsel_clk_src | | | +----------+-----------+ | +--------------------------+ | v +------------<------------|------------>-------------+ | | | | | | +----------v----------+ +----------v----------+ +----------v----------+ |vco_divided_clk_src | | dp_link_2x_clk | | dp_link_2x_clk | | (aux_clk_ops) | | | | | v----------+----------v | divsel_five | | divsel_ten | | dp_link_2x_clk | | vco_divided_clk_src | | vco_divided_clk_src | | divsel_five | | | | | v----------+----------v | divsel_two | | divsel_four | | +----------+----------+ +----------+----------+ | | | v v v | +--------------------+ | Input to MMSSCC block | | | | for DP pixel clock +--> dp_link_2x_clk_mux <--+ | | +----------+---------+ | +---------------------+ | Input to MMSSCC block | | (aux_clk_ops) | | for link clk, crypto clk +--> vco_divided_clk <-+ and interface clock | _src_mux | +----------+----------+ | v Input to MMSSCC block for link clk, crypto clk and interface clock for DP pixel clock ****************************************************************************** */ Loading @@ -68,14 +65,9 @@ v----------+----------v | divsel_five | | divsel_ten | #include "mdss-dp-pll.h" #include "mdss-dp-pll-8998.h" static const struct clk_ops clk_ops_hsclk_divsel_clk_src_c; static const struct clk_ops clk_ops_vco_divided_clk_src_c; static const struct clk_ops clk_ops_link_2x_clk_div_c; static struct clk_div_ops hsclk_divsel_ops = { .set_div = hsclk_divsel_set_div, .get_div = hsclk_divsel_get_div, }; static const struct clk_ops clk_ops_gen_mux_dp; static struct clk_div_ops link2xclk_divsel_ops = { .set_div = link2xclk_divsel_set_div, Loading @@ -101,8 +93,8 @@ static struct clk_mux_ops mdss_mux_ops = { }; static struct dp_pll_vco_clk dp_vco_clk = { .min_rate = DP_VCO_RATE_8100MHz, .max_rate = DP_VCO_RATE_10800MHz, .min_rate = DP_VCO_HSCLK_RATE_1620MHz, .max_rate = DP_VCO_HSCLK_RATE_5400MHz, .c = { .dbg_name = "dp_vco_clk", .ops = &dp_8998_vco_clk_ops, Loading @@ -111,21 +103,6 @@ static struct dp_pll_vco_clk dp_vco_clk = { }, }; static struct div_clk hsclk_divsel_clk_src = { .data = { .min_div = 2, .max_div = 3, }, .ops = &hsclk_divsel_ops, .c = { .parent = &dp_vco_clk.c, .dbg_name = "hsclk_divsel_clk_src", .ops = &clk_ops_hsclk_divsel_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(hsclk_divsel_clk_src.c), }, }; static struct div_clk dp_link_2x_clk_divsel_five = { .data = { .div = 5, Loading @@ -134,7 +111,7 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, .ops = &link2xclk_divsel_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .parent = &dp_vco_clk.c, .dbg_name = "dp_link_2x_clk_divsel_five", .ops = &clk_ops_link_2x_clk_div_c, .flags = CLKFLAG_NO_RATE_CACHE, Loading @@ -142,61 +119,60 @@ static struct div_clk dp_link_2x_clk_divsel_five = { }, }; static struct div_clk dp_link_2x_clk_divsel_ten = { static struct div_clk vco_divsel_four_clk_src = { .data = { .div = 10, .min_div = 10, .max_div = 10, .div = 4, .min_div = 4, .max_div = 4, }, .ops = &link2xclk_divsel_ops, .ops = &vco_divided_clk_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .dbg_name = "dp_link_2x_clk_divsel_ten", .ops = &clk_ops_link_2x_clk_div_c, .parent = &dp_vco_clk.c, .dbg_name = "vco_divsel_four_clk_src", .ops = &clk_ops_vco_divided_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(dp_link_2x_clk_divsel_ten.c), CLK_INIT(vco_divsel_four_clk_src.c), }, }; static struct mux_clk dp_link_2x_clk_mux = { .num_parents = 2, .parents = (struct clk_src[]) { {&dp_link_2x_clk_divsel_five.c, 0}, {&dp_link_2x_clk_divsel_ten.c, 1}, static struct div_clk vco_divsel_two_clk_src = { .data = { .div = 2, .min_div = 2, .max_div = 2, }, .ops = &mdss_mux_ops, .ops = &vco_divided_clk_ops, .c = { .parent = &dp_link_2x_clk_divsel_five.c, .dbg_name = "dp_link_2x_clk_mux", .ops = &clk_ops_gen_mux, .parent = &dp_vco_clk.c, .dbg_name = "vco_divsel_two_clk_src", .ops = &clk_ops_vco_divided_clk_src_c, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(dp_link_2x_clk_mux.c), } CLK_INIT(vco_divsel_two_clk_src.c), }, }; static struct div_clk vco_divided_clk_src = { .data = { .div = 4, .min_div = 4, .max_div = 4, static struct mux_clk vco_divided_clk_src_mux = { .num_parents = 2, .parents = (struct clk_src[]) { {&vco_divsel_two_clk_src.c, 0}, {&vco_divsel_four_clk_src.c, 1}, }, .ops = &vco_divided_clk_ops, .ops = &mdss_mux_ops, .c = { .parent = &hsclk_divsel_clk_src.c, .dbg_name = "vco_divided_clk", .ops = &clk_ops_vco_divided_clk_src_c, .parent = &vco_divsel_two_clk_src.c, .dbg_name = "vco_divided_clk_src_mux", .ops = &clk_ops_gen_mux_dp, .flags = CLKFLAG_NO_RATE_CACHE, CLK_INIT(vco_divided_clk_src.c), }, CLK_INIT(vco_divided_clk_src_mux.c), } }; static struct clk_lookup dp_pllcc_8998[] = { CLK_LIST(dp_vco_clk), CLK_LIST(hsclk_divsel_clk_src), CLK_LIST(dp_link_2x_clk_divsel_five), CLK_LIST(dp_link_2x_clk_divsel_ten), CLK_LIST(dp_link_2x_clk_mux), CLK_LIST(vco_divided_clk_src), CLK_LIST(vco_divsel_four_clk_src), CLK_LIST(vco_divsel_two_clk_src), CLK_LIST(vco_divided_clk_src_mux), }; int dp_pll_clock_register_8998(struct platform_device *pdev, Loading @@ -211,14 +187,10 @@ int dp_pll_clock_register_8998(struct platform_device *pdev, /* Set client data for vco, mux and div clocks */ dp_vco_clk.priv = pll_res; hsclk_divsel_clk_src.priv = pll_res; dp_link_2x_clk_mux.priv = pll_res; vco_divided_clk_src.priv = pll_res; vco_divided_clk_src_mux.priv = pll_res; vco_divsel_two_clk_src.priv = pll_res; vco_divsel_four_clk_src.priv = pll_res; dp_link_2x_clk_divsel_five.priv = pll_res; dp_link_2x_clk_divsel_ten.priv = pll_res; clk_ops_hsclk_divsel_clk_src_c = clk_ops_div; clk_ops_hsclk_divsel_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_link_2x_clk_div_c = clk_ops_div; clk_ops_link_2x_clk_div_c.prepare = mdss_pll_div_prepare; Loading @@ -233,6 +205,9 @@ int dp_pll_clock_register_8998(struct platform_device *pdev, clk_ops_vco_divided_clk_src_c.prepare = mdss_pll_div_prepare; clk_ops_vco_divided_clk_src_c.handoff = vco_divided_clk_handoff; clk_ops_gen_mux_dp = clk_ops_gen_mux; clk_ops_gen_mux_dp.get_rate = parent_get_rate; /* We can select different clock ops for future versions */ dp_vco_clk.c.ops = &dp_8998_vco_clk_ops; Loading
drivers/clk/qcom/mdss/mdss-dp-pll-8998.h +11 −1 Original line number Diff line number Diff line Loading @@ -59,12 +59,19 @@ #define TXn_SLEW_CNTL 0x0030 #define TXn_INTERFACE_SELECT 0x0034 #define TXn_RES_CODE_LANE_TX 0x003C #define TXn_RES_CODE_LANE_RX 0x0040 #define TXn_RES_CODE_LANE_OFFSET_TX 0x0044 #define TXn_RES_CODE_LANE_OFFSET_RX 0x0048 #define TXn_DEBUG_BUS_SEL 0x0058 #define TXn_TRANSCEIVER_BIAS_EN 0x005C #define TXn_HIGHZ_DRVR_EN 0x0060 #define TXn_TX_POL_INV 0x0064 #define TXn_PARRATE_REC_DETECT_IDLE_EN 0x0068 #define TXn_LANE_MODE_1 0x008C #define TXn_TRAN_DRVR_EMP_EN 0x00C0 #define TXn_TX_INTERFACE_MODE 0x00C4 Loading Loading @@ -149,9 +156,12 @@ #define DP_PLL_POLL_TIMEOUT_US 10000 #define DP_VCO_RATE_8100MHz 8100000000ULL #define DP_VCO_RATE_9720MHz 9720000000ULL #define DP_VCO_RATE_10800MHz 10800000000ULL #define DP_VCO_HSCLK_RATE_1620MHz 1620000000ULL #define DP_VCO_HSCLK_RATE_2700MHz 2700000000ULL #define DP_VCO_HSCLK_RATE_5400MHz 5400000000ULL int dp_vco_set_rate(struct clk *c, unsigned long rate); unsigned long dp_vco_get_rate(struct clk *c); long dp_vco_round_rate(struct clk *c, unsigned long rate); Loading