File: /usr/src/linux/arch/i386/lib/delay.c

1     /*
2      *	Precise Delay Loops for i386
3      *
4      *	Copyright (C) 1993 Linus Torvalds
5      *	Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
6      *
7      *	The __delay function must _NOT_ be inlined as its execution time
8      *	depends wildly on alignment on many x86 processors. The additional
9      *	jump magic is needed to get the timing stable on all the CPU's
10      *	we have to worry about.
11      */
12     
13     #include <linux/config.h>
14     #include <linux/sched.h>
15     #include <linux/delay.h>
16     #include <asm/processor.h>
17     #include <asm/delay.h>
18     
19     #ifdef CONFIG_SMP
20     #include <asm/smp.h>
21     #endif
22     
23     int x86_udelay_tsc = 0;		/* Delay via TSC */
24     
25     	
26     /*
27      *	Do a udelay using the TSC for any CPU that happens
28      *	to have one that we trust.
29      */
30     
31     static void __rdtsc_delay(unsigned long loops)
32     {
33     	unsigned long bclock, now;
34     	
35     	rdtscl(bclock);
36     	do
37     	{
38     		rep_nop();
39     		rdtscl(now);
40     	} while ((now-bclock) < loops);
41     }
42     
43     /*
44      *	Non TSC based delay loop for 386, 486, MediaGX
45      */
46      
47     static void __loop_delay(unsigned long loops)
48     {
49     	int d0;
50     	__asm__ __volatile__(
51     		"\tjmp 1f\n"
52     		".align 16\n"
53     		"1:\tjmp 2f\n"
54     		".align 16\n"
55     		"2:\tdecl %0\n\tjns 2b"
56     		:"=&a" (d0)
57     		:"0" (loops));
58     }
59     
60     void __delay(unsigned long loops)
61     {
62     	if (x86_udelay_tsc)
63     		__rdtsc_delay(loops);
64     	else
65     		__loop_delay(loops);
66     }
67     
68     inline void __const_udelay(unsigned long xloops)
69     {
70     	int d0;
71     	__asm__("mull %0"
72     		:"=d" (xloops), "=&a" (d0)
73     		:"1" (xloops),"0" (current_cpu_data.loops_per_jiffy));
74             __delay(xloops * HZ);
75     }
76     
77     void __udelay(unsigned long usecs)
78     {
79     	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
80     }
81