diff options
Diffstat (limited to 'arch/arm/plat-s3c/pwm-clock.c')
-rw-r--r-- | arch/arm/plat-s3c/pwm-clock.c | 71 |
1 files changed, 26 insertions, 45 deletions
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c index e07d82891a92..a318215ab535 100644 --- a/arch/arm/plat-s3c/pwm-clock.c +++ b/arch/arm/plat-s3c/pwm-clock.c | |||
@@ -14,20 +14,20 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/log2.h> | ||
17 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
19 | #include <linux/io.h> | 20 | #include <linux/io.h> |
20 | 21 | ||
21 | #include <mach/hardware.h> | 22 | #include <mach/hardware.h> |
23 | #include <mach/map.h> | ||
22 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
23 | 25 | ||
24 | #include <mach/regs-clock.h> | ||
25 | #include <mach/regs-gpio.h> | ||
26 | |||
27 | #include <plat/clock.h> | 26 | #include <plat/clock.h> |
28 | #include <plat/cpu.h> | 27 | #include <plat/cpu.h> |
29 | 28 | ||
30 | #include <plat/regs-timer.h> | 29 | #include <plat/regs-timer.h> |
30 | #include <mach/pwm-clock.h> | ||
31 | 31 | ||
32 | /* Each of the timers 0 through 5 go through the following | 32 | /* Each of the timers 0 through 5 go through the following |
33 | * clock tree, with the inputs depending on the timers. | 33 | * clock tree, with the inputs depending on the timers. |
@@ -168,11 +168,6 @@ static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk) | |||
168 | return container_of(clk, struct pwm_tdiv_clk, clk); | 168 | return container_of(clk, struct pwm_tdiv_clk, clk); |
169 | } | 169 | } |
170 | 170 | ||
171 | static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) | ||
172 | { | ||
173 | return 1 << (1 + tcfg1); | ||
174 | } | ||
175 | |||
176 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | 171 | static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) |
177 | { | 172 | { |
178 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); | 173 | unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1); |
@@ -181,7 +176,7 @@ static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk) | |||
181 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); | 176 | tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id); |
182 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | 177 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; |
183 | 178 | ||
184 | if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) | 179 | if (pwm_cfg_src_is_tclk(tcfg1)) |
185 | divisor = to_tdiv(clk)->divisor; | 180 | divisor = to_tdiv(clk)->divisor; |
186 | else | 181 | else |
187 | divisor = tcfg_to_divisor(tcfg1); | 182 | divisor = tcfg_to_divisor(tcfg1); |
@@ -198,7 +193,9 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | |||
198 | parent_rate = clk_get_rate(clk->parent); | 193 | parent_rate = clk_get_rate(clk->parent); |
199 | divisor = parent_rate / rate; | 194 | divisor = parent_rate / rate; |
200 | 195 | ||
201 | if (divisor <= 2) | 196 | if (divisor <= 1 && pwm_tdiv_has_div1()) |
197 | divisor = 1; | ||
198 | else if (divisor <= 2) | ||
202 | divisor = 2; | 199 | divisor = 2; |
203 | else if (divisor <= 4) | 200 | else if (divisor <= 4) |
204 | divisor = 4; | 201 | divisor = 4; |
@@ -212,25 +209,7 @@ static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk, | |||
212 | 209 | ||
213 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) | 210 | static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk) |
214 | { | 211 | { |
215 | unsigned long bits; | 212 | return pwm_tdiv_div_bits(divclk->divisor); |
216 | |||
217 | switch (divclk->divisor) { | ||
218 | case 2: | ||
219 | bits = S3C2410_TCFG1_MUX_DIV2; | ||
220 | break; | ||
221 | case 4: | ||
222 | bits = S3C2410_TCFG1_MUX_DIV4; | ||
223 | break; | ||
224 | case 8: | ||
225 | bits = S3C2410_TCFG1_MUX_DIV8; | ||
226 | break; | ||
227 | case 16: | ||
228 | default: | ||
229 | bits = S3C2410_TCFG1_MUX_DIV16; | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | return bits; | ||
234 | } | 213 | } |
235 | 214 | ||
236 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) | 215 | static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk) |
@@ -271,7 +250,7 @@ static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate) | |||
271 | /* Update the current MUX settings if we are currently | 250 | /* Update the current MUX settings if we are currently |
272 | * selected as the clock source for this clock. */ | 251 | * selected as the clock source for this clock. */ |
273 | 252 | ||
274 | if (tcfg1 != S3C2410_TCFG1_MUX_TCLK) | 253 | if (!pwm_cfg_src_is_tclk(tcfg1)) |
275 | clk_pwm_tdiv_update(divclk); | 254 | clk_pwm_tdiv_update(divclk); |
276 | 255 | ||
277 | return 0; | 256 | return 0; |
@@ -358,7 +337,7 @@ static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent) | |||
358 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); | 337 | unsigned long shift = S3C2410_TCFG1_SHIFT(id); |
359 | 338 | ||
360 | if (parent == s3c24xx_pwmclk_tclk(id)) | 339 | if (parent == s3c24xx_pwmclk_tclk(id)) |
361 | bits = S3C2410_TCFG1_MUX_TCLK << shift; | 340 | bits = S3C_TCFG1_MUX_TCLK << shift; |
362 | else if (parent == s3c24xx_pwmclk_tdiv(id)) | 341 | else if (parent == s3c24xx_pwmclk_tdiv(id)) |
363 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; | 342 | bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift; |
364 | else | 343 | else |
@@ -420,7 +399,7 @@ static __init int clk_pwm_tin_register(struct clk *pwm) | |||
420 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); | 399 | tcfg1 >>= S3C2410_TCFG1_SHIFT(id); |
421 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; | 400 | tcfg1 &= S3C2410_TCFG1_MUX_MASK; |
422 | 401 | ||
423 | if (tcfg1 == S3C2410_TCFG1_MUX_TCLK) | 402 | if (pwm_cfg_src_is_tclk(tcfg1)) |
424 | parent = s3c24xx_pwmclk_tclk(id); | 403 | parent = s3c24xx_pwmclk_tclk(id); |
425 | else | 404 | else |
426 | parent = s3c24xx_pwmclk_tdiv(id); | 405 | parent = s3c24xx_pwmclk_tdiv(id); |
@@ -428,7 +407,16 @@ static __init int clk_pwm_tin_register(struct clk *pwm) | |||
428 | return clk_set_parent(pwm, parent); | 407 | return clk_set_parent(pwm, parent); |
429 | } | 408 | } |
430 | 409 | ||
431 | static __init int s3c24xx_pwmclk_init(void) | 410 | /** |
411 | * s3c_pwmclk_init() - initialise pwm clocks | ||
412 | * | ||
413 | * Initialise and register the clocks which provide the inputs for the | ||
414 | * pwm timer blocks. | ||
415 | * | ||
416 | * Note, this call is required by the time core, so must be called after | ||
417 | * the base clocks are added and before any of the initcalls are run. | ||
418 | */ | ||
419 | __init void s3c_pwmclk_init(void) | ||
432 | { | 420 | { |
433 | struct clk *clk_timers; | 421 | struct clk *clk_timers; |
434 | unsigned int clk; | 422 | unsigned int clk; |
@@ -437,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
437 | clk_timers = clk_get(NULL, "timers"); | 425 | clk_timers = clk_get(NULL, "timers"); |
438 | if (IS_ERR(clk_timers)) { | 426 | if (IS_ERR(clk_timers)) { |
439 | printk(KERN_ERR "%s: no parent clock\n", __func__); | 427 | printk(KERN_ERR "%s: no parent clock\n", __func__); |
440 | return -EINVAL; | 428 | return; |
441 | } | 429 | } |
442 | 430 | ||
443 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { | 431 | for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { |
@@ -445,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
445 | ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); | 433 | ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); |
446 | if (ret < 0) { | 434 | if (ret < 0) { |
447 | printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); | 435 | printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); |
448 | goto err; | 436 | return; |
449 | } | 437 | } |
450 | } | 438 | } |
451 | 439 | ||
@@ -453,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
453 | ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); | 441 | ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); |
454 | if (ret < 0) { | 442 | if (ret < 0) { |
455 | printk(KERN_ERR "error adding pww tclk%d\n", clk); | 443 | printk(KERN_ERR "error adding pww tclk%d\n", clk); |
456 | goto err; | 444 | return; |
457 | } | 445 | } |
458 | } | 446 | } |
459 | 447 | ||
@@ -461,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
461 | ret = clk_pwm_tdiv_register(clk); | 449 | ret = clk_pwm_tdiv_register(clk); |
462 | if (ret < 0) { | 450 | if (ret < 0) { |
463 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); | 451 | printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); |
464 | goto err; | 452 | return; |
465 | } | 453 | } |
466 | } | 454 | } |
467 | 455 | ||
@@ -469,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void) | |||
469 | ret = clk_pwm_tin_register(&clk_tin[clk]); | 457 | ret = clk_pwm_tin_register(&clk_tin[clk]); |
470 | if (ret < 0) { | 458 | if (ret < 0) { |
471 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); | 459 | printk(KERN_ERR "error adding pwm%d tin clock\n", clk); |
472 | goto err; | 460 | return; |
473 | } | 461 | } |
474 | } | 462 | } |
475 | |||
476 | return 0; | ||
477 | |||
478 | err: | ||
479 | return ret; | ||
480 | } | 463 | } |
481 | |||
482 | arch_initcall(s3c24xx_pwmclk_init); | ||