summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeinrich Schuchardt <xypron.glpk@gmx.de>2020-10-22 23:52:14 +0200
committerHeinrich Schuchardt <xypron.glpk@gmx.de>2020-10-27 21:13:15 +0100
commit87e9963d5acaa41f3c54c1dee9159c775352f86a (patch)
tree00e9f91b032e54658a8ee3f6558af6777c0eb9bb
parentcbf0ffea14c812a19b2eede887e3db1ccc425cd4 (diff)
downloadu-boot-87e9963d5acaa41f3c54c1dee9159c775352f86a.tar.gz
rtc: provide an emulated RTC
On a board without hardware clock this software real time clock can be used. The build time is used to initialize the RTC. So you will have to adjust the time either manually using the 'date' command or use the 'sntp' to update the RTC with the time from a network time server. See CONFIG_CMD_SNTP and CONFIG_BOOTP_NTPSERVER. The RTC time is advanced according to CPU ticks. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
-rw-r--r--MAINTAINERS1
-rw-r--r--drivers/rtc/Kconfig11
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/emul_rtc.c80
4 files changed, 93 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 69a5bc3768..d9f80325f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -678,6 +678,7 @@ S: Maintained
T: git https://gitlab.denx.de/u-boot/custodians/u-boot-efi.git
F: doc/api/efi.rst
F: doc/uefi/*
+F: drivers/rtc/emul_rtc.c
F: include/capitalization.h
F: include/charset.h
F: include/cp1250.h
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 63662001c2..d06d272e14 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -63,6 +63,17 @@ config RTC_DS3232
Support for Dallas Semiconductor (now Maxim) DS3232 compatible
Real Time Clock devices.
+config RTC_EMULATION
+ bool "Enable emulated RTC"
+ depends on DM_RTC
+ help
+ On a board without hardware clock this software real time clock can be
+ used. The build time is used to initialize the RTC. So you will have
+ to adjust the time either manually using the 'date' command or use
+ the 'sntp' to update the RTC with the time from a network time server.
+ See CONFIG_CMD_SNTP and CONFIG_BOOTP_NTPSERVER. The RTC time is
+ advanced according to CPU ticks.
+
config RTC_ISL1208
bool "Enable ISL1208 driver"
depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 12eb449583..ef66dc4bf0 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_RTC_DS164x) += ds164x.o
obj-$(CONFIG_RTC_DS174x) += ds174x.o
obj-$(CONFIG_RTC_DS3231) += ds3231.o
obj-$(CONFIG_RTC_DS3232) += ds3232.o
+obj-$(CONFIG_RTC_EMULATION) += emul_rtc.o
obj-$(CONFIG_RTC_FTRTC010) += ftrtc010.o
obj-$(CONFIG_SANDBOX) += i2c_rtc_emul.o
obj-$(CONFIG_RTC_IMXDI) += imxdi.o
diff --git a/drivers/rtc/emul_rtc.c b/drivers/rtc/emul_rtc.c
new file mode 100644
index 0000000000..c98c24bbb3
--- /dev/null
+++ b/drivers/rtc/emul_rtc.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
+ *
+ * This driver emulates a real time clock based on timer ticks.
+ */
+
+#include <common.h>
+#include <div64.h>
+#include <dm.h>
+#include <generated/timestamp_autogenerated.h>
+#include <rtc.h>
+
+/**
+ * struct emul_rtc - private data for emulated RTC driver
+ */
+struct emul_rtc {
+ /**
+ * @offset_us: microseconds from 1970-01-01 to timer_get_us() base
+ */
+ u64 offset_us;
+ /**
+ * @isdst: daylight saving time
+ */
+ int isdst;
+};
+
+static int emul_rtc_get(struct udevice *dev, struct rtc_time *time)
+{
+ struct emul_rtc *priv = dev_get_priv(dev);
+ u64 now;
+
+ if (!priv->offset_us) {
+ /* Use the build date as initial time */
+ priv->offset_us = U_BOOT_EPOCH * 1000000ULL - timer_get_us();
+ priv->isdst = -1;
+ }
+
+ now = timer_get_us() + priv->offset_us;
+ do_div(now, 1000000);
+ rtc_to_tm(now, time);
+ time->tm_isdst = priv->isdst;
+
+ return 0;
+}
+
+static int emul_rtc_set(struct udevice *dev, const struct rtc_time *time)
+{
+ struct emul_rtc *priv = dev_get_priv(dev);
+
+ if (time->tm_year < 1970)
+ return -EINVAL;
+
+ priv->offset_us = rtc_mktime(time) * 1000000ULL - timer_get_us();
+
+ if (time->tm_isdst > 0)
+ priv->isdst = 1;
+ else if (time->tm_isdst < 0)
+ priv->isdst = -1;
+ else
+ priv->isdst = 0;
+
+ return 0;
+}
+
+static const struct rtc_ops emul_rtc_ops = {
+ .get = emul_rtc_get,
+ .set = emul_rtc_set,
+};
+
+U_BOOT_DRIVER(rtc_emul) = {
+ .name = "rtc_emul",
+ .id = UCLASS_RTC,
+ .ops = &emul_rtc_ops,
+ .priv_auto_alloc_size = sizeof(struct emul_rtc),
+};
+
+U_BOOT_DEVICE(rtc_emul) = {
+ .name = "rtc_emul",
+};