Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clk-pllv1.c
Go to the documentation of this file.
1 #include <linux/clk.h>
2 #include <linux/clk-provider.h>
3 #include <linux/io.h>
4 #include <linux/slab.h>
5 #include <linux/kernel.h>
6 #include <linux/err.h>
7 #include <mach/common.h>
8 #include <mach/hardware.h>
9 
10 #include "clk.h"
11 
21 struct clk_pllv1 {
22  struct clk_hw hw;
23  void __iomem *base;
24 };
25 
26 #define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
27 
28 static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
29  unsigned long parent_rate)
30 {
31  struct clk_pllv1 *pll = to_clk_pllv1(hw);
32  long long ll;
33  int mfn_abs;
34  unsigned int mfi, mfn, mfd, pd;
35  u32 reg;
36  unsigned long rate;
37 
38  reg = readl(pll->base);
39 
40  /*
41  * Get the resulting clock rate from a PLL register value and the input
42  * frequency. PLLs with this register layout can be found on i.MX1,
43  * i.MX21, i.MX27 and i,MX31
44  *
45  * mfi + mfn / (mfd + 1)
46  * f = 2 * f_ref * --------------------
47  * pd + 1
48  */
49 
50  mfi = (reg >> 10) & 0xf;
51  mfn = reg & 0x3ff;
52  mfd = (reg >> 16) & 0x3ff;
53  pd = (reg >> 26) & 0xf;
54 
55  mfi = mfi <= 5 ? 5 : mfi;
56 
57  mfn_abs = mfn;
58 
59  /*
60  * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
61  * 2's complements number
62  */
63  if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
64  mfn_abs = 0x400 - mfn;
65 
66  rate = parent_rate * 2;
67  rate /= pd + 1;
68 
69  ll = (unsigned long long)rate * mfn_abs;
70 
71  do_div(ll, mfd + 1);
72 
73  if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
74  ll = -ll;
75 
76  ll = (rate * mfi) + ll;
77 
78  return ll;
79 }
80 
82  .recalc_rate = clk_pllv1_recalc_rate,
83 };
84 
85 struct clk *imx_clk_pllv1(const char *name, const char *parent,
86  void __iomem *base)
87 {
88  struct clk_pllv1 *pll;
89  struct clk *clk;
90  struct clk_init_data init;
91 
92  pll = kmalloc(sizeof(*pll), GFP_KERNEL);
93  if (!pll)
94  return ERR_PTR(-ENOMEM);
95 
96  pll->base = base;
97 
98  init.name = name;
99  init.ops = &clk_pllv1_ops;
100  init.flags = 0;
101  init.parent_names = &parent;
102  init.num_parents = 1;
103 
104  pll->hw.init = &init;
105 
106  clk = clk_register(NULL, &pll->hw);
107  if (IS_ERR(clk))
108  kfree(pll);
109 
110  return clk;
111 }