From patchwork Wed Jun 3 05:03:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Jain X-Patchwork-Id: 479769 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id BF57F1402A2 for ; Wed, 3 Jun 2015 15:05:51 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id A99DE1A01AA for ; Wed, 3 Jun 2015 15:05:51 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e23smtp01.au.ibm.com (e23smtp01.au.ibm.com [202.81.31.143]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id EE1A21A005A for ; Wed, 3 Jun 2015 15:05:48 +1000 (AEST) Received: from /spool/local by e23smtp01.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 3 Jun 2015 15:05:48 +1000 Received: from d23dlp02.au.ibm.com (202.81.31.213) by e23smtp01.au.ibm.com (202.81.31.207) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 3 Jun 2015 15:05:47 +1000 Received: from d23relay10.au.ibm.com (d23relay10.au.ibm.com [9.190.26.77]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 305062BB0047 for ; Wed, 3 Jun 2015 15:05:47 +1000 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t5354Oje57409762 for ; Wed, 3 Jun 2015 15:04:32 +1000 Received: from d23av02.au.ibm.com (localhost [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t5353xX2003252 for ; Wed, 3 Jun 2015 15:04:00 +1000 Received: from localhost.in.ibm.com ([9.109.222.210]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t5353wP7002929; Wed, 3 Jun 2015 15:03:59 +1000 From: Vaibhav Jain To: skiboot@lists.ozlabs.org Date: Wed, 3 Jun 2015 10:33:38 +0530 Message-Id: <1433307818-13335-1-git-send-email-vaibhav@linux.vnet.ibm.com> X-Mailer: git-send-email 1.9.3 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15060305-1618-0000-0000-0000023385EE Subject: [Skiboot] [RFC] hw/fake-rtc: Add support for emulated rtc clock X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch adds support for an emulated rtc clock for generic platform (e.g BML) which doesn't have support for rtc. Current implementation provides a fake rtc clock for such platforms which is driven by device tree provided pointer(ibm,fake-rtc) to bcd coded date-time values. In absence of this rtc support is not provided. The patch overcomes this limitation by emulating an rtc clock that's driven by a periodically scheduled timer. If the device tree is missing node "ibm,fake-rtc" it creates the periodic timer and on each tick the rtc counter is incremented. Signed-off-by: Vaibhav Jain --- hw/fake-rtc.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 12 deletions(-) diff --git a/hw/fake-rtc.c b/hw/fake-rtc.c index 1b7c473..c2ac48d 100644 --- a/hw/fake-rtc.c +++ b/hw/fake-rtc.c @@ -17,10 +17,27 @@ #include #include #include +#include +#include +#include +#include +#include static uint32_t *fake_ymd; static uint64_t *fake_hmsm; +/* incase fake rtc clock not configured use these to store and hold rtc value */ +static struct timer emulation_timer; + +/* timebase when synchronization happened */ +static unsigned long tb_synctime; + +/* current rtc value */ +struct tm tm_offset; + +/* protects tm_offset & tb_synctime */ +struct lock emulation_lock; + static int64_t fake_rtc_write(uint32_t ymd, uint64_t hmsm) { *fake_ymd = ymd; @@ -40,28 +57,95 @@ static int64_t fake_rtc_read(uint32_t *ymd, uint64_t *hmsm) return OPAL_SUCCESS; } +static int64_t emulated_rtc_write(uint32_t ymd, uint64_t hmsm) +{ + lock(&emulation_lock); + datetime_to_tm(ymd, hmsm, &tm_offset); + tb_synctime = mftb(); + unlock(&emulation_lock); + + return OPAL_SUCCESS; +} + +static int64_t emulated_rtc_read(uint32_t *ymd, uint64_t *hmsm) +{ + if (!ymd || !hmsm) + return OPAL_PARAMETER; + + lock(&emulation_lock); + tm_to_datetime(&tm_offset, ymd, hmsm); + unlock(&emulation_lock); + + return OPAL_SUCCESS; +} + +/* update the emulated rtc. In case more than 60 seconds have passed + * since last sync then recompute the tm_offset. + */ +static void __emulated_rtc_update(struct timer *tm __unused, + void *data __unused) +{ + time_t sec; + + if (try_lock(&emulation_lock)) { + + sec = tb_to_secs(mftb() - tb_synctime); + tb_synctime = mftb(); + + if ((sec + tm_offset.tm_sec) >= 60) { + sec += mktime(&tm_offset); + gmtime_r(&sec, &tm_offset); + } else { + tm_offset.tm_sec += sec; + } + + unlock(&emulation_lock); + } + /* reschedule the timer */ + schedule_timer(&emulation_timer, secs_to_tb(1)); +} + void fake_rtc_init(void) { struct mem_region *rtc_region = NULL; uint32_t *rtc = NULL; + struct dt_node *np; /* Read initial values from reserved memory */ rtc_region = find_mem_region("ibm,fake-rtc"); - /* Should we register anyway? */ - if (!rtc_region) { - prlog(PR_TRACE, "No initial RTC value found\n"); - return; - } + /* Check if we need to provide emulation */ + if (rtc_region) { + rtc = (uint32_t *) rtc_region->start; + + fake_ymd = rtc; + fake_hmsm = ((uint64_t *) &rtc[1]); + + opal_register(OPAL_RTC_READ, fake_rtc_read, 2); + opal_register(OPAL_RTC_WRITE, fake_rtc_write, 2); + + prlog(PR_TRACE, "Init fake RTC to 0x%x 0x%llx\n", + *fake_ymd, *fake_hmsm); - rtc = (uint32_t *) rtc_region->start; + } else { + const time_t sec = 0; - fake_ymd = rtc; - fake_hmsm = ((uint64_t *) &rtc[1]); + /* use a timer to emulate fake rtc */ + gmtime_r(&sec, &tm_offset); + tb_synctime = mftb(); - prlog(PR_TRACE, "Init fake RTC to 0x%x 0x%llx\n", - *fake_ymd, *fake_hmsm); + init_lock(&emulation_lock); + + init_timer(&emulation_timer, __emulated_rtc_update, NULL); + schedule_timer(&emulation_timer, secs_to_tb(1)); + + opal_register(OPAL_RTC_READ, emulated_rtc_read, 2); + opal_register(OPAL_RTC_WRITE, emulated_rtc_write, 2); + + prlog(PR_TRACE, "Using emulated mode\n"); + } - 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"); }