From patchwork Tue Jan 2 05:10:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "\(Exiting\) Baolin Wang" X-Patchwork-Id: 123090 Delivered-To: patch@linaro.org Received: by 10.140.22.227 with SMTP id 90csp8567236qgn; Mon, 1 Jan 2018 21:10:50 -0800 (PST) X-Google-Smtp-Source: ACJfBotZN/RlZ1hVmbZa2AMtmuDwIaT5cM6tEWngw38ZpJd4eaDeRzLpH1PcG0Pmp8pldbuZOk4k X-Received: by 10.99.2.13 with SMTP id 13mr8628615pgc.427.1514869850099; Mon, 01 Jan 2018 21:10:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1514869850; cv=none; d=google.com; s=arc-20160816; b=BbujXz23Lj61aHJqSkgv2WdABrCT1HWq2fa2m9dBK9D1+fbierPLeheqQn6RWWfutY DMQO8X/tBq9tszMsatC0kJWkcclNShqGUiV5NUCI1eojr84Hiw/UZvzz4Q9iVjA3VPHo vGGclrWTS6Tk28gw+Vr7D4LRQqkGGXl2AhkpJSr1LSlblRiLVlP5BEcD2Ln2CQ8ndA+Z LCTMeGyM/q+lcB1QaOnwZrk6HTCAdR0szxEhS71LPRNJ66Ben7OPSqjgRYO173vqMUhw +EYlQ1SvBHqdPBkz7TXS0hDhgjKU4dJzQtpc1mBqQ6gsrCsG1GjJibx4ThMYECBCR/od HCUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=G9sSaSOkR0mwSBUMiQvlccBzBe4nPRlyOtDuvIoqKnI=; b=PUvsUebg912DCE4azg0pCmfO0Lgfcag1pRRbonqr/NUf7dTWe1qMs3W6CEmQyOs/Is vRZxFMpS8RHvT6Wc7+bxY6la27hYUTHSjrN/D6SrmrP8SIpDb6E9vSv/TvmNllaMhFBF gdl6arDfQmfQyiWff3eNkWI8Tppfb4OTnMptbubY+3BHtaCKTxv7SmxZAybC9aPSarAu C8Z8EBMO3mmqiT6YbJsQmRp1DMEK9wNBUf7TZIpfT4TIMLlp6g6JymWFccJ7W3a0sYzg jJS4o2u+PeIF74dfkXWVrgRRfjXl6uZSKnqn06odtE5azpdmF4vvO2X/Cf6eZYHsvaGr nvJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EDFL2SaY; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id y11si27541101plg.702.2018.01.01.21.10.49; Mon, 01 Jan 2018 21:10:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EDFL2SaY; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751430AbeABFKb (ORCPT + 28 others); Tue, 2 Jan 2018 00:10:31 -0500 Received: from mail-pf0-f196.google.com ([209.85.192.196]:45763 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751242AbeABFK3 (ORCPT ); Tue, 2 Jan 2018 00:10:29 -0500 Received: by mail-pf0-f196.google.com with SMTP id u19so25250247pfa.12 for ; Mon, 01 Jan 2018 21:10:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=G9sSaSOkR0mwSBUMiQvlccBzBe4nPRlyOtDuvIoqKnI=; b=EDFL2SaYjnRfNhse1+q2OaKPfmam0VX1JmiTwDL2zdnVHH2BnEcKU34bZg9ZietuvT nhuz+ZS/pwcp1yL43gulEMR2hj93GIhEs/lh36eoP3zgprRxpKA7JfInzIqAoO4CS7Js 05k0nzFiLT0fUycbO3IgcQWZ1aRQQ0QBbj2Vk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=G9sSaSOkR0mwSBUMiQvlccBzBe4nPRlyOtDuvIoqKnI=; b=bKwjvHa6hM+vDWw6gzdsM/Vt1Smj7+byx/MuhXfwb4bLg8GjDUAu5ngKD6aIjbAOBG 9Dn26mJCUImzGroQomcZUK9ba6cd1aVAOR8LmmTONfeGiNs9JsX/Zym/HKz7VAsn6Ud8 3pKeD9CnsAaqo2BdopwkDLcOHS+hTBgBg3JM/BrG2hXr+MSWFmbJI80scaF8IquvAOLx ZdyU8grEr+GpRfS4++8vLaKZ11ZvNdQRiCNCOVPHoTAE+at6bntaJY0Zaj1ye+jCOK+5 vthoHfODUf170Rwen9xYXfuyssOe0lxO6I3csdijGYNx6Xuoh/7nBUHr6RCcNYpfy1Qi oiBg== X-Gm-Message-State: AKGB3mI5fbmZHSwJ4PkNGhXYPX5tI7JRLmCBzOSFq8gld6W5bh7KkXRr psPEPgl8EmN5gbMhjD5JLUprFACdffQ= X-Received: by 10.101.75.3 with SMTP id r3mr20819364pgq.259.1514869828836; Mon, 01 Jan 2018 21:10:28 -0800 (PST) Received: from baolinwangubtpc.spreadtrum.com ([117.18.48.82]) by smtp.gmail.com with ESMTPSA id 6sm63989675pgf.54.2018.01.01.21.10.26 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 01 Jan 2018 21:10:28 -0800 (PST) From: Baolin Wang To: a.zummo@towertech.it, alexandre.belloni@free-electrons.com, corbet@lwn.net Cc: arnd@arndb.de, broonie@kernel.org, linux-rtc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, baolin.wang@linaro.org Subject: [RFC PATCH 1/4] rtc: Introduce one interface to save the RTC hardware time range Date: Tue, 2 Jan 2018 13:10:05 +0800 Message-Id: <9ab56bdcaeb52241e22b738d6babe7b01728f64c.1514869621.git.baolin.wang@linaro.org> X-Mailer: git-send-email 1.7.9.5 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In order to the setting time values are not beyond the limitation supported by RTC hardware, we introduce one interface to tell the hardware range to the RTC core, which are used to valid if the setting time values are in the RTC hardware range. Moreover we also need the RTC hardware range to expand the RTC range in next patches by adding one offset. Signed-off-by: Baolin Wang --- drivers/rtc/class.c | 13 ++++++++++ drivers/rtc/interface.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rtc.h | 9 +++++++ 3 files changed, 84 insertions(+) -- 1.7.9.5 diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 722d683..31fc0f1 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -247,6 +247,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, dev_set_name(&rtc->dev, "rtc%d", id); + err = rtc_read_range(rtc, &rtc->max_hw_secs, &rtc->min_hw_secs); + if (err) { + dev_err(&rtc->dev, "%s: failed to get RTC range\n", name); + goto exit_ida; + } + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); @@ -436,6 +442,13 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) rtc->owner = owner; + err = rtc_read_range(rtc, &rtc->max_hw_secs, &rtc->min_hw_secs); + if (err) { + dev_err(&rtc->dev, "%s: failed to get RTC range\n", + dev_name(&rtc->dev)); + return err; + } + /* Check to see if there is an ALARM already set in hw */ err = __rtc_read_alarm(rtc, &alrm); if (!err && !rtc_valid_tm(&alrm.time)) diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 672b192..c8090e3 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -65,6 +65,10 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) if (err != 0) return err; + err = rtc_valid_range(rtc, tm); + if (err) + return err; + err = mutex_lock_interruptible(&rtc->ops_lock); if (err) return err; @@ -329,6 +333,11 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) err = rtc_valid_tm(&alarm->time); if (err) return err; + + err = rtc_valid_range(rtc, &alarm->time); + if (err) + return err; + scheduled = rtc_tm_to_time64(&alarm->time); /* Make sure we're not setting alarms in the past */ @@ -1027,3 +1036,56 @@ int rtc_set_offset(struct rtc_device *rtc, long offset) mutex_unlock(&rtc->ops_lock); return ret; } + +/* rtc_read_range - Read the max and min hardware count supported by RTC device + * @ rtc: rtc device to be used. + * @ max_hw_secs: maximum hardware count in seconds, which can represent + * the maximum time values in RTC hardware. + * @ min_hw_secs: minimum hardware count in seconds, which can represent + * the minimum time values in RTC hardware. + * + * The max_hw_secs and min_hw_secs implemented by user must represent the + * correct hardware start time and maximum time, which means the count + * will wrap around to min_hw_secs after the maximum count. + * + * If user did not implement the read_range() interface, we can set max_hw_secs + * and min_hw_secs to 0, which avoids validing the range. + */ +int rtc_read_range(struct rtc_device *rtc, time64_t *max_hw_secs, + time64_t *min_hw_secs) +{ + int ret; + + if (!rtc->ops || !rtc->ops->read_range) { + *max_hw_secs = 0; + *min_hw_secs = 0; + return 0; + } + + mutex_lock(&rtc->ops_lock); + ret = rtc->ops->read_range(rtc->dev.parent, max_hw_secs, min_hw_secs); + mutex_unlock(&rtc->ops_lock); + + return ret; +} + +/* rtc_valid_range - Valid if the setting time in the RTC range + * @ rtc: rtc device to be used. + * @ tm: time values need to valid. + * + * Only the rtc->max_hw_secs was set, then we can valid if the setting time + * values are beyond the RTC range. + */ +int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm) +{ + time64_t secs; + + if (!rtc->max_hw_secs) + return 0; + + secs = rtc_tm_to_time64(tm); + if (secs < rtc->min_hw_secs || secs > rtc->max_hw_secs) + return -EINVAL; + + return 0; +} diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 41319a2..19a8989 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -85,6 +85,8 @@ struct rtc_class_ops { int (*alarm_irq_enable)(struct device *, unsigned int enabled); int (*read_offset)(struct device *, long *offset); int (*set_offset)(struct device *, long offset); + int (*read_range)(struct device *, time64_t *max_hw_secs, + time64_t *min_hw_secs); }; #define RTC_DEVICE_NAME_SIZE 20 @@ -152,6 +154,9 @@ struct rtc_device { bool nvram_old_abi; struct bin_attribute *nvram; + time64_t max_hw_secs; + time64_t min_hw_secs; + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL struct work_struct uie_task; struct timer_list uie_timer; @@ -225,6 +230,10 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer, int rtc_set_offset(struct rtc_device *rtc, long offset); void rtc_timer_do_work(struct work_struct *work); +int rtc_read_range(struct rtc_device *rtc, time64_t *max_hw_secs, + time64_t *min_hw_secs); +int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm); + static inline bool is_leap_year(unsigned int year) { return (!(year % 4) && (year % 100)) || !(year % 400);