📄 time.c
字号:
RTC registers show the second which has precisely just started. Let's hope other operating systems interpret the RTC the same way. */static unsigned long __initrpcc_after_update_in_progress(void){ do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); return rpcc();}void __inittime_init(void){ unsigned int year, mon, day, hour, min, sec, cc1, cc2, epoch; unsigned long cycle_freq, tolerance; long diff; /* Calibrate CPU clock -- attempt #1. */ if (!est_cycle_freq) est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); cc1 = rpcc_after_update_in_progress(); /* Calibrate CPU clock -- attempt #2. */ if (!est_cycle_freq) { cc2 = rpcc_after_update_in_progress(); est_cycle_freq = validate_cc_value(cc2 - cc1); cc1 = cc2; } cycle_freq = hwrpb->cycle_freq; if (est_cycle_freq) { /* If the given value is within 250 PPM of what we calculated, accept it. Otherwise, use what we found. */ tolerance = cycle_freq / 4000; diff = cycle_freq - est_cycle_freq; if (diff < 0) diff = -diff; if ((unsigned long)diff > tolerance) { cycle_freq = est_cycle_freq; printk("HWRPB cycle frequency bogus. " "Estimated %lu Hz\n", cycle_freq); } else { est_cycle_freq = 0; } } else if (! validate_cc_value (cycle_freq)) { printk("HWRPB cycle frequency bogus, " "and unable to estimate a proper value!\n"); } /* From John Bowman <bowman@math.ualberta.ca>: allow the values to settle, as the Update-In-Progress bit going low isn't good enough on some hardware. 2ms is our guess; we haven't found bogomips yet, but this is close on a 500Mhz box. */ __delay(1000000); sec = CMOS_READ(RTC_SECONDS); min = CMOS_READ(RTC_MINUTES); hour = CMOS_READ(RTC_HOURS); day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); year = CMOS_READ(RTC_YEAR); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BCD_TO_BIN(sec); BCD_TO_BIN(min); BCD_TO_BIN(hour); BCD_TO_BIN(day); BCD_TO_BIN(mon); BCD_TO_BIN(year); } /* PC-like is standard; used for year >= 70 */ epoch = 1900; if (year < 20) epoch = 2000; else if (year >= 20 && year < 48) /* NT epoch */ epoch = 1980; else if (year >= 48 && year < 70) /* Digital UNIX epoch */ epoch = 1952; printk(KERN_INFO "Using epoch = %d\n", epoch); if ((year += epoch) < 1970) year += 100; xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = 0; wall_to_monotonic.tv_sec -= xtime.tv_sec; wall_to_monotonic.tv_nsec = 0; if (HZ > (1<<16)) { extern void __you_loose (void); __you_loose(); } state.last_time = cc1; state.scaled_ticks_per_cycle = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq; state.last_rtc_update = 0; state.partial_tick = 0L; /* Startup the timer source. */ alpha_mv.init_rtc();}/* * Use the cycle counter to estimate an displacement from the last time * tick. Unfortunately the Alpha designers made only the low 32-bits of * the cycle counter active, so we overflow on 8.2 seconds on a 500MHz * part. So we can't do the "find absolute time in terms of cycles" thing * that the other ports do. */voiddo_gettimeofday(struct timeval *tv){ unsigned long flags; unsigned long sec, usec, lost, seq; unsigned long delta_cycles, delta_usec, partial_tick; do { seq = read_seqbegin_irqsave(&xtime_lock, flags); delta_cycles = rpcc() - state.last_time; sec = xtime.tv_sec; usec = (xtime.tv_nsec / 1000); partial_tick = state.partial_tick; lost = jiffies - wall_jiffies; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));#ifdef CONFIG_SMP /* Until and unless we figure out how to get cpu cycle counters in sync and keep them there, we can't use the rpcc tricks. */ delta_usec = lost * (1000000 / HZ);#else /* * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks) * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks) * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks) * * which, given a 600MHz cycle and a 1024Hz tick, has a * dynamic range of about 1.7e17, which is less than the * 1.8e19 in an unsigned long, so we are safe from overflow. * * Round, but with .5 up always, since .5 to even is harder * with no clear gain. */ delta_usec = (delta_cycles * state.scaled_ticks_per_cycle + partial_tick + (lost << FIX_SHIFT)) * 15625; delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;#endif usec += delta_usec; if (usec >= 1000000) { sec += 1; usec -= 1000000; } tv->tv_sec = sec; tv->tv_usec = usec;}EXPORT_SYMBOL(do_gettimeofday);intdo_settimeofday(struct timespec *tv){ time_t wtm_sec, sec = tv->tv_sec; long wtm_nsec, nsec = tv->tv_nsec; unsigned long delta_nsec; if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) return -EINVAL; write_seqlock_irq(&xtime_lock); /* The offset that is added into time in do_gettimeofday above must be subtracted out here to keep a coherent view of the time. Without this, a full-tick error is possible. */#ifdef CONFIG_SMP delta_nsec = (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);#else delta_nsec = rpcc() - state.last_time; delta_nsec = (delta_nsec * state.scaled_ticks_per_cycle + state.partial_tick + ((jiffies - wall_jiffies) << FIX_SHIFT)) * 15625; delta_nsec = ((delta_nsec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2; delta_nsec *= 1000;#endif nsec -= delta_nsec; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); set_normalized_timespec(&xtime, sec, nsec); set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); ntp_clear(); write_sequnlock_irq(&xtime_lock); clock_was_set(); return 0;}EXPORT_SYMBOL(do_settimeofday);/* * In order to set the CMOS clock precisely, set_rtc_mmss has to be * called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will * jump to the next second precisely 500 ms later. Check the Motorola * MC146818A or Dallas DS12887 data sheet for details. * * BUG: This routine does not handle hour overflow properly; it just * sets the minutes. Usually you won't notice until after reboot! */static intset_rtc_mmss(unsigned long nowtime){ int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; /* irq are locally disabled here */ spin_lock(&rtc_lock); /* Tell the clock it's being set */ save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); /* Stop and reset prescaler */ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) BCD_TO_BIN(cmos_minutes); /* * since we're only adjusting minutes and seconds, * don't interfere with hour overflow. This avoids * messing with unknown time zones but requires your * RTC not to be off by more than 15 minutes */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) { /* correct for half hour time zone */ real_minutes += 30; } real_minutes %= 60; if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { BIN_TO_BCD(real_seconds); BIN_TO_BCD(real_minutes); } CMOS_WRITE(real_seconds,RTC_SECONDS); CMOS_WRITE(real_minutes,RTC_MINUTES); } else { printk(KERN_WARNING "set_rtc_mmss: can't update from %d to %d\n", cmos_minutes, real_minutes); retval = -1; } /* The following flags have to be released exactly in this order, * otherwise the DS12887 (popular MC146818A clone with integrated * battery and quartz) will not reset the oscillator and will not * update precisely 500 ms later. You won't find this mentioned in * the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ CMOS_WRITE(save_control, RTC_CONTROL); CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); spin_unlock(&rtc_lock); return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -