home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-mips / mc146818-time.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.7 KB  |  120 lines

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