Message ID | 1443502908-13699-1-git-send-email-vaibhav@linux.vnet.ibm.com |
---|---|
State | Accepted |
Headers | show |
Vaibhav Jain <vaibhav@linux.vnet.ibm.com> writes: > This patch adds support for an emulated rtc clock over existing fake rtc > implementation for generic platform (e.g BML). Presently a fake rtc > clock is initialized when reserved region named 'ibm,fake-rtc' is > present in the boot device tree. This mem-region points to the initial > value of bcd coded date-time values. However as this region is in system > memory hence its not updated with time. This results in an error from > hwclock tool which tries to detect a change in system clock and then > complains "Timed out waiting for time change." > > The patch overcomes this issue by emulating an rtc clock whose date-time > values are calculated from the difference of current timebase and its > value when the initial epoch was assigned. The initial epoch is set from > the values at "ibm,fake-rtc" memory region. > > Acked-by: Michael Neuling <mikey@neuling.org> > Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com> Thanks, merged as of ee18d59 - into skiboot master.
Stewart Smith <stewart@linux.vnet.ibm.com> writes: > Vaibhav Jain <vaibhav@linux.vnet.ibm.com> writes: >> This patch adds support for an emulated rtc clock over existing fake rtc >> implementation for generic platform (e.g BML). Presently a fake rtc >> clock is initialized when reserved region named 'ibm,fake-rtc' is >> present in the boot device tree. This mem-region points to the initial >> value of bcd coded date-time values. However as this region is in system >> memory hence its not updated with time. This results in an error from >> hwclock tool which tries to detect a change in system clock and then >> complains "Timed out waiting for time change." >> >> The patch overcomes this issue by emulating an rtc clock whose date-time >> values are calculated from the difference of current timebase and its >> value when the initial epoch was assigned. The initial epoch is set from >> the values at "ibm,fake-rtc" memory region. >> >> Acked-by: Michael Neuling <mikey@neuling.org> >> Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com> > > Thanks, merged as of ee18d59 - into skiboot master. err... as of 6c1658f.
diff --git a/hw/fake-rtc.c b/hw/fake-rtc.c index 1b7c473..bf2fc0b 100644 --- a/hw/fake-rtc.c +++ b/hw/fake-rtc.c @@ -17,25 +17,53 @@ #include <skiboot.h> #include <opal.h> #include <mem_region.h> +#include <device.h> +#include <timebase.h> +#include <time-utils.h> +#include <lock.h> -static uint32_t *fake_ymd; -static uint64_t *fake_hmsm; +/* timebase when tm_offset was assigned */ +static unsigned long tb_synctime; + +/* + * Absolute time that was last assigned. + * Current rtc value is calculated from this. +*/ +static struct tm tm_offset; + +/* protects tm_offset & tb_synctime */ +static struct lock emulation_lock; static int64_t fake_rtc_write(uint32_t ymd, uint64_t hmsm) { - *fake_ymd = ymd; - *fake_hmsm = hmsm; + + lock(&emulation_lock); + + datetime_to_tm(ymd, hmsm, &tm_offset); + tb_synctime = mftb(); + + unlock(&emulation_lock); return OPAL_SUCCESS; } static int64_t fake_rtc_read(uint32_t *ymd, uint64_t *hmsm) { + + time_t sec; + struct tm tm_calculated; + if (!ymd || !hmsm) return OPAL_PARAMETER; - *ymd = *fake_ymd; - *hmsm = *fake_hmsm; + /* Compute the emulated clock value */ + lock(&emulation_lock); + + sec = tb_to_secs(mftb() - tb_synctime) + mktime(&tm_offset); + gmtime_r(&sec, &tm_calculated); + tm_to_datetime(&tm_calculated, ymd, hmsm); + + unlock(&emulation_lock); return OPAL_SUCCESS; } @@ -43,7 +71,9 @@ static int64_t fake_rtc_read(uint32_t *ymd, uint64_t *hmsm) void fake_rtc_init(void) { struct mem_region *rtc_region = NULL; - uint32_t *rtc = NULL; + uint32_t *rtc = NULL, *fake_ymd; + uint64_t *fake_hmsm; + struct dt_node *np; /* Read initial values from reserved memory */ rtc_region = find_mem_region("ibm,fake-rtc"); @@ -54,14 +84,25 @@ void fake_rtc_init(void) return; } + init_lock(&emulation_lock); + + /* Fetch the initial rtc values */ rtc = (uint32_t *) rtc_region->start; fake_ymd = rtc; fake_hmsm = ((uint64_t *) &rtc[1]); - prlog(PR_TRACE, "Init fake RTC to 0x%x 0x%llx\n", - *fake_ymd, *fake_hmsm); + fake_rtc_write(*fake_ymd, *fake_hmsm); + /* Register opal calls */ opal_register(OPAL_RTC_READ, fake_rtc_read, 2); opal_register(OPAL_RTC_WRITE, fake_rtc_write, 2); + + /* add the fake rtc dt node */ + np = dt_new(opal_node, "rtc"); + dt_add_property_strings(np, "compatible", "ibm,opal-rtc"); + + prlog(PR_TRACE, "Init fake RTC to Date:%d-%d-%d Time:%d-%d-%d\n", + tm_offset.tm_mon, tm_offset.tm_mday, tm_offset.tm_year, + tm_offset.tm_hour, tm_offset.tm_min, tm_offset.tm_sec); }