diff mbox series

[v2,2/2] rtc: provide an emulated RTC

Message ID 20201025071316.37416-3-xypron.glpk@gmx.de
State Accepted, archived
Commit 87e9963d5acaa41f3c54c1dee9159c775352f86a
Delegated to: Heinrich Schuchardt
Headers show
Series rtc: provide an emulated RTC | expand

Commit Message

Heinrich Schuchardt Oct. 25, 2020, 7:13 a.m. UTC
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>
---
v2:
	more elaborate Kconfig message
	adjust device name properties
	use build time as initial time
---
 MAINTAINERS            |  1 +
 drivers/rtc/Kconfig    | 11 ++++++
 drivers/rtc/Makefile   |  1 +
 drivers/rtc/emul_rtc.c | 80 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 93 insertions(+)
 create mode 100644 drivers/rtc/emul_rtc.c

--
2.28.0

Comments

Grant Likely Oct. 26, 2020, 3:30 p.m. UTC | #1
On Sun, Oct 25, 2020 at 7:13 AM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> 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>

Looks good to me, and tested on RockPro64 w/ UEFI SCT.

Tested-by: Grant Likely <grant.likely@arm.com>

g.

> ---
> v2:
>         more elaborate Kconfig message
>         adjust device name properties
>         use build time as initial time
> ---
>  MAINTAINERS            |  1 +
>  drivers/rtc/Kconfig    | 11 ++++++
>  drivers/rtc/Makefile   |  1 +
>  drivers/rtc/emul_rtc.c | 80 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 93 insertions(+)
>  create mode 100644 drivers/rtc/emul_rtc.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index fc4fad46ee..a98e0c5b76 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",
> +};
> --
> 2.28.0
>
Heinrich Schuchardt Oct. 26, 2020, 7:18 p.m. UTC | #2
On 26.10.20 16:31, Grant Likely wrote:
> On Mon, Oct 26, 2020 at 3:30 PM Grant Likely <grant.likely@secretlab.ca> wrote:
>>
>> On Sun, Oct 25, 2020 at 7:13 AM Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>>
>>> 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>
>>
>> Looks good to me, and tested on RockPro64 w/ UEFI SCT.
>>
>> Tested-by: Grant Likely <grant.likely@arm.com>
>
> One thought: Can this be automatically enabled if no other RTC driver
> is configured in?

* This RTC does not show the correct time unless you use SNTP to set it.
* There is no need for an RTC to boot an OS.
* Many board maintainers struggle with the size of there U-Boot binary.

So it does not make sense to me to enable this driver as fallback by
default.

Best regards

Heinrich

>
> g.
>
>>
>> g.
>>
>>> ---
>>> v2:
>>>         more elaborate Kconfig message
>>>         adjust device name properties
>>>         use build time as initial time
>>> ---
>>>  MAINTAINERS            |  1 +
>>>  drivers/rtc/Kconfig    | 11 ++++++
>>>  drivers/rtc/Makefile   |  1 +
>>>  drivers/rtc/emul_rtc.c | 80 ++++++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 93 insertions(+)
>>>  create mode 100644 drivers/rtc/emul_rtc.c
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index fc4fad46ee..a98e0c5b76 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",
>>> +};
>>> --
>>> 2.28.0
>>>
Simon Glass Oct. 27, 2020, 4:52 a.m. UTC | #3
Hi Heinrich,

On Sun, 25 Oct 2020 at 01:13, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> 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>
> ---
> v2:
>         more elaborate Kconfig message
>         adjust device name properties
>         use build time as initial time
> ---
>  MAINTAINERS            |  1 +
>  drivers/rtc/Kconfig    | 11 ++++++
>  drivers/rtc/Makefile   |  1 +
>  drivers/rtc/emul_rtc.c | 80 ++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 93 insertions(+)
>  create mode 100644 drivers/rtc/emul_rtc.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>

> diff --git a/MAINTAINERS b/MAINTAINERS
> index fc4fad46ee..a98e0c5b76 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>

put at end

> +#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
> +        */

why not:

/** @.... */


> +       int isdst;
> +};
> +
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index fc4fad46ee..a98e0c5b76 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",
+};