Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp1454953pxv; Fri, 23 Jul 2021 08:42:05 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxrrveO7MISyTPGaC6Pcwh5RKaYE0F8QnVqvmQcjzOjoRalQZTBuWIbts4e2G7oyfCkzs7p X-Received: by 2002:a5e:dc48:: with SMTP id s8mr4436537iop.133.1627054925076; Fri, 23 Jul 2021 08:42:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627054925; cv=none; d=google.com; s=arc-20160816; b=mpOfhY6BhaQntoYFjXFjZhkcPrrap+r+Q0/wTn8E/RGL/Nyv5mIknepMK4l+RaJkCr tr2votX+vmb7PZO7CiKJvQQ456GAkkQ7sb+1+TRkYDvuHs/O4w/IVFWTLul+N780tmSY Uq+q9tak2/j4TMUtthS2oIjzT0ikutzFFqLx2FgnLT0TKoCn966/abuF1JpCO4YEast0 69s0XqompxtCIc/Mr/wOi9sxPovdG6VjFwdP1JXZOpQPu1Z44qgI+JVVBl1NNhhwObv7 9RqwmRG4WftG9Em7/qHY6mV7bQ45ogQNZUXPXqTc8x/iFryR1G/BT2cW/KRKPcgENtLq z1lg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=n2BmqIt60jZrSl9PoA2/Qeolgt0KS9Nx3cn26BLzsKs=; b=mw8d4K0zYgajPmMett+xWgOQNhuHd09SHdfpOhUn/crpE6Cq/7b9sEUL7YCiLekpb+ FtqQirFp8QNhDFs+D9yd8jzblfpyP+JDeREQw+HjJ/6PD8/WbQp88e8qI/2oSAWFvUJt zzBoug7YEVTLWGwATHJKbXVCLrS15FHXV7zGN0wA1OqhmqgCuwJtj31/QN36ioPmPz02 mBYGTyU5BnfAYc3V7ZabHfiG7ItJIyRgRLNo0gDNZ50pSfG/ti2mDknvtna18Sx+6l4p pMg1KUHL0ipIj7BDLzA7FeQN4Uezjr2Hd5lzLk2UxAovvVwevaKIUO8tlvTNLG3O2Zdi 3idA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id b69si36143004jai.66.2021.07.23.08.41.53; Fri, 23 Jul 2021 08:42:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235542AbhGWO67 (ORCPT + 99 others); Fri, 23 Jul 2021 10:58:59 -0400 Received: from foss.arm.com ([217.140.110.172]:47714 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235638AbhGWO6x (ORCPT ); Fri, 23 Jul 2021 10:58:53 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D4D5F13A1; Fri, 23 Jul 2021 08:39:26 -0700 (PDT) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C1F283F73D; Fri, 23 Jul 2021 08:39:24 -0700 (PDT) From: Andre Przywara To: Maxime Ripard , Chen-Yu Tsai , Jernej Skrabec Cc: Rob Herring , Icenowy Zheng , Samuel Holland , linux-arm-kernel@lists.infradead.org, linux-sunxi@googlegroups.com, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Ondrej Jirman , Alessandro Zummo , Alexandre Belloni , linux-rtc@vger.kernel.org Subject: [PATCH v8 05/11] rtc: sun6i: Add support for broken-down alarm registers Date: Fri, 23 Jul 2021 16:38:32 +0100 Message-Id: <20210723153838.6785-6-andre.przywara@arm.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20210723153838.6785-1-andre.przywara@arm.com> References: <20210723153838.6785-1-andre.przywara@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Newer versions of the Allwinner RTC, for instance as found in the H616 SoC, not only store the current day as a linear number, but also change the way the alarm is handled: There are now two registers, that explicitly store the wakeup time, in the same format as the current time. Add support for that variant by writing the requested wakeup time directly into the registers, instead of programming the seconds left, as the old SoCs required. Signed-off-by: Andre Przywara --- drivers/rtc/rtc-sun6i.c | 60 +++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index a02be8bca6f3..f0ee20bfdccb 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -48,7 +48,8 @@ /* Alarm 0 (counter) */ #define SUN6I_ALRM_COUNTER 0x0020 -#define SUN6I_ALRM_CUR_VAL 0x0024 +/* This holds the remaining alarm seconds on older SoCs (current value) */ +#define SUN6I_ALRM_COUNTER_HMS 0x0024 #define SUN6I_ALRM_EN 0x0028 #define SUN6I_ALRM_EN_CNT_EN BIT(0) #define SUN6I_ALRM_IRQ_EN 0x002c @@ -523,32 +524,57 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm) struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); struct rtc_time *alrm_tm = &wkalrm->time; struct rtc_time tm_now; - time64_t time_now, time_set; + time64_t time_set; + u32 counter_val, counter_val_hms; int ret; - ret = sun6i_rtc_gettime(dev, &tm_now); - if (ret < 0) { - dev_err(dev, "Error in getting time\n"); - return -EINVAL; - } - time_set = rtc_tm_to_time64(alrm_tm); - time_now = rtc_tm_to_time64(&tm_now); - if (time_set <= time_now) { - dev_err(dev, "Date to set in the past\n"); - return -EINVAL; - } - if ((time_set - time_now) > U32_MAX) { - dev_err(dev, "Date too far in the future\n"); - return -EINVAL; + if (chip->flags & RTC_LINEAR_DAY) { + time64_t seconds; + + /* + * The alarm registers hold the actual alarm time, encoded + * in the same way (linear day + HMS) as the current time. + */ + counter_val_hms = SUN6I_TIME_SET_SEC_VALUE(alrm_tm->tm_sec) | + SUN6I_TIME_SET_MIN_VALUE(alrm_tm->tm_min) | + SUN6I_TIME_SET_HOUR_VALUE(alrm_tm->tm_hour); + seconds = mktime64(alrm_tm->tm_year + 1900, alrm_tm->tm_mon, + alrm_tm->tm_mday, 0, 0, 0); + counter_val = div_u64(seconds, SECS_PER_DAY); + } else { + /* The alarm register holds the number of seconds left. */ + time64_t time_now; + + ret = sun6i_rtc_gettime(dev, &tm_now); + if (ret < 0) { + dev_err(dev, "Error in getting time\n"); + return -EINVAL; + } + + time_now = rtc_tm_to_time64(&tm_now); + if (time_set <= time_now) { + dev_err(dev, "Date to set in the past\n"); + return -EINVAL; + } + if ((time_set - time_now) > U32_MAX) { + dev_err(dev, "Date too far in the future\n"); + return -EINVAL; + } + + counter_val = time_set - time_now; } sun6i_rtc_setaie(0, chip); writel(0, chip->base + SUN6I_ALRM_COUNTER); + if (chip->flags & RTC_LINEAR_DAY) + writel(0, chip->base + SUN6I_ALRM_COUNTER_HMS); usleep_range(100, 300); - writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER); + writel(counter_val, chip->base + SUN6I_ALRM_COUNTER); + if (chip->flags & RTC_LINEAR_DAY) + writel(counter_val_hms, chip->base + SUN6I_ALRM_COUNTER_HMS); chip->alarm = time_set; sun6i_rtc_setaie(wkalrm->enabled, chip); -- 2.17.6