/* * This was taken from prep_setup.c * Use the NVRAM RTC to time a second to calibrate the decrementer. */ void __init todc_calibrate_decr(void) { ulong freq; ulong tbl, tbu; long i, loop_count; u_char sec; todc_time_init(); /* * Actually this is bad for precision, we should have a loop in * which we only read the seconds counter. todc_read_val writes * the address bytes on every call and this takes a lot of time. * Perhaps an nvram_wait_change method returning a time * stamp with a loop count as parameter would be the solution. */ /* * Need to make sure the tbl doesn't roll over so if tbu increments * during this test, we need to do it again. */ loop_count = 0; sec = todc_read_timereg(todc_info->seconds) & 0x7f; do { tbu = get_tbu(); for (i = 0 ; i < 10000000 ; i++) {/* may take up to 1 second */ tbl = get_tbl(); if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) { break; } } sec = todc_read_timereg(todc_info->seconds) & 0x7f; for (i = 0 ; i < 10000000 ; i++) { /* Should take 1 second */ freq = get_tbl(); if ((todc_read_timereg(todc_info->seconds) & 0x7f) != sec) { break; } } freq -= tbl; } while ((get_tbu() != tbu) && (++loop_count < 2)); printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", freq/1000000, freq%1000000); tb_ticks_per_jiffy = freq / HZ; tb_to_us = mulhwu_scale_factor(freq, 1000000); return; }
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 {
DWORDLONG rdtsc(void) { // Original code (returning the cpu cycle counter) // read 64 bit tbl (time base) using motorola example DWORD lo, hi1, hi2; do { hi1 = get_tbu(); lo = get_tbl(); hi2 = get_tbu(); } while (hi1 != hi2); return ((DWORDLONG) hi1) << 32 | (DWORDLONG) lo; }
void __devinit smp_chrp_give_timebase(void) { spin_lock(&timebase_lock); rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); timebase_upper = get_tbu(); timebase_lower = get_tbl(); spin_unlock(&timebase_lock); while (timebase_upper || timebase_lower) barrier(); rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); }