0001
0002
0003
0004
0005
0006
0007
0008 #ifndef __ASM_MC146818_TIME_H
0009 #define __ASM_MC146818_TIME_H
0010
0011 #include <linux/bcd.h>
0012 #include <linux/mc146818rtc.h>
0013 #include <linux/time.h>
0014
0015
0016
0017
0018 #define USEC_AFTER 500000
0019 #define USEC_BEFORE 500000
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
0032 {
0033 int real_seconds, real_minutes, cmos_minutes;
0034 unsigned char save_control, save_freq_select;
0035 int retval = 0;
0036 unsigned long flags;
0037
0038 spin_lock_irqsave(&rtc_lock, flags);
0039 save_control = CMOS_READ(RTC_CONTROL);
0040 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
0041
0042 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
0043 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
0044
0045 cmos_minutes = CMOS_READ(RTC_MINUTES);
0046 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
0047 cmos_minutes = bcd2bin(cmos_minutes);
0048
0049
0050
0051
0052
0053
0054
0055 real_seconds = nowtime % 60;
0056 real_minutes = nowtime / 60;
0057 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
0058 real_minutes += 30;
0059 real_minutes %= 60;
0060
0061 if (abs(real_minutes - cmos_minutes) < 30) {
0062 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
0063 real_seconds = bin2bcd(real_seconds);
0064 real_minutes = bin2bcd(real_minutes);
0065 }
0066 CMOS_WRITE(real_seconds, RTC_SECONDS);
0067 CMOS_WRITE(real_minutes, RTC_MINUTES);
0068 } else {
0069 printk_once(KERN_NOTICE
0070 "set_rtc_mmss: can't update from %d to %d\n",
0071 cmos_minutes, real_minutes);
0072 retval = -1;
0073 }
0074
0075
0076
0077
0078
0079
0080
0081
0082 CMOS_WRITE(save_control, RTC_CONTROL);
0083 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
0084 spin_unlock_irqrestore(&rtc_lock, flags);
0085
0086 return retval;
0087 }
0088
0089 static inline time64_t mc146818_get_cmos_time(void)
0090 {
0091 unsigned int year, mon, day, hour, min, sec;
0092 unsigned long flags;
0093
0094 spin_lock_irqsave(&rtc_lock, flags);
0095
0096 do {
0097 sec = CMOS_READ(RTC_SECONDS);
0098 min = CMOS_READ(RTC_MINUTES);
0099 hour = CMOS_READ(RTC_HOURS);
0100 day = CMOS_READ(RTC_DAY_OF_MONTH);
0101 mon = CMOS_READ(RTC_MONTH);
0102 year = CMOS_READ(RTC_YEAR);
0103 } while (sec != CMOS_READ(RTC_SECONDS));
0104
0105 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
0106 sec = bcd2bin(sec);
0107 min = bcd2bin(min);
0108 hour = bcd2bin(hour);
0109 day = bcd2bin(day);
0110 mon = bcd2bin(mon);
0111 year = bcd2bin(year);
0112 }
0113 spin_unlock_irqrestore(&rtc_lock, flags);
0114 year = mc146818_decode_year(year);
0115
0116 return mktime64(year, mon, day, hour, min, sec);
0117 }
0118
0119 #endif