libpayload: Improve rtc functions
On Lenovo T500 the RTC readings where wrong, as RTC has different encodings, depending on the statusB register. Support BCD vs binary RTC format and AM/PM vs 24h RTC format. Fixes wrong date and time on Lenovo 500. Change-Id: Id773c33e228973e190a7e14c3d11979678b1a619 Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/18498 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nico Huber <nico.h@gmx.de>
This commit is contained in:
parent
ef613b97cf
commit
9f3e734e5c
|
@ -2,6 +2,7 @@
|
||||||
* This file is part of the libpayload project.
|
* This file is part of the libpayload project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
|
* Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
|
||||||
|
* Copyright (C) 2017 Patrick Rudolph <siro@das-labor.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
|
@ -111,23 +112,51 @@ int nvram_updating(void)
|
||||||
*/
|
*/
|
||||||
void rtc_read_clock(struct tm *time)
|
void rtc_read_clock(struct tm *time)
|
||||||
{
|
{
|
||||||
|
u16 timeout = 10000;
|
||||||
|
u8 statusB;
|
||||||
|
u8 reg8;
|
||||||
|
|
||||||
memset(time, 0, sizeof(*time));
|
memset(time, 0, sizeof(*time));
|
||||||
|
|
||||||
while(nvram_updating());
|
while (nvram_updating())
|
||||||
|
if (!timeout--)
|
||||||
|
return;
|
||||||
|
|
||||||
|
statusB = nvram_read(NVRAM_RTC_STATUSB);
|
||||||
|
|
||||||
|
if (!(statusB & NVRAM_RTC_FORMAT_BINARY)) {
|
||||||
time->tm_mon = bcd2dec(nvram_read(NVRAM_RTC_MONTH)) - 1;
|
time->tm_mon = bcd2dec(nvram_read(NVRAM_RTC_MONTH)) - 1;
|
||||||
time->tm_sec = bcd2dec(nvram_read(NVRAM_RTC_SECONDS));
|
time->tm_sec = bcd2dec(nvram_read(NVRAM_RTC_SECONDS));
|
||||||
time->tm_min = bcd2dec(nvram_read(NVRAM_RTC_MINUTES));
|
time->tm_min = bcd2dec(nvram_read(NVRAM_RTC_MINUTES));
|
||||||
time->tm_mday = bcd2dec(nvram_read(NVRAM_RTC_DAY));
|
time->tm_mday = bcd2dec(nvram_read(NVRAM_RTC_DAY));
|
||||||
|
|
||||||
|
if (!(statusB & NVRAM_RTC_FORMAT_24HOUR)) {
|
||||||
|
reg8 = nvram_read(NVRAM_RTC_HOURS);
|
||||||
|
time->tm_hour = bcd2dec(reg8 & 0x7f);
|
||||||
|
time->tm_hour += (reg8 & 0x80) ? 12 : 0;
|
||||||
|
time->tm_hour %= 24;
|
||||||
|
} else
|
||||||
time->tm_hour = bcd2dec(nvram_read(NVRAM_RTC_HOURS));
|
time->tm_hour = bcd2dec(nvram_read(NVRAM_RTC_HOURS));
|
||||||
|
time->tm_year = bcd2dec(nvram_read(NVRAM_RTC_YEAR));
|
||||||
|
} else {
|
||||||
|
time->tm_mon = nvram_read(NVRAM_RTC_MONTH) - 1;
|
||||||
|
time->tm_sec = nvram_read(NVRAM_RTC_SECONDS);
|
||||||
|
time->tm_min = nvram_read(NVRAM_RTC_MINUTES);
|
||||||
|
time->tm_mday = nvram_read(NVRAM_RTC_DAY);
|
||||||
|
if (!(statusB & NVRAM_RTC_FORMAT_24HOUR)) {
|
||||||
|
reg8 = nvram_read(NVRAM_RTC_HOURS);
|
||||||
|
time->tm_hour = reg8 & 0x7f;
|
||||||
|
time->tm_hour += (reg8 & 0x80) ? 12 : 0;
|
||||||
|
time->tm_hour %= 24;
|
||||||
|
} else
|
||||||
|
time->tm_hour = nvram_read(NVRAM_RTC_HOURS);
|
||||||
|
time->tm_year = nvram_read(NVRAM_RTC_YEAR);
|
||||||
|
}
|
||||||
|
|
||||||
/* Instead of finding the century register,
|
/* Instead of finding the century register,
|
||||||
we just make an assumption that if the year value is
|
we just make an assumption that if the year value is
|
||||||
less then 80, then it is 2000+
|
less then 80, then it is 2000+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
time->tm_year = bcd2dec(nvram_read(NVRAM_RTC_YEAR));
|
|
||||||
|
|
||||||
if (time->tm_year < 80)
|
if (time->tm_year < 80)
|
||||||
time->tm_year += 100;
|
time->tm_year += 100;
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,9 @@ static const char _pstruct(key)[] \
|
||||||
#define NVRAM_RTC_YEAR 9 /**< RTC Year offset in CMOS */
|
#define NVRAM_RTC_YEAR 9 /**< RTC Year offset in CMOS */
|
||||||
#define NVRAM_RTC_FREQ_SELECT 10 /**< RTC Update Status Register */
|
#define NVRAM_RTC_FREQ_SELECT 10 /**< RTC Update Status Register */
|
||||||
#define NVRAM_RTC_UIP 0x80
|
#define NVRAM_RTC_UIP 0x80
|
||||||
|
#define NVRAM_RTC_STATUSB 11 /**< RTC Status Register B */
|
||||||
|
#define NVRAM_RTC_FORMAT_24HOUR 0x02
|
||||||
|
#define NVRAM_RTC_FORMAT_BINARY 0x04
|
||||||
|
|
||||||
/** Broken down time structure */
|
/** Broken down time structure */
|
||||||
struct tm {
|
struct tm {
|
||||||
|
|
Loading…
Reference in New Issue