From patchwork Thu Jul 29 11:36:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 1511186 X-Patchwork-Delegate: monstr@monstr.eu Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=monstr-eu.20150623.gappssmtp.com header.i=@monstr-eu.20150623.gappssmtp.com header.a=rsa-sha256 header.s=20150623 header.b=u9ZlAtGc; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Gb7mj664jz9sSs for ; Thu, 29 Jul 2021 21:37:25 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2C0B582EBD; Thu, 29 Jul 2021 13:36:59 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=monstr-eu.20150623.gappssmtp.com header.i=@monstr-eu.20150623.gappssmtp.com header.b="u9ZlAtGc"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DB40582E6A; Thu, 29 Jul 2021 13:36:36 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C2E4682EB5 for ; Thu, 29 Jul 2021 13:36:31 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=xilinx.com Authentication-Results: phobos.denx.de; spf=none smtp.mailfrom=monstr@monstr.eu Received: by mail-ed1-x52b.google.com with SMTP id h8so7764833ede.4 for ; Thu, 29 Jul 2021 04:36:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=monstr-eu.20150623.gappssmtp.com; s=20150623; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Y0J7tbiOQ7M8C2BvHn3G9YLGMJN3L4XswpM04b9AXGc=; b=u9ZlAtGcwnOwua3TjUZ8nx88/TytptDUucmywnUzQuolhdGbW0Mj40VVH4NyosUXxO UIjOfxNxkvjIGY79JHNGntNlXRd0mB1hCfWr0p3BseJhfX8l8hTsdMsmDox7Miqu9nW+ Iu+xokXZsPzLJgBCqx6TYi/EPZfZHFbxFk+uefSgwuXqMltOWX5CG44rhTCySy8xFQMs zrUYPDwr0U08YM0GSOd2zH22DNbpiIl9RqWVKtc+H5T7kj3YMz3HIfkLnwaTS57I4QlQ azRvLum8YKm0N45aFRhhvL0d24RS3T3RthonwaR5Ar4PaQd9eoBekMy+1d0lDTn/BKtF XhWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=Y0J7tbiOQ7M8C2BvHn3G9YLGMJN3L4XswpM04b9AXGc=; b=P7VAM/za9yEpdUrVR9A3B18t3K+nzMH9v2t9R7toBxGJ9CazBwayn8Gz3dMOcnYnFK yk6/ONRslnmfHvtDlO1lfO+iBqeqaGHhWECU1UmunqxJCLeHaRkOV96B/haVAsAP4zp3 KgasxhBWaWfknyK5HFviOyl9RRPdP2FVNIcpMWL3wuih6n+vRWbMA8Y1AGSlr7LM6+ko 7XiV5pfjq9YzmQKoHh7v910F1OFI8f0pt9anUIXU70becK4TtaPD0cjdGAtlLY/Q7rYH qb5k5XgD8X7/tkPmD0reu2hFK1xczi4G5tvfijxBotTR48vc9RRO3R75MR2QdFg/FF1y 5gcQ== X-Gm-Message-State: AOAM531mjOPu9hU1KhO1o4BMAxfQIJootY+gNGsOd95pI2Ye9HovoekO syBq69TuhPKB+TWoB15674zso+W4cLD+G6IR X-Google-Smtp-Source: ABdhPJzXOZf0ygacrN7hFCyt+m1/GeSEf5bpxFqfabhj74AsfBhvlB0sg93I4J0AoefjYlXaevTCzg== X-Received: by 2002:a05:6402:d2:: with SMTP id i18mr5516305edu.17.1627558591187; Thu, 29 Jul 2021 04:36:31 -0700 (PDT) Received: from localhost ([2a02:768:2307:40d6:f666:9af6:3fed:e53b]) by smtp.gmail.com with ESMTPSA id t25sm1091500edq.29.2021.07.29.04.36.30 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Thu, 29 Jul 2021 04:36:30 -0700 (PDT) From: Michal Simek To: u-boot@lists.denx.de, git@xilinx.com Cc: Bin Meng , Dario Binacchi , Heiko Schocher , Heinrich Schuchardt , =?utf-8?q?Marek_Beh=C3=BAn?= , Michal Simek , Stefan Roese , "Ying-Chun Liu (PaulLiu)" Subject: [PATCH 3/4] rtc: zynqmp: Add support for ZynqMP RTC Date: Thu, 29 Jul 2021 13:36:24 +0200 Message-Id: <7fb0337f46fd574588f23bfc59ebbc7d9c2770ce.1627558582.git.michal.simek@xilinx.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean The whole driver logic is taken from Linux kernel but only set/get/reset functions are implemented. When device is power off RTC is power out of battery. Signed-off-by: Michal Simek --- MAINTAINERS | 1 + drivers/rtc/Kconfig | 7 ++ drivers/rtc/Makefile | 1 + drivers/rtc/zynqmp_rtc.c | 158 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 drivers/rtc/zynqmp_rtc.c diff --git a/MAINTAINERS b/MAINTAINERS index 8a18b3b6d939..5734ebb80363 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,7 @@ F: drivers/mtd/nand/raw/zynq_nand.c F: drivers/net/phy/xilinx_phy.c F: drivers/net/zynq_gem.c F: drivers/serial/serial_zynq.c +F: drivers/rtc/zynqmp_rtc.c F: drivers/spi/zynq_qspi.c F: drivers/spi/zynq_spi.c F: drivers/timer/cadence-ttc.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index cbdfddb80f66..b6692e62df1c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -195,4 +195,11 @@ config RTC_DAVINCI Say "yes" here to support the on chip real time clock present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx. +config RTC_ZYNQMP + bool "Enable ZynqMP RTC driver" + depends on ARCH_ZYNQMP + help + Say "yes" here to support the on chip real time clock + present on Xilinx ZynqMP SoC. + endmenu diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 331a49ab599a..d621be622848 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_RTC_STM32) += stm32_rtc.o obj-$(CONFIG_SANDBOX) += sandbox_rtc.o obj-$(CONFIG_RTC_X1205) += x1205.o obj-$(CONFIG_RTC_ABX80X) += abx80x.o +obj-$(CONFIG_RTC_ZYNQMP) += zynqmp_rtc.o diff --git a/drivers/rtc/zynqmp_rtc.c b/drivers/rtc/zynqmp_rtc.c new file mode 100644 index 000000000000..ab9b93ca9793 --- /dev/null +++ b/drivers/rtc/zynqmp_rtc.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021, Xilinx, Inc. + */ + +#define LOG_CATEGORY UCLASS_RTC + +#include +#include +#include +#include + +/* RTC Registers */ +#define RTC_SET_TM_WR 0x00 +#define RTC_SET_TM_RD 0x04 +#define RTC_CALIB_WR 0x08 +#define RTC_CUR_TM 0x10 +#define RTC_INT_STS 0x20 +#define RTC_CTRL 0x40 + +#define RTC_INT_SEC BIT(0) +#define RTC_BATT_EN BIT(31) +#define RTC_CALIB_DEF 0x198233 +#define RTC_CALIB_MASK 0x1FFFFF + +struct zynqmp_rtc_priv { + fdt_addr_t base; + unsigned int calibval; +}; + +static int zynqmp_rtc_get(struct udevice *dev, struct rtc_time *tm) +{ + struct zynqmp_rtc_priv *priv = dev_get_priv(dev); + u32 status; + unsigned long read_time; + + status = readl(priv->base + RTC_INT_STS); + + if (status & RTC_INT_SEC) { + /* + * RTC has updated the CURRENT_TIME with the time written into + * SET_TIME_WRITE register. + */ + read_time = readl(priv->base + RTC_CUR_TM); + } else { + /* + * Time written in SET_TIME_WRITE has not yet updated into + * the seconds read register, so read the time from the + * SET_TIME_WRITE instead of CURRENT_TIME register. + * Since we add +1 sec while writing, we need to -1 sec while + * reading. + */ + read_time = readl(priv->base + RTC_SET_TM_RD) - 1; + } + + rtc_to_tm(read_time, tm); + + return 0; +} + +static int zynqmp_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + struct zynqmp_rtc_priv *priv = dev_get_priv(dev); + unsigned long new_time = 0; + + if (tm) + /* + * The value written will be updated after 1 sec into the + * seconds read register, so we need to program time +1 sec + * to get the correct time on read. + */ + new_time = rtc_mktime(tm) + 1; + + /* + * Writing into calibration register will clear the Tick Counter and + * force the next second to be signaled exactly in 1 second period + */ + priv->calibval &= RTC_CALIB_MASK; + writel(priv->calibval, (priv->base + RTC_CALIB_WR)); + + writel(new_time, priv->base + RTC_SET_TM_WR); + + /* + * Clear the rtc interrupt status register after setting the + * time. During a read_time function, the code should read the + * RTC_INT_STATUS register and if bit 0 is still 0, it means + * that one second has not elapsed yet since RTC was set and + * the current time should be read from SET_TIME_READ register; + * otherwise, CURRENT_TIME register is read to report the time + */ + writel(RTC_INT_SEC, priv->base + RTC_INT_STS); + + return 0; +} + +static int zynqmp_rtc_reset(struct udevice *dev) +{ + return zynqmp_rtc_set(dev, NULL); +} + +static int zynqmp_rtc_init(struct udevice *dev) +{ + struct zynqmp_rtc_priv *priv = dev_get_priv(dev); + u32 rtc_ctrl; + + /* Enable RTC switch to battery when VCC_PSAUX is not available */ + rtc_ctrl = readl(priv->base + RTC_CTRL); + rtc_ctrl |= RTC_BATT_EN; + writel(rtc_ctrl, priv->base + RTC_CTRL); + + /* + * Based on crystal freq of 33.330 KHz + * set the seconds counter and enable, set fractions counter + * to default value suggested as per design spec + * to correct RTC delay in frequency over period of time. + */ + priv->calibval &= RTC_CALIB_MASK; + writel(priv->calibval, (priv->base + RTC_CALIB_WR)); + + return 0; +} + +static int zynqmp_rtc_probe(struct udevice *dev) +{ + struct zynqmp_rtc_priv *priv = dev_get_priv(dev); + int ret; + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->calibval = dev_read_u32_default(dev, "calibration", + RTC_CALIB_DEF); + + ret = zynqmp_rtc_init(dev); + + return ret; +} + +static const struct rtc_ops zynqmp_rtc_ops = { + .get = zynqmp_rtc_get, + .set = zynqmp_rtc_set, + .reset = zynqmp_rtc_reset, +}; + +static const struct udevice_id zynqmp_rtc_ids[] = { + { .compatible = "xlnx,zynqmp-rtc" }, + { } +}; + +U_BOOT_DRIVER(rtc_zynqmp) = { + .name = "rtc-zynqmp", + .id = UCLASS_RTC, + .probe = zynqmp_rtc_probe, + .of_match = zynqmp_rtc_ids, + .ops = &zynqmp_rtc_ops, + .priv_auto = sizeof(struct zynqmp_rtc_priv), +};