aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s3c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-s3c')
-rw-r--r--arch/arm/plat-s3c/include/plat/clock.h5
-rw-r--r--arch/arm/plat-s3c/pwm-clock.c28
-rw-r--r--arch/arm/plat-s3c/time.c66
3 files changed, 65 insertions, 34 deletions
diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h
index ea1f3ffa9717..a10622eed43a 100644
--- a/arch/arm/plat-s3c/include/plat/clock.h
+++ b/arch/arm/plat-s3c/include/plat/clock.h
@@ -81,3 +81,8 @@ extern void s3c2443_setup_clocks(void);
81/* S3C64XX specific functions and clocks */ 81/* S3C64XX specific functions and clocks */
82 82
83extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable); 83extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
84
85/* Init for pwm clock code */
86
87extern void s3c_pwmclk_init(void);
88
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c
index 988c0cd7ade2..a318215ab535 100644
--- a/arch/arm/plat-s3c/pwm-clock.c
+++ b/arch/arm/plat-s3c/pwm-clock.c
@@ -407,7 +407,16 @@ static __init int clk_pwm_tin_register(struct clk *pwm)
407 return clk_set_parent(pwm, parent); 407 return clk_set_parent(pwm, parent);
408} 408}
409 409
410static __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)
411{ 420{
412 struct clk *clk_timers; 421 struct clk *clk_timers;
413 unsigned int clk; 422 unsigned int clk;
@@ -416,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void)
416 clk_timers = clk_get(NULL, "timers"); 425 clk_timers = clk_get(NULL, "timers");
417 if (IS_ERR(clk_timers)) { 426 if (IS_ERR(clk_timers)) {
418 printk(KERN_ERR "%s: no parent clock\n", __func__); 427 printk(KERN_ERR "%s: no parent clock\n", __func__);
419 return -EINVAL; 428 return;
420 } 429 }
421 430
422 for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) { 431 for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) {
@@ -424,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void)
424 ret = s3c24xx_register_clock(&clk_timer_scaler[clk]); 433 ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
425 if (ret < 0) { 434 if (ret < 0) {
426 printk(KERN_ERR "error adding pwm scaler%d clock\n", clk); 435 printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
427 goto err; 436 return;
428 } 437 }
429 } 438 }
430 439
@@ -432,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void)
432 ret = s3c24xx_register_clock(&clk_timer_tclk[clk]); 441 ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
433 if (ret < 0) { 442 if (ret < 0) {
434 printk(KERN_ERR "error adding pww tclk%d\n", clk); 443 printk(KERN_ERR "error adding pww tclk%d\n", clk);
435 goto err; 444 return;
436 } 445 }
437 } 446 }
438 447
@@ -440,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void)
440 ret = clk_pwm_tdiv_register(clk); 449 ret = clk_pwm_tdiv_register(clk);
441 if (ret < 0) { 450 if (ret < 0) {
442 printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk); 451 printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
443 goto err; 452 return;
444 } 453 }
445 } 454 }
446 455
@@ -448,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void)
448 ret = clk_pwm_tin_register(&clk_tin[clk]); 457 ret = clk_pwm_tin_register(&clk_tin[clk]);
449 if (ret < 0) { 458 if (ret < 0) {
450 printk(KERN_ERR "error adding pwm%d tin clock\n", clk); 459 printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
451 goto err; 460 return;
452 } 461 }
453 } 462 }
454
455 return 0;
456
457 err:
458 return ret;
459} 463}
460
461arch_initcall(s3c24xx_pwmclk_init);
diff --git a/arch/arm/plat-s3c/time.c b/arch/arm/plat-s3c/time.c
index a581ff7ba664..3b27b29da478 100644
--- a/arch/arm/plat-s3c/time.c
+++ b/arch/arm/plat-s3c/time.c
@@ -26,6 +26,7 @@
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/io.h> 28#include <linux/io.h>
29#include <linux/platform_device.h>
29 30
30#include <asm/system.h> 31#include <asm/system.h>
31#include <asm/leds.h> 32#include <asm/leds.h>
@@ -147,6 +148,10 @@ static struct irqaction s3c2410_timer_irq = {
147 machine_is_anubis() || \ 148 machine_is_anubis() || \
148 machine_is_osiris()) 149 machine_is_osiris())
149 150
151static struct clk *tin;
152static struct clk *tdiv;
153static struct clk *timerclk;
154
150/* 155/*
151 * Set up timer interrupt, and return the current time in seconds. 156 * Set up timer interrupt, and return the current time in seconds.
152 * 157 *
@@ -162,12 +167,6 @@ static void s3c2410_timer_setup (void)
162 167
163 tcnt = TICK_MAX; /* default value for tcnt */ 168 tcnt = TICK_MAX; /* default value for tcnt */
164 169
165 /* read the current timer configuration bits */
166
167 tcon = __raw_readl(S3C2410_TCON);
168 tcfg1 = __raw_readl(S3C2410_TCFG1);
169 tcfg0 = __raw_readl(S3C2410_TCFG0);
170
171 /* configure the system for whichever machine is in use */ 170 /* configure the system for whichever machine is in use */
172 171
173 if (use_tclk1_12()) { 172 if (use_tclk1_12()) {
@@ -175,11 +174,13 @@ static void s3c2410_timer_setup (void)
175 timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); 174 timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
176 tcnt = 12000000 / HZ; 175 tcnt = 12000000 / HZ;
177 176
177 tcfg1 = __raw_readl(S3C2410_TCFG1);
178 tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; 178 tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
179 tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1; 179 tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
180 __raw_writel(tcfg1, S3C2410_TCFG1);
180 } else { 181 } else {
181 unsigned long pclk; 182 unsigned long pclk;
182 struct clk *clk; 183 struct clk *tscaler;
183 184
184 /* for the h1940 (and others), we use the pclk from the core 185 /* for the h1940 (and others), we use the pclk from the core
185 * to generate the timer values. since values around 50 to 186 * to generate the timer values. since values around 50 to
@@ -190,29 +191,25 @@ static void s3c2410_timer_setup (void)
190 * (8.45 ticks per usec) 191 * (8.45 ticks per usec)
191 */ 192 */
192 193
193 /* this is used as default if no other timer can be found */ 194 pclk = clk_get_rate(timerclk);
194
195 clk = clk_get(NULL, "timers");
196 if (IS_ERR(clk))
197 panic("failed to get clock for system timer");
198
199 clk_enable(clk);
200
201 pclk = clk_get_rate(clk);
202 195
203 /* configure clock tick */ 196 /* configure clock tick */
204 197
205 timer_usec_ticks = timer_mask_usec_ticks(6, pclk); 198 timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
206 199
207 tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK; 200 tscaler = clk_get_parent(tdiv);
208 tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
209 201
210 tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK; 202 clk_set_rate(tscaler, pclk / 3);
211 tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT; 203 clk_set_rate(tdiv, pclk / 6);
204 clk_set_parent(tin, tdiv);
212 205
213 tcnt = (pclk / 6) / HZ; 206 tcnt = clk_get_rate(tin) / HZ;
214 } 207 }
215 208
209 tcon = __raw_readl(S3C2410_TCON);
210 tcfg0 = __raw_readl(S3C2410_TCFG0);
211 tcfg1 = __raw_readl(S3C2410_TCFG1);
212
216 /* timers reload after counting zero, so reduce the count by 1 */ 213 /* timers reload after counting zero, so reduce the count by 1 */
217 214
218 tcnt--; 215 tcnt--;
@@ -248,8 +245,35 @@ static void s3c2410_timer_setup (void)
248 __raw_writel(tcon, S3C2410_TCON); 245 __raw_writel(tcon, S3C2410_TCON);
249} 246}
250 247
248static void __init s3c2410_timer_resources(void)
249{
250 struct platform_device tmpdev;
251
252 tmpdev.dev.bus = &platform_bus_type;
253 tmpdev.id = 4;
254
255 timerclk = clk_get(NULL, "timers");
256 if (IS_ERR(timerclk))
257 panic("failed to get clock for system timer");
258
259 clk_enable(timerclk);
260
261 if (!use_tclk1_12()) {
262 tin = clk_get(&tmpdev.dev, "pwm-tin");
263 if (IS_ERR(tin))
264 panic("failed to get pwm-tin clock for system timer");
265
266 tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
267 if (IS_ERR(tdiv))
268 panic("failed to get pwm-tdiv clock for system timer");
269 }
270
271 clk_enable(tin);
272}
273
251static void __init s3c2410_timer_init(void) 274static void __init s3c2410_timer_init(void)
252{ 275{
276 s3c2410_timer_resources();
253 s3c2410_timer_setup(); 277 s3c2410_timer_setup();
254 setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); 278 setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
255} 279}