]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
soc: xilinx: vcu: Optimize the VCU PLL calculation.
authorDhaval Shah <dhaval.shah@xilinx.com>
Thu, 26 Apr 2018 07:00:31 +0000 (00:00 -0700)
committerMichal Simek <michal.simek@xilinx.com>
Thu, 26 Apr 2018 14:32:20 +0000 (16:32 +0200)
Calculate the maximum and minimum possible FBDIV
values so that number of iteration can be reduce to
calculate FBDIV and divisor for the provided clock
information.

Signed-off-by: Dhaval Shah <dhaval.shah@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
drivers/soc/xilinx/xlnx_vcu.c

index d7808a09a11c3ccb5f3ac6abcd6ad84a30c5e156..0451d9fc2d5b41cb3d10f5e1f146d663972dff0b 100644 (file)
@@ -352,6 +352,7 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
        u32 divisor_mcu, divisor_core, fvco;
        u32 clkoutdiv, vcu_pll_ctrl, pll_clk;
        u32 cfg_val, mod, ctrl;
+       u32 fbdiv_max, fbdiv_min;
        int ret, i;
        const struct xvcu_pll_cfg *found = NULL;
 
@@ -382,6 +383,15 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
 
        refclk = clk_get_rate(xvcu->pll_ref);
 
+       /* Calculate max and min possible FBDIV value */
+       fbdiv_max = FVCO_MAX / refclk;
+       if (fbdiv_max >= ARRAY_SIZE(xvcu_pll_cfg))
+               fbdiv_max = ARRAY_SIZE(xvcu_pll_cfg) - 1;
+
+       fbdiv_min = DIV_ROUND_UP(FVCO_MIN, refclk);
+       dev_dbg(xvcu->dev, "Maximum possible fbdiv value is %u\n", fbdiv_max);
+       dev_dbg(xvcu->dev, "Minimum possible fbdiv value is %u\n", fbdiv_min);
+
        /*
         * The divide-by-2 should be always enabled (==1)
         * to meet the timing in the design.
@@ -395,32 +405,30 @@ static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu)
                return -EINVAL;
        }
 
-       for (i = ARRAY_SIZE(xvcu_pll_cfg) - 1; i >= 0; i--) {
+       for (i = fbdiv_max; i >= fbdiv_min; i--) {
                const struct xvcu_pll_cfg *cfg = &xvcu_pll_cfg[i];
 
                fvco = cfg->fbdiv * refclk;
-               if (fvco >= FVCO_MIN && fvco <= FVCO_MAX) {
-                       pll_clk = fvco / VCU_PLL_DIV2;
-                       if (fvco % VCU_PLL_DIV2 != 0)
-                               pll_clk++;
-                       mod = pll_clk % coreclk;
-                       if (mod < LIMIT) {
-                               divisor_core = pll_clk / coreclk;
-                       } else if (coreclk - mod < LIMIT) {
-                               divisor_core = pll_clk / coreclk;
-                               divisor_core++;
-                       } else {
-                               continue;
-                       }
-                       if (divisor_core >= DIVISOR_MIN &&
-                           divisor_core <= DIVISOR_MAX) {
-                               found = cfg;
-                               divisor_mcu = pll_clk / mcuclk;
-                               mod = pll_clk % mcuclk;
-                               if (mod != 0)
-                                       divisor_mcu++;
-                               break;
-                       }
+               pll_clk = fvco / VCU_PLL_DIV2;
+               if (fvco % VCU_PLL_DIV2 != 0)
+                       pll_clk++;
+               mod = pll_clk % coreclk;
+               if (mod < LIMIT) {
+                       divisor_core = pll_clk / coreclk;
+               } else if (coreclk - mod < LIMIT) {
+                       divisor_core = pll_clk / coreclk;
+                       divisor_core++;
+               } else {
+                       continue;
+               }
+               if (divisor_core >= DIVISOR_MIN &&
+                   divisor_core <= DIVISOR_MAX) {
+                       found = cfg;
+                       divisor_mcu = pll_clk / mcuclk;
+                       mod = pll_clk % mcuclk;
+                       if (mod != 0)
+                               divisor_mcu++;
+                       break;
                }
        }