linux-mips
[Top] [All Lists]

[PATCH] delay.h fix for HZ != 100 or 128

To: "linux-mips@oss.sgi.com"@ayrnetworks.com, ralf@oss.sgi.com
Subject: [PATCH] delay.h fix for HZ != 100 or 128
From: William Jhun <wjhun@ayrnetworks.com>
Date: Fri, 9 Aug 2002 19:27:30 -0700
Sender: owner-linux-mips@oss.sgi.com
User-agent: Mutt/1.2.5i
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


<Prev in Thread] Current Thread [Next in Thread>
  • [PATCH] delay.h fix for HZ != 100 or 128, William Jhun <=