select OLD_SIGSUSPEND3 if X86_32 || IA32_EMULATION
        select OLD_SIGACTION if X86_32
        select COMPAT_OLD_SIGACTION if IA32_EMULATION
+       select RTC_LIB
 
 config INSTRUCTION_DECODER
        def_bool y
 
 #include <asm/x86_init.h>
 #include <asm/time.h>
 #include <asm/mrst.h>
+#include <asm/rtc.h>
 
 #ifdef CONFIG_X86_32
 /*
  * 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'll only notice that after reboot!
  */
 int mach_set_rtc_mmss(unsigned long nowtime)
 {
-       int real_seconds, real_minutes, cmos_minutes;
-       unsigned char save_control, save_freq_select;
-       unsigned long flags;
+       struct rtc_time tm;
        int retval = 0;
 
-       spin_lock_irqsave(&rtc_lock, flags);
-
-        /* 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)
-               cmos_minutes = bcd2bin(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;
-       /* correct for half hour time zone */
-       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-               real_minutes += 30;
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       real_seconds = bin2bcd(real_seconds);
-                       real_minutes = bin2bcd(real_minutes);
-               }
-               CMOS_WRITE(real_seconds, RTC_SECONDS);
-               CMOS_WRITE(real_minutes, RTC_MINUTES);
+       rtc_time_to_tm(nowtime, &tm);
+       if (!rtc_valid_tm(&tm)) {
+               retval = set_rtc_time(&tm);
+               if (retval)
+                       printk(KERN_ERR "%s: RTC write failed with error %d\n",
+                              __FUNCTION__, retval);
        } else {
-               printk_once(KERN_NOTICE
-                      "set_rtc_mmss: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
+               printk(KERN_ERR
+                      "%s: Invalid RTC value: write of %lx to RTC failed\n",
+                       __FUNCTION__, nowtime);
+               retval = -EINVAL;
        }
-
-       /* 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_irqrestore(&rtc_lock, flags);
-
        return retval;
 }
 
 
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
+#include <asm/rtc.h>
 
 #define EFI_DEBUG      1
 
 
 int efi_set_rtc_mmss(unsigned long nowtime)
 {
-       int real_seconds, real_minutes;
        efi_status_t    status;
        efi_time_t      eft;
        efi_time_cap_t  cap;
+       struct rtc_time tm;
 
        status = efi.get_time(&eft, &cap);
        if (status != EFI_SUCCESS) {
                return -1;
        }
 
-       real_seconds = nowtime % 60;
-       real_minutes = nowtime / 60;
-       if (((abs(real_minutes - eft.minute) + 15)/30) & 1)
-               real_minutes += 30;
-       real_minutes %= 60;
-       eft.minute = real_minutes;
-       eft.second = real_seconds;
+       rtc_time_to_tm(nowtime, &tm);
+       if (!rtc_valid_tm(&tm)) {
+               eft.year = tm.tm_year + 1900;
+               eft.month = tm.tm_mon + 1;
+               eft.day = tm.tm_mday;
+               eft.minute = tm.tm_min;
+               eft.second = tm.tm_sec;
+               eft.nanosecond = 0;
+       } else {
+               printk(KERN_ERR
+                      "%s: Invalid EFI RTC value: write of %lx to EFI RTC failed\n",
+                      __FUNCTION__, nowtime);
+               return -1;
+       }
 
        status = efi.set_time(&eft);
        if (status != EFI_SUCCESS) {
 
        return mktime(year, mon, mday, hour, min, sec);
 }
 
-/* Only care about the minutes and seconds */
 int vrtc_set_mmss(unsigned long nowtime)
 {
-       int real_sec, real_min;
        unsigned long flags;
-       int vrtc_min;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-       vrtc_min = vrtc_cmos_read(RTC_MINUTES);
-
-       real_sec = nowtime % 60;
-       real_min = nowtime / 60;
-       if (((abs(real_min - vrtc_min) + 15)/30) & 1)
-               real_min += 30;
-       real_min %= 60;
-
-       vrtc_cmos_write(real_sec, RTC_SECONDS);
-       vrtc_cmos_write(real_min, RTC_MINUTES);
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       return 0;
+       struct rtc_time tm;
+       int year;
+       int retval = 0;
+
+       rtc_time_to_tm(nowtime, &tm);
+       if (!rtc_valid_tm(&tm) && tm.tm_year >= 72) {
+               /*
+                * tm.year is the number of years since 1900, and the
+                * vrtc need the years since 1972.
+                */
+               year = tm.tm_year - 72;
+               spin_lock_irqsave(&rtc_lock, flags);
+               vrtc_cmos_write(year, RTC_YEAR);
+               vrtc_cmos_write(tm.tm_mon, RTC_MONTH);
+               vrtc_cmos_write(tm.tm_mday, RTC_DAY_OF_MONTH);
+               vrtc_cmos_write(tm.tm_hour, RTC_HOURS);
+               vrtc_cmos_write(tm.tm_min, RTC_MINUTES);
+               vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
+               spin_unlock_irqrestore(&rtc_lock, flags);
+       } else {
+               printk(KERN_ERR
+                      "%s: Invalid vRTC value: write of %lx to vRTC failed\n",
+                       __FUNCTION__, nowtime);
+               retval = -EINVAL;
+       }
+       return retval;
 }
 
 void __init mrst_rtc_init(void)