/* This function is only called on the boot processor */ void __init time_init(void) { time_t sec, old_sec; unsigned old_stamp, stamp, elapsed; if (ppc_md.time_init != NULL) time_offset = ppc_md.time_init(); if (__USE_RTC()) { /* 601 processor: dec counts down by 128 every 128ns */ tb_ticks_per_jiffy = DECREMENTER_COUNT_601; /* mulhwu_scale_factor(1000000000, 1000000) is 0x418937 */ tb_to_us = 0x418937; } else { ppc_md.calibrate_decr(); } /* Now that the decrementer is calibrated, it can be used in case the * clock is stuck, but the fact that we have to handle the 601 * makes things more complex. Repeatedly read the RTC until the * next second boundary to try to achieve some precision. If there * is no RTC, we still need to set tb_last_stamp and * last_jiffy_stamp(cpu 0) to the current stamp. */ stamp = get_native_tbl(); if (ppc_md.get_rtc_time) { sec = ppc_md.get_rtc_time(); elapsed = 0; do { old_stamp = stamp; old_sec = sec; stamp = get_native_tbl(); if (__USE_RTC() && stamp < old_stamp) old_stamp -= 1000000000; elapsed += stamp - old_stamp; sec = ppc_md.get_rtc_time(); } while ( sec == old_sec && elapsed < 2*HZ*tb_ticks_per_jiffy); if (sec == old_sec) printk("Warning: real time clock seems stuck!\n"); xtime.tv_sec = sec; xtime.tv_usec = 0; /* No update now, we just read the time from the RTC ! */ last_rtc_update = xtime.tv_sec; } last_jiffy_stamp(0) = tb_last_stamp = stamp; /* Not exact, but the timer interrupt takes care of this */ set_dec(tb_ticks_per_jiffy); /* If platform provided a timezone (pmac), we correct the time * using do_sys_settimeofday() which in turn calls warp_clock() */ if (time_offset) { struct timezone tz; tz.tz_minuteswest = -time_offset / 60; tz.tz_dsttime = 0; do_sys_settimeofday(NULL, &tz); } }
/* Timer interrupt helper function */ static inline int tb_delta(unsigned *jiffy_stamp) { int delta; if (__USE_RTC()) { delta = get_rtcl(); if (delta < *jiffy_stamp) *jiffy_stamp -= 1000000000; delta -= *jiffy_stamp; } else { delta = get_tbl() - *jiffy_stamp; } return delta; }
unsigned long long sched_clock(void) { unsigned long lo, hi, hi2; unsigned long long tb; if (!__USE_RTC()) { do { hi = get_tbu(); lo = get_tbl(); hi2 = get_tbu(); } while (hi2 != hi); tb = ((unsigned long long) hi << 32) | lo; tb = (tb * tb_to_ns_scale) >> 10; } else { do {