From patchwork Thu Nov 27 12:02:39 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "pang.xunlei" X-Patchwork-Id: 41616 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 235BE244C2 for ; Thu, 27 Nov 2014 12:03:55 +0000 (UTC) Received: by mail-wi0-f198.google.com with SMTP id r20sf3116501wiv.5 for ; Thu, 27 Nov 2014 04:03:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=RbU+F7F5Q4gPUaP41BakEAV4DXECI5CyBEto5AXPyyk=; b=YID/J5tuDHgFKMuYDe2ddT3npzvDn2it1ZGqC5RqvU5Go19VZcFB+6bEz6Pn8+nPmN VhOdNGSLw/amYCVxG7q2r1J9YZftDXbrj2Tjm0eZCS4hyk+sanrOXNI8Tmf+1P5B9L6s Bjg1tmb13wzjE2MJ4M+jDUtotiHoJwdvSf8DC9oCWFuqLSWafU/EwTDAZMWmYh/gpFlw 0CUjUUtVkhqGjFUjgt9p6IEoG9q58t8hJTjkSKEGpX92Ho21g7MCOktiyfl7XRJ0NR9U wrmLZOmmE0ywJga9nsl9VLxFpWuYeRGyLb+v7sVZUHHLEucq9j0ZF8pwD0oHINNBOCHd QcMA== X-Gm-Message-State: ALoCoQmqXB2PMujFK6fp404mZ416wkcJZWagivQArS7irY31/J+sjROHX5KthJUEkC6hyuLVIqDN X-Received: by 10.112.147.131 with SMTP id tk3mr10515983lbb.2.1417089834448; Thu, 27 Nov 2014 04:03:54 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.23.130 with SMTP id m2ls816625laf.63.gmail; Thu, 27 Nov 2014 04:03:54 -0800 (PST) X-Received: by 10.152.43.166 with SMTP id x6mr28978691lal.14.1417089833981; Thu, 27 Nov 2014 04:03:53 -0800 (PST) Received: from mail-lb0-f172.google.com (mail-lb0-f172.google.com. [209.85.217.172]) by mx.google.com with ESMTPS id t8si7062722lbw.102.2014.11.27.04.03.53 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 27 Nov 2014 04:03:53 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.172 as permitted sender) client-ip=209.85.217.172; Received: by mail-lb0-f172.google.com with SMTP id u10so4086009lbd.3 for ; Thu, 27 Nov 2014 04:03:53 -0800 (PST) X-Received: by 10.112.52.37 with SMTP id q5mr38277543lbo.32.1417089833878; Thu, 27 Nov 2014 04:03:53 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.184.201 with SMTP id ew9csp786923lbc; Thu, 27 Nov 2014 04:03:52 -0800 (PST) X-Received: by 10.66.140.102 with SMTP id rf6mr2687730pab.1.1417089831147; Thu, 27 Nov 2014 04:03:51 -0800 (PST) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id vz6si11421798pab.0.2014.11.27.04.03.50 for ; Thu, 27 Nov 2014 04:03:51 -0800 (PST) Received-SPF: none (google.com: linux-kernel-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754933AbaK0MDg (ORCPT + 26 others); Thu, 27 Nov 2014 07:03:36 -0500 Received: from mail-pa0-f45.google.com ([209.85.220.45]:57762 "EHLO mail-pa0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754867AbaK0MDc (ORCPT ); Thu, 27 Nov 2014 07:03:32 -0500 Received: by mail-pa0-f45.google.com with SMTP id lj1so4925479pab.32 for ; Thu, 27 Nov 2014 04:03:31 -0800 (PST) X-Received: by 10.68.216.65 with SMTP id oo1mr41317853pbc.105.1417089811685; Thu, 27 Nov 2014 04:03:31 -0800 (PST) Received: from wangdeqiang.com ([210.21.223.3]) by mx.google.com with ESMTPSA id cf12sm6955128pdb.77.2014.11.27.04.03.26 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 27 Nov 2014 04:03:31 -0800 (PST) From: Xunlei Pang To: linux-kernel@vger.kernel.org Cc: rtc-linux@googlegroups.com, Thomas Gleixner , Alessandro Zummo , Sven Schnelle , Xunlei Pang , John Stultz , Arnd Bergmann Subject: [RFC PATCH 3/4] rtc/lib: Provide interfaces to map between 32bit hardware and 64bit time Date: Thu, 27 Nov 2014 20:02:39 +0800 Message-Id: <1417089760-26848-4-git-send-email-pang.xunlei@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1417089760-26848-1-git-send-email-pang.xunlei@linaro.org> References: <1417089760-26848-1-git-send-email-pang.xunlei@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: pang.xunlei@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.172 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , To attack the 32bit rtc hardware limitations which will bring about y2106 issues to their rtc drivers as those marked "y2106 issue" tags in the former patch, this patch adds a common rtc epoch offset, and provides two interfaces to map between 32bit rtc hardware and 64bit time using this rtc epoch offset. These two interfaces can be used to write rtc drivers for 32-bit rtc hardware. - Add "rtc_epoch" boot parameter, default offset value is hardcoded to 1970 for consistency with Unix epoch. This default value can be overrided through boot command if you have problematic rtc hardware. Once you are doing this, should be aware of following side effects: a) Can't set time before your rtc epoch. b) Can't boot into different OSes relying on the same rtc hardware. "rtc epoch" must stay invariable once finalized on one machine. - Add rtc_time64_to_hw32(): This interface converts 64-bit seconds since unix 1970 epoch to 32bit seconds since rtc epoch which can be maintained by 32-bit rtc hardware. - Add rtc_hw32_to_time64(): This interface converts 32bit seconds since rtc epoch which can be used by 32-bit rtc hardware to 64bit seconds since unix 1970 epoch. There're also other ways to implement this function: For example, some driver(vr41xx) implements the same logic using RTC_EPOCH_SET ioctl and an rtc epoch offset variable. But the approach in this patch is more flexible and common than that. Cc: John Stultz Cc: Arnd Bergmann Signed-off-by: Xunlei Pang --- drivers/rtc/class.c | 25 +++++++++++++++++++++++++ drivers/rtc/rtc-lib.c | 28 ++++++++++++++++++++++++++++ include/linux/rtc.h | 3 +++ 3 files changed, 56 insertions(+) diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 38e26be..7f1950f8 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -358,6 +358,29 @@ void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc) } EXPORT_SYMBOL_GPL(devm_rtc_device_unregister); +/* Rtc epoch year, can be overrided by command line */ +static unsigned int rtc_epoch = 1970; +time64_t rtc_epoch_secs_since_1970; + +static int __init +set_rtc_epoch(char *str) +{ + unsigned int epoch; + + if (kstrtou32(str, 0, &epoch) != 0) { + printk(KERN_WARNING "Invalid setup epoch %u!\n", epoch); + return 1; + } + + if (rtc_epoch < 1970) + printk(KERN_WARNING "Epoch %u is smaller than 1970!\n", epoch); + else + rtc_epoch = epoch; + + return 1; +} +__setup("rtc_epoch=", set_rtc_epoch); + static int __init rtc_init(void) { rtc_class = class_create(THIS_MODULE, "rtc"); @@ -366,6 +389,8 @@ static int __init rtc_init(void) return PTR_ERR(rtc_class); } rtc_class->pm = RTC_CLASS_DEV_PM_OPS; + + rtc_epoch_secs_since_1970 = mktime64(rtc_epoch, 1, 1, 0, 0, 0); rtc_dev_init(); rtc_sysfs_init(rtc_class); return 0; diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index e6bfb9c..d26814c 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -124,6 +124,34 @@ time64_t rtc_tm_to_time64(struct rtc_time *tm) EXPORT_SYMBOL(rtc_tm_to_time64); /* + * Convert seconds since rtc epoch to seconds since Unix epoch. + */ +time64_t rtc_hw32_to_time64(u32 hwtime) +{ + return (rtc_epoch_secs_since_1970 + hwtime); +} +EXPORT_SYMBOL_GPL(rtc_hw32_to_time64); + +/* + * Convert seconds since Unix epoch to seconds since rtc epoch. + */ +int rtc_time64_to_hw32(time64_t time, u32 *hwtime) +{ + /* time must be after rtc epoch */ + if (time < rtc_epoch_secs_since_1970) + return -EINVAL; + + /* rtc epoch may be too small? */ + if (time - rtc_epoch_secs_since_1970 > UINT_MAX) + return -EOVERFLOW; + + *hwtime = time - rtc_epoch_secs_since_1970; + + return 0; +} +EXPORT_SYMBOL_GPL(rtc_time64_to_hw32); + +/* * Convert rtc_time to ktime */ ktime_t rtc_tm_to_ktime(struct rtc_time tm) diff --git a/include/linux/rtc.h b/include/linux/rtc.h index d080606..32f7c22 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -16,11 +16,14 @@ #include #include +extern time64_t rtc_epoch_secs_since_1970; extern int rtc_month_days(unsigned int month, unsigned int year); extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year); extern int rtc_valid_tm(struct rtc_time *tm); extern time64_t rtc_tm_to_time64(struct rtc_time *tm); extern void rtc_time64_to_tm(time64_t time, struct rtc_time *tm); +extern int rtc_time64_to_hw32(time64_t time, u32 *hwtime); +extern time64_t rtc_hw32_to_time64(u32 hwtime); ktime_t rtc_tm_to_ktime(struct rtc_time tm); struct rtc_time rtc_ktime_to_tm(ktime_t kt);