6f84fa2f3e
This converts the i386 arch to use the generic timeofday subsystem. It enabled the GENERIC_TIME option, disables the timer_opts code and other arch specific timekeeping code and reworks the delay code. While this patch enables the generic timekeeping, please note that this patch does not provide any i386 clocksource. Thus only the jiffies clocksource will be available. To get full replacements for the code being disabled here, the timeofday-clocks-i386 patch will needed. Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
105 lines
1.9 KiB
C
105 lines
1.9 KiB
C
/*
|
|
* Precise Delay Loops for i386
|
|
*
|
|
* Copyright (C) 1993 Linus Torvalds
|
|
* Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
|
|
*
|
|
* The __delay function must _NOT_ be inlined as its execution time
|
|
* depends wildly on alignment on many x86 processors. The additional
|
|
* jump magic is needed to get the timing stable on all the CPU's
|
|
* we have to worry about.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/config.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include <asm/processor.h>
|
|
#include <asm/delay.h>
|
|
#include <asm/timer.h>
|
|
|
|
#ifdef CONFIG_SMP
|
|
# include <asm/smp.h>
|
|
#endif
|
|
|
|
/* simple loop based delay: */
|
|
static void delay_loop(unsigned long loops)
|
|
{
|
|
int d0;
|
|
|
|
__asm__ __volatile__(
|
|
"\tjmp 1f\n"
|
|
".align 16\n"
|
|
"1:\tjmp 2f\n"
|
|
".align 16\n"
|
|
"2:\tdecl %0\n\tjns 2b"
|
|
:"=&a" (d0)
|
|
:"0" (loops));
|
|
}
|
|
|
|
/* TSC based delay: */
|
|
static void delay_tsc(unsigned long loops)
|
|
{
|
|
unsigned long bclock, now;
|
|
|
|
rdtscl(bclock);
|
|
do {
|
|
rep_nop();
|
|
rdtscl(now);
|
|
} while ((now-bclock) < loops);
|
|
}
|
|
|
|
/*
|
|
* Since we calibrate only once at boot, this
|
|
* function should be set once at boot and not changed
|
|
*/
|
|
static void (*delay_fn)(unsigned long) = delay_loop;
|
|
|
|
void use_tsc_delay(void)
|
|
{
|
|
delay_fn = delay_tsc;
|
|
}
|
|
|
|
int read_current_timer(unsigned long *timer_val)
|
|
{
|
|
if (delay_fn == delay_tsc) {
|
|
rdtscl(*timer_val);
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void __delay(unsigned long loops)
|
|
{
|
|
delay_fn(loops);
|
|
}
|
|
|
|
inline void __const_udelay(unsigned long xloops)
|
|
{
|
|
int d0;
|
|
|
|
xloops *= 4;
|
|
__asm__("mull %0"
|
|
:"=d" (xloops), "=&a" (d0)
|
|
:"1" (xloops), "0"
|
|
(cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
|
|
|
|
__delay(++xloops);
|
|
}
|
|
|
|
void __udelay(unsigned long usecs)
|
|
{
|
|
__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
|
|
}
|
|
|
|
void __ndelay(unsigned long nsecs)
|
|
{
|
|
__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
|
|
}
|
|
|
|
EXPORT_SYMBOL(__delay);
|
|
EXPORT_SYMBOL(__const_udelay);
|
|
EXPORT_SYMBOL(__udelay);
|
|
EXPORT_SYMBOL(__ndelay);
|