aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c2412/clock.c1
-rw-r--r--arch/arm/mach-s3c2443/clock.c2
-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
-rw-r--r--arch/arm/plat-s3c24xx/s3c2410-clock.c1
-rw-r--r--arch/arm/plat-s3c64xx/clock.c2
7 files changed, 71 insertions, 34 deletions
diff --git a/arch/arm/mach-s3c2412/clock.c b/arch/arm/mach-s3c2412/clock.c
index 3ce15e0..a037df5 100644
--- a/arch/arm/mach-s3c2412/clock.c
+++ b/arch/arm/mach-s3c2412/clock.c
@@ -767,5 +767,6 @@ int __init s3c2412_baseclk_add(void)
s3c2412_clkcon_enable(clkp, 0);
}
+ s3c_pwmclk_init();
return 0;
}
diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c
index 363f396..fdd4ec3 100644
--- a/arch/arm/mach-s3c2443/clock.c
+++ b/arch/arm/mach-s3c2443/clock.c
@@ -1107,4 +1107,6 @@ void __init s3c2443_init_clocks(int xtal)
(clkp->enable)(clkp, 0);
}
+
+ s3c_pwmclk_init();
}
diff --git a/arch/arm/plat-s3c/include/plat/clock.h b/arch/arm/plat-s3c/include/plat/clock.h
index ea1f3ff..a10622e 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);
/* S3C64XX specific functions and clocks */
extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
+
+/* Init for pwm clock code */
+
+extern void s3c_pwmclk_init(void);
+
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c
index 988c0cd..a318215 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)
return clk_set_parent(pwm, parent);
}
-static __init int s3c24xx_pwmclk_init(void)
+/**
+ * s3c_pwmclk_init() - initialise pwm clocks
+ *
+ * Initialise and register the clocks which provide the inputs for the
+ * pwm timer blocks.
+ *
+ * Note, this call is required by the time core, so must be called after
+ * the base clocks are added and before any of the initcalls are run.
+ */
+__init void s3c_pwmclk_init(void)
{
struct clk *clk_timers;
unsigned int clk;
@@ -416,7 +425,7 @@ static __init int s3c24xx_pwmclk_init(void)
clk_timers = clk_get(NULL, "timers");
if (IS_ERR(clk_timers)) {
printk(KERN_ERR "%s: no parent clock\n", __func__);
- return -EINVAL;
+ return;
}
for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) {
@@ -424,7 +433,7 @@ static __init int s3c24xx_pwmclk_init(void)
ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
if (ret < 0) {
printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
- goto err;
+ return;
}
}
@@ -432,7 +441,7 @@ static __init int s3c24xx_pwmclk_init(void)
ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
if (ret < 0) {
printk(KERN_ERR "error adding pww tclk%d\n", clk);
- goto err;
+ return;
}
}
@@ -440,7 +449,7 @@ static __init int s3c24xx_pwmclk_init(void)
ret = clk_pwm_tdiv_register(clk);
if (ret < 0) {
printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
- goto err;
+ return;
}
}
@@ -448,14 +457,7 @@ static __init int s3c24xx_pwmclk_init(void)
ret = clk_pwm_tin_register(&clk_tin[clk]);
if (ret < 0) {
printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
- goto err;
+ return;
}
}
-
- return 0;
-
- err:
- return ret;
}
-
-arch_initcall(s3c24xx_pwmclk_init);
diff --git a/arch/arm/plat-s3c/time.c b/arch/arm/plat-s3c/time.c
index a581ff7..3b27b29 100644
--- a/arch/arm/plat-s3c/time.c
+++ b/arch/arm/plat-s3c/time.c
@@ -26,6 +26,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <asm/system.h>
#include <asm/leds.h>
@@ -147,6 +148,10 @@ static struct irqaction s3c2410_timer_irq = {
machine_is_anubis() || \
machine_is_osiris())
+static struct clk *tin;
+static struct clk *tdiv;
+static struct clk *timerclk;
+
/*
* Set up timer interrupt, and return the current time in seconds.
*
@@ -162,12 +167,6 @@ static void s3c2410_timer_setup (void)
tcnt = TICK_MAX; /* default value for tcnt */
- /* read the current timer configuration bits */
-
- tcon = __raw_readl(S3C2410_TCON);
- tcfg1 = __raw_readl(S3C2410_TCFG1);
- tcfg0 = __raw_readl(S3C2410_TCFG0);
-
/* configure the system for whichever machine is in use */
if (use_tclk1_12()) {
@@ -175,11 +174,13 @@ static void s3c2410_timer_setup (void)
timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
tcnt = 12000000 / HZ;
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
+ __raw_writel(tcfg1, S3C2410_TCFG1);
} else {
unsigned long pclk;
- struct clk *clk;
+ struct clk *tscaler;
/* for the h1940 (and others), we use the pclk from the core
* to generate the timer values. since values around 50 to
@@ -190,29 +191,25 @@ static void s3c2410_timer_setup (void)
* (8.45 ticks per usec)
*/
- /* this is used as default if no other timer can be found */
-
- clk = clk_get(NULL, "timers");
- if (IS_ERR(clk))
- panic("failed to get clock for system timer");
-
- clk_enable(clk);
-
- pclk = clk_get_rate(clk);
+ pclk = clk_get_rate(timerclk);
/* configure clock tick */
timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
- tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
- tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
+ tscaler = clk_get_parent(tdiv);
- tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
- tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
+ clk_set_rate(tscaler, pclk / 3);
+ clk_set_rate(tdiv, pclk / 6);
+ clk_set_parent(tin, tdiv);
- tcnt = (pclk / 6) / HZ;
+ tcnt = clk_get_rate(tin) / HZ;
}
+ tcon = __raw_readl(S3C2410_TCON);
+ tcfg0 = __raw_readl(S3C2410_TCFG0);
+ tcfg1 = __raw_readl(S3C2410_TCFG1);
+
/* timers reload after counting zero, so reduce the count by 1 */
tcnt--;
@@ -248,8 +245,35 @@ static void s3c2410_timer_setup (void)
__raw_writel(tcon, S3C2410_TCON);
}
+static void __init s3c2410_timer_resources(void)
+{
+ struct platform_device tmpdev;
+
+ tmpdev.dev.bus = &platform_bus_type;
+ tmpdev.id = 4;
+
+ timerclk = clk_get(NULL, "timers");
+ if (IS_ERR(timerclk))
+ panic("failed to get clock for system timer");
+
+ clk_enable(timerclk);
+
+ if (!use_tclk1_12()) {
+ tin = clk_get(&tmpdev.dev, "pwm-tin");
+ if (IS_ERR(tin))
+ panic("failed to get pwm-tin clock for system timer");
+
+ tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
+ if (IS_ERR(tdiv))
+ panic("failed to get pwm-tdiv clock for system timer");
+ }
+
+ clk_enable(tin);
+}
+
static void __init s3c2410_timer_init(void)
{
+ s3c2410_timer_resources();
s3c2410_timer_setup();
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
}
diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c
index 4e07943..b61bdb7 100644
--- a/arch/arm/plat-s3c24xx/s3c2410-clock.c
+++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c
@@ -272,5 +272,6 @@ int __init s3c2410_baseclk_add(void)
(clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
(clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
+ s3c_pwmclk_init();
return 0;
}
diff --git a/arch/arm/plat-s3c64xx/clock.c b/arch/arm/plat-s3c64xx/clock.c
index 523da0c..5a1e97e 100644
--- a/arch/arm/plat-s3c64xx/clock.c
+++ b/arch/arm/plat-s3c64xx/clock.c
@@ -277,4 +277,6 @@ void s3c64xx_register_clocks(void)
(clkp->enable)(clkp, 0);
}
+
+ s3c_pwmclk_init();
}