diff options
author | Zheng Da <zhengda1936@gmail.com> | 2010-07-12 22:46:28 +0200 |
---|---|---|
committer | Zheng Da <zhengda1936@gmail.com> | 2010-07-12 22:46:28 +0200 |
commit | 91af4ed54bbdb3a2cae9606eb69ebbaddff5602c (patch) | |
tree | beaa39c7071abbd4718d620e08675fabfe1a48fd /libdde_linux26 | |
parent | 2b91d7ba805279f3f871f95d5d49c6c1b7d6b879 (diff) |
calibrate the delay loop several times.
It's necessary when we do it in the user space, as that the CPU switches
to other processes and the result is too imprecise.
Diffstat (limited to 'libdde_linux26')
-rw-r--r-- | libdde_linux26/lib/src/init/calibrate.c | 78 |
1 files changed, 48 insertions, 30 deletions
diff --git a/libdde_linux26/lib/src/init/calibrate.c b/libdde_linux26/lib/src/init/calibrate.c index aede8e53..687da473 100644 --- a/libdde_linux26/lib/src/init/calibrate.c +++ b/libdde_linux26/lib/src/init/calibrate.c @@ -123,11 +123,50 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} */ #define LPS_PREC 8 -void __cpuinit calibrate_delay(void) +static unsigned long __cpuinit calibrate_delay_estimate(void) { unsigned long ticks, loopbit; int lps_precision = LPS_PREC; + int loops_per_jiffy; + + loops_per_jiffy = (1<<12); + + while ((loops_per_jiffy <<= 1) != 0) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + /* Go .. */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + + /* + * Do a binary approximation to get loops_per_jiffy set to + * equal one clock (up to lps_precision bits) + */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while (lps_precision-- && (loopbit >>= 1)) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } + return loops_per_jiffy; +} +#define NRETRIES 3 + +void __cpuinit calibrate_delay(void) +{ if (preset_lpj) { loops_per_jiffy = preset_lpj; printk(KERN_INFO @@ -141,38 +180,17 @@ void __cpuinit calibrate_delay(void) printk(KERN_INFO "Calibrating delay using timer specific routine.. "); } else { - loops_per_jiffy = (1<<12); + int i; + unsigned long result; printk(KERN_INFO "Calibrating delay loop... "); - while ((loops_per_jiffy <<= 1) != 0) { - /* wait for "start of" clock tick */ - ticks = jiffies; - while (ticks == jiffies) - /* nothing */; - /* Go .. */ - ticks = jiffies; - __delay(loops_per_jiffy); - ticks = jiffies - ticks; - if (ticks) - break; - } - - /* - * Do a binary approximation to get loops_per_jiffy set to - * equal one clock (up to lps_precision bits) - */ - loops_per_jiffy >>= 1; - loopbit = loops_per_jiffy; - while (lps_precision-- && (loopbit >>= 1)) { - loops_per_jiffy |= loopbit; - ticks = jiffies; - while (ticks == jiffies) - /* nothing */; - ticks = jiffies; - __delay(loops_per_jiffy); - if (jiffies != ticks) /* longer than 1 tick */ - loops_per_jiffy &= ~loopbit; + loops_per_jiffy = 0; + for (i = 0; i < NRETRIES; i++) { + result = calibrate_delay_estimate(); + if (result > loops_per_jiffy) + loops_per_jiffy = result; } + } printk(KERN_CONT "%lu.%02lu BogoMIPS (lpj=%lu)\n", loops_per_jiffy/(500000/HZ), |