Message ID | 20201023003509.58957-1-xypron.glpk@gmx.de |
---|---|
State | Changes Requested |
Delegated to: | Simon Glass |
Headers | show |
Series | [1/1] rtc: provide an emulated RTC | expand |
Hi Heinrich, On Thu, 22 Oct 2020 at 18:35, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote: > > For testing purposes like running the UEFI SCT an RTC may be required. > Provide an emulated RTC if we do not have a hardware one. > > Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> > --- > MAINTAINERS | 1 + > drivers/rtc/Kconfig | 6 ++++ > drivers/rtc/Makefile | 1 + > drivers/rtc/emul_rtc.c | 79 ++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 87 insertions(+) > create mode 100644 drivers/rtc/emul_rtc.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 196d635bdd..2465b51136 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -675,6 +675,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 59e2fc44ba..5c22d70ca9 100644 > --- a/drivers/rtc/Kconfig > +++ b/drivers/rtc/Kconfig > @@ -63,6 +63,12 @@ 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 > + Provide an emulated real time clock for testing purposes. This is a good place to add a bit of detail about its behaviour...where does it get the time from, what happens when you set the time, etc. > + > 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..f291d19ab5 > --- /dev/null > +++ b/drivers/rtc/emul_rtc.c > @@ -0,0 +1,79 @@ > +// 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 <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) { > + /* Assume it is 2021-01-11T00:00:00Z */ > + priv->offset_us = 1610323200000000ULL - 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 = "emulated RTC", > + .id = UCLASS_RTC, > + .ops = &emul_rtc_ops, > + .priv_auto_alloc_size = sizeof(struct emul_rtc), > +}; > + > +U_BOOT_DEVICE(rtc_emul) = { > + .name = "emulated RTC", Please use rtc_emul to avoid of-platdata warnings. Also it might be worth adding a simple sandbox test for this. Regards, SImon
diff --git a/MAINTAINERS b/MAINTAINERS index 196d635bdd..2465b51136 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -675,6 +675,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 59e2fc44ba..5c22d70ca9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -63,6 +63,12 @@ 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 + Provide an emulated real time clock for testing purposes. + 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..f291d19ab5 --- /dev/null +++ b/drivers/rtc/emul_rtc.c @@ -0,0 +1,79 @@ +// 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 <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) { + /* Assume it is 2021-01-11T00:00:00Z */ + priv->offset_us = 1610323200000000ULL - 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 = "emulated RTC", + .id = UCLASS_RTC, + .ops = &emul_rtc_ops, + .priv_auto_alloc_size = sizeof(struct emul_rtc), +}; + +U_BOOT_DEVICE(rtc_emul) = { + .name = "emulated RTC", +};
For testing purposes like running the UEFI SCT an RTC may be required. Provide an emulated RTC if we do not have a hardware one. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> --- MAINTAINERS | 1 + drivers/rtc/Kconfig | 6 ++++ drivers/rtc/Makefile | 1 + drivers/rtc/emul_rtc.c | 79 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 drivers/rtc/emul_rtc.c -- 2.28.0