1*384740dcSRalf Baechle /* 2*384740dcSRalf Baechle * This file is subject to the terms and conditions of the GNU General Public 3*384740dcSRalf Baechle * License. See the file "COPYING" in the main directory of this archive 4*384740dcSRalf Baechle * for more details. 5*384740dcSRalf Baechle * 6*384740dcSRalf Baechle * Machine dependent access functions for RTC registers. 7*384740dcSRalf Baechle */ 8*384740dcSRalf Baechle #ifndef __ASM_MC146818_TIME_H 9*384740dcSRalf Baechle #define __ASM_MC146818_TIME_H 10*384740dcSRalf Baechle 11*384740dcSRalf Baechle #include <linux/bcd.h> 12*384740dcSRalf Baechle #include <linux/mc146818rtc.h> 13*384740dcSRalf Baechle #include <linux/time.h> 14*384740dcSRalf Baechle 15*384740dcSRalf Baechle /* 16*384740dcSRalf Baechle * For check timing call set_rtc_mmss() 500ms; used in timer interrupt. 17*384740dcSRalf Baechle */ 18*384740dcSRalf Baechle #define USEC_AFTER 500000 19*384740dcSRalf Baechle #define USEC_BEFORE 500000 20*384740dcSRalf Baechle 21*384740dcSRalf Baechle /* 22*384740dcSRalf Baechle * In order to set the CMOS clock precisely, set_rtc_mmss has to be 23*384740dcSRalf Baechle * called 500 ms after the second nowtime has started, because when 24*384740dcSRalf Baechle * nowtime is written into the registers of the CMOS clock, it will 25*384740dcSRalf Baechle * jump to the next second precisely 500 ms later. Check the Motorola 26*384740dcSRalf Baechle * MC146818A or Dallas DS12887 data sheet for details. 27*384740dcSRalf Baechle * 28*384740dcSRalf Baechle * BUG: This routine does not handle hour overflow properly; it just 29*384740dcSRalf Baechle * sets the minutes. Usually you'll only notice that after reboot! 30*384740dcSRalf Baechle */ 31*384740dcSRalf Baechle static inline int mc146818_set_rtc_mmss(unsigned long nowtime) 32*384740dcSRalf Baechle { 33*384740dcSRalf Baechle int real_seconds, real_minutes, cmos_minutes; 34*384740dcSRalf Baechle unsigned char save_control, save_freq_select; 35*384740dcSRalf Baechle int retval = 0; 36*384740dcSRalf Baechle unsigned long flags; 37*384740dcSRalf Baechle 38*384740dcSRalf Baechle spin_lock_irqsave(&rtc_lock, flags); 39*384740dcSRalf Baechle save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ 40*384740dcSRalf Baechle CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); 41*384740dcSRalf Baechle 42*384740dcSRalf Baechle save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ 43*384740dcSRalf Baechle CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); 44*384740dcSRalf Baechle 45*384740dcSRalf Baechle cmos_minutes = CMOS_READ(RTC_MINUTES); 46*384740dcSRalf Baechle if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) 47*384740dcSRalf Baechle BCD_TO_BIN(cmos_minutes); 48*384740dcSRalf Baechle 49*384740dcSRalf Baechle /* 50*384740dcSRalf Baechle * since we're only adjusting minutes and seconds, 51*384740dcSRalf Baechle * don't interfere with hour overflow. This avoids 52*384740dcSRalf Baechle * messing with unknown time zones but requires your 53*384740dcSRalf Baechle * RTC not to be off by more than 15 minutes 54*384740dcSRalf Baechle */ 55*384740dcSRalf Baechle real_seconds = nowtime % 60; 56*384740dcSRalf Baechle real_minutes = nowtime / 60; 57*384740dcSRalf Baechle if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) 58*384740dcSRalf Baechle real_minutes += 30; /* correct for half hour time zone */ 59*384740dcSRalf Baechle real_minutes %= 60; 60*384740dcSRalf Baechle 61*384740dcSRalf Baechle if (abs(real_minutes - cmos_minutes) < 30) { 62*384740dcSRalf Baechle if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 63*384740dcSRalf Baechle BIN_TO_BCD(real_seconds); 64*384740dcSRalf Baechle BIN_TO_BCD(real_minutes); 65*384740dcSRalf Baechle } 66*384740dcSRalf Baechle CMOS_WRITE(real_seconds, RTC_SECONDS); 67*384740dcSRalf Baechle CMOS_WRITE(real_minutes, RTC_MINUTES); 68*384740dcSRalf Baechle } else { 69*384740dcSRalf Baechle printk(KERN_WARNING 70*384740dcSRalf Baechle "set_rtc_mmss: can't update from %d to %d\n", 71*384740dcSRalf Baechle cmos_minutes, real_minutes); 72*384740dcSRalf Baechle retval = -1; 73*384740dcSRalf Baechle } 74*384740dcSRalf Baechle 75*384740dcSRalf Baechle /* The following flags have to be released exactly in this order, 76*384740dcSRalf Baechle * otherwise the DS12887 (popular MC146818A clone with integrated 77*384740dcSRalf Baechle * battery and quartz) will not reset the oscillator and will not 78*384740dcSRalf Baechle * update precisely 500 ms later. You won't find this mentioned in 79*384740dcSRalf Baechle * the Dallas Semiconductor data sheets, but who believes data 80*384740dcSRalf Baechle * sheets anyway ... -- Markus Kuhn 81*384740dcSRalf Baechle */ 82*384740dcSRalf Baechle CMOS_WRITE(save_control, RTC_CONTROL); 83*384740dcSRalf Baechle CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); 84*384740dcSRalf Baechle spin_unlock_irqrestore(&rtc_lock, flags); 85*384740dcSRalf Baechle 86*384740dcSRalf Baechle return retval; 87*384740dcSRalf Baechle } 88*384740dcSRalf Baechle 89*384740dcSRalf Baechle static inline unsigned long mc146818_get_cmos_time(void) 90*384740dcSRalf Baechle { 91*384740dcSRalf Baechle unsigned int year, mon, day, hour, min, sec; 92*384740dcSRalf Baechle unsigned long flags; 93*384740dcSRalf Baechle 94*384740dcSRalf Baechle spin_lock_irqsave(&rtc_lock, flags); 95*384740dcSRalf Baechle 96*384740dcSRalf Baechle do { 97*384740dcSRalf Baechle sec = CMOS_READ(RTC_SECONDS); 98*384740dcSRalf Baechle min = CMOS_READ(RTC_MINUTES); 99*384740dcSRalf Baechle hour = CMOS_READ(RTC_HOURS); 100*384740dcSRalf Baechle day = CMOS_READ(RTC_DAY_OF_MONTH); 101*384740dcSRalf Baechle mon = CMOS_READ(RTC_MONTH); 102*384740dcSRalf Baechle year = CMOS_READ(RTC_YEAR); 103*384740dcSRalf Baechle } while (sec != CMOS_READ(RTC_SECONDS)); 104*384740dcSRalf Baechle 105*384740dcSRalf Baechle if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { 106*384740dcSRalf Baechle BCD_TO_BIN(sec); 107*384740dcSRalf Baechle BCD_TO_BIN(min); 108*384740dcSRalf Baechle BCD_TO_BIN(hour); 109*384740dcSRalf Baechle BCD_TO_BIN(day); 110*384740dcSRalf Baechle BCD_TO_BIN(mon); 111*384740dcSRalf Baechle BCD_TO_BIN(year); 112*384740dcSRalf Baechle } 113*384740dcSRalf Baechle spin_unlock_irqrestore(&rtc_lock, flags); 114*384740dcSRalf Baechle year = mc146818_decode_year(year); 115*384740dcSRalf Baechle 116*384740dcSRalf Baechle return mktime(year, mon, day, hour, min, sec); 117*384740dcSRalf Baechle } 118*384740dcSRalf Baechle 119*384740dcSRalf Baechle #endif /* __ASM_MC146818_TIME_H */ 120