[ARM] 3346/1: Fix udelay() for HZ values different from 100

Patch from Peter Teichmann

Currently, if the kernels HZ value is greater than 100, delays with the udelay function are too short. This can cause trouble for instance with the zd1201 usb wlan driver.

This patch suggests a solution that keeps the overhead small and maintains (hopefully) sufficient resolution.

Signed-off-by: Peter Teichmann
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S
index b3fb475..9183b06 100644
--- a/arch/arm/lib/delay.S
+++ b/arch/arm/lib/delay.S
@@ -9,28 +9,32 @@
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/param.h>
 		.text
 
 .LC0:		.word	loops_per_jiffy
+.LC1:		.word	(2199023*HZ)>>11
 
 /*
- * 0 <= r0 <= 2000
+ * r0  <= 2000
+ * lpj <= 0x01ffffff (max. 3355 bogomips)
+ * HZ  <= 1000
  */
+
 ENTRY(__udelay)
-		mov	r2,     #0x6800
-		orr	r2, r2, #0x00db
+		ldr	r2, .LC1
 		mul	r0, r2, r0
-ENTRY(__const_udelay)				@ 0 <= r0 <= 0x01ffffff
+ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
 		ldr	r2, .LC0
-		ldr	r2, [r2]		@ max = 0x0fffffff
-		mov	r0, r0, lsr #11		@ max = 0x00003fff
-		mov	r2, r2, lsr #11		@ max = 0x0003ffff
+		ldr	r2, [r2]		@ max = 0x01ffffff
+		mov	r0, r0, lsr #14		@ max = 0x0001ffff
+		mov	r2, r2, lsr #10		@ max = 0x00007fff
 		mul	r0, r2, r0		@ max = 2^32-1
 		movs	r0, r0, lsr #6
 		RETINSTR(moveq,pc,lr)
 
 /*
- * loops = (r0 * 0x10c6 * 100 * loops_per_jiffy) / 2^32
+ * loops = r0 * HZ * loops_per_jiffy / 1000000
  *
  * Oh, if only we had a cycle counter...
  */