/*
- * 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
#include <linux/err.h>
#include "clk.h"
+#define BYPASS_RATE 24000000
+
/**
* struct clk_pfd - IMX PFD clock
* @clk_hw: clock source
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;
}
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;
}
u64 tmp = parent_rate;
u8 frac;
+ if (tmp == BYPASS_RATE)
+ return 0;
+
tmp = tmp * 18 + rate / 2;
do_div(tmp, rate);
frac = tmp;
#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
{
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;
{
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;