Add support for the Microcrystal RV8263 and compatible RTCs. The driver's name was taken from linux. It should work with any NXP PCF85063 compatible RTCs. It was tested with a RV8263.
Signed-off-by: Michael Walle <[email protected]> --- drivers/rtc/Kconfig | 8 +++ drivers/rtc/Makefile | 1 + drivers/rtc/pcf85063.c | 107 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 drivers/rtc/pcf85063.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ed903999f06..2336f2e57c9 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -161,6 +161,14 @@ config RTC_MAX313XX - Temperature sensor - CLKOUT generation +config RTC_PCF85063 + tristate "Enable PCF85063 driver" + depends on DM_I2C + depends on DM_RTC + help + If you say yes here you get support for the NXP PCF85063 RTC + and compatible chips. + config RTC_PCF8563 tristate "Philips PCF8563" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index a4ede413cd1..9d84aa836a1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_RTC_MC146818) += mc146818.o obj-$(CONFIG_MCFRTC) += mcfrtc.o obj-$(CONFIG_RTC_MV) += mvrtc.o obj-$(CONFIG_RTC_MXS) += mxsrtc.o +obj-$(CONFIG_RTC_PCF85063) += pcf85063.o obj-$(CONFIG_RTC_PCF8563) += pcf8563.o obj-$(CONFIG_RTC_PCF2127) += pcf2127.o obj-$(CONFIG_RTC_PL031) += pl031.o diff --git a/drivers/rtc/pcf85063.c b/drivers/rtc/pcf85063.c new file mode 100644 index 00000000000..737d4547aca --- /dev/null +++ b/drivers/rtc/pcf85063.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PCF85063 and compatible I2C RTC driver + * + * Copyright (c) 2025 Kontron Europe GmbH. + */ + +#include <dm.h> +#include <i2c.h> +#include <rtc.h> +#include <dm/device_compat.h> + +#define PCF85063_REG_CTRL1 0x00 /* status */ +#define PCF85063_REG_CTRL1_SR 0x58 + +#define PCF85063_REG_SC 0x04 /* datetime */ +#define PCF85063_REG_SC_OS 0x80 + +static int pcf85063_get_time(struct udevice *dev, struct rtc_time *tm) +{ + u8 regs[7]; + int ret; + + ret = dm_i2c_read(dev, PCF85063_REG_SC, regs, sizeof(regs)); + if (ret) + return ret; + + if (regs[0] & PCF85063_REG_SC_OS) { + dev_err(dev, "Power loss detected, Invalid time\n"); + return -EINVAL; + } + + 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 pcf85063_set_time(struct udevice *dev, const struct rtc_time *tm) +{ + u8 regs[7]; + + 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); + + return dm_i2c_write(dev, PCF85063_REG_SC, regs, sizeof(regs)); +} + +static int pcf85063_reset(struct udevice *dev) +{ + return dm_i2c_reg_write(dev, PCF85063_REG_CTRL1, PCF85063_REG_CTRL1_SR); +} + +static int pcf85063_read(struct udevice *dev, unsigned int offset, u8 *buf, + unsigned int len) +{ + return dm_i2c_read(dev, offset, buf, len); +} + +static int pcf85063_write(struct udevice *dev, unsigned int offset, + const u8 *buf, unsigned int len) +{ + return dm_i2c_write(dev, offset, buf, len); +} + +static const struct rtc_ops pcf85063_rtc_ops = { + .get = pcf85063_get_time, + .set = pcf85063_set_time, + .reset = pcf85063_reset, + .read = pcf85063_read, + .write = pcf85063_write, +}; + +static int pcf85063_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 pcf85063_of_id[] = { + { .compatible = "microcrystal,rv8263" }, + { } +}; + +U_BOOT_DRIVER(rtc_pcf85063) = { + .name = "rtc-pcf85063", + .id = UCLASS_RTC, + .probe = pcf85063_probe, + .of_match = pcf85063_of_id, + .ops = &pcf85063_rtc_ops, +}; -- 2.47.3

