static int set_rtc_mmss(unsigned long nowtime)
{
int retval = 0.
int real_seconds, real_minutes, cmos_minutes.
unsigned char save_control, save_freq_0select.
/* gets recalled with irq locally disabled */
spin_lock(&.rtc_lock).
save_control = CMOS_READ(RTC_CONTROL). /* tell the clock it s being set */
CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL).
save_freq_0select = CMOS_READ(RTC_FREQ_SELECT). /* stop and reset prescaler */
CMOS_WRITE((save_freq_0select|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)
real_minutes = 30. /* correct for half hour time zone */
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 0update 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
* 0update 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_0select, RTC_FREQ_SELECT).
spin_unlock(&.rtc_lock).
return retval.
} |