[coreboot] New patch to review for coreboot: bf95bd9 mc146818rtc: disable RTC before writing to nvram

Patrick Georgi (patrick@georgi-clan.de) gerrit at coreboot.org
Fri Nov 16 10:41:18 CET 2012


Patrick Georgi (patrick at georgi-clan.de) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1868

-gerrit

commit bf95bd979647ab29aa1f2c98a607b6ca9827dc81
Author: Patrick Georgi <patrick.georgi at secunet.com>
Date:   Thu Nov 15 14:54:05 2012 +0100

    mc146818rtc: disable RTC before writing to nvram
    
    In principle this isn't necessary. However there's a byte (or several)
    outside the first 14 bytes that are part of the RTC, and require
    locking (century/altCentury).
    
    Since their location is mostly unknown, guard writes properly.
    
    Change-Id: I847cd4efa92722e8504d29feaf7dbfa5c5244b4e
    Signed-off-by: Patrick Georgi <patrick.georgi at secunet.com>
---
 src/include/pc80/mc146818rtc.h | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h
index 31322ea..ee1473b 100644
--- a/src/include/pc80/mc146818rtc.h
+++ b/src/include/pc80/mc146818rtc.h
@@ -110,7 +110,7 @@ static inline unsigned char cmos_read(unsigned char addr)
 	return inb(RTC_BASE_PORT + offs + 1);
 }
 
-static inline void cmos_write(unsigned char val, unsigned char addr)
+static inline void cmos_write_inner(unsigned char val, unsigned char addr)
 {
 	int offs = 0;
 	if (addr >= 128) {
@@ -121,6 +121,35 @@ static inline void cmos_write(unsigned char val, unsigned char addr)
 	outb(val, RTC_BASE_PORT + offs + 1);
 }
 
+static inline void cmos_write(unsigned char val, unsigned char addr)
+{
+	u8 control_state = cmos_read(RTC_CONTROL);
+	/* There are various places where RTC bits might be hiding,
+	 * eg. the Century / AltCentury byte. So to be safe, disable
+	 * RTC before changing any value.
+	 */
+	if ((addr != RTC_CONTROL) && !(control_state & RTC_SET)) {
+		cmos_write_inner(control_state | RTC_SET, RTC_CONTROL);
+	}
+	cmos_write_inner(val, addr);
+	/* reset to prior configuration */
+	if ((addr != RTC_CONTROL) && !(control_state & RTC_SET)) {
+		cmos_write_inner(control_state, RTC_CONTROL);
+	}
+}
+
+static inline void cmos_disable_rtc(void)
+{
+	u8 control_state = cmos_read(RTC_CONTROL);
+	cmos_write(control_state | RTC_SET, RTC_CONTROL);
+}
+
+static inline void cmos_enable_rtc(void)
+{
+	u8 control_state = cmos_read(RTC_CONTROL);
+	cmos_write(control_state & ~RTC_SET, RTC_CONTROL);
+}
+
 static inline u32 cmos_read32(u8 offset)
 {
 	u32 value = 0;




More information about the coreboot mailing list