Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[firefly-linux-kernel-4.4.55.git] / drivers / clk / samsung / clk-pll.c
1 /*
2  * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3  * Copyright (c) 2013 Linaro Ltd.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This file contains the utility functions to register the pll clocks.
10 */
11
12 #include <linux/errno.h>
13 #include "clk.h"
14 #include "clk-pll.h"
15
16 /*
17  * PLL35xx Clock Type
18  */
19
20 #define PLL35XX_MDIV_MASK       (0x3FF)
21 #define PLL35XX_PDIV_MASK       (0x3F)
22 #define PLL35XX_SDIV_MASK       (0x7)
23 #define PLL35XX_MDIV_SHIFT      (16)
24 #define PLL35XX_PDIV_SHIFT      (8)
25 #define PLL35XX_SDIV_SHIFT      (0)
26
27 struct samsung_clk_pll35xx {
28         struct clk_hw           hw;
29         const void __iomem      *con_reg;
30 };
31
32 #define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
33
34 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
35                                 unsigned long parent_rate)
36 {
37         struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
38         u32 mdiv, pdiv, sdiv, pll_con;
39         u64 fvco = parent_rate;
40
41         pll_con = __raw_readl(pll->con_reg);
42         mdiv = (pll_con >> PLL35XX_MDIV_SHIFT) & PLL35XX_MDIV_MASK;
43         pdiv = (pll_con >> PLL35XX_PDIV_SHIFT) & PLL35XX_PDIV_MASK;
44         sdiv = (pll_con >> PLL35XX_SDIV_SHIFT) & PLL35XX_SDIV_MASK;
45
46         fvco *= mdiv;
47         do_div(fvco, (pdiv << sdiv));
48
49         return (unsigned long)fvco;
50 }
51
52 static const struct clk_ops samsung_pll35xx_clk_ops = {
53         .recalc_rate = samsung_pll35xx_recalc_rate,
54 };
55
56 struct clk * __init samsung_clk_register_pll35xx(const char *name,
57                         const char *pname, const void __iomem *con_reg)
58 {
59         struct samsung_clk_pll35xx *pll;
60         struct clk *clk;
61         struct clk_init_data init;
62
63         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
64         if (!pll) {
65                 pr_err("%s: could not allocate pll clk %s\n", __func__, name);
66                 return NULL;
67         }
68
69         init.name = name;
70         init.ops = &samsung_pll35xx_clk_ops;
71         init.flags = CLK_GET_RATE_NOCACHE;
72         init.parent_names = &pname;
73         init.num_parents = 1;
74
75         pll->hw.init = &init;
76         pll->con_reg = con_reg;
77
78         clk = clk_register(NULL, &pll->hw);
79         if (IS_ERR(clk)) {
80                 pr_err("%s: failed to register pll clock %s\n", __func__,
81                                 name);
82                 kfree(pll);
83         }
84
85         if (clk_register_clkdev(clk, name, NULL))
86                 pr_err("%s: failed to register lookup for %s", __func__, name);
87
88         return clk;
89 }
90
91 /*
92  * PLL36xx Clock Type
93  */
94
95 #define PLL36XX_KDIV_MASK       (0xFFFF)
96 #define PLL36XX_MDIV_MASK       (0x1FF)
97 #define PLL36XX_PDIV_MASK       (0x3F)
98 #define PLL36XX_SDIV_MASK       (0x7)
99 #define PLL36XX_MDIV_SHIFT      (16)
100 #define PLL36XX_PDIV_SHIFT      (8)
101 #define PLL36XX_SDIV_SHIFT      (0)
102
103 struct samsung_clk_pll36xx {
104         struct clk_hw           hw;
105         const void __iomem      *con_reg;
106 };
107
108 #define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
109
110 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
111                                 unsigned long parent_rate)
112 {
113         struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
114         u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
115         u64 fvco = parent_rate;
116
117         pll_con0 = __raw_readl(pll->con_reg);
118         pll_con1 = __raw_readl(pll->con_reg + 4);
119         mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK;
120         pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK;
121         sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK;
122         kdiv = pll_con1 & PLL36XX_KDIV_MASK;
123
124         fvco *= (mdiv << 16) + kdiv;
125         do_div(fvco, (pdiv << sdiv));
126         fvco >>= 16;
127
128         return (unsigned long)fvco;
129 }
130
131 static const struct clk_ops samsung_pll36xx_clk_ops = {
132         .recalc_rate = samsung_pll36xx_recalc_rate,
133 };
134
135 struct clk * __init samsung_clk_register_pll36xx(const char *name,
136                         const char *pname, const void __iomem *con_reg)
137 {
138         struct samsung_clk_pll36xx *pll;
139         struct clk *clk;
140         struct clk_init_data init;
141
142         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
143         if (!pll) {
144                 pr_err("%s: could not allocate pll clk %s\n", __func__, name);
145                 return NULL;
146         }
147
148         init.name = name;
149         init.ops = &samsung_pll36xx_clk_ops;
150         init.flags = CLK_GET_RATE_NOCACHE;
151         init.parent_names = &pname;
152         init.num_parents = 1;
153
154         pll->hw.init = &init;
155         pll->con_reg = con_reg;
156
157         clk = clk_register(NULL, &pll->hw);
158         if (IS_ERR(clk)) {
159                 pr_err("%s: failed to register pll clock %s\n", __func__,
160                                 name);
161                 kfree(pll);
162         }
163
164         if (clk_register_clkdev(clk, name, NULL))
165                 pr_err("%s: failed to register lookup for %s", __func__, name);
166
167         return clk;
168 }
169
170 /*
171  * PLL45xx Clock Type
172  */
173
174 #define PLL45XX_MDIV_MASK       (0x3FF)
175 #define PLL45XX_PDIV_MASK       (0x3F)
176 #define PLL45XX_SDIV_MASK       (0x7)
177 #define PLL45XX_MDIV_SHIFT      (16)
178 #define PLL45XX_PDIV_SHIFT      (8)
179 #define PLL45XX_SDIV_SHIFT      (0)
180
181 struct samsung_clk_pll45xx {
182         struct clk_hw           hw;
183         enum pll45xx_type       type;
184         const void __iomem      *con_reg;
185 };
186
187 #define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
188
189 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
190                                 unsigned long parent_rate)
191 {
192         struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
193         u32 mdiv, pdiv, sdiv, pll_con;
194         u64 fvco = parent_rate;
195
196         pll_con = __raw_readl(pll->con_reg);
197         mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK;
198         pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK;
199         sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK;
200
201         if (pll->type == pll_4508)
202                 sdiv = sdiv - 1;
203
204         fvco *= mdiv;
205         do_div(fvco, (pdiv << sdiv));
206
207         return (unsigned long)fvco;
208 }
209
210 static const struct clk_ops samsung_pll45xx_clk_ops = {
211         .recalc_rate = samsung_pll45xx_recalc_rate,
212 };
213
214 struct clk * __init samsung_clk_register_pll45xx(const char *name,
215                         const char *pname, const void __iomem *con_reg,
216                         enum pll45xx_type type)
217 {
218         struct samsung_clk_pll45xx *pll;
219         struct clk *clk;
220         struct clk_init_data init;
221
222         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
223         if (!pll) {
224                 pr_err("%s: could not allocate pll clk %s\n", __func__, name);
225                 return NULL;
226         }
227
228         init.name = name;
229         init.ops = &samsung_pll45xx_clk_ops;
230         init.flags = CLK_GET_RATE_NOCACHE;
231         init.parent_names = &pname;
232         init.num_parents = 1;
233
234         pll->hw.init = &init;
235         pll->con_reg = con_reg;
236         pll->type = type;
237
238         clk = clk_register(NULL, &pll->hw);
239         if (IS_ERR(clk)) {
240                 pr_err("%s: failed to register pll clock %s\n", __func__,
241                                 name);
242                 kfree(pll);
243         }
244
245         if (clk_register_clkdev(clk, name, NULL))
246                 pr_err("%s: failed to register lookup for %s", __func__, name);
247
248         return clk;
249 }
250
251 /*
252  * PLL46xx Clock Type
253  */
254
255 #define PLL46XX_MDIV_MASK       (0x1FF)
256 #define PLL46XX_PDIV_MASK       (0x3F)
257 #define PLL46XX_SDIV_MASK       (0x7)
258 #define PLL46XX_MDIV_SHIFT      (16)
259 #define PLL46XX_PDIV_SHIFT      (8)
260 #define PLL46XX_SDIV_SHIFT      (0)
261
262 #define PLL46XX_KDIV_MASK       (0xFFFF)
263 #define PLL4650C_KDIV_MASK      (0xFFF)
264 #define PLL46XX_KDIV_SHIFT      (0)
265
266 struct samsung_clk_pll46xx {
267         struct clk_hw           hw;
268         enum pll46xx_type       type;
269         const void __iomem      *con_reg;
270 };
271
272 #define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
273
274 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
275                                 unsigned long parent_rate)
276 {
277         struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw);
278         u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
279         u64 fvco = parent_rate;
280
281         pll_con0 = __raw_readl(pll->con_reg);
282         pll_con1 = __raw_readl(pll->con_reg + 4);
283         mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK;
284         pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK;
285         sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK;
286         kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
287                                         pll_con1 & PLL46XX_KDIV_MASK;
288
289         shift = pll->type == pll_4600 ? 16 : 10;
290         fvco *= (mdiv << shift) + kdiv;
291         do_div(fvco, (pdiv << sdiv));
292         fvco >>= shift;
293
294         return (unsigned long)fvco;
295 }
296
297 static const struct clk_ops samsung_pll46xx_clk_ops = {
298         .recalc_rate = samsung_pll46xx_recalc_rate,
299 };
300
301 struct clk * __init samsung_clk_register_pll46xx(const char *name,
302                         const char *pname, const void __iomem *con_reg,
303                         enum pll46xx_type type)
304 {
305         struct samsung_clk_pll46xx *pll;
306         struct clk *clk;
307         struct clk_init_data init;
308
309         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
310         if (!pll) {
311                 pr_err("%s: could not allocate pll clk %s\n", __func__, name);
312                 return NULL;
313         }
314
315         init.name = name;
316         init.ops = &samsung_pll46xx_clk_ops;
317         init.flags = CLK_GET_RATE_NOCACHE;
318         init.parent_names = &pname;
319         init.num_parents = 1;
320
321         pll->hw.init = &init;
322         pll->con_reg = con_reg;
323         pll->type = type;
324
325         clk = clk_register(NULL, &pll->hw);
326         if (IS_ERR(clk)) {
327                 pr_err("%s: failed to register pll clock %s\n", __func__,
328                                 name);
329                 kfree(pll);
330         }
331
332         if (clk_register_clkdev(clk, name, NULL))
333                 pr_err("%s: failed to register lookup for %s", __func__, name);
334
335         return clk;
336 }
337
338 /*
339  * PLL2550x Clock Type
340  */
341
342 #define PLL2550X_R_MASK       (0x1)
343 #define PLL2550X_P_MASK       (0x3F)
344 #define PLL2550X_M_MASK       (0x3FF)
345 #define PLL2550X_S_MASK       (0x7)
346 #define PLL2550X_R_SHIFT      (20)
347 #define PLL2550X_P_SHIFT      (14)
348 #define PLL2550X_M_SHIFT      (4)
349 #define PLL2550X_S_SHIFT      (0)
350
351 struct samsung_clk_pll2550x {
352         struct clk_hw           hw;
353         const void __iomem      *reg_base;
354         unsigned long           offset;
355 };
356
357 #define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
358
359 static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
360                                 unsigned long parent_rate)
361 {
362         struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
363         u32 r, p, m, s, pll_stat;
364         u64 fvco = parent_rate;
365
366         pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
367         r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
368         if (!r)
369                 return 0;
370         p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
371         m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
372         s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
373
374         fvco *= m;
375         do_div(fvco, (p << s));
376
377         return (unsigned long)fvco;
378 }
379
380 static const struct clk_ops samsung_pll2550x_clk_ops = {
381         .recalc_rate = samsung_pll2550x_recalc_rate,
382 };
383
384 struct clk * __init samsung_clk_register_pll2550x(const char *name,
385                         const char *pname, const void __iomem *reg_base,
386                         const unsigned long offset)
387 {
388         struct samsung_clk_pll2550x *pll;
389         struct clk *clk;
390         struct clk_init_data init;
391
392         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
393         if (!pll) {
394                 pr_err("%s: could not allocate pll clk %s\n", __func__, name);
395                 return NULL;
396         }
397
398         init.name = name;
399         init.ops = &samsung_pll2550x_clk_ops;
400         init.flags = CLK_GET_RATE_NOCACHE;
401         init.parent_names = &pname;
402         init.num_parents = 1;
403
404         pll->hw.init = &init;
405         pll->reg_base = reg_base;
406         pll->offset = offset;
407
408         clk = clk_register(NULL, &pll->hw);
409         if (IS_ERR(clk)) {
410                 pr_err("%s: failed to register pll clock %s\n", __func__,
411                                 name);
412                 kfree(pll);
413         }
414
415         if (clk_register_clkdev(clk, name, NULL))
416                 pr_err("%s: failed to register lookup for %s", __func__, name);
417
418         return clk;
419 }