diff options
author | Marc Zyngier <Marc.Zyngier@arm.com> | 2011-12-15 06:19:23 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-12-18 18:00:26 -0500 |
commit | 2f0778afac79bd8d226225556858a636931eeabc (patch) | |
tree | e00cea674f3d6cc8c5584aa5b75239f11f6d229d /arch/arm | |
parent | 3bdc3484e8f2b1b219ad0397d81ce4601fbaf76d (diff) |
ARM: 7205/2: sched_clock: allow sched_clock to be selected at runtime
sched_clock() is yet another blocker on the road to the single
image. This patch implements an idea by Russell King:
http://www.spinics.net/lists/linux-omap/msg49561.html
Instead of asking the platform to implement both sched_clock()
itself and the rollover callback, simply register a read()
function, and let the ARM code care about sched_clock() itself,
the conversion to ns and the rollover. sched_clock() uses
this read() function as an indirection to the platform code.
If the platform doesn't provide a read(), the code falls back
to the jiffy counter (just like the default sched_clock).
This allow some simplifications and possibly some footprint gain
when multiple platforms are compiled in. Among the drawbacks,
the removal of the *_fixed_sched_clock optimization which could
negatively impact some platforms (sa1100, tegra, versatile
and omap).
Tested on 11MPCore, OMAP4 and Tegra.
Cc: Imre Kaloz <kaloz@openwrt.org>
Cc: Eric Miao <eric.y.miao@gmail.com>
Cc: Colin Cross <ccross@android.com>
Cc: Erik Gilling <konkers@android.com>
Cc: Olof Johansson <olof@lixom.net>
Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: Alessandro Rubini <rubini@unipv.it>
Cc: STEricsson <STEricsson_nomadik_linux@list.st.com>
Cc: Lennert Buytenhek <kernel@wantstofly.org>
Cc: Ben Dooks <ben-linux@fluff.org>
Tested-by: Jamie Iles <jamie@jamieiles.com>
Tested-by: Tony Lindgren <tony@atomide.com>
Tested-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Krzysztof Halasa <khc@pm.waw.pl>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/sched_clock.h | 108 | ||||
-rw-r--r-- | arch/arm/kernel/sched_clock.c | 118 | ||||
-rw-r--r-- | arch/arm/mach-ixp4xx/common.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-mmp/time.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-omap1/time.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-picoxcell/time.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-pxa/time.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/time.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-tegra/timer.c | 24 | ||||
-rw-r--r-- | arch/arm/mach-u300/timer.c | 15 | ||||
-rw-r--r-- | arch/arm/plat-iop/time.c | 16 | ||||
-rw-r--r-- | arch/arm/plat-mxc/time.c | 15 | ||||
-rw-r--r-- | arch/arm/plat-nomadik/timer.c | 20 | ||||
-rw-r--r-- | arch/arm/plat-omap/counter_32k.c | 40 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/common.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-orion/time.c | 21 | ||||
-rw-r--r-- | arch/arm/plat-s5p/s5p-time.c | 19 | ||||
-rw-r--r-- | arch/arm/plat-versatile/sched-clock.c | 29 |
19 files changed, 161 insertions, 435 deletions
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index c8e6ddf3e860..e3f757263438 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h | |||
@@ -8,113 +8,7 @@ | |||
8 | #ifndef ASM_SCHED_CLOCK | 8 | #ifndef ASM_SCHED_CLOCK |
9 | #define ASM_SCHED_CLOCK | 9 | #define ASM_SCHED_CLOCK |
10 | 10 | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/types.h> | ||
13 | |||
14 | struct clock_data { | ||
15 | u64 epoch_ns; | ||
16 | u32 epoch_cyc; | ||
17 | u32 epoch_cyc_copy; | ||
18 | u32 mult; | ||
19 | u32 shift; | ||
20 | }; | ||
21 | |||
22 | #define DEFINE_CLOCK_DATA(name) struct clock_data name | ||
23 | |||
24 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
25 | { | ||
26 | return (cyc * mult) >> shift; | ||
27 | } | ||
28 | |||
29 | /* | ||
30 | * Atomically update the sched_clock epoch. Your update callback will | ||
31 | * be called from a timer before the counter wraps - read the current | ||
32 | * counter value, and call this function to safely move the epochs | ||
33 | * forward. Only use this from the update callback. | ||
34 | */ | ||
35 | static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask) | ||
36 | { | ||
37 | unsigned long flags; | ||
38 | u64 ns = cd->epoch_ns + | ||
39 | cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift); | ||
40 | |||
41 | /* | ||
42 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
43 | * detectable in cyc_to_fixed_sched_clock(). | ||
44 | */ | ||
45 | raw_local_irq_save(flags); | ||
46 | cd->epoch_cyc = cyc; | ||
47 | smp_wmb(); | ||
48 | cd->epoch_ns = ns; | ||
49 | smp_wmb(); | ||
50 | cd->epoch_cyc_copy = cyc; | ||
51 | raw_local_irq_restore(flags); | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * If your clock rate is known at compile time, using this will allow | ||
56 | * you to optimize the mult/shift loads away. This is paired with | ||
57 | * init_fixed_sched_clock() to ensure that your mult/shift are correct. | ||
58 | */ | ||
59 | static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd, | ||
60 | u32 cyc, u32 mask, u32 mult, u32 shift) | ||
61 | { | ||
62 | u64 epoch_ns; | ||
63 | u32 epoch_cyc; | ||
64 | |||
65 | /* | ||
66 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
67 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
68 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
69 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
70 | * the middle of an update, and we should repeat the load. | ||
71 | */ | ||
72 | do { | ||
73 | epoch_cyc = cd->epoch_cyc; | ||
74 | smp_rmb(); | ||
75 | epoch_ns = cd->epoch_ns; | ||
76 | smp_rmb(); | ||
77 | } while (epoch_cyc != cd->epoch_cyc_copy); | ||
78 | |||
79 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Otherwise, you need to use this, which will obtain the mult/shift | ||
84 | * from the clock_data structure. Use init_sched_clock() with this. | ||
85 | */ | ||
86 | static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd, | ||
87 | u32 cyc, u32 mask) | ||
88 | { | ||
89 | return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift); | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Initialize the clock data - calculate the appropriate multiplier | ||
94 | * and shift. Also setup a timer to ensure that the epoch is refreshed | ||
95 | * at the appropriate time interval, which will call your update | ||
96 | * handler. | ||
97 | */ | ||
98 | void init_sched_clock(struct clock_data *, void (*)(void), | ||
99 | unsigned int, unsigned long); | ||
100 | |||
101 | /* | ||
102 | * Use this initialization function rather than init_sched_clock() if | ||
103 | * you're using cyc_to_fixed_sched_clock, which will warn if your | ||
104 | * constants are incorrect. | ||
105 | */ | ||
106 | static inline void init_fixed_sched_clock(struct clock_data *cd, | ||
107 | void (*update)(void), unsigned int bits, unsigned long rate, | ||
108 | u32 mult, u32 shift) | ||
109 | { | ||
110 | init_sched_clock(cd, update, bits, rate); | ||
111 | if (cd->mult != mult || cd->shift != shift) { | ||
112 | pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n" | ||
113 | "sched_clock: fix multiply/shift to avoid scheduler hiccups\n", | ||
114 | mult, shift, cd->mult, cd->shift); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | extern void sched_clock_postinit(void); | 11 | extern void sched_clock_postinit(void); |
12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | ||
119 | 13 | ||
120 | #endif | 14 | #endif |
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index 9a46370fe9da..5416c7c12528 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c | |||
@@ -14,61 +14,153 @@ | |||
14 | 14 | ||
15 | #include <asm/sched_clock.h> | 15 | #include <asm/sched_clock.h> |
16 | 16 | ||
17 | struct clock_data { | ||
18 | u64 epoch_ns; | ||
19 | u32 epoch_cyc; | ||
20 | u32 epoch_cyc_copy; | ||
21 | u32 mult; | ||
22 | u32 shift; | ||
23 | }; | ||
24 | |||
17 | static void sched_clock_poll(unsigned long wrap_ticks); | 25 | static void sched_clock_poll(unsigned long wrap_ticks); |
18 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); | 26 | static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0); |
19 | static void (*sched_clock_update_fn)(void); | 27 | |
28 | static struct clock_data cd = { | ||
29 | .mult = NSEC_PER_SEC / HZ, | ||
30 | }; | ||
31 | |||
32 | static u32 __read_mostly sched_clock_mask = 0xffffffff; | ||
33 | |||
34 | static u32 notrace jiffy_sched_clock_read(void) | ||
35 | { | ||
36 | return (u32)(jiffies - INITIAL_JIFFIES); | ||
37 | } | ||
38 | |||
39 | static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read; | ||
40 | |||
41 | static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift) | ||
42 | { | ||
43 | return (cyc * mult) >> shift; | ||
44 | } | ||
45 | |||
46 | static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask) | ||
47 | { | ||
48 | u64 epoch_ns; | ||
49 | u32 epoch_cyc; | ||
50 | |||
51 | /* | ||
52 | * Load the epoch_cyc and epoch_ns atomically. We do this by | ||
53 | * ensuring that we always write epoch_cyc, epoch_ns and | ||
54 | * epoch_cyc_copy in strict order, and read them in strict order. | ||
55 | * If epoch_cyc and epoch_cyc_copy are not equal, then we're in | ||
56 | * the middle of an update, and we should repeat the load. | ||
57 | */ | ||
58 | do { | ||
59 | epoch_cyc = cd.epoch_cyc; | ||
60 | smp_rmb(); | ||
61 | epoch_ns = cd.epoch_ns; | ||
62 | smp_rmb(); | ||
63 | } while (epoch_cyc != cd.epoch_cyc_copy); | ||
64 | |||
65 | return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, cd.mult, cd.shift); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Atomically update the sched_clock epoch. | ||
70 | */ | ||
71 | static void notrace update_sched_clock(void) | ||
72 | { | ||
73 | unsigned long flags; | ||
74 | u32 cyc; | ||
75 | u64 ns; | ||
76 | |||
77 | cyc = read_sched_clock(); | ||
78 | ns = cd.epoch_ns + | ||
79 | cyc_to_ns((cyc - cd.epoch_cyc) & sched_clock_mask, | ||
80 | cd.mult, cd.shift); | ||
81 | /* | ||
82 | * Write epoch_cyc and epoch_ns in a way that the update is | ||
83 | * detectable in cyc_to_fixed_sched_clock(). | ||
84 | */ | ||
85 | raw_local_irq_save(flags); | ||
86 | cd.epoch_cyc = cyc; | ||
87 | smp_wmb(); | ||
88 | cd.epoch_ns = ns; | ||
89 | smp_wmb(); | ||
90 | cd.epoch_cyc_copy = cyc; | ||
91 | raw_local_irq_restore(flags); | ||
92 | } | ||
20 | 93 | ||
21 | static void sched_clock_poll(unsigned long wrap_ticks) | 94 | static void sched_clock_poll(unsigned long wrap_ticks) |
22 | { | 95 | { |
23 | mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); | 96 | mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks)); |
24 | sched_clock_update_fn(); | 97 | update_sched_clock(); |
25 | } | 98 | } |
26 | 99 | ||
27 | void __init init_sched_clock(struct clock_data *cd, void (*update)(void), | 100 | void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) |
28 | unsigned int clock_bits, unsigned long rate) | ||
29 | { | 101 | { |
30 | unsigned long r, w; | 102 | unsigned long r, w; |
31 | u64 res, wrap; | 103 | u64 res, wrap; |
32 | char r_unit; | 104 | char r_unit; |
33 | 105 | ||
34 | sched_clock_update_fn = update; | 106 | BUG_ON(bits > 32); |
107 | WARN_ON(!irqs_disabled()); | ||
108 | WARN_ON(read_sched_clock != jiffy_sched_clock_read); | ||
109 | read_sched_clock = read; | ||
110 | sched_clock_mask = (1 << bits) - 1; | ||
35 | 111 | ||
36 | /* calculate the mult/shift to convert counter ticks to ns. */ | 112 | /* calculate the mult/shift to convert counter ticks to ns. */ |
37 | clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 0); | 113 | clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); |
38 | 114 | ||
39 | r = rate; | 115 | r = rate; |
40 | if (r >= 4000000) { | 116 | if (r >= 4000000) { |
41 | r /= 1000000; | 117 | r /= 1000000; |
42 | r_unit = 'M'; | 118 | r_unit = 'M'; |
43 | } else { | 119 | } else if (r >= 1000) { |
44 | r /= 1000; | 120 | r /= 1000; |
45 | r_unit = 'k'; | 121 | r_unit = 'k'; |
46 | } | 122 | } else |
123 | r_unit = ' '; | ||
47 | 124 | ||
48 | /* calculate how many ns until we wrap */ | 125 | /* calculate how many ns until we wrap */ |
49 | wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift); | 126 | wrap = cyc_to_ns((1ULL << bits) - 1, cd.mult, cd.shift); |
50 | do_div(wrap, NSEC_PER_MSEC); | 127 | do_div(wrap, NSEC_PER_MSEC); |
51 | w = wrap; | 128 | w = wrap; |
52 | 129 | ||
53 | /* calculate the ns resolution of this counter */ | 130 | /* calculate the ns resolution of this counter */ |
54 | res = cyc_to_ns(1ULL, cd->mult, cd->shift); | 131 | res = cyc_to_ns(1ULL, cd.mult, cd.shift); |
55 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", | 132 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n", |
56 | clock_bits, r, r_unit, res, w); | 133 | bits, r, r_unit, res, w); |
57 | 134 | ||
58 | /* | 135 | /* |
59 | * Start the timer to keep sched_clock() properly updated and | 136 | * Start the timer to keep sched_clock() properly updated and |
60 | * sets the initial epoch. | 137 | * sets the initial epoch. |
61 | */ | 138 | */ |
62 | sched_clock_timer.data = msecs_to_jiffies(w - (w / 10)); | 139 | sched_clock_timer.data = msecs_to_jiffies(w - (w / 10)); |
63 | update(); | 140 | update_sched_clock(); |
64 | 141 | ||
65 | /* | 142 | /* |
66 | * Ensure that sched_clock() starts off at 0ns | 143 | * Ensure that sched_clock() starts off at 0ns |
67 | */ | 144 | */ |
68 | cd->epoch_ns = 0; | 145 | cd.epoch_ns = 0; |
146 | |||
147 | pr_debug("Registered %pF as sched_clock source\n", read); | ||
148 | } | ||
149 | |||
150 | unsigned long long notrace sched_clock(void) | ||
151 | { | ||
152 | u32 cyc = read_sched_clock(); | ||
153 | return cyc_to_sched_clock(cyc, sched_clock_mask); | ||
69 | } | 154 | } |
70 | 155 | ||
71 | void __init sched_clock_postinit(void) | 156 | void __init sched_clock_postinit(void) |
72 | { | 157 | { |
158 | /* | ||
159 | * If no sched_clock function has been provided at that point, | ||
160 | * make it the final one one. | ||
161 | */ | ||
162 | if (read_sched_clock == jiffy_sched_clock_read) | ||
163 | setup_sched_clock(jiffy_sched_clock_read, 32, HZ); | ||
164 | |||
73 | sched_clock_poll(sched_clock_timer.data); | 165 | sched_clock_poll(sched_clock_timer.data); |
74 | } | 166 | } |
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index b86a0055ab96..c1b12f945fc9 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/serial.h> | 19 | #include <linux/serial.h> |
20 | #include <linux/sched.h> | ||
21 | #include <linux/tty.h> | 20 | #include <linux/tty.h> |
22 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
23 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
@@ -403,18 +402,9 @@ void __init ixp4xx_sys_init(void) | |||
403 | /* | 402 | /* |
404 | * sched_clock() | 403 | * sched_clock() |
405 | */ | 404 | */ |
406 | static DEFINE_CLOCK_DATA(cd); | 405 | static u32 notrace ixp4xx_read_sched_clock(void) |
407 | |||
408 | unsigned long long notrace sched_clock(void) | ||
409 | { | 406 | { |
410 | u32 cyc = *IXP4XX_OSTS; | 407 | return *IXP4XX_OSTS; |
411 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
412 | } | ||
413 | |||
414 | static void notrace ixp4xx_update_sched_clock(void) | ||
415 | { | ||
416 | u32 cyc = *IXP4XX_OSTS; | ||
417 | update_sched_clock(&cd, cyc, (u32)~0); | ||
418 | } | 408 | } |
419 | 409 | ||
420 | /* | 410 | /* |
@@ -430,7 +420,7 @@ unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; | |||
430 | EXPORT_SYMBOL(ixp4xx_timer_freq); | 420 | EXPORT_SYMBOL(ixp4xx_timer_freq); |
431 | static void __init ixp4xx_clocksource_init(void) | 421 | static void __init ixp4xx_clocksource_init(void) |
432 | { | 422 | { |
433 | init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq); | 423 | setup_sched_clock(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq); |
434 | 424 | ||
435 | clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, | 425 | clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, |
436 | ixp4xx_clocksource_read); | 426 | ixp4xx_clocksource_read); |
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c index 4e91ee6e27c8..71fc4ee4602c 100644 --- a/arch/arm/mach-mmp/time.c +++ b/arch/arm/mach-mmp/time.c | |||
@@ -25,7 +25,6 @@ | |||
25 | 25 | ||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/irq.h> | 27 | #include <linux/irq.h> |
28 | #include <linux/sched.h> | ||
29 | 28 | ||
30 | #include <asm/sched_clock.h> | 29 | #include <asm/sched_clock.h> |
31 | #include <mach/addr-map.h> | 30 | #include <mach/addr-map.h> |
@@ -42,8 +41,6 @@ | |||
42 | #define MAX_DELTA (0xfffffffe) | 41 | #define MAX_DELTA (0xfffffffe) |
43 | #define MIN_DELTA (16) | 42 | #define MIN_DELTA (16) |
44 | 43 | ||
45 | static DEFINE_CLOCK_DATA(cd); | ||
46 | |||
47 | /* | 44 | /* |
48 | * FIXME: the timer needs some delay to stablize the counter capture | 45 | * FIXME: the timer needs some delay to stablize the counter capture |
49 | */ | 46 | */ |
@@ -59,16 +56,9 @@ static inline uint32_t timer_read(void) | |||
59 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1)); | 56 | return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(1)); |
60 | } | 57 | } |
61 | 58 | ||
62 | unsigned long long notrace sched_clock(void) | 59 | static u32 notrace mmp_read_sched_clock(void) |
63 | { | 60 | { |
64 | u32 cyc = timer_read(); | 61 | return timer_read(); |
65 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
66 | } | ||
67 | |||
68 | static void notrace mmp_update_sched_clock(void) | ||
69 | { | ||
70 | u32 cyc = timer_read(); | ||
71 | update_sched_clock(&cd, cyc, (u32)~0); | ||
72 | } | 62 | } |
73 | 63 | ||
74 | static irqreturn_t timer_interrupt(int irq, void *dev_id) | 64 | static irqreturn_t timer_interrupt(int irq, void *dev_id) |
@@ -201,7 +191,7 @@ void __init timer_init(int irq) | |||
201 | { | 191 | { |
202 | timer_config(); | 192 | timer_config(); |
203 | 193 | ||
204 | init_sched_clock(&cd, mmp_update_sched_clock, 32, CLOCK_TICK_RATE); | 194 | setup_sched_clock(mmp_read_sched_clock, 32, CLOCK_TICK_RATE); |
205 | 195 | ||
206 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); | 196 | ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift); |
207 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); | 197 | ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt); |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index 485a21d31004..b8faffa44f9e 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
40 | #include <linux/sched.h> | ||
41 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
42 | #include <linux/clk.h> | 41 | #include <linux/clk.h> |
43 | #include <linux/err.h> | 42 | #include <linux/err.h> |
@@ -190,30 +189,9 @@ static __init void omap_init_mpu_timer(unsigned long rate) | |||
190 | * --------------------------------------------------------------------------- | 189 | * --------------------------------------------------------------------------- |
191 | */ | 190 | */ |
192 | 191 | ||
193 | static DEFINE_CLOCK_DATA(cd); | 192 | static u32 notrace omap_mpu_read_sched_clock(void) |
194 | |||
195 | static inline unsigned long long notrace _omap_mpu_sched_clock(void) | ||
196 | { | ||
197 | u32 cyc = ~omap_mpu_timer_read(1); | ||
198 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
199 | } | ||
200 | |||
201 | #ifndef CONFIG_OMAP_32K_TIMER | ||
202 | unsigned long long notrace sched_clock(void) | ||
203 | { | ||
204 | return _omap_mpu_sched_clock(); | ||
205 | } | ||
206 | #else | ||
207 | static unsigned long long notrace omap_mpu_sched_clock(void) | ||
208 | { | ||
209 | return _omap_mpu_sched_clock(); | ||
210 | } | ||
211 | #endif | ||
212 | |||
213 | static void notrace mpu_update_sched_clock(void) | ||
214 | { | 193 | { |
215 | u32 cyc = ~omap_mpu_timer_read(1); | 194 | return ~omap_mpu_timer_read(1); |
216 | update_sched_clock(&cd, cyc, (u32)~0); | ||
217 | } | 195 | } |
218 | 196 | ||
219 | static void __init omap_init_clocksource(unsigned long rate) | 197 | static void __init omap_init_clocksource(unsigned long rate) |
@@ -223,7 +201,7 @@ static void __init omap_init_clocksource(unsigned long rate) | |||
223 | "%s: can't register clocksource!\n"; | 201 | "%s: can't register clocksource!\n"; |
224 | 202 | ||
225 | omap_mpu_timer_start(1, ~0, 1); | 203 | omap_mpu_timer_start(1, ~0, 1); |
226 | init_sched_clock(&cd, mpu_update_sched_clock, 32, rate); | 204 | setup_sched_clock(omap_mpu_read_sched_clock, 32, rate); |
227 | 205 | ||
228 | if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate, | 206 | if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate, |
229 | 300, 32, clocksource_mmio_readl_down)) | 207 | 300, 32, clocksource_mmio_readl_down)) |
@@ -254,30 +232,6 @@ static inline void omap_mpu_timer_init(void) | |||
254 | } | 232 | } |
255 | #endif /* CONFIG_OMAP_MPU_TIMER */ | 233 | #endif /* CONFIG_OMAP_MPU_TIMER */ |
256 | 234 | ||
257 | #if defined(CONFIG_OMAP_MPU_TIMER) && defined(CONFIG_OMAP_32K_TIMER) | ||
258 | static unsigned long long (*preferred_sched_clock)(void); | ||
259 | |||
260 | unsigned long long notrace sched_clock(void) | ||
261 | { | ||
262 | if (!preferred_sched_clock) | ||
263 | return 0; | ||
264 | |||
265 | return preferred_sched_clock(); | ||
266 | } | ||
267 | |||
268 | static inline void preferred_sched_clock_init(bool use_32k_sched_clock) | ||
269 | { | ||
270 | if (use_32k_sched_clock) | ||
271 | preferred_sched_clock = omap_32k_sched_clock; | ||
272 | else | ||
273 | preferred_sched_clock = omap_mpu_sched_clock; | ||
274 | } | ||
275 | #else | ||
276 | static inline void preferred_sched_clock_init(bool use_32k_sched_clcok) | ||
277 | { | ||
278 | } | ||
279 | #endif | ||
280 | |||
281 | static inline int omap_32k_timer_usable(void) | 235 | static inline int omap_32k_timer_usable(void) |
282 | { | 236 | { |
283 | int res = false; | 237 | int res = false; |
@@ -299,12 +253,8 @@ static inline int omap_32k_timer_usable(void) | |||
299 | */ | 253 | */ |
300 | static void __init omap1_timer_init(void) | 254 | static void __init omap1_timer_init(void) |
301 | { | 255 | { |
302 | if (omap_32k_timer_usable()) { | 256 | if (!omap_32k_timer_usable()) |
303 | preferred_sched_clock_init(1); | ||
304 | } else { | ||
305 | omap_mpu_timer_init(); | 257 | omap_mpu_timer_init(); |
306 | preferred_sched_clock_init(0); | ||
307 | } | ||
308 | } | 258 | } |
309 | 259 | ||
310 | struct sys_timer omap1_timer = { | 260 | struct sys_timer omap1_timer = { |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 9edcd520510f..6eeff0e0ae01 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -254,7 +254,6 @@ static struct omap_dm_timer clksrc; | |||
254 | /* | 254 | /* |
255 | * clocksource | 255 | * clocksource |
256 | */ | 256 | */ |
257 | static DEFINE_CLOCK_DATA(cd); | ||
258 | static cycle_t clocksource_read_cycles(struct clocksource *cs) | 257 | static cycle_t clocksource_read_cycles(struct clocksource *cs) |
259 | { | 258 | { |
260 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1); | 259 | return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1); |
@@ -268,23 +267,12 @@ static struct clocksource clocksource_gpt = { | |||
268 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 267 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
269 | }; | 268 | }; |
270 | 269 | ||
271 | static void notrace dmtimer_update_sched_clock(void) | 270 | static u32 notrace dmtimer_read_sched_clock(void) |
272 | { | 271 | { |
273 | u32 cyc; | ||
274 | |||
275 | cyc = __omap_dm_timer_read_counter(&clksrc, 1); | ||
276 | |||
277 | update_sched_clock(&cd, cyc, (u32)~0); | ||
278 | } | ||
279 | |||
280 | unsigned long long notrace sched_clock(void) | ||
281 | { | ||
282 | u32 cyc = 0; | ||
283 | |||
284 | if (clksrc.reserved) | 272 | if (clksrc.reserved) |
285 | cyc = __omap_dm_timer_read_counter(&clksrc, 1); | 273 | return __omap_dm_timer_read_counter(clksrc.io_base, 1); |
286 | 274 | ||
287 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | 275 | return 0; |
288 | } | 276 | } |
289 | 277 | ||
290 | /* Setup free-running counter for clocksource */ | 278 | /* Setup free-running counter for clocksource */ |
@@ -301,7 +289,7 @@ static void __init omap2_gp_clocksource_init(int gptimer_id, | |||
301 | 289 | ||
302 | __omap_dm_timer_load_start(&clksrc, | 290 | __omap_dm_timer_load_start(&clksrc, |
303 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); | 291 | OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); |
304 | init_sched_clock(&cd, dmtimer_update_sched_clock, 32, clksrc.rate); | 292 | setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate); |
305 | 293 | ||
306 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) | 294 | if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) |
307 | pr_err("Could not register clocksource %s\n", | 295 | pr_err("Could not register clocksource %s\n", |
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c index 90a554ff4499..6c89cf8ab22e 100644 --- a/arch/arm/mach-picoxcell/time.c +++ b/arch/arm/mach-picoxcell/time.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
12 | #include <linux/of_address.h> | 12 | #include <linux/of_address.h> |
13 | #include <linux/of_irq.h> | 13 | #include <linux/of_irq.h> |
14 | #include <linux/sched.h> | ||
15 | 14 | ||
16 | #include <asm/mach/time.h> | 15 | #include <asm/mach/time.h> |
17 | #include <asm/sched_clock.h> | 16 | #include <asm/sched_clock.h> |
@@ -66,21 +65,11 @@ static void picoxcell_add_clocksource(struct device_node *source_timer) | |||
66 | dw_apb_clocksource_register(cs); | 65 | dw_apb_clocksource_register(cs); |
67 | } | 66 | } |
68 | 67 | ||
69 | static DEFINE_CLOCK_DATA(cd); | ||
70 | static void __iomem *sched_io_base; | 68 | static void __iomem *sched_io_base; |
71 | 69 | ||
72 | unsigned long long notrace sched_clock(void) | 70 | unsigned u32 notrace picoxcell_read_sched_clock(void) |
73 | { | 71 | { |
74 | cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0; | 72 | return __raw_readl(sched_io_base); |
75 | |||
76 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
77 | } | ||
78 | |||
79 | static void notrace picoxcell_update_sched_clock(void) | ||
80 | { | ||
81 | cycle_t cyc = sched_io_base ? __raw_readl(sched_io_base) : 0; | ||
82 | |||
83 | update_sched_clock(&cd, cyc, (u32)~0); | ||
84 | } | 73 | } |
85 | 74 | ||
86 | static const struct of_device_id picoxcell_rtc_ids[] __initconst = { | 75 | static const struct of_device_id picoxcell_rtc_ids[] __initconst = { |
@@ -100,7 +89,7 @@ static void picoxcell_init_sched_clock(void) | |||
100 | timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); | 89 | timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); |
101 | of_node_put(sched_timer); | 90 | of_node_put(sched_timer); |
102 | 91 | ||
103 | init_sched_clock(&cd, picoxcell_update_sched_clock, 32, rate); | 92 | setup_sched_clock(picoxcell_read_sched_clock, 32, rate); |
104 | } | 93 | } |
105 | 94 | ||
106 | static const struct of_device_id picoxcell_timer_ids[] __initconst = { | 95 | static const struct of_device_id picoxcell_timer_ids[] __initconst = { |
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index de684701449c..b503049d6d26 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/clockchips.h> | 18 | #include <linux/clockchips.h> |
19 | #include <linux/sched.h> | ||
20 | 19 | ||
21 | #include <asm/div64.h> | 20 | #include <asm/div64.h> |
22 | #include <asm/mach/irq.h> | 21 | #include <asm/mach/irq.h> |
@@ -32,18 +31,10 @@ | |||
32 | * long as there is always less than 582 seconds between successive | 31 | * long as there is always less than 582 seconds between successive |
33 | * calls to sched_clock() which should always be the case in practice. | 32 | * calls to sched_clock() which should always be the case in practice. |
34 | */ | 33 | */ |
35 | static DEFINE_CLOCK_DATA(cd); | ||
36 | 34 | ||
37 | unsigned long long notrace sched_clock(void) | 35 | static u32 notrace pxa_read_sched_clock(void) |
38 | { | 36 | { |
39 | u32 cyc = OSCR; | 37 | return OSCR; |
40 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
41 | } | ||
42 | |||
43 | static void notrace pxa_update_sched_clock(void) | ||
44 | { | ||
45 | u32 cyc = OSCR; | ||
46 | update_sched_clock(&cd, cyc, (u32)~0); | ||
47 | } | 38 | } |
48 | 39 | ||
49 | 40 | ||
@@ -119,7 +110,7 @@ static void __init pxa_timer_init(void) | |||
119 | OIER = 0; | 110 | OIER = 0; |
120 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 111 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
121 | 112 | ||
122 | init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate); | 113 | setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); |
123 | 114 | ||
124 | clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); | 115 | clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4); |
125 | ckevt_pxa_osmr0.max_delta_ns = | 116 | ckevt_pxa_osmr0.max_delta_ns = |
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index fa6602491d54..1ee6d4ca8dd7 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
15 | #include <linux/sched.h> /* just for sched_clock() - funny that */ | ||
16 | #include <linux/timex.h> | 15 | #include <linux/timex.h> |
17 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
18 | 17 | ||
@@ -20,29 +19,9 @@ | |||
20 | #include <asm/sched_clock.h> | 19 | #include <asm/sched_clock.h> |
21 | #include <mach/hardware.h> | 20 | #include <mach/hardware.h> |
22 | 21 | ||
23 | /* | 22 | static u32 notrace sa100_read_sched_clock(void) |
24 | * This is the SA11x0 sched_clock implementation. | ||
25 | */ | ||
26 | static DEFINE_CLOCK_DATA(cd); | ||
27 | |||
28 | /* | ||
29 | * Constants generated by clocks_calc_mult_shift(m, s, 3.6864MHz, | ||
30 | * NSEC_PER_SEC, 60). | ||
31 | * This gives a resolution of about 271ns and a wrap period of about 19min. | ||
32 | */ | ||
33 | #define SC_MULT 2275555556u | ||
34 | #define SC_SHIFT 23 | ||
35 | |||
36 | unsigned long long notrace sched_clock(void) | ||
37 | { | ||
38 | u32 cyc = OSCR; | ||
39 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
40 | } | ||
41 | |||
42 | static void notrace sa1100_update_sched_clock(void) | ||
43 | { | 23 | { |
44 | u32 cyc = OSCR; | 24 | return OSCR; |
45 | update_sched_clock(&cd, cyc, (u32)~0); | ||
46 | } | 25 | } |
47 | 26 | ||
48 | #define MIN_OSCR_DELTA 2 | 27 | #define MIN_OSCR_DELTA 2 |
@@ -109,8 +88,7 @@ static void __init sa1100_timer_init(void) | |||
109 | OIER = 0; | 88 | OIER = 0; |
110 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; | 89 | OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; |
111 | 90 | ||
112 | init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32, | 91 | setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); |
113 | 3686400, SC_MULT, SC_SHIFT); | ||
114 | 92 | ||
115 | clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); | 93 | clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4); |
116 | ckevt_sa1100_osmr0.max_delta_ns = | 94 | ckevt_sa1100_osmr0.max_delta_ns = |
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index e2272d263a83..732c724008b1 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/sched.h> | ||
23 | #include <linux/time.h> | 22 | #include <linux/time.h> |
24 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
25 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
@@ -106,25 +105,9 @@ static struct clock_event_device tegra_clockevent = { | |||
106 | .set_mode = tegra_timer_set_mode, | 105 | .set_mode = tegra_timer_set_mode, |
107 | }; | 106 | }; |
108 | 107 | ||
109 | static DEFINE_CLOCK_DATA(cd); | 108 | static u32 notrace tegra_read_sched_clock(void) |
110 | |||
111 | /* | ||
112 | * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60). | ||
113 | * This gives a resolution of about 1us and a wrap period of about 1h11min. | ||
114 | */ | ||
115 | #define SC_MULT 4194304000u | ||
116 | #define SC_SHIFT 22 | ||
117 | |||
118 | unsigned long long notrace sched_clock(void) | ||
119 | { | ||
120 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); | ||
121 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
122 | } | ||
123 | |||
124 | static void notrace tegra_update_sched_clock(void) | ||
125 | { | 109 | { |
126 | u32 cyc = timer_readl(TIMERUS_CNTR_1US); | 110 | return timer_readl(TIMERUS_CNTR_1US); |
127 | update_sched_clock(&cd, cyc, (u32)~0); | ||
128 | } | 111 | } |
129 | 112 | ||
130 | /* | 113 | /* |
@@ -218,8 +201,7 @@ static void __init tegra_init_timer(void) | |||
218 | WARN(1, "Unknown clock rate"); | 201 | WARN(1, "Unknown clock rate"); |
219 | } | 202 | } |
220 | 203 | ||
221 | init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32, | 204 | setup_sched_clock(tegra_read_sched_clock, 32, 1000000); |
222 | 1000000, SC_MULT, SC_SHIFT); | ||
223 | 205 | ||
224 | if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, | 206 | if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, |
225 | "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { | 207 | "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) { |
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 5f51bdeef0ef..bc1c7897e82d 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * Author: Linus Walleij <linus.walleij@stericsson.com> | 9 | * Author: Linus Walleij <linus.walleij@stericsson.com> |
10 | */ | 10 | */ |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/sched.h> | ||
13 | #include <linux/time.h> | 12 | #include <linux/time.h> |
14 | #include <linux/timex.h> | 13 | #include <linux/timex.h> |
15 | #include <linux/clockchips.h> | 14 | #include <linux/clockchips.h> |
@@ -337,18 +336,10 @@ static struct irqaction u300_timer_irq = { | |||
337 | * this wraps around for now, since it is just a relative time | 336 | * this wraps around for now, since it is just a relative time |
338 | * stamp. (Inspired by OMAP implementation.) | 337 | * stamp. (Inspired by OMAP implementation.) |
339 | */ | 338 | */ |
340 | static DEFINE_CLOCK_DATA(cd); | ||
341 | 339 | ||
342 | unsigned long long notrace sched_clock(void) | 340 | static u32 notrace u300_read_sched_clock(void) |
343 | { | 341 | { |
344 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | 342 | return readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); |
345 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
346 | } | ||
347 | |||
348 | static void notrace u300_update_sched_clock(void) | ||
349 | { | ||
350 | u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC); | ||
351 | update_sched_clock(&cd, cyc, (u32)~0); | ||
352 | } | 343 | } |
353 | 344 | ||
354 | 345 | ||
@@ -366,7 +357,7 @@ static void __init u300_timer_init(void) | |||
366 | clk_enable(clk); | 357 | clk_enable(clk); |
367 | rate = clk_get_rate(clk); | 358 | rate = clk_get_rate(clk); |
368 | 359 | ||
369 | init_sched_clock(&cd, u300_update_sched_clock, 32, rate); | 360 | setup_sched_clock(u300_read_sched_clock, 32, rate); |
370 | 361 | ||
371 | /* | 362 | /* |
372 | * Disable the "OS" and "DD" timers - these are designed for Symbian! | 363 | * Disable the "OS" and "DD" timers - these are designed for Symbian! |
diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c index 568dd0223d17..cbfbbe461788 100644 --- a/arch/arm/plat-iop/time.c +++ b/arch/arm/plat-iop/time.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/timex.h> | 20 | #include <linux/timex.h> |
21 | #include <linux/sched.h> | ||
22 | #include <linux/io.h> | 21 | #include <linux/io.h> |
23 | #include <linux/clocksource.h> | 22 | #include <linux/clocksource.h> |
24 | #include <linux/clockchips.h> | 23 | #include <linux/clockchips.h> |
@@ -52,21 +51,12 @@ static struct clocksource iop_clocksource = { | |||
52 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 51 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
53 | }; | 52 | }; |
54 | 53 | ||
55 | static DEFINE_CLOCK_DATA(cd); | ||
56 | |||
57 | /* | 54 | /* |
58 | * IOP sched_clock() implementation via its clocksource. | 55 | * IOP sched_clock() implementation via its clocksource. |
59 | */ | 56 | */ |
60 | unsigned long long notrace sched_clock(void) | 57 | static u32 notrace iop_read_sched_clock(void) |
61 | { | 58 | { |
62 | u32 cyc = 0xffffffffu - read_tcr1(); | 59 | return 0xffffffffu - read_tcr1(); |
63 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
64 | } | ||
65 | |||
66 | static void notrace iop_update_sched_clock(void) | ||
67 | { | ||
68 | u32 cyc = 0xffffffffu - read_tcr1(); | ||
69 | update_sched_clock(&cd, cyc, (u32)~0); | ||
70 | } | 60 | } |
71 | 61 | ||
72 | /* | 62 | /* |
@@ -152,7 +142,7 @@ void __init iop_init_time(unsigned long tick_rate) | |||
152 | { | 142 | { |
153 | u32 timer_ctl; | 143 | u32 timer_ctl; |
154 | 144 | ||
155 | init_sched_clock(&cd, iop_update_sched_clock, 32, tick_rate); | 145 | setup_sched_clock(iop_read_sched_clock, 32, tick_rate); |
156 | 146 | ||
157 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); | 147 | ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ); |
158 | iop_tick_rate = tick_rate; | 148 | iop_tick_rate = tick_rate; |
diff --git a/arch/arm/plat-mxc/time.c b/arch/arm/plat-mxc/time.c index 4b0fe285e83c..1c96cdb4c35e 100644 --- a/arch/arm/plat-mxc/time.c +++ b/arch/arm/plat-mxc/time.c | |||
@@ -108,18 +108,9 @@ static void gpt_irq_acknowledge(void) | |||
108 | 108 | ||
109 | static void __iomem *sched_clock_reg; | 109 | static void __iomem *sched_clock_reg; |
110 | 110 | ||
111 | static DEFINE_CLOCK_DATA(cd); | 111 | static u32 notrace mxc_read_sched_clock(void) |
112 | unsigned long long notrace sched_clock(void) | ||
113 | { | 112 | { |
114 | cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; | 113 | return sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; |
115 | |||
116 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
117 | } | ||
118 | |||
119 | static void notrace mxc_update_sched_clock(void) | ||
120 | { | ||
121 | cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0; | ||
122 | update_sched_clock(&cd, cyc, (u32)~0); | ||
123 | } | 114 | } |
124 | 115 | ||
125 | static int __init mxc_clocksource_init(struct clk *timer_clk) | 116 | static int __init mxc_clocksource_init(struct clk *timer_clk) |
@@ -129,7 +120,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk) | |||
129 | 120 | ||
130 | sched_clock_reg = reg; | 121 | sched_clock_reg = reg; |
131 | 122 | ||
132 | init_sched_clock(&cd, mxc_update_sched_clock, 32, c); | 123 | setup_sched_clock(mxc_read_sched_clock, 32, c); |
133 | return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, | 124 | return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, |
134 | clocksource_mmio_readl_up); | 125 | clocksource_mmio_readl_up); |
135 | } | 126 | } |
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index 30b6433d910d..ad1b45b605a4 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/sched.h> | ||
21 | #include <asm/mach/time.h> | 20 | #include <asm/mach/time.h> |
22 | #include <asm/sched_clock.h> | 21 | #include <asm/sched_clock.h> |
23 | 22 | ||
@@ -79,23 +78,12 @@ void __iomem *mtu_base; /* Assigned by machine code */ | |||
79 | * local implementation which uses the clocksource to get some | 78 | * local implementation which uses the clocksource to get some |
80 | * better resolution when scheduling the kernel. | 79 | * better resolution when scheduling the kernel. |
81 | */ | 80 | */ |
82 | static DEFINE_CLOCK_DATA(cd); | 81 | static u32 notrace nomadik_read_sched_clock(void) |
83 | |||
84 | unsigned long long notrace sched_clock(void) | ||
85 | { | 82 | { |
86 | u32 cyc; | ||
87 | |||
88 | if (unlikely(!mtu_base)) | 83 | if (unlikely(!mtu_base)) |
89 | return 0; | 84 | return 0; |
90 | 85 | ||
91 | cyc = -readl(mtu_base + MTU_VAL(0)); | 86 | return -readl(mtu_base + MTU_VAL(0)); |
92 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
93 | } | ||
94 | |||
95 | static void notrace nomadik_update_sched_clock(void) | ||
96 | { | ||
97 | u32 cyc = -readl(mtu_base + MTU_VAL(0)); | ||
98 | update_sched_clock(&cd, cyc, (u32)~0); | ||
99 | } | 87 | } |
100 | #endif | 88 | #endif |
101 | 89 | ||
@@ -231,9 +219,11 @@ void __init nmdk_timer_init(void) | |||
231 | rate, 200, 32, clocksource_mmio_readl_down)) | 219 | rate, 200, 32, clocksource_mmio_readl_down)) |
232 | pr_err("timer: failed to initialize clock source %s\n", | 220 | pr_err("timer: failed to initialize clock source %s\n", |
233 | "mtu_0"); | 221 | "mtu_0"); |
222 | |||
234 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK | 223 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK |
235 | init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate); | 224 | setup_sched_clock(nomadik_read_sched_clock, 32, rate); |
236 | #endif | 225 | #endif |
226 | |||
237 | /* Timer 1 is used for events */ | 227 | /* Timer 1 is used for events */ |
238 | 228 | ||
239 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); | 229 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); |
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index a6cbb712da51..5f0f2292b7fb 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/sched.h> | ||
21 | #include <linux/clocksource.h> | 20 | #include <linux/clocksource.h> |
22 | 21 | ||
23 | #include <asm/sched_clock.h> | 22 | #include <asm/sched_clock.h> |
@@ -37,41 +36,9 @@ static void __iomem *timer_32k_base; | |||
37 | 36 | ||
38 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 | 37 | #define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 |
39 | 38 | ||
40 | /* | 39 | static u32 notrace omap_32k_read_sched_clock(void) |
41 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
42 | * around for now, as it's just a relative time stamp. | ||
43 | */ | ||
44 | static DEFINE_CLOCK_DATA(cd); | ||
45 | |||
46 | /* | ||
47 | * Constants generated by clocks_calc_mult_shift(m, s, 32768, NSEC_PER_SEC, 60). | ||
48 | * This gives a resolution of about 30us and a wrap period of about 36hrs. | ||
49 | */ | ||
50 | #define SC_MULT 4000000000u | ||
51 | #define SC_SHIFT 17 | ||
52 | |||
53 | static inline unsigned long long notrace _omap_32k_sched_clock(void) | ||
54 | { | ||
55 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; | ||
56 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT); | ||
57 | } | ||
58 | |||
59 | #if defined(CONFIG_OMAP_32K_TIMER) && !defined(CONFIG_OMAP_MPU_TIMER) | ||
60 | unsigned long long notrace sched_clock(void) | ||
61 | { | ||
62 | return _omap_32k_sched_clock(); | ||
63 | } | ||
64 | #else | ||
65 | unsigned long long notrace omap_32k_sched_clock(void) | ||
66 | { | ||
67 | return _omap_32k_sched_clock(); | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | static void notrace omap_update_sched_clock(void) | ||
72 | { | 40 | { |
73 | u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0; | 41 | return timer_32k_base ? __raw_readl(timer_32k_base) : 0; |
74 | update_sched_clock(&cd, cyc, (u32)~0); | ||
75 | } | 42 | } |
76 | 43 | ||
77 | /** | 44 | /** |
@@ -147,8 +114,7 @@ int __init omap_init_clocksource_32k(void) | |||
147 | clocksource_mmio_readl_up)) | 114 | clocksource_mmio_readl_up)) |
148 | printk(err, "32k_counter"); | 115 | printk(err, "32k_counter"); |
149 | 116 | ||
150 | init_fixed_sched_clock(&cd, omap_update_sched_clock, 32, | 117 | setup_sched_clock(omap_32k_read_sched_clock, 32, 32768); |
151 | 32768, SC_MULT, SC_SHIFT); | ||
152 | } | 118 | } |
153 | return 0; | 119 | return 0; |
154 | } | 120 | } |
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index 257f9770b2da..b4d7ec3fbfbe 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <plat/omap_hwmod.h> | 31 | #include <plat/omap_hwmod.h> |
32 | 32 | ||
33 | extern int __init omap_init_clocksource_32k(void); | 33 | extern int __init omap_init_clocksource_32k(void); |
34 | extern unsigned long long notrace omap_32k_sched_clock(void); | ||
35 | 34 | ||
36 | extern void omap_reserve(void); | 35 | extern void omap_reserve(void); |
37 | extern int omap_dss_reset(struct omap_hwmod *); | 36 | extern int omap_dss_reset(struct omap_hwmod *); |
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 69a61367e4b8..1ed8d1397fcf 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c | |||
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/sched.h> | ||
16 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
17 | #include <linux/clockchips.h> | 16 | #include <linux/clockchips.h> |
18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
@@ -60,24 +59,10 @@ static u32 ticks_per_jiffy; | |||
60 | * Orion's sched_clock implementation. It has a resolution of | 59 | * Orion's sched_clock implementation. It has a resolution of |
61 | * at least 7.5ns (133MHz TCLK). | 60 | * at least 7.5ns (133MHz TCLK). |
62 | */ | 61 | */ |
63 | static DEFINE_CLOCK_DATA(cd); | ||
64 | 62 | ||
65 | unsigned long long notrace sched_clock(void) | 63 | static u32 notrace orion_read_sched_clock(void) |
66 | { | 64 | { |
67 | u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF); | 65 | return ~readl(timer_base + TIMER0_VAL_OFF); |
68 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); | ||
69 | } | ||
70 | |||
71 | |||
72 | static void notrace orion_update_sched_clock(void) | ||
73 | { | ||
74 | u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF); | ||
75 | update_sched_clock(&cd, cyc, (u32)~0); | ||
76 | } | ||
77 | |||
78 | static void __init setup_sched_clock(unsigned long tclk) | ||
79 | { | ||
80 | init_sched_clock(&cd, orion_update_sched_clock, 32, tclk); | ||
81 | } | 66 | } |
82 | 67 | ||
83 | /* | 68 | /* |
@@ -217,7 +202,7 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask, | |||
217 | /* | 202 | /* |
218 | * Set scale and timer for sched_clock. | 203 | * Set scale and timer for sched_clock. |
219 | */ | 204 | */ |
220 | setup_sched_clock(tclk); | 205 | setup_sched_clock(orion_read_sched_clock, 32, tclk); |
221 | 206 | ||
222 | /* | 207 | /* |
223 | * Setup free-running clocksource timer (interrupts | 208 | * Setup free-running clocksource timer (interrupts |
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c index c833e7b57599..17c0a2c58dfd 100644 --- a/arch/arm/plat-s5p/s5p-time.c +++ b/arch/arm/plat-s5p/s5p-time.c | |||
@@ -10,7 +10,6 @@ | |||
10 | * published by the Free Software Foundation. | 10 | * published by the Free Software Foundation. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
15 | #include <linux/irq.h> | 14 | #include <linux/irq.h> |
16 | #include <linux/err.h> | 15 | #include <linux/err.h> |
@@ -321,26 +320,14 @@ static void __iomem *s5p_timer_reg(void) | |||
321 | * this wraps around for now, since it is just a relative time | 320 | * this wraps around for now, since it is just a relative time |
322 | * stamp. (Inspired by U300 implementation.) | 321 | * stamp. (Inspired by U300 implementation.) |
323 | */ | 322 | */ |
324 | static DEFINE_CLOCK_DATA(cd); | 323 | static u32 notrace s5p_read_sched_clock(void) |
325 | |||
326 | unsigned long long notrace sched_clock(void) | ||
327 | { | 324 | { |
328 | void __iomem *reg = s5p_timer_reg(); | 325 | void __iomem *reg = s5p_timer_reg(); |
329 | 326 | ||
330 | if (!reg) | 327 | if (!reg) |
331 | return 0; | 328 | return 0; |
332 | 329 | ||
333 | return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | 330 | return ~__raw_readl(reg); |
334 | } | ||
335 | |||
336 | static void notrace s5p_update_sched_clock(void) | ||
337 | { | ||
338 | void __iomem *reg = s5p_timer_reg(); | ||
339 | |||
340 | if (!reg) | ||
341 | return; | ||
342 | |||
343 | update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0); | ||
344 | } | 331 | } |
345 | 332 | ||
346 | static void __init s5p_clocksource_init(void) | 333 | static void __init s5p_clocksource_init(void) |
@@ -358,7 +345,7 @@ static void __init s5p_clocksource_init(void) | |||
358 | s5p_time_setup(timer_source.source_id, TCNT_MAX); | 345 | s5p_time_setup(timer_source.source_id, TCNT_MAX); |
359 | s5p_time_start(timer_source.source_id, PERIODIC); | 346 | s5p_time_start(timer_source.source_id, PERIODIC); |
360 | 347 | ||
361 | init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate); | 348 | setup_sched_clock(s5p_read_sched_clock, 32, clock_rate); |
362 | 349 | ||
363 | if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", | 350 | if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer", |
364 | clock_rate, 250, 32, clocksource_mmio_readl_down)) | 351 | clock_rate, 250, 32, clocksource_mmio_readl_down)) |
diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c index 3d6a4c292cab..b33b74c87232 100644 --- a/arch/arm/plat-versatile/sched-clock.c +++ b/arch/arm/plat-versatile/sched-clock.c | |||
@@ -18,41 +18,24 @@ | |||
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | ||
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/sched.h> | ||
23 | 23 | ||
24 | #include <asm/sched_clock.h> | 24 | #include <asm/sched_clock.h> |
25 | #include <plat/sched_clock.h> | 25 | #include <plat/sched_clock.h> |
26 | 26 | ||
27 | static DEFINE_CLOCK_DATA(cd); | ||
28 | static void __iomem *ctr; | 27 | static void __iomem *ctr; |
29 | 28 | ||
30 | /* | 29 | static u32 notrace versatile_read_sched_clock(void) |
31 | * Constants generated by clocks_calc_mult_shift(m, s, 24MHz, NSEC_PER_SEC, 60). | ||
32 | * This gives a resolution of about 41ns and a wrap period of about 178s. | ||
33 | */ | ||
34 | #define SC_MULT 2796202667u | ||
35 | #define SC_SHIFT 26 | ||
36 | |||
37 | unsigned long long notrace sched_clock(void) | ||
38 | { | 30 | { |
39 | if (ctr) { | 31 | if (ctr) |
40 | u32 cyc = readl(ctr); | 32 | return readl(ctr); |
41 | return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, | ||
42 | SC_MULT, SC_SHIFT); | ||
43 | } else | ||
44 | return 0; | ||
45 | } | ||
46 | 33 | ||
47 | static void notrace versatile_update_sched_clock(void) | 34 | return 0; |
48 | { | ||
49 | u32 cyc = readl(ctr); | ||
50 | update_sched_clock(&cd, cyc, (u32)~0); | ||
51 | } | 35 | } |
52 | 36 | ||
53 | void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) | 37 | void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate) |
54 | { | 38 | { |
55 | ctr = reg; | 39 | ctr = reg; |
56 | init_fixed_sched_clock(&cd, versatile_update_sched_clock, | 40 | setup_sched_clock(versatile_read_sched_clock, 32, rate); |
57 | 32, rate, SC_MULT, SC_SHIFT); | ||
58 | } | 41 | } |