From 77e0baa6e99761462af4c69c7beda0af9571525e Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <siro@das-labor.org>
Date: Sat, 3 Feb 2018 11:50:56 +0100
Subject: libpayload/drivers/nvram: Add function to write RTC

Add a function to set the RTC to provided struct tm.

Change-Id: I17b4c1ee0dcc649738ac6a7400b087d07213eaf0
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/23585
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
---
 payloads/libpayload/drivers/nvram.c      | 52 ++++++++++++++++++++++++++++++++
 payloads/libpayload/include/libpayload.h |  1 +
 2 files changed, 53 insertions(+)

diff --git a/payloads/libpayload/drivers/nvram.c b/payloads/libpayload/drivers/nvram.c
index 34ee0331e1..0196bb5c7c 100644
--- a/payloads/libpayload/drivers/nvram.c
+++ b/payloads/libpayload/drivers/nvram.c
@@ -160,3 +160,55 @@ void rtc_read_clock(struct tm *time)
 	if (time->tm_year < 80)
 		time->tm_year += 100;
 }
+
+/**
+ * Write the current time and date to the RTC
+ *
+ * @param time A pointer to a broken-down time structure
+ */
+void rtc_write_clock(const struct tm *time)
+{
+	u16 timeout = 10000;
+	u8 statusB;
+	u8 reg8, year;
+
+	while (nvram_updating())
+		if (!timeout--)
+			return;
+
+	statusB = nvram_read(NVRAM_RTC_STATUSB);
+
+	year = time->tm_year;
+	if (year > 100)
+		year -= 100;
+
+	if (!(statusB & NVRAM_RTC_FORMAT_BINARY)) {
+		nvram_write(dec2bcd(time->tm_mon + 1), NVRAM_RTC_MONTH);
+		nvram_write(dec2bcd(time->tm_sec), NVRAM_RTC_SECONDS);
+		nvram_write(dec2bcd(time->tm_min), NVRAM_RTC_MINUTES);
+		nvram_write(dec2bcd(time->tm_mday), NVRAM_RTC_DAY);
+		if (!(statusB & NVRAM_RTC_FORMAT_24HOUR)) {
+			if (time->tm_hour > 12)
+				reg8 = dec2bcd(time->tm_hour - 12) | 0x80;
+			else
+				reg8 = dec2bcd(time->tm_hour);
+		} else
+			reg8 = dec2bcd(time->tm_hour);
+		nvram_write(reg8, NVRAM_RTC_HOURS);
+		nvram_write(dec2bcd(year), NVRAM_RTC_YEAR);
+	} else {
+		nvram_write(time->tm_mon + 1, NVRAM_RTC_MONTH);
+		nvram_write(time->tm_sec, NVRAM_RTC_SECONDS);
+		nvram_write(time->tm_min, NVRAM_RTC_MINUTES);
+		nvram_write(time->tm_mday, NVRAM_RTC_DAY);
+		if (!(statusB & NVRAM_RTC_FORMAT_24HOUR)) {
+			if (time->tm_hour > 12)
+				reg8 = (time->tm_hour - 12) | 0x80;
+			else
+				reg8 = time->tm_hour;
+		} else
+			reg8 = time->tm_hour;
+		nvram_write(reg8, NVRAM_RTC_HOURS);
+		nvram_write(year, NVRAM_RTC_YEAR);
+	}
+}
diff --git a/payloads/libpayload/include/libpayload.h b/payloads/libpayload/include/libpayload.h
index 74969726bf..e3f8fd363f 100644
--- a/payloads/libpayload/include/libpayload.h
+++ b/payloads/libpayload/include/libpayload.h
@@ -151,6 +151,7 @@ u8 nvram_read(u8 addr);
 void nvram_write(u8 val, u8 addr);
 int nvram_updating(void);
 void rtc_read_clock(struct tm *tm);
+void rtc_write_clock(const struct tm *tm);
 /** @} */
 
 /**
-- 
cgit v1.2.3