]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00280101-3 [iMX6x] Add support for bypass mode rates
authorRanjani Vaidyanathan <ra5478@freescale.com>
Tue, 17 Sep 2013 22:14:05 +0000 (17:14 -0500)
committerLothar Waßmann <LW@KARO-electronics.de>
Wed, 20 Aug 2014 08:06:32 +0000 (10:06 +0200)
Fix the code to report correct PFD and PLL clock rates when
the PLL is in bypass state.

Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
arch/arm/mach-imx/clk-pfd.c
arch/arm/mach-imx/clk-pllv3.c

index 0b0f6f66ec56b680219bdcad3e550670e7130131..6b0ba7f3ea9bd1b2cf0e1d2ea4d998a81fa81cbe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
  * Copyright 2012 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -17,6 +17,8 @@
 #include <linux/err.h>
 #include "clk.h"
 
+#define BYPASS_RATE            24000000
+
 /**
  * struct clk_pfd - IMX PFD clock
  * @clk_hw:    clock source
@@ -62,9 +64,14 @@ static unsigned long clk_pfd_recalc_rate(struct clk_hw *hw,
        u64 tmp = parent_rate;
        u8 frac = (readl_relaxed(pfd->reg) >> (pfd->idx * 8)) & 0x3f;
 
-       tmp *= 18;
-       do_div(tmp, frac);
-
+       /*
+        * If the parent PLL is in bypass state, the PFDs
+        * are also in bypass state.
+        */
+       if (tmp != BYPASS_RATE) {
+               tmp *= 18;
+               do_div(tmp, frac);
+       }
        return tmp;
 }
 
@@ -74,17 +81,22 @@ static long clk_pfd_round_rate(struct clk_hw *hw, unsigned long rate,
        u64 tmp = *prate;
        u8 frac;
 
-       tmp = tmp * 18 + rate / 2;
-       do_div(tmp, rate);
-       frac = tmp;
-       if (frac < 12)
-               frac = 12;
-       else if (frac > 35)
-               frac = 35;
-       tmp = *prate;
-       tmp *= 18;
-       do_div(tmp, frac);
-
+       /*
+        * If the parent PLL is in bypass state, the PFDs
+        * are also in bypass state.
+        */
+       if (tmp != BYPASS_RATE) {
+               tmp = tmp * 18 + rate / 2;
+               do_div(tmp, rate);
+               frac = tmp;
+               if (frac < 12)
+                       frac = 12;
+               else if (frac > 35)
+                       frac = 35;
+               tmp = *prate;
+               tmp *= 18;
+               do_div(tmp, frac);
+       }
        return tmp;
 }
 
@@ -95,6 +107,9 @@ static int clk_pfd_set_rate(struct clk_hw *hw, unsigned long rate,
        u64 tmp = parent_rate;
        u8 frac;
 
+       if (tmp == BYPASS_RATE)
+               return 0;
+
        tmp = tmp * 18 + rate / 2;
        do_div(tmp, rate);
        frac = tmp;
index 633068bbc3c3c8bf4231d5e3dd8a7bd891a273ca..a7284e4a9da18dee9a1bb2d07fb616194f4d2cf9 100644 (file)
@@ -26,6 +26,8 @@
 #define BM_PLL_ENABLE          (0x1 << 13)
 #define BM_PLL_BYPASS          (0x1 << 16)
 #define BM_PLL_LOCK            (0x1 << 31)
+#define BYPASS_RATE            24000000
+#define BYPASS_MASK    0x10000
 
 /**
  * struct clk_pllv3 - IMX PLL clock version 3
@@ -135,14 +137,27 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
 {
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
        u32 div = readl_relaxed(pll->base)  & pll->div_mask;
+       u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
+       u32 rate;
 
-       return (div == 1) ? parent_rate * 22 : parent_rate * 20;
+       if (bypass)
+               rate = BYPASS_RATE;
+       else
+               rate = (div == 1) ? parent_rate * 22 : parent_rate * 20;
+
+       return rate;
 }
 
 static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
                                 unsigned long *prate)
 {
        unsigned long parent_rate = *prate;
+       struct clk_pllv3 *pll = to_clk_pllv3(hw);
+       u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
+
+       /* If the PLL is bypassed, its rate is 24MHz. */
+       if (bypass)
+               return BYPASS_RATE;
 
        return (rate >= parent_rate * 22) ? parent_rate * 22 :
                                            parent_rate * 20;
@@ -153,6 +168,11 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_pllv3 *pll = to_clk_pllv3(hw);
        u32 val, div;
+       u32 bypass = readl_relaxed(pll->base) & BYPASS_MASK;
+
+       /* If the PLL is bypassed, its rate is 24MHz. */
+       if (bypass)
+               return 0;
 
        if (rate == parent_rate * 22)
                div = 1;