void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
 int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
        struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
+void msm_dsi_pll_save_state(struct msm_dsi_pll *pll);
+int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll);
 #else
 static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
                         enum msm_dsi_phy_type type, int id) {
 {
        return -ENODEV;
 }
+static inline void msm_dsi_pll_save_state(struct msm_dsi_pll *pll)
+{
+}
+static inline int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll)
+{
+       return 0;
+}
 #endif
 
 /* dsi host */
 
        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
        struct msm_dsi_phy *phy = msm_dsi->phy;
        int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
+       struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
        int ret;
 
        ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
        if (ret)
                return ret;
 
+       /*
+        * Reset DSI PHY silently changes its PLL registers to reset status,
+        * which will confuse clock driver and result in wrong output rate of
+        * link clocks. Restore PLL status if its PLL is being used as clock
+        * source.
+        */
+       if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER)) {
+               ret = msm_dsi_pll_restore_state(pll);
+               if (ret) {
+                       pr_err("%s: failed to restore pll state\n", __func__);
+                       msm_dsi_phy_disable(phy);
+                       return ret;
+               }
+       }
+
        msm_dsi->phy_enabled = true;
        msm_dsi_phy_get_clk_pre_post(phy, clk_pre, clk_post);
 
        struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
        struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
        struct msm_dsi_phy *phy = msm_dsi->phy;
+       struct msm_dsi_pll *pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+
+       /* Save PLL status if it is a clock source */
+       if (!IS_DUAL_DSI() || (id == DSI_CLOCK_MASTER))
+               msm_dsi_pll_save_state(pll);
 
        /* disable DSI phy
         * In dual-dsi configuration, the phy should be disabled for the
 
 int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw)
 {
        struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
-       int ret;
-
-       /*
-        * Certain PLLs need to update the same VCO rate and registers
-        * after resume in suspend/resume scenario.
-        */
-       if (pll->restore_state) {
-               ret = pll->restore_state(pll);
-               if (ret)
-                       goto error;
-       }
 
-       ret = dsi_pll_enable(pll);
-
-error:
-       return ret;
+       return dsi_pll_enable(pll);
 }
 
 void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw)
 {
        struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
 
-       if (pll->save_state)
-               pll->save_state(pll);
-
        dsi_pll_disable(pll);
 }
 
                pll->destroy(pll);
 }
 
+void msm_dsi_pll_save_state(struct msm_dsi_pll *pll)
+{
+       if (pll->save_state) {
+               pll->save_state(pll);
+               pll->state_saved = true;
+       }
+}
+
+int msm_dsi_pll_restore_state(struct msm_dsi_pll *pll)
+{
+       int ret;
+
+       if (pll->restore_state && pll->state_saved) {
+               ret = pll->restore_state(pll);
+               if (ret)
+                       return ret;
+
+               pll->state_saved = false;
+       }
+
+       return 0;
+}
+
 struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
                        enum msm_dsi_phy_type type, int id)
 {
 
 
        struct clk_hw   clk_hw;
        bool            pll_on;
+       bool            state_saved;
 
        unsigned long   min_rate;
        unsigned long   max_rate;
 
        void __iomem *base = pll_28nm->mmio;
        int ret;
 
-       if ((cached_state->vco_rate != 0) &&
-               (cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) {
-               ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
-                                               cached_state->vco_rate, 0);
-               if (ret) {
-                       dev_err(&pll_28nm->pdev->dev,
-                               "restore vco rate failed. ret=%d\n", ret);
-                       return ret;
-               }
-
-               pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
-                               cached_state->postdiv3);
-               pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
-                               cached_state->postdiv1);
-               pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
-                               cached_state->byte_mux);
-
-               cached_state->vco_rate = 0;
+       ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
+                                       cached_state->vco_rate, 0);
+       if (ret) {
+               dev_err(&pll_28nm->pdev->dev,
+                       "restore vco rate failed. ret=%d\n", ret);
+               return ret;
        }
 
+       pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+                       cached_state->postdiv3);
+       pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+                       cached_state->postdiv1);
+       pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
+                       cached_state->byte_mux);
+
        return 0;
 }