From: Ranjani Vaidyanathan Date: Tue, 17 Sep 2013 22:14:05 +0000 (-0500) Subject: ENGR00280101-3 [iMX6x] Add support for bypass mode rates X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=1b84e825f12f76f358167ec317b5486efa0c727e;p=karo-tx-linux.git ENGR00280101-3 [iMX6x] Add support for bypass mode rates Fix the code to report correct PFD and PLL clock rates when the PLL is in bypass state. Signed-off-by: Ranjani Vaidyanathan --- diff --git a/arch/arm/mach-imx/clk-pfd.c b/arch/arm/mach-imx/clk-pfd.c index e2ed4160f329..9e480751c11a 100644 --- a/arch/arm/mach-imx/clk-pfd.c +++ b/arch/arm/mach-imx/clk-pfd.c @@ -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 #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; diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 331ae0d30b9e..6559a5ccf585 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c @@ -25,6 +25,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 @@ -128,14 +130,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; @@ -146,6 +161,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;