]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
rtc: provide an emulated RTC
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Thu, 22 Oct 2020 21:52:14 +0000 (23:52 +0200)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Tue, 27 Oct 2020 20:13:15 +0000 (21:13 +0100)
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>
MAINTAINERS
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/emul_rtc.c [new file with mode: 0644]

index 69a5bc37689315cb7e77d1b7093f75eb367c9b7c..d9f80325f573d7a97948ab98e9b71d3472388af7 100644 (file)
@@ -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
index 63662001c26df0d046985f9bbe65ebaadc832902..d06d272e14b040646ee388f07095837cea17e4a4 100644 (file)
@@ -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
index 12eb449583a2d16bca5df95c19d220f502e598dc..ef66dc4bf024657141fa659b4d9b46ee840f8155 100644 (file)
@@ -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 (file)
index 0000000..c98c24b
--- /dev/null
@@ -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",
+};