@@ -90,6 +90,13 @@ struct dsi_pll_7nm {
9090 /* protects REG_DSI_7nm_PHY_CMN_CLK_CFG1 register */
9191 spinlock_t pclk_mux_lock ;
9292
93+ /*
94+ * protects REG_DSI_7nm_PHY_CMN_CTRL_0 register and pll_enable_cnt
95+ * member
96+ */
97+ spinlock_t pll_enable_lock ;
98+ int pll_enable_cnt ;
99+
93100 struct pll_7nm_cached_state cached_state ;
94101
95102 struct dsi_pll_7nm * slave ;
@@ -103,6 +110,9 @@ struct dsi_pll_7nm {
103110 */
104111static struct dsi_pll_7nm * pll_7nm_list [DSI_MAX ];
105112
113+ static void dsi_pll_enable_pll_bias (struct dsi_pll_7nm * pll );
114+ static void dsi_pll_disable_pll_bias (struct dsi_pll_7nm * pll );
115+
106116static void dsi_pll_setup_config (struct dsi_pll_config * config )
107117{
108118 config -> ssc_freq = 31500 ;
@@ -340,6 +350,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
340350 struct dsi_pll_7nm * pll_7nm = to_pll_7nm (hw );
341351 struct dsi_pll_config config ;
342352
353+ dsi_pll_enable_pll_bias (pll_7nm );
343354 DBG ("DSI PLL%d rate=%lu, parent's=%lu" , pll_7nm -> phy -> id , rate ,
344355 parent_rate );
345356
@@ -357,6 +368,7 @@ static int dsi_pll_7nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
357368
358369 dsi_pll_ssc_commit (pll_7nm , & config );
359370
371+ dsi_pll_disable_pll_bias (pll_7nm );
360372 /* flush, ensure all register writes are done*/
361373 wmb ();
362374
@@ -385,24 +397,47 @@ static int dsi_pll_7nm_lock_status(struct dsi_pll_7nm *pll)
385397
386398static void dsi_pll_disable_pll_bias (struct dsi_pll_7nm * pll )
387399{
400+ unsigned long flags ;
388401 u32 data ;
389402
403+ spin_lock_irqsave (& pll -> pll_enable_lock , flags );
404+ -- pll -> pll_enable_cnt ;
405+ if (pll -> pll_enable_cnt < 0 ) {
406+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
407+ DRM_DEV_ERROR_RATELIMITED (& pll -> phy -> pdev -> dev ,
408+ "bug: imbalance in disabling PLL bias\n" );
409+ return ;
410+ } else if (pll -> pll_enable_cnt > 0 ) {
411+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
412+ return ;
413+ } /* else: == 0 */
414+
390415 data = readl (pll -> phy -> base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
391416 data &= ~DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB ;
392417 writel (0 , pll -> phy -> pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES );
393418 writel (data , pll -> phy -> base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
419+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
394420 ndelay (250 );
395421}
396422
397423static void dsi_pll_enable_pll_bias (struct dsi_pll_7nm * pll )
398424{
425+ unsigned long flags ;
399426 u32 data ;
400427
428+ spin_lock_irqsave (& pll -> pll_enable_lock , flags );
429+ if (pll -> pll_enable_cnt ++ ) {
430+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
431+ WARN_ON (pll -> pll_enable_cnt == INT_MAX );
432+ return ;
433+ }
434+
401435 data = readl (pll -> phy -> base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
402436 data |= DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB ;
403437 writel (data , pll -> phy -> base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
404438
405439 writel (0xc0 , pll -> phy -> pll_base + REG_DSI_7nm_PHY_PLL_SYSTEM_MUXES );
440+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
406441 ndelay (250 );
407442}
408443
@@ -543,6 +578,7 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
543578 u32 dec ;
544579 u64 pll_freq , tmp64 ;
545580
581+ dsi_pll_enable_pll_bias (pll_7nm );
546582 dec = readl (base + REG_DSI_7nm_PHY_PLL_DECIMAL_DIV_START_1 );
547583 dec &= 0xff ;
548584
@@ -567,6 +603,8 @@ static unsigned long dsi_pll_7nm_vco_recalc_rate(struct clk_hw *hw,
567603 DBG ("DSI PLL%d returning vco rate = %lu, dec = %x, frac = %x" ,
568604 pll_7nm -> phy -> id , (unsigned long )vco_rate , dec , frac );
569605
606+ dsi_pll_disable_pll_bias (pll_7nm );
607+
570608 return (unsigned long )vco_rate ;
571609}
572610
@@ -600,6 +638,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
600638 void __iomem * phy_base = pll_7nm -> phy -> base ;
601639 u32 cmn_clk_cfg0 , cmn_clk_cfg1 ;
602640
641+ dsi_pll_enable_pll_bias (pll_7nm );
603642 cached -> pll_out_div = readl (pll_7nm -> phy -> pll_base +
604643 REG_DSI_7nm_PHY_PLL_PLL_OUTDIV_RATE );
605644 cached -> pll_out_div &= 0x3 ;
@@ -611,6 +650,7 @@ static void dsi_7nm_pll_save_state(struct msm_dsi_phy *phy)
611650 cmn_clk_cfg1 = readl (phy_base + REG_DSI_7nm_PHY_CMN_CLK_CFG1 );
612651 cached -> pll_mux = FIELD_GET (DSI_7nm_PHY_CMN_CLK_CFG1_DSICLK_SEL__MASK , cmn_clk_cfg1 );
613652
653+ dsi_pll_disable_pll_bias (pll_7nm );
614654 DBG ("DSI PLL%d outdiv %x bit_clk_div %x pix_clk_div %x pll_mux %x" ,
615655 pll_7nm -> phy -> id , cached -> pll_out_div , cached -> bit_clk_div ,
616656 cached -> pix_clk_div , cached -> pll_mux );
@@ -833,8 +873,10 @@ static int dsi_pll_7nm_init(struct msm_dsi_phy *phy)
833873
834874 spin_lock_init (& pll_7nm -> postdiv_lock );
835875 spin_lock_init (& pll_7nm -> pclk_mux_lock );
876+ spin_lock_init (& pll_7nm -> pll_enable_lock );
836877
837878 pll_7nm -> phy = phy ;
879+ phy -> pll_data = pll_7nm ;
838880
839881 ret = pll_7nm_register (pll_7nm , phy -> provided_clocks -> hws );
840882 if (ret ) {
@@ -923,8 +965,10 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
923965 u32 const delay_us = 5 ;
924966 u32 const timeout_us = 1000 ;
925967 struct msm_dsi_dphy_timing * timing = & phy -> timing ;
968+ struct dsi_pll_7nm * pll = phy -> pll_data ;
926969 void __iomem * base = phy -> base ;
927970 bool less_than_1500_mhz ;
971+ unsigned long flags ;
928972 u32 vreg_ctrl_0 , vreg_ctrl_1 , lane_ctrl0 ;
929973 u32 glbl_pemph_ctrl_0 ;
930974 u32 glbl_str_swi_cal_sel_ctrl , glbl_hstx_str_ctrl_0 ;
@@ -1046,10 +1090,13 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy,
10461090 glbl_rescode_bot_ctrl = 0x3c ;
10471091 }
10481092
1093+ spin_lock_irqsave (& pll -> pll_enable_lock , flags );
1094+ pll -> pll_enable_cnt = 1 ;
10491095 /* de-assert digital and pll power down */
10501096 data = DSI_7nm_PHY_CMN_CTRL_0_DIGTOP_PWRDN_B |
10511097 DSI_7nm_PHY_CMN_CTRL_0_PLL_SHUTDOWNB ;
10521098 writel (data , base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
1099+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
10531100
10541101 /* Assert PLL core reset */
10551102 writel (0x00 , base + REG_DSI_7nm_PHY_CMN_PLL_CNTRL );
@@ -1162,7 +1209,9 @@ static bool dsi_7nm_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
11621209
11631210static void dsi_7nm_phy_disable (struct msm_dsi_phy * phy )
11641211{
1212+ struct dsi_pll_7nm * pll = phy -> pll_data ;
11651213 void __iomem * base = phy -> base ;
1214+ unsigned long flags ;
11661215 u32 data ;
11671216
11681217 DBG ("" );
@@ -1189,8 +1238,12 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy)
11891238 writel (data , base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
11901239 writel (0 , base + REG_DSI_7nm_PHY_CMN_LANE_CTRL0 );
11911240
1241+ spin_lock_irqsave (& pll -> pll_enable_lock , flags );
1242+ pll -> pll_enable_cnt = 0 ;
11921243 /* Turn off all PHY blocks */
11931244 writel (0x00 , base + REG_DSI_7nm_PHY_CMN_CTRL_0 );
1245+ spin_unlock_irqrestore (& pll -> pll_enable_lock , flags );
1246+
11941247 /* make sure phy is turned off */
11951248 wmb ();
11961249
0 commit comments