Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Fix delay functions for 601 processors

My earlier merge of delay.h introduced a timebase-based udelay for
32-bit machines but also broke the 601, which doesn't have the
timebase register. This fixes it by using the 601's RTC register on
the 601, and also moves __delay() and udelay() to be out-of-line in
arch/powerpc/kernel/time.c. These functions aren't really performance
critical, after all.

Signed-off-by: Paul Mackerras <paulus@samba.org>

+30 -46
-8
arch/powerpc/kernel/misc_32.S
··· 27 27 28 28 .text 29 29 30 - .align 5 31 - _GLOBAL(__delay) 32 - cmpwi 0,r3,0 33 - mtctr r3 34 - beqlr 35 - 1: bdnz 1b 36 - blr 37 - 38 30 /* 39 31 * This returns the high 64 bits of the product of two 64-bit numbers. 40 32 */
+28
arch/powerpc/kernel/time.c
··· 130 130 */ 131 131 DEFINE_PER_CPU(unsigned long, last_jiffy); 132 132 133 + void __delay(unsigned long loops) 134 + { 135 + unsigned long start; 136 + int diff; 137 + 138 + if (__USE_RTC()) { 139 + start = get_rtcl(); 140 + do { 141 + /* the RTCL register wraps at 1000000000 */ 142 + diff = get_rtcl() - start; 143 + if (diff < 0) 144 + diff += 1000000000; 145 + } while (diff < loops); 146 + } else { 147 + start = get_tbl(); 148 + while (get_tbl() - start < loops) 149 + HMT_low(); 150 + HMT_medium(); 151 + } 152 + } 153 + EXPORT_SYMBOL(__delay); 154 + 155 + void udelay(unsigned long usecs) 156 + { 157 + __delay(tb_ticks_per_usec * usecs); 158 + } 159 + EXPORT_SYMBOL(udelay); 160 + 133 161 static __inline__ void timer_check_rtc(void) 134 162 { 135 163 /*
+2 -38
include/asm-powerpc/delay.h
··· 13 13 * Anton Blanchard. 14 14 */ 15 15 16 - extern unsigned long tb_ticks_per_usec; 17 - 18 - #ifdef CONFIG_PPC64 19 - /* define these here to prevent circular dependencies */ 20 - /* these instructions control the thread priority on multi-threaded cpus */ 21 - #define __HMT_low() asm volatile("or 1,1,1") 22 - #define __HMT_medium() asm volatile("or 2,2,2") 23 - #else 24 - #define __HMT_low() 25 - #define __HMT_medium() 26 - #endif 27 - 28 - #define __barrier() asm volatile("" ::: "memory") 29 - 30 - static inline unsigned long __get_tb(void) 31 - { 32 - unsigned long rval; 33 - 34 - asm volatile("mftb %0" : "=r" (rval)); 35 - return rval; 36 - } 37 - 38 - static inline void __delay(unsigned long loops) 39 - { 40 - unsigned long start = __get_tb(); 41 - 42 - while((__get_tb() - start) < loops) 43 - __HMT_low(); 44 - __HMT_medium(); 45 - __barrier(); 46 - } 47 - 48 - static inline void udelay(unsigned long usecs) 49 - { 50 - unsigned long loops = tb_ticks_per_usec * usecs; 51 - 52 - __delay(loops); 53 - } 16 + extern void __delay(unsigned long loops); 17 + extern void udelay(unsigned long usecs); 54 18 55 19 #endif /* _ASM_POWERPC_DELAY_H */