2 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
3 * Copyright (c) 2013 Linaro Ltd.
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.
9 * This file contains the utility functions to register the pll clocks.
12 #include <linux/errno.h>
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)
27 struct samsung_clk_pll35xx
{
29 const void __iomem
*con_reg
;
32 #define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
34 static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw
*hw
,
35 unsigned long parent_rate
)
37 struct samsung_clk_pll35xx
*pll
= to_clk_pll35xx(hw
);
38 u32 mdiv
, pdiv
, sdiv
, pll_con
;
39 u64 fvco
= parent_rate
;
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
;
47 do_div(fvco
, (pdiv
<< sdiv
));
49 return (unsigned long)fvco
;
52 static const struct clk_ops samsung_pll35xx_clk_ops
= {
53 .recalc_rate
= samsung_pll35xx_recalc_rate
,
56 struct clk
* __init
samsung_clk_register_pll35xx(const char *name
,
57 const char *pname
, const void __iomem
*con_reg
)
59 struct samsung_clk_pll35xx
*pll
;
61 struct clk_init_data init
;
63 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
65 pr_err("%s: could not allocate pll clk %s\n", __func__
, name
);
70 init
.ops
= &samsung_pll35xx_clk_ops
;
71 init
.flags
= CLK_GET_RATE_NOCACHE
;
72 init
.parent_names
= &pname
;
76 pll
->con_reg
= con_reg
;
78 clk
= clk_register(NULL
, &pll
->hw
);
80 pr_err("%s: failed to register pll clock %s\n", __func__
,
85 if (clk_register_clkdev(clk
, name
, NULL
))
86 pr_err("%s: failed to register lookup for %s", __func__
, name
);
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)
103 struct samsung_clk_pll36xx
{
105 const void __iomem
*con_reg
;
108 #define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
110 static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw
*hw
,
111 unsigned long parent_rate
)
113 struct samsung_clk_pll36xx
*pll
= to_clk_pll36xx(hw
);
114 u32 mdiv
, pdiv
, sdiv
, pll_con0
, pll_con1
;
116 u64 fvco
= parent_rate
;
118 pll_con0
= __raw_readl(pll
->con_reg
);
119 pll_con1
= __raw_readl(pll
->con_reg
+ 4);
120 mdiv
= (pll_con0
>> PLL36XX_MDIV_SHIFT
) & PLL36XX_MDIV_MASK
;
121 pdiv
= (pll_con0
>> PLL36XX_PDIV_SHIFT
) & PLL36XX_PDIV_MASK
;
122 sdiv
= (pll_con0
>> PLL36XX_SDIV_SHIFT
) & PLL36XX_SDIV_MASK
;
123 kdiv
= (s16
)(pll_con1
& PLL36XX_KDIV_MASK
);
125 fvco
*= (mdiv
<< 16) + kdiv
;
126 do_div(fvco
, (pdiv
<< sdiv
));
129 return (unsigned long)fvco
;
132 static const struct clk_ops samsung_pll36xx_clk_ops
= {
133 .recalc_rate
= samsung_pll36xx_recalc_rate
,
136 struct clk
* __init
samsung_clk_register_pll36xx(const char *name
,
137 const char *pname
, const void __iomem
*con_reg
)
139 struct samsung_clk_pll36xx
*pll
;
141 struct clk_init_data init
;
143 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
145 pr_err("%s: could not allocate pll clk %s\n", __func__
, name
);
150 init
.ops
= &samsung_pll36xx_clk_ops
;
151 init
.flags
= CLK_GET_RATE_NOCACHE
;
152 init
.parent_names
= &pname
;
153 init
.num_parents
= 1;
155 pll
->hw
.init
= &init
;
156 pll
->con_reg
= con_reg
;
158 clk
= clk_register(NULL
, &pll
->hw
);
160 pr_err("%s: failed to register pll clock %s\n", __func__
,
165 if (clk_register_clkdev(clk
, name
, NULL
))
166 pr_err("%s: failed to register lookup for %s", __func__
, name
);
175 #define PLL45XX_MDIV_MASK (0x3FF)
176 #define PLL45XX_PDIV_MASK (0x3F)
177 #define PLL45XX_SDIV_MASK (0x7)
178 #define PLL45XX_MDIV_SHIFT (16)
179 #define PLL45XX_PDIV_SHIFT (8)
180 #define PLL45XX_SDIV_SHIFT (0)
182 struct samsung_clk_pll45xx
{
184 enum pll45xx_type type
;
185 const void __iomem
*con_reg
;
188 #define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
190 static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw
*hw
,
191 unsigned long parent_rate
)
193 struct samsung_clk_pll45xx
*pll
= to_clk_pll45xx(hw
);
194 u32 mdiv
, pdiv
, sdiv
, pll_con
;
195 u64 fvco
= parent_rate
;
197 pll_con
= __raw_readl(pll
->con_reg
);
198 mdiv
= (pll_con
>> PLL45XX_MDIV_SHIFT
) & PLL45XX_MDIV_MASK
;
199 pdiv
= (pll_con
>> PLL45XX_PDIV_SHIFT
) & PLL45XX_PDIV_MASK
;
200 sdiv
= (pll_con
>> PLL45XX_SDIV_SHIFT
) & PLL45XX_SDIV_MASK
;
202 if (pll
->type
== pll_4508
)
206 do_div(fvco
, (pdiv
<< sdiv
));
208 return (unsigned long)fvco
;
211 static const struct clk_ops samsung_pll45xx_clk_ops
= {
212 .recalc_rate
= samsung_pll45xx_recalc_rate
,
215 struct clk
* __init
samsung_clk_register_pll45xx(const char *name
,
216 const char *pname
, const void __iomem
*con_reg
,
217 enum pll45xx_type type
)
219 struct samsung_clk_pll45xx
*pll
;
221 struct clk_init_data init
;
223 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
225 pr_err("%s: could not allocate pll clk %s\n", __func__
, name
);
230 init
.ops
= &samsung_pll45xx_clk_ops
;
231 init
.flags
= CLK_GET_RATE_NOCACHE
;
232 init
.parent_names
= &pname
;
233 init
.num_parents
= 1;
235 pll
->hw
.init
= &init
;
236 pll
->con_reg
= con_reg
;
239 clk
= clk_register(NULL
, &pll
->hw
);
241 pr_err("%s: failed to register pll clock %s\n", __func__
,
246 if (clk_register_clkdev(clk
, name
, NULL
))
247 pr_err("%s: failed to register lookup for %s", __func__
, name
);
256 #define PLL46XX_MDIV_MASK (0x1FF)
257 #define PLL46XX_PDIV_MASK (0x3F)
258 #define PLL46XX_SDIV_MASK (0x7)
259 #define PLL46XX_MDIV_SHIFT (16)
260 #define PLL46XX_PDIV_SHIFT (8)
261 #define PLL46XX_SDIV_SHIFT (0)
263 #define PLL46XX_KDIV_MASK (0xFFFF)
264 #define PLL4650C_KDIV_MASK (0xFFF)
265 #define PLL46XX_KDIV_SHIFT (0)
267 struct samsung_clk_pll46xx
{
269 enum pll46xx_type type
;
270 const void __iomem
*con_reg
;
273 #define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
275 static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw
*hw
,
276 unsigned long parent_rate
)
278 struct samsung_clk_pll46xx
*pll
= to_clk_pll46xx(hw
);
279 u32 mdiv
, pdiv
, sdiv
, kdiv
, pll_con0
, pll_con1
, shift
;
280 u64 fvco
= parent_rate
;
282 pll_con0
= __raw_readl(pll
->con_reg
);
283 pll_con1
= __raw_readl(pll
->con_reg
+ 4);
284 mdiv
= (pll_con0
>> PLL46XX_MDIV_SHIFT
) & PLL46XX_MDIV_MASK
;
285 pdiv
= (pll_con0
>> PLL46XX_PDIV_SHIFT
) & PLL46XX_PDIV_MASK
;
286 sdiv
= (pll_con0
>> PLL46XX_SDIV_SHIFT
) & PLL46XX_SDIV_MASK
;
287 kdiv
= pll
->type
== pll_4650c
? pll_con1
& PLL4650C_KDIV_MASK
:
288 pll_con1
& PLL46XX_KDIV_MASK
;
290 shift
= pll
->type
== pll_4600
? 16 : 10;
291 fvco
*= (mdiv
<< shift
) + kdiv
;
292 do_div(fvco
, (pdiv
<< sdiv
));
295 return (unsigned long)fvco
;
298 static const struct clk_ops samsung_pll46xx_clk_ops
= {
299 .recalc_rate
= samsung_pll46xx_recalc_rate
,
302 struct clk
* __init
samsung_clk_register_pll46xx(const char *name
,
303 const char *pname
, const void __iomem
*con_reg
,
304 enum pll46xx_type type
)
306 struct samsung_clk_pll46xx
*pll
;
308 struct clk_init_data init
;
310 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
312 pr_err("%s: could not allocate pll clk %s\n", __func__
, name
);
317 init
.ops
= &samsung_pll46xx_clk_ops
;
318 init
.flags
= CLK_GET_RATE_NOCACHE
;
319 init
.parent_names
= &pname
;
320 init
.num_parents
= 1;
322 pll
->hw
.init
= &init
;
323 pll
->con_reg
= con_reg
;
326 clk
= clk_register(NULL
, &pll
->hw
);
328 pr_err("%s: failed to register pll clock %s\n", __func__
,
333 if (clk_register_clkdev(clk
, name
, NULL
))
334 pr_err("%s: failed to register lookup for %s", __func__
, name
);
340 * PLL2550x Clock Type
343 #define PLL2550X_R_MASK (0x1)
344 #define PLL2550X_P_MASK (0x3F)
345 #define PLL2550X_M_MASK (0x3FF)
346 #define PLL2550X_S_MASK (0x7)
347 #define PLL2550X_R_SHIFT (20)
348 #define PLL2550X_P_SHIFT (14)
349 #define PLL2550X_M_SHIFT (4)
350 #define PLL2550X_S_SHIFT (0)
352 struct samsung_clk_pll2550x
{
354 const void __iomem
*reg_base
;
355 unsigned long offset
;
358 #define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
360 static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw
*hw
,
361 unsigned long parent_rate
)
363 struct samsung_clk_pll2550x
*pll
= to_clk_pll2550x(hw
);
364 u32 r
, p
, m
, s
, pll_stat
;
365 u64 fvco
= parent_rate
;
367 pll_stat
= __raw_readl(pll
->reg_base
+ pll
->offset
* 3);
368 r
= (pll_stat
>> PLL2550X_R_SHIFT
) & PLL2550X_R_MASK
;
371 p
= (pll_stat
>> PLL2550X_P_SHIFT
) & PLL2550X_P_MASK
;
372 m
= (pll_stat
>> PLL2550X_M_SHIFT
) & PLL2550X_M_MASK
;
373 s
= (pll_stat
>> PLL2550X_S_SHIFT
) & PLL2550X_S_MASK
;
376 do_div(fvco
, (p
<< s
));
378 return (unsigned long)fvco
;
381 static const struct clk_ops samsung_pll2550x_clk_ops
= {
382 .recalc_rate
= samsung_pll2550x_recalc_rate
,
385 struct clk
* __init
samsung_clk_register_pll2550x(const char *name
,
386 const char *pname
, const void __iomem
*reg_base
,
387 const unsigned long offset
)
389 struct samsung_clk_pll2550x
*pll
;
391 struct clk_init_data init
;
393 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
395 pr_err("%s: could not allocate pll clk %s\n", __func__
, name
);
400 init
.ops
= &samsung_pll2550x_clk_ops
;
401 init
.flags
= CLK_GET_RATE_NOCACHE
;
402 init
.parent_names
= &pname
;
403 init
.num_parents
= 1;
405 pll
->hw
.init
= &init
;
406 pll
->reg_base
= reg_base
;
407 pll
->offset
= offset
;
409 clk
= clk_register(NULL
, &pll
->hw
);
411 pr_err("%s: failed to register pll clock %s\n", __func__
,
416 if (clk_register_clkdev(clk
, name
, NULL
))
417 pr_err("%s: failed to register lookup for %s", __func__
, name
);