regmap_write(regmap, PLL_CONFIG_CTL(pll),
                                                config->config_ctl_val);
 
+       if (config->config_ctl_hi_val)
+               regmap_write(regmap, PLL_CONFIG_CTL_U(pll),
+                                               config->config_ctl_hi_val);
+
+       if (config->user_ctl_val)
+               regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val);
+
+       if (config->user_ctl_hi_val)
+               regmap_write(regmap, PLL_USER_CTL_U(pll),
+                                               config->user_ctl_hi_val);
+
+       if (config->test_ctl_val)
+               regmap_write(regmap, PLL_TEST_CTL(pll),
+                                               config->test_ctl_val);
+
+       if (config->test_ctl_hi_val)
+               regmap_write(regmap, PLL_TEST_CTL_U(pll),
+                                               config->test_ctl_hi_val);
+
        if (config->post_div_mask) {
                mask = config->post_div_mask;
                val = config->post_div_val;
        return __clk_alpha_pll_update_latch(pll);
 }
 
+static int alpha_pll_fabia_prepare(struct clk_hw *hw)
+{
+       struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+       const struct pll_vco *vco;
+       struct clk_hw *parent_hw;
+       unsigned long cal_freq, rrate;
+       u32 cal_l, val, alpha_width = pll_alpha_width(pll);
+       u64 a;
+       int ret;
+
+       /* Check if calibration needs to be done i.e. PLL is in reset */
+       ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
+       if (ret)
+               return ret;
+
+       /* Return early if calibration is not needed. */
+       if (val & PLL_RESET_N)
+               return 0;
+
+       vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+       if (!vco) {
+               pr_err("alpha pll: not in a valid vco range\n");
+               return -EINVAL;
+       }
+
+       cal_freq = DIV_ROUND_CLOSEST((pll->vco_table[0].min_freq +
+                               pll->vco_table[0].max_freq) * 54, 100);
+
+       parent_hw = clk_hw_get_parent(hw);
+       if (!parent_hw)
+               return -EINVAL;
+
+       rrate = alpha_pll_round_rate(cal_freq, clk_hw_get_rate(parent_hw),
+                                       &cal_l, &a, alpha_width);
+       /*
+        * Due to a limited number of bits for fractional rate programming, the
+        * rounded up rate could be marginally higher than the requested rate.
+        */
+       if (rrate > (cal_freq + FABIA_PLL_RATE_MARGIN) || rrate < cal_freq)
+               return -EINVAL;
+
+       /* Setup PLL for calibration frequency */
+       regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l);
+
+       /* Bringup the PLL at calibration frequency */
+       ret = clk_alpha_pll_enable(hw);
+       if (ret) {
+               pr_err("alpha pll calibration failed\n");
+               return ret;
+       }
+
+       clk_alpha_pll_disable(hw);
+
+       return 0;
+}
+
 const struct clk_ops clk_alpha_pll_fabia_ops = {
+       .prepare = alpha_pll_fabia_prepare,
        .enable = alpha_pll_fabia_enable,
        .disable = alpha_pll_fabia_disable,
        .is_enabled = clk_alpha_pll_is_enabled,