void __devinit calibrate_delay(void)
{
unsigned long ticks, loopbit;
int lps_precision = LPS_PREC;
/* 不知道preset_lpj是什么,查了一下,说是可以在引导程序里面设置的 */
if (preset_lpj) {
loops_per_jiffy = preset_lpj;
printk("Calibrating delay loop (skipped)... "
"%lu.%02lu BogoMIPS preset\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
printk("Calibrating delay using timer specific routine.. ");
printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100,
loops_per_jiffy);
} else {
/* 先假设了loops_per_jiffy是一个挺大的数字1<<12 */
loops_per_jiffy = (1<<12);
printk(KERN_DEBUG "Calibrating delay loop... ");
/* 第一次循环,每次都将loops_per_jiffy扩大2倍 */
while ((loops_per_jiffy <<= 1) != 0) {
/* 下面这段是循环直到一个新的节拍的开始 */
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
/* Go .. */
/* 纪录新的节拍开始的tick值 */
ticks = jiffies;
/* __delay下面说明,是执行loops_per_jiffy次指令 */
__delay(loops_per_jiffy);
/* 执行完了看看当前的ticks是否>0(意味着超过了1个节拍) */
/* 超过一个节拍就跳出循环 */
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是满足这样子的条件,*/
/* 即执行它超过一个节拍,但是loop_per_jiffy/2则不到一个节拍 */
/* 具体一个节拍需要多少次loops_per_jiffy, */
/* 则一定在[ loops_per_jiffy/2, loops_per_jiffy ]区间内。*/
/* 这次循环是更加精确的寻找 */
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
/* 从loops_per_jiffy / 2开始探测 */
/* 当前探测值 = loops_per_jiffy | loopbit */
/* lps_precision决定了循环的次数,从而影响了结果的精度 */
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit;
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
ticks = jiffies;
__delay(loops_per_jiffy);
/* 大于一个tick,说明loops_per_jiffy取值过大 */
/* 恢复原来的loops_per_jiffy,且loopbit会在下个循环 */
/* 里将值变小*/
if (jiffies != ticks) /* longer than 1 tick */
loops_per_jiffy &= ~loopbit;
}
/* Round the value and print it */
/* loops_per_jiffy表示的是每个tick内执行的指令条数 */
/* 打印的结果应该是1/500000秒执行的指令条数,这只是打印结果 */
/* 并不影响loops_per_jiffy的值 */
printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100,
loops_per_jiffy);
}
}