diff options
Diffstat (limited to 'arch/arm/mach-omap1/time.c')
-rw-r--r-- | arch/arm/mach-omap1/time.c | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index ed7a61ff916a..f83fc335c613 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -44,16 +44,21 @@ | |||
44 | #include <linux/clocksource.h> | 44 | #include <linux/clocksource.h> |
45 | #include <linux/clockchips.h> | 45 | #include <linux/clockchips.h> |
46 | #include <linux/io.h> | 46 | #include <linux/io.h> |
47 | #include <linux/sched.h> | ||
47 | 48 | ||
48 | #include <asm/system.h> | 49 | #include <asm/system.h> |
49 | #include <mach/hardware.h> | 50 | #include <mach/hardware.h> |
50 | #include <asm/leds.h> | 51 | #include <asm/leds.h> |
51 | #include <asm/irq.h> | 52 | #include <asm/irq.h> |
53 | #include <asm/sched_clock.h> | ||
54 | |||
52 | #include <asm/mach/irq.h> | 55 | #include <asm/mach/irq.h> |
53 | #include <asm/mach/time.h> | 56 | #include <asm/mach/time.h> |
54 | 57 | ||
55 | #include <plat/common.h> | 58 | #include <plat/common.h> |
56 | 59 | ||
60 | #ifdef CONFIG_OMAP_MPU_TIMER | ||
61 | |||
57 | #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE | 62 | #define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE |
58 | #define OMAP_MPU_TIMER_OFFSET 0x100 | 63 | #define OMAP_MPU_TIMER_OFFSET 0x100 |
59 | 64 | ||
@@ -67,7 +72,7 @@ typedef struct { | |||
67 | ((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ | 72 | ((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE + \ |
68 | (n)*OMAP_MPU_TIMER_OFFSET)) | 73 | (n)*OMAP_MPU_TIMER_OFFSET)) |
69 | 74 | ||
70 | static inline unsigned long omap_mpu_timer_read(int nr) | 75 | static inline unsigned long notrace omap_mpu_timer_read(int nr) |
71 | { | 76 | { |
72 | volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); | 77 | volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr); |
73 | return timer->read_tim; | 78 | return timer->read_tim; |
@@ -212,6 +217,32 @@ static struct clocksource clocksource_mpu = { | |||
212 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 217 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
213 | }; | 218 | }; |
214 | 219 | ||
220 | static DEFINE_CLOCK_DATA(cd); | ||
221 | |||
222 | static inline unsigned long long notrace _omap_mpu_sched_clock(void) | ||
223 | { | ||
224 | u32 cyc = mpu_read(&clocksource_mpu); | ||
225 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
226 | } | ||
227 | |||
228 | #ifndef CONFIG_OMAP_32K_TIMER | ||
229 | unsigned long long notrace sched_clock(void) | ||
230 | { | ||
231 | return _omap_mpu_sched_clock(); | ||
232 | } | ||
233 | #else | ||
234 | static unsigned long long notrace omap_mpu_sched_clock(void) | ||
235 | { | ||
236 | return _omap_mpu_sched_clock(); | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | static void notrace mpu_update_sched_clock(void) | ||
241 | { | ||
242 | u32 cyc = mpu_read(&clocksource_mpu); | ||
243 | update_sched_clock(&cd, cyc, (u32)~0); | ||
244 | } | ||
245 | |||
215 | static void __init omap_init_clocksource(unsigned long rate) | 246 | static void __init omap_init_clocksource(unsigned long rate) |
216 | { | 247 | { |
217 | static char err[] __initdata = KERN_ERR | 248 | static char err[] __initdata = KERN_ERR |
@@ -219,17 +250,13 @@ static void __init omap_init_clocksource(unsigned long rate) | |||
219 | 250 | ||
220 | setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); | 251 | setup_irq(INT_TIMER2, &omap_mpu_timer2_irq); |
221 | omap_mpu_timer_start(1, ~0, 1); | 252 | omap_mpu_timer_start(1, ~0, 1); |
253 | init_sched_clock(&cd, mpu_update_sched_clock, 32, rate); | ||
222 | 254 | ||
223 | if (clocksource_register_hz(&clocksource_mpu, rate)) | 255 | if (clocksource_register_hz(&clocksource_mpu, rate)) |
224 | printk(err, clocksource_mpu.name); | 256 | printk(err, clocksource_mpu.name); |
225 | } | 257 | } |
226 | 258 | ||
227 | /* | 259 | static void __init omap_mpu_timer_init(void) |
228 | * --------------------------------------------------------------------------- | ||
229 | * Timer initialization | ||
230 | * --------------------------------------------------------------------------- | ||
231 | */ | ||
232 | static void __init omap_timer_init(void) | ||
233 | { | 260 | { |
234 | struct clk *ck_ref = clk_get(NULL, "ck_ref"); | 261 | struct clk *ck_ref = clk_get(NULL, "ck_ref"); |
235 | unsigned long rate; | 262 | unsigned long rate; |
@@ -246,6 +273,66 @@ static void __init omap_timer_init(void) | |||
246 | omap_init_clocksource(rate); | 273 | omap_init_clocksource(rate); |
247 | } | 274 | } |
248 | 275 | ||
276 | #else | ||
277 | static inline void omap_mpu_timer_init(void) | ||
278 | { | ||
279 | pr_err("Bogus timer, should not happen\n"); | ||
280 | } | ||
281 | #endif /* CONFIG_OMAP_MPU_TIMER */ | ||
282 | |||
283 | #if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER) | ||
284 | static unsigned long long (*preferred_sched_clock)(void); | ||
285 | |||
286 | unsigned long long notrace sched_clock(void) | ||
287 | { | ||
288 | if (!preferred_sched_clock) | ||
289 | return 0; | ||
290 | |||
291 | return preferred_sched_clock(); | ||
292 | } | ||
293 | |||
294 | static inline void preferred_sched_clock_init(bool use_32k_sched_clock) | ||
295 | { | ||
296 | if (use_32k_sched_clock) | ||
297 | preferred_sched_clock = omap_32k_sched_clock; | ||
298 | else | ||
299 | preferred_sched_clock = omap_mpu_sched_clock; | ||
300 | } | ||
301 | #else | ||
302 | static inline void preferred_sched_clock_init(bool use_32k_sched_clcok) | ||
303 | { | ||
304 | } | ||
305 | #endif | ||
306 | |||
307 | static inline int omap_32k_timer_usable(void) | ||
308 | { | ||
309 | int res = false; | ||
310 | |||
311 | if (cpu_is_omap730() || cpu_is_omap15xx()) | ||
312 | return res; | ||
313 | |||
314 | #ifdef CONFIG_OMAP_32K_TIMER | ||
315 | res = omap_32k_timer_init(); | ||
316 | #endif | ||
317 | |||
318 | return res; | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * --------------------------------------------------------------------------- | ||
323 | * Timer initialization | ||
324 | * --------------------------------------------------------------------------- | ||
325 | */ | ||
326 | static void __init omap_timer_init(void) | ||
327 | { | ||
328 | if (omap_32k_timer_usable()) { | ||
329 | preferred_sched_clock_init(1); | ||
330 | } else { | ||
331 | omap_mpu_timer_init(); | ||
332 | preferred_sched_clock_init(0); | ||
333 | } | ||
334 | } | ||
335 | |||
249 | struct sys_timer omap_timer = { | 336 | struct sys_timer omap_timer = { |
250 | .init = omap_timer_init, | 337 | .init = omap_timer_init, |
251 | }; | 338 | }; |