Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 366170
b: refs/heads/master
c: 3195ef5
h: refs/heads/master
v: v3
  • Loading branch information
Prarit Bhargava authored and John Stultz committed Mar 15, 2013
1 parent 83a7810 commit 7e4df7a
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 84 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7859e404ae73fe4f38b8cfc1af19ea82f153084e
refs/heads/master: 3195ef59cb42cda3aeeb24a7fd2ba1b900c4a3cc
1 change: 1 addition & 0 deletions trunk/arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ config X86
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
Expand Down
69 changes: 12 additions & 57 deletions trunk/arch/x86/kernel/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <asm/x86_init.h>
#include <asm/time.h>
#include <asm/mrst.h>
#include <asm/rtc.h>

#ifdef CONFIG_X86_32
/*
Expand All @@ -36,70 +37,24 @@ EXPORT_SYMBOL(rtc_lock);
* 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;
}

Expand Down
24 changes: 16 additions & 8 deletions trunk/arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/x86_init.h>
#include <asm/rtc.h>

#define EFI_DEBUG 1

Expand Down Expand Up @@ -258,24 +259,31 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,

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) {
pr_err("Oops: efitime: can't read time!\n");
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) {
Expand Down
44 changes: 26 additions & 18 deletions trunk/arch/x86/platform/mrst/vrtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,27 +85,35 @@ unsigned long vrtc_get_time(void)
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)
Expand Down

0 comments on commit 7e4df7a

Please sign in to comment.