Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp1453971pxv; Fri, 23 Jul 2021 08:40:35 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyn24HXrW+FsoRpD3aMtdC1ARceHrnBzP+QF0X+vY1b92zzjR88ommuDJgl6HAzxjKnoho5 X-Received: by 2002:a02:8783:: with SMTP id t3mr4599062jai.45.1627054834974; Fri, 23 Jul 2021 08:40:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1627054834; cv=none; d=google.com; s=arc-20160816; b=J1MvUBNWfxwcCeS/sQgQOw+a6gb9WjCURLrCTmrC1ZzL5k2BpdWOq++ur9Iui+BhAK 4ztNaKC8kg4HOjX6nETbiJWYY8jhdQLgw65V/P1v6Y0kO5WCBXJ/iMVrFiqQqbxR9iqB SNuWJDRDDLqBgiBFizmf+lqAYf5NTEsDSCGG2zkq83AdWx7H/QP8AsJnF6kwSyvnxxsj DxCjEZLXA3CAPxrEOhEfqSmZmNf0BIrb4ZdFezQQKSponcUE8T6y8QfUE0kwZ1EcjRbU lHc97VC9Wy/YBlthid/v1i+3KzlG3xNpb/aXicBFuJiGXtIeycBQ4dZaxfUkv8xs95zt YMIg== 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=TMu1sLW8dOHYwpCEkUvNBu2Trf7y/6gdo8VsMWnskG8=; b=XxeDJM3wJiTvBC6bWxYJVULS8DCB8KwgOrM0NndBfXzH5RHIaVC1R4Xm77frhbVw7d anoEJOKuQujrRcM6KVH+AJK+cioyy50CiVRs98VHGGY8blMlaNy5kcl4jhC4GmMS7gj9 k0eCCMY87fR66TMJrOzrhNJpcRT6L3gM3z+poVn7DYgRaWE/w3f7M4uLKRJ7QRlxSJFy IkYTTLcaasTwHwGAdcJwgDoqq1ihtIhoF/UKLprIIBeL7qRJG7cMmM16rJh9ebh7fPtC XvefJX7HjuOVJmOOh03J4E8GPW58C/4VHoccjLZXWRHP/MsQUWNvn8s3bPzUF61QVBIP 07cg== 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 j8si6554403jak.67.2021.07.23.08.40.22; Fri, 23 Jul 2021 08:40:34 -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 S235554AbhGWO64 (ORCPT + 99 others); Fri, 23 Jul 2021 10:58:56 -0400 Received: from foss.arm.com ([217.140.110.172]:47676 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235631AbhGWO6v (ORCPT ); Fri, 23 Jul 2021 10:58:51 -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 8B603139F; Fri, 23 Jul 2021 08:39:24 -0700 (PDT) Received: from localhost.localdomain (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 779053F73D; Fri, 23 Jul 2021 08:39:22 -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 04/11] rtc: sun6i: Add support for linear day storage Date: Fri, 23 Jul 2021 16:38:31 +0100 Message-Id: <20210723153838.6785-5-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, as for instance found in the H616 SoC, no longer store a broken-down day/month/year representation in the RTC_DAY_REG, but just a linear day number. The user manual does not give any indication about the expected epoch time of this day count, but the BSP kernel uses the UNIX epoch, which allows easy support due to existing conversion functions in the kernel. Allow tagging a compatible string with a flag, and use that to mark those new RTCs. Then convert between a UNIX day number (converted into seconds) and the broken-down day representation using mktime64() and time64_to_tm() in the set_time/get_time functions. That enables support for the RTC in those new chips. Signed-off-by: Andre Przywara --- drivers/rtc/rtc-sun6i.c | 66 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index c551ebf0ac00..a02be8bca6f3 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -110,6 +110,8 @@ #define SUN6I_YEAR_MIN 1970 #define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900) +#define SECS_PER_DAY (24 * 3600ULL) + /* * There are other differences between models, including: * @@ -133,12 +135,15 @@ struct sun6i_rtc_clk_data { unsigned int has_auto_swt : 1; }; +#define RTC_LINEAR_DAY BIT(0) + struct sun6i_rtc_dev { struct rtc_device *rtc; const struct sun6i_rtc_clk_data *data; void __iomem *base; int irq; time64_t alarm; + unsigned long flags; struct clk_hw hw; struct clk_hw *int_osc; @@ -467,22 +472,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) } while ((date != readl(chip->base + SUN6I_RTC_YMD)) || (time != readl(chip->base + SUN6I_RTC_HMS))); + if (chip->flags & RTC_LINEAR_DAY) { + /* + * Newer chips store a linear day number, the manual + * does not mandate any epoch base. The BSP driver uses + * the UNIX epoch, let's just copy that, as it's the + * easiest anyway. + */ + rtc_time64_to_tm((date & 0xffff) * SECS_PER_DAY, rtc_tm); + } else { + rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); + rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date) - 1; + rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + rtc_tm->tm_year += SUN6I_YEAR_OFF; + } + rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time); rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); - rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); - rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); - rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); - - rtc_tm->tm_mon -= 1; - - /* - * switch from (data_year->min)-relative offset to - * a (1900)-relative one - */ - rtc_tm->tm_year += SUN6I_YEAR_OFF; - return 0; } @@ -567,20 +580,27 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) u32 date = 0; u32 time = 0; - rtc_tm->tm_year -= SUN6I_YEAR_OFF; - rtc_tm->tm_mon += 1; - - date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | - SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | - SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); - - if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) - date |= SUN6I_LEAP_SET_VALUE(1); - time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour); + if (chip->flags & RTC_LINEAR_DAY) { + rtc_tm->tm_sec = 0; + rtc_tm->tm_min = 0; + rtc_tm->tm_hour = 0; + date = div_u64(rtc_tm_to_time64(rtc_tm), SECS_PER_DAY); + } else { + rtc_tm->tm_year -= SUN6I_YEAR_OFF; + rtc_tm->tm_mon += 1; + + date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | + SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | + SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); + + if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) + date |= SUN6I_LEAP_SET_VALUE(1); + } + /* Check whether registers are writable */ if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL, SUN6I_LOSC_CTRL_ACC_MASK, 50)) { @@ -674,6 +694,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev); + chip->irq = platform_get_irq(pdev, 0); if (chip->irq < 0) return chip->irq; -- 2.17.6