From patchwork Fri Jul 10 15:50:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 11656927 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D913B618 for ; Fri, 10 Jul 2020 15:51:54 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B073520720 for ; Fri, 10 Jul 2020 15:51:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kZTJrDfY"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=amarulasolutions.com header.i=@amarulasolutions.com header.b="Fa2M0CVe" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B073520720 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=GZaLR98w15SxwVSQ927uK2j15+wkCDKLmOYo/ZVpGBc=; b=kZTJrDfYoxBDypj+3m9Q/u3C3 /nn4mxwmDNh+fK3bSSpWGLGEgGVayF2vL4xqUe4Sim3hcUOxNg6/4A697f8gwVkc7D93VkksJYo1j OIp5FK5q8i3hRsfH2NzROXihdStesG1OenKUaaIfp6D0KB77CvVLFjvn/t3/yHcOE8tK+3TjtDDWq 3HZU6e7ExQeihfEK4cHpIgk/nMgNPbw9Y6OoZjN1rO7s1wFlaS+0ScIogqCUbQOQixe1z8YNgStdX AtRWdiNJUygVWqz9XWofaiEhTuVnv8Vwz+xY3dffq69eef4aR7nKtC2DBSR+oX4p6zNfE+TW6q79X b+EtSru9Q==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jtvJY-0004od-Pv; Fri, 10 Jul 2020 15:51:52 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jtvJW-0004nB-Gs for linux-rockchip@lists.infradead.org; Fri, 10 Jul 2020 15:51:51 +0000 Received: by mail-pl1-x644.google.com with SMTP id x8so2409572plm.10 for ; Fri, 10 Jul 2020 08:51:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FSewoexwVyBwrPVuoElI4BFd+yaXthXy6Cp0PRRDxzg=; b=Fa2M0CVefNY9xfKkABsLhlO93Z93mxnwrGvtIX7G40O1biDmUGLepJVHhYoVw270ZT 4GNbwbjhVaH9cqkjc+CnDYl7G4ZEYaxddI7lH6BBYJ92/GySIW96kSgqD3HPYh2cSuDB K7pm7bvq1+4N6r4URLOvHiq+bw/Oh/1TYvvmE= 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=FSewoexwVyBwrPVuoElI4BFd+yaXthXy6Cp0PRRDxzg=; b=PRqVMCwlUV9dno84v9HJAO5zUyGl/OSpQjpSyJarZIMZKbNCu0Re2lA6GHbz0XDCZq E2NLrMd36XXdZtLqMkN8ppcC0N2PjqLsHQUVUpadQNin6t6XRyN0ioEq5+ZbrWHJLk28 BpvloDSLLEiLT4r+Px4B7trGwYsmSUqto+qjpkTbeYOO8MSOILKpzuCM4s9JfSpU6lr1 A/rszTlDwFknlR7xI51tlVgt1pD0c0NvQ6k0YtDwwpx+mQkFKBUwWjsA2AUiAWeb0JJK piHezNAsHnJYNKvPPOsFz+DoSyqXhWGzbcKAG0viyNUTV1RzpdoWPDbt7nj9bAlIXYae c3LQ== X-Gm-Message-State: AOAM5303kIWlnLTdrQTZfg6KBlgPxlDq2OzJsmlQibfEhW64pJyrgk56 JVk263131TlFWWJ0yM++jtjKyA== X-Google-Smtp-Source: ABdhPJy6QtfLUsVNpbqBeJpmLL+g36Ko9uJXGThP2YiEEqOMefDpC0eJnI3N8jhMqkckOs1nU4EzFA== X-Received: by 2002:a17:90a:a608:: with SMTP id c8mr6092496pjq.114.1594396307866; Fri, 10 Jul 2020 08:51:47 -0700 (PDT) Received: from localhost.localdomain ([2405:201:c809:c7d5:a1d6:54e3:577a:ace0]) by smtp.gmail.com with ESMTPSA id lx2sm6398917pjb.16.2020.07.10.08.51.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 Jul 2020 08:51:47 -0700 (PDT) From: Jagan Teki To: Kever Yang , Philipp Tomsich , Simon Glass Subject: [PATCH v4 3/4] rtc: rk8xx: Add base support for the RK808 PMIC RTC Date: Fri, 10 Jul 2020 21:20:56 +0530 Message-Id: <20200710155057.310168-4-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200710155057.310168-1-jagan@amarulasolutions.com> References: <20200710155057.310168-1-jagan@amarulasolutions.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200710_115150_578609_175D6E26 X-CRM114-Status: GOOD ( 20.12 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from 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 -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: U-Boot-Denx , linux-rockchip@lists.infradead.org, linux-amarula , Jagan Teki , Suniel Mahesh Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org From: Suniel Mahesh Rockchip RK808 PMIC provides an integrated RTC module. It is commonly used with Rockchip SoCs. Add basic support to access date and time. Signed-off-by: Jagan Teki --- Change for v4: - rebase - style fixes - warning fixes drivers/rtc/Kconfig | 8 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rk808-rtc.c | 173 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 drivers/rtc/rk808-rtc.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 59e2fc44ba..a754d1b4f1 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -75,6 +75,14 @@ config RTC_ISL1208 This driver supports reading and writing the RTC/calendar and detects total power failures. +config RTC_RK808 + bool "Enable Rockchip RK8XX RTC driver" + depends on DM_RTC && PMIC_RK8XX + default y + help + Basic support for Rockchip RK808 PMIC Real Time Clock devices for + time and date. + config RTC_RV3029 bool "Enable RV3029 driver" depends on DM_RTC diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 12eb449583..63e2c3413d 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_PCF8563) += pcf8563.o obj-$(CONFIG_RTC_PCF2127) += pcf2127.o obj-$(CONFIG_RTC_PL031) += pl031.o obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o +obj-$(CONFIG_RTC_RK808) += rk808-rtc.o obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o obj-$(CONFIG_RTC_RV3029) += rv3029.o obj-$(CONFIG_RTC_RV8803) += rv8803.o diff --git a/drivers/rtc/rk808-rtc.c b/drivers/rtc/rk808-rtc.c new file mode 100644 index 0000000000..50cca4dd4b --- /dev/null +++ b/drivers/rtc/rk808-rtc.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * RTC driver for Rockchip RK808 PMIC. + * + * Copyright (C) 2020 Amarula Solutions(India). + * Suniel Mahesh + * + * Based on code from Linux kernel: + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * Author: Chris Zhong + * Author: Zhang Qing + * + * Date & Time support (no alarms and interrupts) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* RTC_CTRL_REG bitfields */ +#define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0) + +/* RK808 has a shadowed register for saving a "frozen" RTC time. + * When user setting "GET_TIME" to 1, the time will save in this shadowed + * register. If set "READSEL" to 1, user read rtc time register, actually + * get the time of that moment. If we need the real time, clr this bit. + */ + +#define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6) +#define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7) +#define RTC_STATUS_MASK 0xFE + +#define SECONDS_REG_MSK 0x7F +#define MINUTES_REG_MAK 0x7F +#define HOURS_REG_MSK 0x3F +#define DAYS_REG_MSK 0x3F +#define MONTHS_REG_MSK 0x1F +#define YEARS_REG_MSK 0xFF +#define WEEKS_REG_MSK 0x7 + +/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */ + +#define NUM_TIME_REGS (REG_WEEKS - REG_SECONDS + 1) + +static int rk808_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + u8 rtc_data[NUM_TIME_REGS]; + + debug("RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); + + rtc_data[0] = bin2bcd(tm->tm_sec); + rtc_data[1] = bin2bcd(tm->tm_min); + rtc_data[2] = bin2bcd(tm->tm_hour); + rtc_data[3] = bin2bcd(tm->tm_mday); + rtc_data[4] = bin2bcd(tm->tm_mon); + rtc_data[5] = bin2bcd(tm->tm_year - 2000); + rtc_data[6] = bin2bcd(tm->tm_wday); + + /* Stop RTC while updating the RTC registers */ + pmic_clrsetbits(dev->parent, REG_RTC_CTRL, 0, + BIT_RTC_CTRL_REG_STOP_RTC_M); + pmic_write(dev->parent, REG_SECONDS, rtc_data, NUM_TIME_REGS); + + /* Start RTC again */ + pmic_clrsetbits(dev->parent, REG_RTC_CTRL, + BIT_RTC_CTRL_REG_STOP_RTC_M, 0); + + return 0; +} + +static int rk808_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + u8 rtc_data[NUM_TIME_REGS]; + + /* Force an update of the shadowed registers right now */ + pmic_clrsetbits(dev->parent, REG_RTC_CTRL, 0, + BIT_RTC_CTRL_REG_RTC_GET_TIME); + + /* + * After we set the GET_TIME bit, the rtc time can't be read + * immediately. So we should wait up to 31.25 us, about one cycle of + * 32khz. If we clear the GET_TIME bit here, the time of i2c transfer + * certainly more than 31.25us: 16 * 2.5us at 400kHz bus frequency. + */ + pmic_clrsetbits(dev->parent, REG_RTC_CTRL, + BIT_RTC_CTRL_REG_RTC_GET_TIME, 0); + pmic_read(dev->parent, REG_SECONDS, rtc_data, NUM_TIME_REGS); + + tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK); + tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK); + tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK); + tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK); + tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)); + tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 2000; + tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK); + + /* + * RK808 PMIC RTC h/w counts/has 31 days in november. This is corrected + * when date cmd is invoked on prompt. checks for the current day and + * if it is 31 November, then adjusts it to 1 December. + * + * h/w also has weeks register which counts from 0 to 7(0(sun)-6(sat)). + * 7 is an unknown state, reset it back to 0(sun). + */ + if (tm->tm_mon == 11 && tm->tm_mday == 31) { + debug("correcting Nov 31st to Dec 1st (HW bug)\n"); + tm->tm_mon += 1; + tm->tm_mday = 1; + if (tm->tm_wday == 7) + tm->tm_wday = 0; + rk808_rtc_set(dev, tm); + } + + if (tm->tm_wday == 7) { + tm->tm_wday = 0; + rk808_rtc_set(dev, tm); + } + + debug("RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +static int rk808_rtc_reset(struct udevice *dev) +{ +/* Not needed */ + return 0; +} + +static int rk808_rtc_init(struct udevice *dev) +{ + struct rtc_time tm; + + /* start rtc running by default, and use shadowed timer. */ + pmic_clrsetbits(dev->parent, REG_RTC_CTRL, 0, + BIT_RTC_CTRL_REG_RTC_READSEL_M); + pmic_reg_write(dev->parent, REG_RTC_STATUS, RTC_STATUS_MASK); + + /* set init time */ + rk808_rtc_get(dev, &tm); + + return 0; +} + +static int rk808_rtc_probe(struct udevice *dev) +{ + rk808_rtc_init(dev); + + return 0; +} + +static const struct rtc_ops rk808_rtc_ops = { + .get = rk808_rtc_get, + .set = rk808_rtc_set, + .reset = rk808_rtc_reset, +}; + +U_BOOT_DRIVER(rk808_rtc) = { + .name = "rk808_rtc", + .id = UCLASS_RTC, + .ops = &rk808_rtc_ops, + .probe = rk808_rtc_probe, +};