diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-15 16:55:06 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-12-22 17:44:49 -0500 |
commit | f06a1624621527ef597ae4b3b795553fc1b2eff2 (patch) | |
tree | bceabde5032fc27d71d6da436e74c7f848022825 /arch/arm | |
parent | dc548fbbd2ecd0fc3b02301d551e5f8e19ae58fd (diff) |
ARM: orion: convert sched_clock() to use new infrastructure
Convert orion platforms to use the new sched_clock() infrastructure for
extending 32bit counters to full 64-bit nanoseconds.
Acked-by: Nicolas Pitre <nico@fluxnic.net>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/plat-orion/time.c | 44 |
2 files changed, 10 insertions, 35 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 726279fe3f5..92e8c0174dd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -997,6 +997,7 @@ config PLAT_IOP | |||
997 | 997 | ||
998 | config PLAT_ORION | 998 | config PLAT_ORION |
999 | bool | 999 | bool |
1000 | select HAVE_SCHED_CLOCK | ||
1000 | 1001 | ||
1001 | config PLAT_PXA | 1002 | config PLAT_PXA |
1002 | bool | 1003 | bool |
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c index 123f96f4194..c3da2478b2a 100644 --- a/arch/arm/plat-orion/time.c +++ b/arch/arm/plat-orion/time.c | |||
@@ -13,11 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/cnt32_to_63.h> | ||
17 | #include <linux/timer.h> | 16 | #include <linux/timer.h> |
18 | #include <linux/clockchips.h> | 17 | #include <linux/clockchips.h> |
19 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
20 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <asm/sched_clock.h> | ||
21 | #include <asm/mach/time.h> | 21 | #include <asm/mach/time.h> |
22 | #include <mach/bridge-regs.h> | 22 | #include <mach/bridge-regs.h> |
23 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
@@ -44,52 +44,26 @@ static u32 ticks_per_jiffy; | |||
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Orion's sched_clock implementation. It has a resolution of | 46 | * Orion's sched_clock implementation. It has a resolution of |
47 | * at least 7.5ns (133MHz TCLK) and a maximum value of 834 days. | 47 | * at least 7.5ns (133MHz TCLK). |
48 | * | ||
49 | * Because the hardware timer period is quite short (21 secs if | ||
50 | * 200MHz TCLK) and because cnt32_to_63() needs to be called at | ||
51 | * least once per half period to work properly, a kernel timer is | ||
52 | * set up to ensure this requirement is always met. | ||
53 | */ | 48 | */ |
54 | #define TCLK2NS_SCALE_FACTOR 8 | 49 | static DEFINE_CLOCK_DATA(cd); |
55 | |||
56 | static unsigned long tclk2ns_scale; | ||
57 | 50 | ||
58 | unsigned long long notrace sched_clock(void) | 51 | unsigned long long notrace sched_clock(void) |
59 | { | 52 | { |
60 | unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL)); | 53 | u32 cyc = 0xffffffff - readl(TIMER0_VAL); |
61 | return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR; | 54 | return cyc_to_sched_clock(&cd, cyc, (u32)~0); |
62 | } | 55 | } |
63 | 56 | ||
64 | static struct timer_list cnt32_to_63_keepwarm_timer; | ||
65 | 57 | ||
66 | static void cnt32_to_63_keepwarm(unsigned long data) | 58 | static void notrace orion_update_sched_clock(void) |
67 | { | 59 | { |
68 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); | 60 | u32 cyc = 0xffffffff - readl(TIMER0_VAL); |
69 | (void) sched_clock(); | 61 | update_sched_clock(&cd, cyc, (u32)~0); |
70 | } | 62 | } |
71 | 63 | ||
72 | static void __init setup_sched_clock(unsigned long tclk) | 64 | static void __init setup_sched_clock(unsigned long tclk) |
73 | { | 65 | { |
74 | unsigned long long v; | 66 | init_sched_clock(&cd, orion_update_sched_clock, 32, tclk); |
75 | unsigned long data; | ||
76 | |||
77 | v = NSEC_PER_SEC; | ||
78 | v <<= TCLK2NS_SCALE_FACTOR; | ||
79 | v += tclk/2; | ||
80 | do_div(v, tclk); | ||
81 | /* | ||
82 | * We want an even value to automatically clear the top bit | ||
83 | * returned by cnt32_to_63() without an additional run time | ||
84 | * instruction. So if the LSB is 1 then round it up. | ||
85 | */ | ||
86 | if (v & 1) | ||
87 | v++; | ||
88 | tclk2ns_scale = v; | ||
89 | |||
90 | data = (0xffffffffUL / tclk / 2 - 2) * HZ; | ||
91 | setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data); | ||
92 | mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); | ||
93 | } | 67 | } |
94 | 68 | ||
95 | /* | 69 | /* |