diff options
author | Olof Johansson <olof@lixom.net> | 2013-04-17 13:10:01 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-04-17 13:10:01 -0400 |
commit | c3e0c873d0653e6e7628b5a8a9fcb3745444ca9e (patch) | |
tree | dd7448d5515c56604cd8e57f3d6399f5640d57a3 /arch/arm/kernel | |
parent | 228e3023eb0430b4b9ed0736f8f87c96a6cd9c7a (diff) | |
parent | 69a517b2471bcd1c5a175aad82647c1e2c24f08b (diff) |
Merge tag 'clksrc-cleanup-for-3.10-part2' of git://sources.calxeda.com/kernel/linux into late/clksrc
This is the 2nd part of ARM timer clean-ups for 3.10. This series has
the following changes:
- Add sched_clock selection logic to select the highest frequency clock
- Use full 64-bit arch timer counter for sched_clock
- Convert arch timer, sp804 and integrator-cp timers to CLKSRC_OF and
adapt all users to use clocksource_of_init
* tag 'clksrc-cleanup-for-3.10-part2' of git://sources.calxeda.com/kernel/linux:
devtree: add binding documentation for sp804
ARM: integrator-cp: convert use CLKSRC_OF for timer init
ARM: versatile: use OF init for sp804 timer
ARM: versatile: add versatile dtbs to dtbs target
ARM: vexpress: remove extra timer-sp control register clearing
ARM: dts: vexpress: disable CA9 core tile sp804 timer
ARM: vexpress: remove sp804 OF init
ARM: highbank: use OF init for sp804 timer
ARM: timer-sp: convert to use CLKSRC_OF init
OF: add empty of_device_is_available for !OF
ARM: convert arm/arm64 arch timer to use CLKSRC_OF init
ARM: make machine_desc->init_time default to clocksource_of_init
ARM: arch_timer: use full 64-bit counter for sched_clock
ARM: make sched_clock just call a function pointer
ARM: sched_clock: allow changing to higher frequency counter
Signed-off-by: Olof Johansson <olof@lixom.net>
This has a nasty set of conflicts with the exynos MCT code, which was
moved in a separate branch, and then fixed up when merged in, but still
conflicts a bit here. It should have been sorted out by this merge though.
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/arch_timer.c | 29 | ||||
-rw-r--r-- | arch/arm/kernel/sched_clock.c | 15 | ||||
-rw-r--r-- | arch/arm/kernel/time.c | 7 |
3 files changed, 32 insertions, 19 deletions
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index d957a51435d8..59dcdced6e30 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c | |||
@@ -22,9 +22,11 @@ static unsigned long arch_timer_read_counter_long(void) | |||
22 | return arch_timer_read_counter(); | 22 | return arch_timer_read_counter(); |
23 | } | 23 | } |
24 | 24 | ||
25 | static u32 arch_timer_read_counter_u32(void) | 25 | static u32 sched_clock_mult __read_mostly; |
26 | |||
27 | static unsigned long long notrace arch_timer_sched_clock(void) | ||
26 | { | 28 | { |
27 | return arch_timer_read_counter(); | 29 | return arch_timer_read_counter() * sched_clock_mult; |
28 | } | 30 | } |
29 | 31 | ||
30 | static struct delay_timer arch_delay_timer; | 32 | static struct delay_timer arch_delay_timer; |
@@ -37,25 +39,20 @@ static void __init arch_timer_delay_timer_register(void) | |||
37 | register_current_timer_delay(&arch_delay_timer); | 39 | register_current_timer_delay(&arch_delay_timer); |
38 | } | 40 | } |
39 | 41 | ||
40 | int __init arch_timer_of_register(void) | 42 | int __init arch_timer_arch_init(void) |
41 | { | 43 | { |
42 | int ret; | 44 | u32 arch_timer_rate = arch_timer_get_rate(); |
43 | 45 | ||
44 | ret = arch_timer_init(); | 46 | if (arch_timer_rate == 0) |
45 | if (ret) | 47 | return -ENXIO; |
46 | return ret; | ||
47 | 48 | ||
48 | arch_timer_delay_timer_register(); | 49 | arch_timer_delay_timer_register(); |
49 | 50 | ||
50 | return 0; | 51 | /* Cache the sched_clock multiplier to save a divide in the hot path. */ |
51 | } | 52 | sched_clock_mult = NSEC_PER_SEC / arch_timer_rate; |
52 | 53 | sched_clock_func = arch_timer_sched_clock; | |
53 | int __init arch_timer_sched_clock_init(void) | 54 | pr_info("sched_clock: ARM arch timer >56 bits at %ukHz, resolution %uns\n", |
54 | { | 55 | arch_timer_rate / 1000, sched_clock_mult); |
55 | if (arch_timer_get_rate() == 0) | ||
56 | return -ENXIO; | ||
57 | 56 | ||
58 | setup_sched_clock(arch_timer_read_counter_u32, | ||
59 | 32, arch_timer_get_rate()); | ||
60 | return 0; | 57 | return 0; |
61 | } | 58 | } |
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c index bd6f56b9ec21..880584852fca 100644 --- a/arch/arm/kernel/sched_clock.c +++ b/arch/arm/kernel/sched_clock.c | |||
@@ -20,6 +20,7 @@ struct clock_data { | |||
20 | u64 epoch_ns; | 20 | u64 epoch_ns; |
21 | u32 epoch_cyc; | 21 | u32 epoch_cyc; |
22 | u32 epoch_cyc_copy; | 22 | u32 epoch_cyc_copy; |
23 | unsigned long rate; | ||
23 | u32 mult; | 24 | u32 mult; |
24 | u32 shift; | 25 | u32 shift; |
25 | bool suspended; | 26 | bool suspended; |
@@ -113,11 +114,14 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) | |||
113 | u64 res, wrap; | 114 | u64 res, wrap; |
114 | char r_unit; | 115 | char r_unit; |
115 | 116 | ||
117 | if (cd.rate > rate) | ||
118 | return; | ||
119 | |||
116 | BUG_ON(bits > 32); | 120 | BUG_ON(bits > 32); |
117 | WARN_ON(!irqs_disabled()); | 121 | WARN_ON(!irqs_disabled()); |
118 | WARN_ON(read_sched_clock != jiffy_sched_clock_read); | ||
119 | read_sched_clock = read; | 122 | read_sched_clock = read; |
120 | sched_clock_mask = (1 << bits) - 1; | 123 | sched_clock_mask = (1 << bits) - 1; |
124 | cd.rate = rate; | ||
121 | 125 | ||
122 | /* calculate the mult/shift to convert counter ticks to ns. */ | 126 | /* calculate the mult/shift to convert counter ticks to ns. */ |
123 | clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); | 127 | clocks_calc_mult_shift(&cd.mult, &cd.shift, rate, NSEC_PER_SEC, 0); |
@@ -161,12 +165,19 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate) | |||
161 | pr_debug("Registered %pF as sched_clock source\n", read); | 165 | pr_debug("Registered %pF as sched_clock source\n", read); |
162 | } | 166 | } |
163 | 167 | ||
164 | unsigned long long notrace sched_clock(void) | 168 | static unsigned long long notrace sched_clock_32(void) |
165 | { | 169 | { |
166 | u32 cyc = read_sched_clock(); | 170 | u32 cyc = read_sched_clock(); |
167 | return cyc_to_sched_clock(cyc, sched_clock_mask); | 171 | return cyc_to_sched_clock(cyc, sched_clock_mask); |
168 | } | 172 | } |
169 | 173 | ||
174 | unsigned long long __read_mostly (*sched_clock_func)(void) = sched_clock_32; | ||
175 | |||
176 | unsigned long long notrace sched_clock(void) | ||
177 | { | ||
178 | return sched_clock_func(); | ||
179 | } | ||
180 | |||
170 | void __init sched_clock_postinit(void) | 181 | void __init sched_clock_postinit(void) |
171 | { | 182 | { |
172 | /* | 183 | /* |
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 955d92d265e5..abff4e9aaee0 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/profile.h> | 23 | #include <linux/profile.h> |
24 | #include <linux/timer.h> | 24 | #include <linux/timer.h> |
25 | #include <linux/clocksource.h> | ||
25 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
26 | 27 | ||
27 | #include <asm/thread_info.h> | 28 | #include <asm/thread_info.h> |
@@ -115,6 +116,10 @@ int __init register_persistent_clock(clock_access_fn read_boot, | |||
115 | 116 | ||
116 | void __init time_init(void) | 117 | void __init time_init(void) |
117 | { | 118 | { |
118 | machine_desc->init_time(); | 119 | if (machine_desc->init_time) |
120 | machine_desc->init_time(); | ||
121 | else | ||
122 | clocksource_of_init(); | ||
123 | |||
119 | sched_clock_postinit(); | 124 | sched_clock_postinit(); |
120 | } | 125 | } |