Merge branch 'msm-fix' of git://codeaurora.org/quic/kernel/davidb/linux-msm into...
[pandora-kernel.git] / arch / arm / plat-samsung / pwm-clock.c
1 /* linux/arch/arm/plat-s3c24xx/pwm-clock.c
2  *
3  * Copyright (c) 2007 Simtec Electronics
4  * Copyright (c) 2007, 2008 Ben Dooks
5  *      Ben Dooks <ben-linux@fluff.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License.
10 */
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/list.h>
16 #include <linux/errno.h>
17 #include <linux/log2.h>
18 #include <linux/clk.h>
19 #include <linux/err.h>
20 #include <linux/io.h>
21
22 #include <mach/hardware.h>
23 #include <mach/map.h>
24 #include <asm/irq.h>
25
26 #include <plat/clock.h>
27 #include <plat/cpu.h>
28
29 #include <plat/regs-timer.h>
30 #include <plat/pwm-clock.h>
31
32 /* Each of the timers 0 through 5 go through the following
33  * clock tree, with the inputs depending on the timers.
34  *
35  * pclk ---- [ prescaler 0 ] -+---> timer 0
36  *                            +---> timer 1
37  *
38  * pclk ---- [ prescaler 1 ] -+---> timer 2
39  *                            +---> timer 3
40  *                            \---> timer 4
41  *
42  * Which are fed into the timers as so:
43  *
44  * prescaled 0 ---- [ div 2,4,8,16 ] ---\
45  *                                     [mux] -> timer 0
46  * tclk 0 ------------------------------/
47  *
48  * prescaled 0 ---- [ div 2,4,8,16 ] ---\
49  *                                     [mux] -> timer 1
50  * tclk 0 ------------------------------/
51  *
52  *
53  * prescaled 1 ---- [ div 2,4,8,16 ] ---\
54  *                                     [mux] -> timer 2
55  * tclk 1 ------------------------------/
56  *
57  * prescaled 1 ---- [ div 2,4,8,16 ] ---\
58  *                                     [mux] -> timer 3
59  * tclk 1 ------------------------------/
60  *
61  * prescaled 1 ---- [ div 2,4,8, 16 ] --\
62  *                                     [mux] -> timer 4
63  * tclk 1 ------------------------------/
64  *
65  * Since the mux and the divider are tied together in the
66  * same register space, it is impossible to set the parent
67  * and the rate at the same time. To avoid this, we add an
68  * intermediate 'prescaled-and-divided' clock to select
69  * as the parent for the timer input clock called tdiv.
70  *
71  * prescaled clk --> pwm-tdiv ---\
72  *                             [ mux ] --> timer X
73  * tclk -------------------------/
74 */
75
76 static struct clk clk_timer_scaler[];
77
78 static unsigned long clk_pwm_scaler_get_rate(struct clk *clk)
79 {
80         unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
81
82         if (clk == &clk_timer_scaler[1]) {
83                 tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
84                 tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
85         } else {
86                 tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
87         }
88
89         return clk_get_rate(clk->parent) / (tcfg0 + 1);
90 }
91
92 static unsigned long clk_pwm_scaler_round_rate(struct clk *clk,
93                                                unsigned long rate)
94 {
95         unsigned long parent_rate = clk_get_rate(clk->parent);
96         unsigned long divisor = parent_rate / rate;
97
98         if (divisor > 256)
99                 divisor = 256;
100         else if (divisor < 2)
101                 divisor = 2;
102
103         return parent_rate / divisor;
104 }
105
106 static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate)
107 {
108         unsigned long round = clk_pwm_scaler_round_rate(clk, rate);
109         unsigned long tcfg0;
110         unsigned long divisor;
111         unsigned long flags;
112
113         divisor = clk_get_rate(clk->parent) / round;
114         divisor--;
115
116         local_irq_save(flags);
117         tcfg0 = __raw_readl(S3C2410_TCFG0);
118
119         if (clk == &clk_timer_scaler[1]) {
120                 tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
121                 tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT;
122         } else {
123                 tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
124                 tcfg0 |= divisor;
125         }
126
127         __raw_writel(tcfg0, S3C2410_TCFG0);
128         local_irq_restore(flags);
129
130         return 0;
131 }
132
133 static struct clk_ops clk_pwm_scaler_ops = {
134         .get_rate       = clk_pwm_scaler_get_rate,
135         .set_rate       = clk_pwm_scaler_set_rate,
136         .round_rate     = clk_pwm_scaler_round_rate,
137 };
138
139 static struct clk clk_timer_scaler[] = {
140         [0]     = {
141                 .name           = "pwm-scaler0",
142                 .id             = -1,
143                 .ops            = &clk_pwm_scaler_ops,
144         },
145         [1]     = {
146                 .name           = "pwm-scaler1",
147                 .id             = -1,
148                 .ops            = &clk_pwm_scaler_ops,
149         },
150 };
151
152 static struct clk clk_timer_tclk[] = {
153         [0]     = {
154                 .name           = "pwm-tclk0",
155                 .id             = -1,
156         },
157         [1]     = {
158                 .name           = "pwm-tclk1",
159                 .id             = -1,
160         },
161 };
162
163 struct pwm_tdiv_clk {
164         struct clk      clk;
165         unsigned int    divisor;
166 };
167
168 static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
169 {
170         return container_of(clk, struct pwm_tdiv_clk, clk);
171 }
172
173 static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
174 {
175         unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
176         unsigned int divisor;
177
178         tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
179         tcfg1 &= S3C2410_TCFG1_MUX_MASK;
180
181         if (pwm_cfg_src_is_tclk(tcfg1))
182                 divisor = to_tdiv(clk)->divisor;
183         else
184                 divisor = tcfg_to_divisor(tcfg1);
185
186         return clk_get_rate(clk->parent) / divisor;
187 }
188
189 static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
190                                              unsigned long rate)
191 {
192         unsigned long parent_rate;
193         unsigned long divisor;
194
195         parent_rate = clk_get_rate(clk->parent);
196         divisor = parent_rate / rate;
197
198         if (divisor <= 1 && pwm_tdiv_has_div1())
199                 divisor = 1;
200         else if (divisor <= 2)
201                 divisor = 2;
202         else if (divisor <= 4)
203                 divisor = 4;
204         else if (divisor <= 8)
205                 divisor = 8;
206         else
207                 divisor = 16;
208
209         return parent_rate / divisor;
210 }
211
212 static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
213 {
214         return pwm_tdiv_div_bits(divclk->divisor);
215 }
216
217 static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
218 {
219         unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
220         unsigned long bits = clk_pwm_tdiv_bits(divclk);
221         unsigned long flags;
222         unsigned long shift =  S3C2410_TCFG1_SHIFT(divclk->clk.id);
223
224         local_irq_save(flags);
225
226         tcfg1 = __raw_readl(S3C2410_TCFG1);
227         tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
228         tcfg1 |= bits << shift;
229         __raw_writel(tcfg1, S3C2410_TCFG1);
230
231         local_irq_restore(flags);
232 }
233
234 static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
235 {
236         struct pwm_tdiv_clk *divclk = to_tdiv(clk);
237         unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
238         unsigned long parent_rate = clk_get_rate(clk->parent);
239         unsigned long divisor;
240
241         tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
242         tcfg1 &= S3C2410_TCFG1_MUX_MASK;
243
244         rate = clk_round_rate(clk, rate);
245         divisor = parent_rate / rate;
246
247         if (divisor > 16)
248                 return -EINVAL;
249
250         divclk->divisor = divisor;
251
252         /* Update the current MUX settings if we are currently
253          * selected as the clock source for this clock. */
254
255         if (!pwm_cfg_src_is_tclk(tcfg1))
256                 clk_pwm_tdiv_update(divclk);
257
258         return 0;
259 }
260
261 static struct clk_ops clk_tdiv_ops = {
262         .get_rate       = clk_pwm_tdiv_get_rate,
263         .set_rate       = clk_pwm_tdiv_set_rate,
264         .round_rate     = clk_pwm_tdiv_round_rate,
265 };
266
267 static struct pwm_tdiv_clk clk_timer_tdiv[] = {
268         [0]     = {
269                 .clk    = {
270                         .name   = "pwm-tdiv",
271                         .devname        = "s3c24xx-pwm.0",
272                         .ops    = &clk_tdiv_ops,
273                         .parent = &clk_timer_scaler[0],
274                 },
275         },
276         [1]     = {
277                 .clk    = {
278                         .name   = "pwm-tdiv",
279                         .devname        = "s3c24xx-pwm.1",
280                         .ops    = &clk_tdiv_ops,
281                         .parent = &clk_timer_scaler[0],
282                 }
283         },
284         [2]     = {
285                 .clk    = {
286                         .name   = "pwm-tdiv",
287                         .devname        = "s3c24xx-pwm.2",
288                         .ops    = &clk_tdiv_ops,
289                         .parent = &clk_timer_scaler[1],
290                 },
291         },
292         [3]     = {
293                 .clk    = {
294                         .name   = "pwm-tdiv",
295                         .devname        = "s3c24xx-pwm.3",
296                         .ops    = &clk_tdiv_ops,
297                         .parent = &clk_timer_scaler[1],
298                 },
299         },
300         [4]     = {
301                 .clk    = {
302                         .name   = "pwm-tdiv",
303                         .devname        = "s3c24xx-pwm.4",
304                         .ops    = &clk_tdiv_ops,
305                         .parent = &clk_timer_scaler[1],
306                 },
307         },
308 };
309
310 static int __init clk_pwm_tdiv_register(unsigned int id)
311 {
312         struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
313         unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
314
315         tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
316         tcfg1 &= S3C2410_TCFG1_MUX_MASK;
317
318         divclk->clk.id = id;
319         divclk->divisor = tcfg_to_divisor(tcfg1);
320
321         return s3c24xx_register_clock(&divclk->clk);
322 }
323
324 static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
325 {
326         return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
327 }
328
329 static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
330 {
331         return &clk_timer_tdiv[id].clk;
332 }
333
334 static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
335 {
336         unsigned int id = clk->id;
337         unsigned long tcfg1;
338         unsigned long flags;
339         unsigned long bits;
340         unsigned long shift = S3C2410_TCFG1_SHIFT(id);
341
342         unsigned long mux_tclk;
343
344         if (soc_is_s3c24xx())
345                 mux_tclk = S3C2410_TCFG1_MUX_TCLK;
346         else if (soc_is_s5p6440() || soc_is_s5p6450())
347                 mux_tclk = 0;
348         else
349                 mux_tclk = S3C64XX_TCFG1_MUX_TCLK;
350
351         if (parent == s3c24xx_pwmclk_tclk(id))
352                 bits = mux_tclk << shift;
353         else if (parent == s3c24xx_pwmclk_tdiv(id))
354                 bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
355         else
356                 return -EINVAL;
357
358         clk->parent = parent;
359
360         local_irq_save(flags);
361
362         tcfg1 = __raw_readl(S3C2410_TCFG1);
363         tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
364         __raw_writel(tcfg1 | bits, S3C2410_TCFG1);
365
366         local_irq_restore(flags);
367
368         return 0;
369 }
370
371 static struct clk_ops clk_tin_ops = {
372         .set_parent     = clk_pwm_tin_set_parent,
373 };
374
375 static struct clk clk_tin[] = {
376         [0]     = {
377                 .name   = "pwm-tin",
378                 .devname        = "s3c24xx-pwm.0",
379                 .id     = 0,
380                 .ops    = &clk_tin_ops,
381         },
382         [1]     = {
383                 .name   = "pwm-tin",
384                 .devname        = "s3c24xx-pwm.1",
385                 .id     = 1,
386                 .ops    = &clk_tin_ops,
387         },
388         [2]     = {
389                 .name   = "pwm-tin",
390                 .devname        = "s3c24xx-pwm.2",
391                 .id     = 2,
392                 .ops    = &clk_tin_ops,
393         },
394         [3]     = {
395                 .name   = "pwm-tin",
396                 .devname        = "s3c24xx-pwm.3",
397                 .id     = 3,
398                 .ops    = &clk_tin_ops,
399         },
400         [4]     = {
401                 .name   = "pwm-tin",
402                 .devname        = "s3c24xx-pwm.4",
403                 .id     = 4,
404                 .ops    = &clk_tin_ops,
405         },
406 };
407
408 static __init int clk_pwm_tin_register(struct clk *pwm)
409 {
410         unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
411         unsigned int id = pwm->id;
412
413         struct clk *parent;
414         int ret;
415
416         ret = s3c24xx_register_clock(pwm);
417         if (ret < 0)
418                 return ret;
419
420         tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
421         tcfg1 &= S3C2410_TCFG1_MUX_MASK;
422
423         if (pwm_cfg_src_is_tclk(tcfg1))
424                 parent = s3c24xx_pwmclk_tclk(id);
425         else
426                 parent = s3c24xx_pwmclk_tdiv(id);
427
428         return clk_set_parent(pwm, parent);
429 }
430
431 /**
432  * s3c_pwmclk_init() - initialise pwm clocks
433  *
434  * Initialise and register the clocks which provide the inputs for the
435  * pwm timer blocks.
436  *
437  * Note, this call is required by the time core, so must be called after
438  * the base clocks are added and before any of the initcalls are run.
439  */
440 __init void s3c_pwmclk_init(void)
441 {
442         struct clk *clk_timers;
443         unsigned int clk;
444         int ret;
445
446         clk_timers = clk_get(NULL, "timers");
447         if (IS_ERR(clk_timers)) {
448                 printk(KERN_ERR "%s: no parent clock\n", __func__);
449                 return;
450         }
451
452         for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++)
453                 clk_timer_scaler[clk].parent = clk_timers;
454
455         s3c_register_clocks(clk_timer_scaler, ARRAY_SIZE(clk_timer_scaler));
456         s3c_register_clocks(clk_timer_tclk, ARRAY_SIZE(clk_timer_tclk));
457
458         for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
459                 ret = clk_pwm_tdiv_register(clk);
460
461                 if (ret < 0) {
462                         printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
463                         return;
464                 }
465         }
466
467         for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
468                 ret = clk_pwm_tin_register(&clk_tin[clk]);
469                 if (ret < 0) {
470                         printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
471                         return;
472                 }
473         }
474 }