diff options
Diffstat (limited to 'arch/arm/plat-nomadik/timer.c')
-rw-r--r-- | arch/arm/plat-nomadik/timer.c | 60 |
1 files changed, 24 insertions, 36 deletions
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index aedf9c1d645e..ef74e157a9d5 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 STMicroelectronics | 4 | * Copyright (C) 2008 STMicroelectronics |
5 | * Copyright (C) 2010 Alessandro Rubini | 5 | * Copyright (C) 2010 Alessandro Rubini |
6 | * Copyright (C) 2010 Linus Walleij for ST-Ericsson | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2, as | 9 | * it under the terms of the GNU General Public License version 2, as |
@@ -16,48 +17,36 @@ | |||
16 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
17 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
18 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/sched.h> | ||
19 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
22 | #include <asm/sched_clock.h> | ||
20 | 23 | ||
21 | #include <plat/mtu.h> | 24 | #include <plat/mtu.h> |
22 | 25 | ||
23 | void __iomem *mtu_base; /* ssigned by machine code */ | 26 | void __iomem *mtu_base; /* Assigned by machine code */ |
24 | 27 | ||
25 | /* | 28 | /* |
26 | * Kernel assumes that sched_clock can be called early | 29 | * Override the global weak sched_clock symbol with this |
27 | * but the MTU may not yet be initialized. | 30 | * local implementation which uses the clocksource to get some |
31 | * better resolution when scheduling the kernel. | ||
28 | */ | 32 | */ |
29 | static cycle_t nmdk_read_timer_dummy(struct clocksource *cs) | 33 | static DEFINE_CLOCK_DATA(cd); |
30 | { | ||
31 | return 0; | ||
32 | } | ||
33 | 34 | ||
34 | /* clocksource: MTU decrements, so we negate the value being read. */ | 35 | unsigned long long notrace sched_clock(void) |
35 | static cycle_t nmdk_read_timer(struct clocksource *cs) | ||
36 | { | 36 | { |
37 | return -readl(mtu_base + MTU_VAL(0)); | 37 | u32 cyc; |
38 | } | ||
39 | 38 | ||
40 | static struct clocksource nmdk_clksrc = { | 39 | if (unlikely(!mtu_base)) |
41 | .name = "mtu_0", | 40 | return 0; |
42 | .rating = 200, | ||
43 | .read = nmdk_read_timer_dummy, | ||
44 | .mask = CLOCKSOURCE_MASK(32), | ||
45 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
46 | }; | ||
47 | 41 | ||
48 | /* | 42 | cyc = -readl(mtu_base + MTU_VAL(0)); |
49 | * Override the global weak sched_clock symbol with this | 43 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
50 | * local implementation which uses the clocksource to get some | 44 | } |
51 | * better resolution when scheduling the kernel. We accept that | 45 | |
52 | * this wraps around for now, since it is just a relative time | 46 | static void notrace nomadik_update_sched_clock(void) |
53 | * stamp. (Inspired by OMAP implementation.) | ||
54 | */ | ||
55 | unsigned long long notrace sched_clock(void) | ||
56 | { | 47 | { |
57 | return clocksource_cyc2ns(nmdk_clksrc.read( | 48 | u32 cyc = -readl(mtu_base + MTU_VAL(0)); |
58 | &nmdk_clksrc), | 49 | update_sched_clock(&cd, cyc, (u32)~0); |
59 | nmdk_clksrc.mult, | ||
60 | nmdk_clksrc.shift); | ||
61 | } | 50 | } |
62 | 51 | ||
63 | /* Clockevent device: use one-shot mode */ | 52 | /* Clockevent device: use one-shot mode */ |
@@ -153,7 +142,6 @@ void __init nmdk_timer_init(void) | |||
153 | } else { | 142 | } else { |
154 | cr |= MTU_CRn_PRESCALE_1; | 143 | cr |= MTU_CRn_PRESCALE_1; |
155 | } | 144 | } |
156 | clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE); | ||
157 | 145 | ||
158 | /* Timer 0 is the free running clocksource */ | 146 | /* Timer 0 is the free running clocksource */ |
159 | writel(cr, mtu_base + MTU_CR(0)); | 147 | writel(cr, mtu_base + MTU_CR(0)); |
@@ -161,12 +149,12 @@ void __init nmdk_timer_init(void) | |||
161 | writel(0, mtu_base + MTU_BGLR(0)); | 149 | writel(0, mtu_base + MTU_BGLR(0)); |
162 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); | 150 | writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); |
163 | 151 | ||
164 | /* Now the scheduling clock is ready */ | 152 | if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0", |
165 | nmdk_clksrc.read = nmdk_read_timer; | 153 | rate, 200, 32, clocksource_mmio_readl_down)) |
166 | |||
167 | if (clocksource_register(&nmdk_clksrc)) | ||
168 | pr_err("timer: failed to initialize clock source %s\n", | 154 | pr_err("timer: failed to initialize clock source %s\n", |
169 | nmdk_clksrc.name); | 155 | "mtu_0"); |
156 | |||
157 | init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); | ||
170 | 158 | ||
171 | /* Timer 1 is used for events */ | 159 | /* Timer 1 is used for events */ |
172 | 160 | ||