Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d4518d7 authored by Peter Teichmann's avatar Peter Teichmann Committed by Russell King
Browse files

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 0328ad23
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -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...
 */
+7 −5
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
#ifndef __ASM_ARM_DELAY_H
#define __ASM_ARM_DELAY_H

#include <asm/param.h>	/* HZ */

extern void __delay(int loops);

/*
@@ -13,7 +15,7 @@ extern void __delay(int loops);
 * it, it means that you're calling udelay() with an out of range value.
 *
 * With currently imposed limits, this means that we support a max delay
 * of 2000us and 671 bogomips
 * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
 */
extern void __bad_udelay(void);

@@ -35,7 +37,7 @@ extern void __const_udelay(unsigned long);
#define udelay(n)							\
	(__builtin_constant_p(n) ?					\
	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\
			__const_udelay((n) * 0x68dbul)) :	\
			__const_udelay((n) * ((2199023U*HZ)>>11))) :	\
	  __udelay(n))

#endif /* defined(_ARM_DELAY_H) */