aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s3c/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-s3c/time.c')
-rw-r--r--arch/arm/plat-s3c/time.c66
1 files changed, 45 insertions, 21 deletions
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}