GNU Linux-libre 4.4.292-gnu1
[releases.git] / drivers / clk / spear / clk-frac-synth.c
1 /*
2  * Copyright (C) 2012 ST Microelectronics
3  * Viresh Kumar <vireshk@kernel.org>
4  *
5  * This file is licensed under the terms of the GNU General Public
6  * License version 2. This program is licensed "as is" without any
7  * warranty of any kind, whether express or implied.
8  *
9  * Fractional Synthesizer clock implementation
10  */
11
12 #define pr_fmt(fmt) "clk-frac-synth: " fmt
13
14 #include <linux/clk-provider.h>
15 #include <linux/slab.h>
16 #include <linux/io.h>
17 #include <linux/err.h>
18 #include "clk.h"
19
20 #define DIV_FACTOR_MASK         0x1FFFF
21
22 /*
23  * DOC: Fractional Synthesizer clock
24  *
25  * Fout from synthesizer can be given from below equation:
26  *
27  * Fout= Fin/2*div (division factor)
28  * div is 17 bits:-
29  *      0-13 (fractional part)
30  *      14-16 (integer part)
31  *      div is (16-14 bits).(13-0 bits) (in binary)
32  *
33  *      Fout = Fin/(2 * div)
34  *      Fout = ((Fin / 10000)/(2 * div)) * 10000
35  *      Fout = (2^14 * (Fin / 10000)/(2^14 * (2 * div))) * 10000
36  *      Fout = (((Fin / 10000) << 14)/(2 * (div << 14))) * 10000
37  *
38  * div << 14 simply 17 bit value written at register.
39  * Max error due to scaling down by 10000 is 10 KHz
40  */
41
42 #define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw)
43
44 static unsigned long frac_calc_rate(struct clk_hw *hw, unsigned long prate,
45                 int index)
46 {
47         struct clk_frac *frac = to_clk_frac(hw);
48         struct frac_rate_tbl *rtbl = frac->rtbl;
49
50         prate /= 10000;
51         prate <<= 14;
52         prate /= (2 * rtbl[index].div);
53         prate *= 10000;
54
55         return prate;
56 }
57
58 static long clk_frac_round_rate(struct clk_hw *hw, unsigned long drate,
59                 unsigned long *prate)
60 {
61         struct clk_frac *frac = to_clk_frac(hw);
62         int unused;
63
64         return clk_round_rate_index(hw, drate, *prate, frac_calc_rate,
65                         frac->rtbl_cnt, &unused);
66 }
67
68 static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
69                 unsigned long parent_rate)
70 {
71         struct clk_frac *frac = to_clk_frac(hw);
72         unsigned long flags = 0;
73         unsigned int div = 1, val;
74
75         if (frac->lock)
76                 spin_lock_irqsave(frac->lock, flags);
77
78         val = readl_relaxed(frac->reg);
79
80         if (frac->lock)
81                 spin_unlock_irqrestore(frac->lock, flags);
82
83         div = val & DIV_FACTOR_MASK;
84
85         if (!div)
86                 return 0;
87
88         parent_rate = parent_rate / 10000;
89
90         parent_rate = (parent_rate << 14) / (2 * div);
91         return parent_rate * 10000;
92 }
93
94 /* Configures new clock rate of frac */
95 static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate,
96                                 unsigned long prate)
97 {
98         struct clk_frac *frac = to_clk_frac(hw);
99         struct frac_rate_tbl *rtbl = frac->rtbl;
100         unsigned long flags = 0, val;
101         int i;
102
103         clk_round_rate_index(hw, drate, prate, frac_calc_rate, frac->rtbl_cnt,
104                         &i);
105
106         if (frac->lock)
107                 spin_lock_irqsave(frac->lock, flags);
108
109         val = readl_relaxed(frac->reg) & ~DIV_FACTOR_MASK;
110         val |= rtbl[i].div & DIV_FACTOR_MASK;
111         writel_relaxed(val, frac->reg);
112
113         if (frac->lock)
114                 spin_unlock_irqrestore(frac->lock, flags);
115
116         return 0;
117 }
118
119 static struct clk_ops clk_frac_ops = {
120         .recalc_rate = clk_frac_recalc_rate,
121         .round_rate = clk_frac_round_rate,
122         .set_rate = clk_frac_set_rate,
123 };
124
125 struct clk *clk_register_frac(const char *name, const char *parent_name,
126                 unsigned long flags, void __iomem *reg,
127                 struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock)
128 {
129         struct clk_init_data init;
130         struct clk_frac *frac;
131         struct clk *clk;
132
133         if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
134                 pr_err("Invalid arguments passed");
135                 return ERR_PTR(-EINVAL);
136         }
137
138         frac = kzalloc(sizeof(*frac), GFP_KERNEL);
139         if (!frac) {
140                 pr_err("could not allocate frac clk\n");
141                 return ERR_PTR(-ENOMEM);
142         }
143
144         /* struct clk_frac assignments */
145         frac->reg = reg;
146         frac->rtbl = rtbl;
147         frac->rtbl_cnt = rtbl_cnt;
148         frac->lock = lock;
149         frac->hw.init = &init;
150
151         init.name = name;
152         init.ops = &clk_frac_ops;
153         init.flags = flags;
154         init.parent_names = &parent_name;
155         init.num_parents = 1;
156
157         clk = clk_register(NULL, &frac->hw);
158         if (!IS_ERR_OR_NULL(clk))
159                 return clk;
160
161         pr_err("clk register failed\n");
162         kfree(frac);
163
164         return NULL;
165 }