diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-10-20 00:37:05 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-10-24 21:54:18 -0400 |
commit | 859deea949c382d9ccb6397fe33df3703ecef45d (patch) | |
tree | b0fe2d7a814143f3ff61a73a0727522a1a3dd6e4 /include/asm-powerpc/time.h | |
parent | 21c4ff80cba5e24932f3ef79c8482c0491630b2b (diff) |
[POWERPC] Cell timebase bug workaround
The Cell CPU timebase has an erratum. When reading the entire 64 bits
of the timebase with one mftb instruction, there is a handful of cycles
window during which one might read a value with the low order 32 bits
already reset to 0x00000000 but the high order bits not yet incremeted
by one. This fixes it by reading the timebase again until the low order
32 bits is no longer 0. That might introduce occasional latencies if
hitting mftb just at the wrong time, but no more than 70ns on a cell
blade, and that was considered acceptable.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include/asm-powerpc/time.h')
-rw-r--r-- | include/asm-powerpc/time.h | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index b051d4c88c3b..a78285010d62 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h | |||
@@ -82,30 +82,35 @@ struct div_result { | |||
82 | #define __USE_RTC() 0 | 82 | #define __USE_RTC() 0 |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | /* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */ | 85 | #ifdef CONFIG_PPC64 |
86 | |||
87 | /* For compatibility, get_tbl() is defined as get_tb() on ppc64 */ | ||
88 | #define get_tbl get_tb | ||
89 | |||
90 | #else | ||
91 | |||
86 | static inline unsigned long get_tbl(void) | 92 | static inline unsigned long get_tbl(void) |
87 | { | 93 | { |
88 | unsigned long tbl; | ||
89 | |||
90 | #if defined(CONFIG_403GCX) | 94 | #if defined(CONFIG_403GCX) |
95 | unsigned long tbl; | ||
91 | asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); | 96 | asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); |
97 | return tbl; | ||
92 | #else | 98 | #else |
93 | asm volatile("mftb %0" : "=r" (tbl)); | 99 | return mftbl(); |
94 | #endif | 100 | #endif |
95 | return tbl; | ||
96 | } | 101 | } |
97 | 102 | ||
98 | static inline unsigned int get_tbu(void) | 103 | static inline unsigned int get_tbu(void) |
99 | { | 104 | { |
105 | #ifdef CONFIG_403GCX | ||
100 | unsigned int tbu; | 106 | unsigned int tbu; |
101 | |||
102 | #if defined(CONFIG_403GCX) | ||
103 | asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); | 107 | asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); |
108 | return tbu; | ||
104 | #else | 109 | #else |
105 | asm volatile("mftbu %0" : "=r" (tbu)); | 110 | return mftbu(); |
106 | #endif | 111 | #endif |
107 | return tbu; | ||
108 | } | 112 | } |
113 | #endif /* !CONFIG_PPC64 */ | ||
109 | 114 | ||
110 | static inline unsigned int get_rtcl(void) | 115 | static inline unsigned int get_rtcl(void) |
111 | { | 116 | { |
@@ -131,7 +136,7 @@ static inline u64 get_tb(void) | |||
131 | { | 136 | { |
132 | return mftb(); | 137 | return mftb(); |
133 | } | 138 | } |
134 | #else | 139 | #else /* CONFIG_PPC64 */ |
135 | static inline u64 get_tb(void) | 140 | static inline u64 get_tb(void) |
136 | { | 141 | { |
137 | unsigned int tbhi, tblo, tbhi2; | 142 | unsigned int tbhi, tblo, tbhi2; |
@@ -144,7 +149,7 @@ static inline u64 get_tb(void) | |||
144 | 149 | ||
145 | return ((u64)tbhi << 32) | tblo; | 150 | return ((u64)tbhi << 32) | tblo; |
146 | } | 151 | } |
147 | #endif | 152 | #endif /* !CONFIG_PPC64 */ |
148 | 153 | ||
149 | static inline void set_tb(unsigned int upper, unsigned int lower) | 154 | static inline void set_tb(unsigned int upper, unsigned int lower) |
150 | { | 155 | { |