From patchwork Wed Dec 12 05:56:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 1864641 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id C99C84006E for ; Wed, 12 Dec 2012 06:00:46 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TifJV-0000yJ-Ul; Wed, 12 Dec 2012 05:57:02 +0000 Received: from quartz.orcorp.ca ([184.70.90.242]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1TifJS-0000xk-3v for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2012 05:56:58 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=obsidianresearch.com; s=rsa1; h=Content-Type:MIME-Version:Message-ID:Subject:To:From:Date; bh=WP1tGTk9/O9dc7JhmgSNteRxzCNzAIwl3HWtGoIaMa0=; b=VO+I3uylNfcUH5AYxL6N81yrLHYuzvAmZBQZOdCqlC4w5FUXbOyRT0dH7g9lAf8ojT/Lj1j3zNcZL+lkzX84q3bhHKR/NaOj3jculVSV/eYlBDF9Kk75KSsCvcA9JdXbFZM0QoXlPr36UMXjM5sUV8uHt2gztuuHdxGdt1ytbmc=; Received: from [10.0.0.162] (helo=jggl.edm.orcorp.ca) by quartz.orcorp.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.72) (envelope-from ) id 1TifJD-0007Nr-UT; Tue, 11 Dec 2012 22:56:43 -0700 Received: from jgg by jggl.edm.orcorp.ca with local (Exim 4.76) (envelope-from ) id 1TifJD-0004iw-Ow; Tue, 11 Dec 2012 22:56:43 -0700 Date: Tue, 11 Dec 2012 22:56:43 -0700 From: Jason Gunthorpe To: Alessandro Zummo , John Stultz , homas Gleixner , rtc-linux@googlegroups.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH] NTP: Add a CONFIG_RTC_SYSTOHC configuration Message-ID: <20121212055643.GA18078@obsidianresearch.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.162 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121212_005658_332267_A618F6A8 X-CRM114-Status: GOOD ( 24.28 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org The purpose of this option is to allow ARM/etc systems that rely on the class RTC subsystem to have the same kind of automatic NTP based synchronization that we have on PC platforms. Today ARM does not implement update_persistent_clock and makes extensive use of the class RTC system. When enabled CONFIG_RTC_SYSTOHC will provide a generic rtc_update_persistent_clock that stores the current time in the RTC and is intended complement the existing CONFIG_RTC_HCTOSYS option that loads the RTC at boot. The option also overrides the call to any platform update_persistent_clock so that the RTC subsystem completely and generically replaces this functionality. Tested on ARM kirkwood and PPC405 Signed-off-by: Jason Gunthorpe --- drivers/rtc/Kconfig | 8 ++++++++ drivers/rtc/Makefile | 1 + drivers/rtc/systohc.c | 30 ++++++++++++++++++++++++++++++ include/linux/time.h | 1 + kernel/time/ntp.c | 12 ++++++++++-- 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 drivers/rtc/systohc.c I saw on Google an older version of a similar patch to this, but I couldn't find any indication what happened to it. So here is a slightly different take, tested on 3.7. I've been running basically this idea buried in PPC platform specific code since 2.6.16.. diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 19c03ab..30a866a 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -48,6 +48,14 @@ config RTC_HCTOSYS_DEVICE sleep states. Do not specify an RTC here unless it stays powered during all this system's supported sleep states. +config RTC_SYSTOHC + bool "Set the RTC time based on NTP synchronization" + default y + help + If you say yes here, the system time (wall clock) will be stored + in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11 + minutes if the NTP status is synchronized. + config RTC_DEBUG bool "RTC debug support" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 56297f0..69d11f1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG obj-$(CONFIG_RTC_LIB) += rtc-lib.o obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o +obj-$(CONFIG_RTC_SYSTOHC) += systohc.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o rtc-core-y := class.o interface.o diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c new file mode 100644 index 0000000..0536cae --- /dev/null +++ b/drivers/rtc/systohc.c @@ -0,0 +1,30 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ +#include +#include + +/* Replacement for the NTP platform function 'update_persistent_clock' + * that does the opposite of rtc_hctosys.c */ +int rtc_update_persistent_clock(struct timespec now) +{ + struct rtc_device *rtc; + struct rtc_time tm; + int err = -ENODEV; + + if (now.tv_nsec < (NSEC_PER_SEC >> 1)) + rtc_time_to_tm(now.tv_sec, &tm); + else + rtc_time_to_tm(now.tv_sec + 1, &tm); + + rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + if (rtc) { + err = rtc_set_mmss(rtc, now.tv_sec); + rtc_class_close(rtc); + } + + return err; +} diff --git a/include/linux/time.h b/include/linux/time.h index 4d358e9..d668f9c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -118,6 +118,7 @@ static inline bool timespec_valid_strict(const struct timespec *ts) extern void read_persistent_clock(struct timespec *ts); extern void read_boot_clock(struct timespec *ts); extern int update_persistent_clock(struct timespec now); +extern int rtc_update_persistent_clock(struct timespec now); void timekeeping_init(void); extern int timekeeping_suspended; diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 24174b4..f79ab16 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -483,7 +483,15 @@ out: return leap; } -#ifdef CONFIG_GENERIC_CMOS_UPDATE +#if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC) + +/* Only do one, if using CONFIG_RTC_SYSTOHC then the platform function + * might be mapped to the RTC code already. */ +#ifdef CONFIG_RTC_SYSTOHC +#define __update_persistent_clock rtc_update_persistent_clock +#else +#define __update_persistent_clock update_persistent_clock +#endif static void sync_cmos_clock(struct work_struct *work); @@ -511,7 +519,7 @@ static void sync_cmos_clock(struct work_struct *work) getnstimeofday(&now); if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) - fail = update_persistent_clock(now); + fail = __update_persistent_clock(now); next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2); if (next.tv_nsec <= 0)