The current include/asm-mips/delay.h uses fixed constants for either HZ
= 100 or 128, but won't work for other values, such as HZ = 1000 or
1024. This patch calculates that constant (still to infinite precision)
and does 64-bit arithmetic (not really, though - gcc does it with only
one additional 32-bit multiply) for HZ > 1000 so that udelay() will
still work for usec <= 1000 (mdelay(), etc).
Thanks,
Will
---
Index: include/asm-mips/delay.h
===================================================================
RCS file: /cvs/linux/include/asm-mips/delay.h,v
retrieving revision 1.10.2.1
diff -u -r1.10.2.1 delay.h
--- include/asm-mips/delay.h 2002/08/09 22:17:48 1.10.2.1
+++ include/asm-mips/delay.h 2002/08/10 02:18:47
@@ -29,26 +29,35 @@
/*
* division by multiplication: you don't have to worry about
* loss of precision.
- *
- * Use only for very small delays ( < 1 msec). Should probably use a
+ *
+ * Use only for very small delays ( <= 1 msec). Should probably use a
* lookup table, really, as the multiplications take much too long with
* short delays. This is a "reasonable" implementation, though (and the
* first constant multiplications gets optimized away if the delay is
* a constant)
*/
extern __inline__ void __udelay(unsigned long usecs, unsigned long lpj)
-{
- unsigned long lo;
-
-#if (HZ == 100)
- usecs *= 0x00068db8; /* 2**32 / (1000000 / HZ) */
-#elif (HZ == 128)
- usecs *= 0x0008637b; /* 2**32 / (1000000 / HZ) */
+{
+ const unsigned long long mult_const =
+ (((unsigned long long)HZ << 32)/1000000);
+#if (HZ > 1000)
+ /* If HZ > 1000, udelay() did't work for usecs <= 1000.
+ *
+ * GCC is smart enough to do this with just three
+ * 32-bit multiplies.
+ */
+ unsigned long long xusecs;
+ xusecs = (unsigned long long)usecs * (unsigned long long)lpj *
+ mult_const;
+ __delay((unsigned long)(xusecs>>32));
+#else
+ unsigned long lo;
+ usecs *= (unsigned long long)mult_const;
+ __asm__("multu\t%2,%3"
+ :"=h" (usecs), "=l" (lo)
+ :"r" (usecs),"r" (lpj));
+ __delay(usecs);
#endif
- __asm__("multu\t%2,%3"
- :"=h" (usecs), "=l" (lo)
- :"r" (usecs),"r" (lpj));
- __delay(usecs);
}
#ifdef CONFIG_SMP
|