00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/console.h>
00016 #include <agnix/counters.h>
00017 #include <agnix/timer.h>
00018 #include <agnix/adi/adi.h>
00019 #include <asm/cpu_ops.h>
00020
00021 #define MOD_NAME "BOGO: "
00022
00023 extern struct chip_s cpu_chip;
00024 extern int counter_jiffies_desc;
00025
00026 unsigned long loops_per_jiffy = (1<<12);
00027
00028 #define LPS_PREC 8
00029
00030 void __tsc_delay(unsigned long loops)
00031 {
00032 u32 tsc_s[2];
00033 u32 tsc_c[2];
00034
00035 rdtsc(tsc_s[0], tsc_s[1]);
00036
00037 do {
00038 rdtsc(tsc_c[0], tsc_c[1]);
00039 } while ((tsc_c[0] - tsc_s[0]) < loops);
00040 }
00041
00042 void __normal_delay(unsigned long loops)
00043 {
00044 __asm__ __volatile__ (
00045 "jmp 1f\n\t"
00046 ".align 16\n\t"
00047 "1: jmp 2f\n\t"
00048 ".align 16\n\t"
00049 "2: decl %%eax\t\n"
00050 "jns 2b"
00051 :
00052 :"a"(loops)
00053 );
00054 }
00055
00056 void __delay(unsigned long loops)
00057 {
00058 if (!(read_cr4() & CPU_CR4_TSD))
00059 __tsc_delay(loops);
00060 else
00061 __normal_delay(loops);
00062 }
00063
00064 void __init _cpu_calibrate_delay(void (*delay_routine)(unsigned long), const char *text)
00065 {
00066 struct cpu_parm_s *cpu_parm = cpu_parm(&cpu_chip);
00067 u32 ticks, ticks_cur, loopbit;
00068 u32 jiffies_latch[2];
00069 int lps_precision = LPS_PREC;
00070
00071 loops_per_jiffy = (1<<12);
00072
00073 printk("CPU_0: Calibrating delay loop...");
00074 while (loops_per_jiffy <<= 1) {
00075
00076 counter_read(counter_jiffies_desc, jiffies_latch);
00077 ticks = jiffies_latch[0];
00078
00079 do {
00080 counter_read(counter_jiffies_desc, jiffies_latch);
00081 ticks_cur = jiffies_latch[0];
00082 } while(ticks_cur == ticks);
00083
00084 counter_read(counter_jiffies_desc, jiffies_latch);
00085 ticks = jiffies_latch[0];
00086 delay_routine(loops_per_jiffy);
00087
00088 counter_read(counter_jiffies_desc, jiffies_latch);
00089 ticks = jiffies_latch[0] - ticks;
00090 if (ticks)
00091 break;
00092 }
00093
00094 loops_per_jiffy >>= 1;
00095 loopbit = loops_per_jiffy;
00096 while ( lps_precision-- && (loopbit >>= 1) ) {
00097 loops_per_jiffy |= loopbit;
00098
00099 counter_read(counter_jiffies_desc, jiffies_latch);
00100 ticks = jiffies_latch[0];
00101
00102 do {
00103 counter_read(counter_jiffies_desc, jiffies_latch);
00104 ticks_cur = jiffies_latch[0];
00105 } while(ticks_cur == ticks);
00106
00107 counter_read(counter_jiffies_desc, jiffies_latch);
00108 ticks = jiffies_latch[0];
00109 delay_routine(loops_per_jiffy);
00110
00111 counter_read(counter_jiffies_desc, jiffies_latch);
00112 if (jiffies_latch[0] != ticks)
00113 loops_per_jiffy &= ~loopbit;
00114 }
00115
00116 cpu_parm->cpu_bogomips = loops_per_jiffy;
00117
00118 printk(" %d.%02d BogoMIPS (%s)\n", loops_per_jiffy/(500000/TIMER_HZ),
00119 (loops_per_jiffy/(5000/TIMER_HZ)) % 100, text);
00120 }
00121
00122 void __init cpu_calibrate_delay(void)
00123 {
00124 _cpu_calibrate_delay(__tsc_delay, "fake");
00125 _cpu_calibrate_delay(__normal_delay, "true");
00126 }