diff options
-rw-r--r-- | drivers/clk/samsung/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-pll.c | 499 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-pll.h | 41 |
3 files changed, 541 insertions, 1 deletions
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index bd920b43f6e7..78e5aaa55b40 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # Samsung Clock specific Makefile | 2 | # Samsung Clock specific Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_COMMON_CLK) += clk.o | 5 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o |
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c new file mode 100644 index 000000000000..4b2451129d44 --- /dev/null +++ b/drivers/clk/samsung/clk-pll.c | |||
@@ -0,0 +1,499 @@ | |||
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 | /* todo: implement pl35xx clock round rate operation */ | ||
53 | static long samsung_pll35xx_round_rate(struct clk_hw *hw, | ||
54 | unsigned long drate, unsigned long *prate) | ||
55 | { | ||
56 | return -ENOTSUPP; | ||
57 | } | ||
58 | |||
59 | /* todo: implement pl35xx clock set rate */ | ||
60 | static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
61 | unsigned long prate) | ||
62 | { | ||
63 | return -ENOTSUPP; | ||
64 | } | ||
65 | |||
66 | static const struct clk_ops samsung_pll35xx_clk_ops = { | ||
67 | .recalc_rate = samsung_pll35xx_recalc_rate, | ||
68 | .round_rate = samsung_pll35xx_round_rate, | ||
69 | .set_rate = samsung_pll35xx_set_rate, | ||
70 | }; | ||
71 | |||
72 | struct clk * __init samsung_clk_register_pll35xx(const char *name, | ||
73 | const char *pname, const void __iomem *con_reg) | ||
74 | { | ||
75 | struct samsung_clk_pll35xx *pll; | ||
76 | struct clk *clk; | ||
77 | struct clk_init_data init; | ||
78 | |||
79 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
80 | if (!pll) { | ||
81 | pr_err("%s: could not allocate pll clk %s\n", __func__, name); | ||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | init.name = name; | ||
86 | init.ops = &samsung_pll35xx_clk_ops; | ||
87 | init.flags = CLK_GET_RATE_NOCACHE; | ||
88 | init.parent_names = &pname; | ||
89 | init.num_parents = 1; | ||
90 | |||
91 | pll->hw.init = &init; | ||
92 | pll->con_reg = con_reg; | ||
93 | |||
94 | clk = clk_register(NULL, &pll->hw); | ||
95 | if (IS_ERR(clk)) { | ||
96 | pr_err("%s: failed to register pll clock %s\n", __func__, | ||
97 | name); | ||
98 | kfree(pll); | ||
99 | } | ||
100 | |||
101 | if (clk_register_clkdev(clk, name, NULL)) | ||
102 | pr_err("%s: failed to register lookup for %s", __func__, name); | ||
103 | |||
104 | return clk; | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * PLL36xx Clock Type | ||
109 | */ | ||
110 | |||
111 | #define PLL36XX_KDIV_MASK (0xFFFF) | ||
112 | #define PLL36XX_MDIV_MASK (0x1FF) | ||
113 | #define PLL36XX_PDIV_MASK (0x3F) | ||
114 | #define PLL36XX_SDIV_MASK (0x7) | ||
115 | #define PLL36XX_MDIV_SHIFT (16) | ||
116 | #define PLL36XX_PDIV_SHIFT (8) | ||
117 | #define PLL36XX_SDIV_SHIFT (0) | ||
118 | |||
119 | struct samsung_clk_pll36xx { | ||
120 | struct clk_hw hw; | ||
121 | const void __iomem *con_reg; | ||
122 | }; | ||
123 | |||
124 | #define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw) | ||
125 | |||
126 | static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw, | ||
127 | unsigned long parent_rate) | ||
128 | { | ||
129 | struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw); | ||
130 | u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; | ||
131 | u64 fvco = parent_rate; | ||
132 | |||
133 | pll_con0 = __raw_readl(pll->con_reg); | ||
134 | pll_con1 = __raw_readl(pll->con_reg + 4); | ||
135 | mdiv = (pll_con0 >> PLL36XX_MDIV_SHIFT) & PLL36XX_MDIV_MASK; | ||
136 | pdiv = (pll_con0 >> PLL36XX_PDIV_SHIFT) & PLL36XX_PDIV_MASK; | ||
137 | sdiv = (pll_con0 >> PLL36XX_SDIV_SHIFT) & PLL36XX_SDIV_MASK; | ||
138 | kdiv = pll_con1 & PLL36XX_KDIV_MASK; | ||
139 | |||
140 | fvco *= (mdiv << 16) + kdiv; | ||
141 | do_div(fvco, (pdiv << sdiv)); | ||
142 | fvco >>= 16; | ||
143 | |||
144 | return (unsigned long)fvco; | ||
145 | } | ||
146 | |||
147 | /* todo: implement pl36xx clock round rate operation */ | ||
148 | static long samsung_pll36xx_round_rate(struct clk_hw *hw, | ||
149 | unsigned long drate, unsigned long *prate) | ||
150 | { | ||
151 | return -ENOTSUPP; | ||
152 | } | ||
153 | |||
154 | /* todo: implement pl36xx clock set rate */ | ||
155 | static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
156 | unsigned long prate) | ||
157 | { | ||
158 | return -ENOTSUPP; | ||
159 | } | ||
160 | |||
161 | static const struct clk_ops samsung_pll36xx_clk_ops = { | ||
162 | .recalc_rate = samsung_pll36xx_recalc_rate, | ||
163 | .round_rate = samsung_pll36xx_round_rate, | ||
164 | .set_rate = samsung_pll36xx_set_rate, | ||
165 | }; | ||
166 | |||
167 | struct clk * __init samsung_clk_register_pll36xx(const char *name, | ||
168 | const char *pname, const void __iomem *con_reg) | ||
169 | { | ||
170 | struct samsung_clk_pll36xx *pll; | ||
171 | struct clk *clk; | ||
172 | struct clk_init_data init; | ||
173 | |||
174 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
175 | if (!pll) { | ||
176 | pr_err("%s: could not allocate pll clk %s\n", __func__, name); | ||
177 | return NULL; | ||
178 | } | ||
179 | |||
180 | init.name = name; | ||
181 | init.ops = &samsung_pll36xx_clk_ops; | ||
182 | init.flags = CLK_GET_RATE_NOCACHE; | ||
183 | init.parent_names = &pname; | ||
184 | init.num_parents = 1; | ||
185 | |||
186 | pll->hw.init = &init; | ||
187 | pll->con_reg = con_reg; | ||
188 | |||
189 | clk = clk_register(NULL, &pll->hw); | ||
190 | if (IS_ERR(clk)) { | ||
191 | pr_err("%s: failed to register pll clock %s\n", __func__, | ||
192 | name); | ||
193 | kfree(pll); | ||
194 | } | ||
195 | |||
196 | if (clk_register_clkdev(clk, name, NULL)) | ||
197 | pr_err("%s: failed to register lookup for %s", __func__, name); | ||
198 | |||
199 | return clk; | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * PLL45xx Clock Type | ||
204 | */ | ||
205 | |||
206 | #define PLL45XX_MDIV_MASK (0x3FF) | ||
207 | #define PLL45XX_PDIV_MASK (0x3F) | ||
208 | #define PLL45XX_SDIV_MASK (0x7) | ||
209 | #define PLL45XX_MDIV_SHIFT (16) | ||
210 | #define PLL45XX_PDIV_SHIFT (8) | ||
211 | #define PLL45XX_SDIV_SHIFT (0) | ||
212 | |||
213 | struct samsung_clk_pll45xx { | ||
214 | struct clk_hw hw; | ||
215 | enum pll45xx_type type; | ||
216 | const void __iomem *con_reg; | ||
217 | }; | ||
218 | |||
219 | #define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw) | ||
220 | |||
221 | static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw, | ||
222 | unsigned long parent_rate) | ||
223 | { | ||
224 | struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw); | ||
225 | u32 mdiv, pdiv, sdiv, pll_con; | ||
226 | u64 fvco = parent_rate; | ||
227 | |||
228 | pll_con = __raw_readl(pll->con_reg); | ||
229 | mdiv = (pll_con >> PLL45XX_MDIV_SHIFT) & PLL45XX_MDIV_MASK; | ||
230 | pdiv = (pll_con >> PLL45XX_PDIV_SHIFT) & PLL45XX_PDIV_MASK; | ||
231 | sdiv = (pll_con >> PLL45XX_SDIV_SHIFT) & PLL45XX_SDIV_MASK; | ||
232 | |||
233 | if (pll->type == pll_4508) | ||
234 | sdiv = sdiv - 1; | ||
235 | |||
236 | fvco *= mdiv; | ||
237 | do_div(fvco, (pdiv << sdiv)); | ||
238 | |||
239 | return (unsigned long)fvco; | ||
240 | } | ||
241 | |||
242 | /* todo: implement pl45xx clock round rate operation */ | ||
243 | static long samsung_pll45xx_round_rate(struct clk_hw *hw, | ||
244 | unsigned long drate, unsigned long *prate) | ||
245 | { | ||
246 | return -ENOTSUPP; | ||
247 | } | ||
248 | |||
249 | /* todo: implement pl45xx clock set rate */ | ||
250 | static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
251 | unsigned long prate) | ||
252 | { | ||
253 | return -ENOTSUPP; | ||
254 | } | ||
255 | |||
256 | static const struct clk_ops samsung_pll45xx_clk_ops = { | ||
257 | .recalc_rate = samsung_pll45xx_recalc_rate, | ||
258 | .round_rate = samsung_pll45xx_round_rate, | ||
259 | .set_rate = samsung_pll45xx_set_rate, | ||
260 | }; | ||
261 | |||
262 | struct clk * __init samsung_clk_register_pll45xx(const char *name, | ||
263 | const char *pname, const void __iomem *con_reg, | ||
264 | enum pll45xx_type type) | ||
265 | { | ||
266 | struct samsung_clk_pll45xx *pll; | ||
267 | struct clk *clk; | ||
268 | struct clk_init_data init; | ||
269 | |||
270 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
271 | if (!pll) { | ||
272 | pr_err("%s: could not allocate pll clk %s\n", __func__, name); | ||
273 | return NULL; | ||
274 | } | ||
275 | |||
276 | init.name = name; | ||
277 | init.ops = &samsung_pll45xx_clk_ops; | ||
278 | init.flags = CLK_GET_RATE_NOCACHE; | ||
279 | init.parent_names = &pname; | ||
280 | init.num_parents = 1; | ||
281 | |||
282 | pll->hw.init = &init; | ||
283 | pll->con_reg = con_reg; | ||
284 | pll->type = type; | ||
285 | |||
286 | clk = clk_register(NULL, &pll->hw); | ||
287 | if (IS_ERR(clk)) { | ||
288 | pr_err("%s: failed to register pll clock %s\n", __func__, | ||
289 | name); | ||
290 | kfree(pll); | ||
291 | } | ||
292 | |||
293 | if (clk_register_clkdev(clk, name, NULL)) | ||
294 | pr_err("%s: failed to register lookup for %s", __func__, name); | ||
295 | |||
296 | return clk; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * PLL46xx Clock Type | ||
301 | */ | ||
302 | |||
303 | #define PLL46XX_MDIV_MASK (0x1FF) | ||
304 | #define PLL46XX_PDIV_MASK (0x3F) | ||
305 | #define PLL46XX_SDIV_MASK (0x7) | ||
306 | #define PLL46XX_MDIV_SHIFT (16) | ||
307 | #define PLL46XX_PDIV_SHIFT (8) | ||
308 | #define PLL46XX_SDIV_SHIFT (0) | ||
309 | |||
310 | #define PLL46XX_KDIV_MASK (0xFFFF) | ||
311 | #define PLL4650C_KDIV_MASK (0xFFF) | ||
312 | #define PLL46XX_KDIV_SHIFT (0) | ||
313 | |||
314 | struct samsung_clk_pll46xx { | ||
315 | struct clk_hw hw; | ||
316 | enum pll46xx_type type; | ||
317 | const void __iomem *con_reg; | ||
318 | }; | ||
319 | |||
320 | #define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw) | ||
321 | |||
322 | static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw, | ||
323 | unsigned long parent_rate) | ||
324 | { | ||
325 | struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw); | ||
326 | u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift; | ||
327 | u64 fvco = parent_rate; | ||
328 | |||
329 | pll_con0 = __raw_readl(pll->con_reg); | ||
330 | pll_con1 = __raw_readl(pll->con_reg + 4); | ||
331 | mdiv = (pll_con0 >> PLL46XX_MDIV_SHIFT) & PLL46XX_MDIV_MASK; | ||
332 | pdiv = (pll_con0 >> PLL46XX_PDIV_SHIFT) & PLL46XX_PDIV_MASK; | ||
333 | sdiv = (pll_con0 >> PLL46XX_SDIV_SHIFT) & PLL46XX_SDIV_MASK; | ||
334 | kdiv = pll->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK : | ||
335 | pll_con1 & PLL46XX_KDIV_MASK; | ||
336 | |||
337 | shift = pll->type == pll_4600 ? 16 : 10; | ||
338 | fvco *= (mdiv << shift) + kdiv; | ||
339 | do_div(fvco, (pdiv << sdiv)); | ||
340 | fvco >>= shift; | ||
341 | |||
342 | return (unsigned long)fvco; | ||
343 | } | ||
344 | |||
345 | /* todo: implement pl46xx clock round rate operation */ | ||
346 | static long samsung_pll46xx_round_rate(struct clk_hw *hw, | ||
347 | unsigned long drate, unsigned long *prate) | ||
348 | { | ||
349 | return -ENOTSUPP; | ||
350 | } | ||
351 | |||
352 | /* todo: implement pl46xx clock set rate */ | ||
353 | static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, | ||
354 | unsigned long prate) | ||
355 | { | ||
356 | return -ENOTSUPP; | ||
357 | } | ||
358 | |||
359 | static const struct clk_ops samsung_pll46xx_clk_ops = { | ||
360 | .recalc_rate = samsung_pll46xx_recalc_rate, | ||
361 | .round_rate = samsung_pll46xx_round_rate, | ||
362 | .set_rate = samsung_pll46xx_set_rate, | ||
363 | }; | ||
364 | |||
365 | struct clk * __init samsung_clk_register_pll46xx(const char *name, | ||
366 | const char *pname, const void __iomem *con_reg, | ||
367 | enum pll46xx_type type) | ||
368 | { | ||
369 | struct samsung_clk_pll46xx *pll; | ||
370 | struct clk *clk; | ||
371 | struct clk_init_data init; | ||
372 | |||
373 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
374 | if (!pll) { | ||
375 | pr_err("%s: could not allocate pll clk %s\n", __func__, name); | ||
376 | return NULL; | ||
377 | } | ||
378 | |||
379 | init.name = name; | ||
380 | init.ops = &samsung_pll46xx_clk_ops; | ||
381 | init.flags = CLK_GET_RATE_NOCACHE; | ||
382 | init.parent_names = &pname; | ||
383 | init.num_parents = 1; | ||
384 | |||
385 | pll->hw.init = &init; | ||
386 | pll->con_reg = con_reg; | ||
387 | pll->type = type; | ||
388 | |||
389 | clk = clk_register(NULL, &pll->hw); | ||
390 | if (IS_ERR(clk)) { | ||
391 | pr_err("%s: failed to register pll clock %s\n", __func__, | ||
392 | name); | ||
393 | kfree(pll); | ||
394 | } | ||
395 | |||
396 | if (clk_register_clkdev(clk, name, NULL)) | ||
397 | pr_err("%s: failed to register lookup for %s", __func__, name); | ||
398 | |||
399 | return clk; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * PLL2550x Clock Type | ||
404 | */ | ||
405 | |||
406 | #define PLL2550X_R_MASK (0x1) | ||
407 | #define PLL2550X_P_MASK (0x3F) | ||
408 | #define PLL2550X_M_MASK (0x3FF) | ||
409 | #define PLL2550X_S_MASK (0x7) | ||
410 | #define PLL2550X_R_SHIFT (20) | ||
411 | #define PLL2550X_P_SHIFT (14) | ||
412 | #define PLL2550X_M_SHIFT (4) | ||
413 | #define PLL2550X_S_SHIFT (0) | ||
414 | |||
415 | struct samsung_clk_pll2550x { | ||
416 | struct clk_hw hw; | ||
417 | const void __iomem *reg_base; | ||
418 | unsigned long offset; | ||
419 | }; | ||
420 | |||
421 | #define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw) | ||
422 | |||
423 | static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw, | ||
424 | unsigned long parent_rate) | ||
425 | { | ||
426 | struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw); | ||
427 | u32 r, p, m, s, pll_stat; | ||
428 | u64 fvco = parent_rate; | ||
429 | |||
430 | pll_stat = __raw_readl(pll->reg_base + pll->offset * 3); | ||
431 | r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK; | ||
432 | if (!r) | ||
433 | return 0; | ||
434 | p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK; | ||
435 | m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK; | ||
436 | s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK; | ||
437 | |||
438 | fvco *= m; | ||
439 | do_div(fvco, (p << s)); | ||
440 | |||
441 | return (unsigned long)fvco; | ||
442 | } | ||
443 | |||
444 | /* todo: implement pl2550x clock round rate operation */ | ||
445 | static long samsung_pll2550x_round_rate(struct clk_hw *hw, | ||
446 | unsigned long drate, unsigned long *prate) | ||
447 | { | ||
448 | return -ENOTSUPP; | ||
449 | } | ||
450 | |||
451 | /* todo: implement pl2550x clock set rate */ | ||
452 | static int samsung_pll2550x_set_rate(struct clk_hw *hw, unsigned long drate, | ||
453 | unsigned long prate) | ||
454 | { | ||
455 | return -ENOTSUPP; | ||
456 | } | ||
457 | |||
458 | static const struct clk_ops samsung_pll2550x_clk_ops = { | ||
459 | .recalc_rate = samsung_pll2550x_recalc_rate, | ||
460 | .round_rate = samsung_pll2550x_round_rate, | ||
461 | .set_rate = samsung_pll2550x_set_rate, | ||
462 | }; | ||
463 | |||
464 | struct clk * __init samsung_clk_register_pll2550x(const char *name, | ||
465 | const char *pname, const void __iomem *reg_base, | ||
466 | const unsigned long offset) | ||
467 | { | ||
468 | struct samsung_clk_pll2550x *pll; | ||
469 | struct clk *clk; | ||
470 | struct clk_init_data init; | ||
471 | |||
472 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
473 | if (!pll) { | ||
474 | pr_err("%s: could not allocate pll clk %s\n", __func__, name); | ||
475 | return NULL; | ||
476 | } | ||
477 | |||
478 | init.name = name; | ||
479 | init.ops = &samsung_pll2550x_clk_ops; | ||
480 | init.flags = CLK_GET_RATE_NOCACHE; | ||
481 | init.parent_names = &pname; | ||
482 | init.num_parents = 1; | ||
483 | |||
484 | pll->hw.init = &init; | ||
485 | pll->reg_base = reg_base; | ||
486 | pll->offset = offset; | ||
487 | |||
488 | clk = clk_register(NULL, &pll->hw); | ||
489 | if (IS_ERR(clk)) { | ||
490 | pr_err("%s: failed to register pll clock %s\n", __func__, | ||
491 | name); | ||
492 | kfree(pll); | ||
493 | } | ||
494 | |||
495 | if (clk_register_clkdev(clk, name, NULL)) | ||
496 | pr_err("%s: failed to register lookup for %s", __func__, name); | ||
497 | |||
498 | return clk; | ||
499 | } | ||
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h new file mode 100644 index 000000000000..f33786e9a78b --- /dev/null +++ b/drivers/clk/samsung/clk-pll.h | |||
@@ -0,0 +1,41 @@ | |||
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 | * Common Clock Framework support for all PLL's in Samsung platforms | ||
10 | */ | ||
11 | |||
12 | #ifndef __SAMSUNG_CLK_PLL_H | ||
13 | #define __SAMSUNG_CLK_PLL_H | ||
14 | |||
15 | enum pll45xx_type { | ||
16 | pll_4500, | ||
17 | pll_4502, | ||
18 | pll_4508 | ||
19 | }; | ||
20 | |||
21 | enum pll46xx_type { | ||
22 | pll_4600, | ||
23 | pll_4650, | ||
24 | pll_4650c, | ||
25 | }; | ||
26 | |||
27 | extern struct clk * __init samsung_clk_register_pll35xx(const char *name, | ||
28 | const char *pname, const void __iomem *con_reg); | ||
29 | extern struct clk * __init samsung_clk_register_pll36xx(const char *name, | ||
30 | const char *pname, const void __iomem *con_reg); | ||
31 | extern struct clk * __init samsung_clk_register_pll45xx(const char *name, | ||
32 | const char *pname, const void __iomem *con_reg, | ||
33 | enum pll45xx_type type); | ||
34 | extern struct clk * __init samsung_clk_register_pll46xx(const char *name, | ||
35 | const char *pname, const void __iomem *con_reg, | ||
36 | enum pll46xx_type type); | ||
37 | extern struct clk * __init samsung_clk_register_pll2550x(const char *name, | ||
38 | const char *pname, const void __iomem *reg_base, | ||
39 | const unsigned long offset); | ||
40 | |||
41 | #endif /* __SAMSUNG_CLK_PLL_H */ | ||