rtc: Check update-in-progress bit
While the real-time clock updates its count, values may not be correctly read or written. On reads, ensure the UIP bit is clear which guarantees a minimum of 244 microseconds exists before the update begins. Writes already avoid the problem by disabling the RTC count via the SET bit. Change-Id: I39e34493113015d32582f1c280fafa9e97f43a40 Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com> Reviewed-on: https://review.coreboot.org/17369 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
05abe4351b
commit
5a043fe08d
2 changed files with 12 additions and 0 deletions
|
@ -360,6 +360,7 @@ void cmos_check_update_date(void)
|
||||||
u8 year, century;
|
u8 year, century;
|
||||||
|
|
||||||
/* Assume hardware always supports RTC_CLK_ALTCENTURY. */
|
/* Assume hardware always supports RTC_CLK_ALTCENTURY. */
|
||||||
|
wait_uip();
|
||||||
century = cmos_read(RTC_CLK_ALTCENTURY);
|
century = cmos_read(RTC_CLK_ALTCENTURY);
|
||||||
year = cmos_read(RTC_CLK_YEAR);
|
year = cmos_read(RTC_CLK_YEAR);
|
||||||
|
|
||||||
|
@ -388,6 +389,7 @@ int rtc_set(const struct rtc_time *time)
|
||||||
|
|
||||||
int rtc_get(struct rtc_time *time)
|
int rtc_get(struct rtc_time *time)
|
||||||
{
|
{
|
||||||
|
wait_uip();
|
||||||
time->sec = bcd2bin(cmos_read(RTC_CLK_SECOND));
|
time->sec = bcd2bin(cmos_read(RTC_CLK_SECOND));
|
||||||
time->min = bcd2bin(cmos_read(RTC_CLK_MINUTE));
|
time->min = bcd2bin(cmos_read(RTC_CLK_MINUTE));
|
||||||
time->hour = bcd2bin(cmos_read(RTC_CLK_HOUR));
|
time->hour = bcd2bin(cmos_read(RTC_CLK_HOUR));
|
||||||
|
|
|
@ -112,6 +112,16 @@ static inline unsigned char cmos_read(unsigned char addr)
|
||||||
return inb(RTC_BASE_PORT + offs + 1);
|
return inb(RTC_BASE_PORT + offs + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Upon return the caller is guaranteed 244 microseconds to complete any
|
||||||
|
* RTC operations. wait_uip may be called a single time prior to multiple
|
||||||
|
* accesses, but sequences requiring more time should call wait_uip again.
|
||||||
|
*/
|
||||||
|
static inline void wait_uip(void)
|
||||||
|
{
|
||||||
|
while (cmos_read(RTC_REG_A) & RTC_UIP)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void cmos_write_inner(unsigned char val, unsigned char addr)
|
static inline void cmos_write_inner(unsigned char val, unsigned char addr)
|
||||||
{
|
{
|
||||||
int offs = 0;
|
int offs = 0;
|
||||||
|
|
Loading…
Reference in a new issue