From: Michael Walle <mwalle@kernel.org>
To: Tom Rini <trini@konsulko.com>
Cc: u-boot@lists.denx.de, Michael Walle <mwalle@kernel.org>
Subject: [PATCH 2/2] drivers: rtc: add RV3032 support
Date: Fri, 14 Nov 2025 16:12:48 +0100 [thread overview]
Message-ID: <20251114151255.2008694-3-mwalle@kernel.org> (raw)
In-Reply-To: <20251114151255.2008694-1-mwalle@kernel.org>
Add support for the Microcrystal RV3032 RTC.
Signed-off-by: Michael Walle <mwalle@kernel.org>
---
drivers/rtc/Kconfig | 7 +++
drivers/rtc/Makefile | 1 +
drivers/rtc/rv3032.c | 121 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 129 insertions(+)
create mode 100644 drivers/rtc/rv3032.c
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2336f2e57c9..c6c6a02221a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -194,6 +194,13 @@ config RTC_RV3029
This driver supports reading and writing the RTC/calendar and the
battery-baced SRAM section.
+config RTC_RV3032
+ bool "Enable RV3032 driver"
+ depends on DM_RTC
+ help
+ If you say yes here you get support for the Micro Crystal RV3032
+ RTC.
+
config RTC_RV8803
bool "Enable RV8803 driver"
depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 9d84aa836a1..9df373d5148 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_RTC_PL031) += pl031.o
obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
obj-$(CONFIG_RTC_RV3028) += rv3028.o
obj-$(CONFIG_RTC_RV3029) += rv3029.o
+obj-$(CONFIG_RTC_RV3032) += rv3032.o
obj-$(CONFIG_RTC_RV8803) += rv8803.o
obj-$(CONFIG_RTC_RX8025) += rx8025.o
obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
diff --git a/drivers/rtc/rv3032.c b/drivers/rtc/rv3032.c
new file mode 100644
index 00000000000..87ff5204e73
--- /dev/null
+++ b/drivers/rtc/rv3032.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Micro Crystal RV3032 I2C RTC driver
+ *
+ * Copyright (c) 2025 Kontron Europe GmbH.
+ */
+
+#include <dm.h>
+#include <i2c.h>
+#include <rtc.h>
+#include <dm/device_compat.h>
+
+#define RV3032_REG_SEC 0x01
+#define RV3032_REG_STATUS 0x0d
+#define RV3032_REG_STATUS_VLF BIT(0)
+#define RV3032_REG_STATUS_PORF BIT(1)
+
+static int rv3032_get_time(struct udevice *dev, struct rtc_time *tm)
+{
+ int ret, status;
+ u8 regs[7];
+
+ status = dm_i2c_reg_read(dev, RV3032_REG_STATUS);
+ if (status < 0)
+ return status;
+
+ if (status & (RV3032_REG_STATUS_PORF | RV3032_REG_STATUS_VLF)) {
+ dev_err(dev, "Power loss detected, Invalid time\n");
+ return -EINVAL;
+ }
+
+ ret = dm_i2c_read(dev, RV3032_REG_SEC, regs, sizeof(regs));
+ if (ret)
+ return ret;
+
+ tm->tm_sec = bcd2bin(regs[0] & 0x7f);
+ tm->tm_min = bcd2bin(regs[1] & 0x7f);
+ tm->tm_hour = bcd2bin(regs[2] & 0x3f);
+ tm->tm_mday = bcd2bin(regs[3] & 0x3f);
+ tm->tm_wday = regs[4] & 0x07;
+ tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
+ tm->tm_year = bcd2bin(regs[6]) + 2000;
+
+ return 0;
+}
+
+static int rv3032_set_time(struct udevice *dev, const struct rtc_time *tm)
+{
+ u8 regs[7];
+ int ret;
+
+ if (tm->tm_year < 2000 || tm->tm_year > 2099) {
+ dev_err(dev, "Year must be between 2000 and 2099.\n");
+ return -EINVAL;
+ }
+
+ regs[0] = bin2bcd(tm->tm_sec);
+ regs[1] = bin2bcd(tm->tm_min);
+ regs[2] = bin2bcd(tm->tm_hour);
+ regs[3] = bin2bcd(tm->tm_mday);
+ regs[4] = tm->tm_wday;
+ regs[5] = bin2bcd(tm->tm_mon + 1);
+ regs[6] = bin2bcd(tm->tm_year % 100);
+
+ ret = dm_i2c_write(dev, RV3032_REG_SEC, regs, sizeof(regs));
+ if (ret)
+ return ret;
+
+ return dm_i2c_reg_clrset(dev, RV3032_REG_STATUS,
+ RV3032_REG_STATUS_PORF | RV3032_REG_STATUS_VLF,
+ 0);
+}
+
+static int rv3032_read(struct udevice *dev, unsigned int offset, u8 *buf,
+ unsigned int len)
+{
+ return dm_i2c_read(dev, offset, buf, len);
+}
+
+static int rv3032_write(struct udevice *dev, unsigned int offset,
+ const u8 *buf, unsigned int len)
+{
+ return dm_i2c_write(dev, offset, buf, len);
+}
+
+static int rv3032_reset(struct udevice *dev)
+{
+ /*
+ * There is no reset, but the "date reset" command needs this op to
+ * actually set the default time
+ */
+ return 0;
+}
+
+static const struct rtc_ops rv3032_rtc_ops = {
+ .get = rv3032_get_time,
+ .set = rv3032_set_time,
+ .read = rv3032_read,
+ .write = rv3032_write,
+ .reset = rv3032_reset,
+};
+
+static int rv3032_probe(struct udevice *dev)
+{
+ i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS | DM_I2C_CHIP_WR_ADDRESS);
+
+ return 0;
+}
+
+static const struct udevice_id rv3032_of_id[] = {
+ { .compatible = "microcrystal,rv3032" },
+ { }
+};
+
+U_BOOT_DRIVER(rtc_rv3032) = {
+ .name = "rtc-rv3032",
+ .id = UCLASS_RTC,
+ .probe = rv3032_probe,
+ .of_match = rv3032_of_id,
+ .ops = &rv3032_rtc_ops,
+};
--
2.47.3
prev parent reply other threads:[~2025-11-14 15:13 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-14 15:12 [PATCH 0/2] Add support for two RTCs Michael Walle
2025-11-14 15:12 ` [PATCH 1/2] drivers: rtc: add PCF85063 support Michael Walle
2025-11-14 15:22 ` Tom Rini
2025-11-17 8:13 ` Michael Walle
2025-11-17 13:30 ` Tom Rini
2025-11-14 15:12 ` Michael Walle [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251114151255.2008694-3-mwalle@kernel.org \
--to=mwalle@kernel.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.