On 5/30/2023 9:41 AM, Joy Zou wrote:
Caution: This is an external email. Please take care when clicking links or 
opening attachments. When in doubt, report the message using the 'Report this 
email' button


Adding support for pcf2131 RTC chip.

The pcf2131 is similar to the pcf2127. The driver support rtc register
read/write by using rtc cmd and rtc date set/get by using date cmd.

Signed-off-by: Joy Zou <joy....@nxp.com>
---
  drivers/rtc/Kconfig   |  10 +++
  drivers/rtc/Makefile  |   1 +
  drivers/rtc/pcf2131.c | 189 ++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 200 insertions(+)
  create mode 100644 drivers/rtc/pcf2131.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 23173139e0..507dc6cbcb 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -64,6 +64,16 @@ config RTC_PCF2127
           has a selectable I2C-bus or SPI-bus, a backup battery switch-over 
circuit, a
           programmable watchdog function, a timestamp function, and many other 
features.

+config RTC_PCF2131
+       bool "Enable PCF2131 driver"
+       depends on DM_RTC
+       help
+         The PCF2131 is a CMOS Real Time Clock (RTC) and calendar with an 
integrated
+         Temperature Compensated Crystal (Xtal) Oscillator (TCXO) and a 32.768 
kHz quartz
+         crystal optimized for very high accuracy and very low power 
consumption. The PCF2127
+         has a selectable I2C-bus or SPI-bus, a backup battery switch-over 
circuit, a
+         programmable watchdog function, a timestamp function, and many other 
features.
+
  config RTC_DS1307
         bool "Enable DS1307 driver"
         depends on DM_RTC
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 308fab8da9..722f2be98f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_RTC_MV) += mvrtc.o
  obj-$(CONFIG_RTC_MXS) += mxsrtc.o
  obj-$(CONFIG_RTC_PCF8563) += pcf8563.o
  obj-$(CONFIG_RTC_PCF2127) += pcf2127.o
+obj-$(CONFIG_RTC_PCF2131) += pcf2131.o
  obj-$(CONFIG_RTC_PL031) += pl031.o
  obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
  obj-$(CONFIG_RTC_RV3028) += rv3028.o
diff --git a/drivers/rtc/pcf2131.c b/drivers/rtc/pcf2131.c
new file mode 100644
index 0000000000..8b9c17a2c8
--- /dev/null
+++ b/drivers/rtc/pcf2131.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * The NXP PCF2131 RTC uboot driver.
+ * Copyright 2023 NXP
+ * Date & Time support for PCF2131 RTC
+ */
+
+/*      #define DEBUG   */

Drop this line.

+
+#include <common.h>
+#include <command.h>
+#include <dm.h>
+#include <i2c.h>
+#include <log.h>
+#include <rtc.h>
+
+#define PCF2131_REG_CTRL1               0x00
+#define PCF2131_BIT_CTRL1_STOP          BIT(5)
+#define PCF2131_BIT_CTRL1_100TH_S_DIS   BIT(4)
+#define PCF2131_REG_CTRL2               0x01
+#define PCF2131_REG_CTRL3               0x02
+#define PCF2131_REG_SR_RESET            0x05
+#define PCF2131_SR_VAL_Clr_Pres         0xa4
+#define PCF2131_REG_SC                  0x07
+#define PCF2131_REG_MN                  0x08
+#define PCF2131_REG_HR                  0x09
+#define PCF2131_REG_DM                  0x0a
+#define PCF2131_REG_DW                  0x0b
+#define PCF2131_REG_MO                  0x0c
+#define PCF2131_REG_YR                  0x0d
+
+static int pcf2131_rtc_read(struct udevice *dev, uint offset, u8 *buffer, uint 
len)
+{
+       struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
+       struct i2c_msg msg;
+       int ret;
+
+       /* Set the address of the start register to be read */
+       ret = dm_i2c_write(dev, offset, NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       /* Read register's data */
+       msg.addr = chip->chip_addr;
+       msg.flags |= I2C_M_RD;
+       msg.len = len;
+       msg.buf = buffer;
+
+       return dm_i2c_xfer(dev, &msg, 1);
+}
+
+static int pcf2131_rtc_lock(struct udevice *dev)
+{
+       int ret = 0;
+       uchar buf[6] = { PCF2131_REG_CTRL1 };
+
+       ret = pcf2131_rtc_read(dev, PCF2131_REG_CTRL1, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       buf[PCF2131_REG_CTRL1] |= PCF2131_BIT_CTRL1_STOP;
+       ret = dm_i2c_write(dev, PCF2131_REG_CTRL1, &buf[PCF2131_REG_CTRL1], 1);
+       if (ret < 0)
+               return ret;
+
+       buf[PCF2131_REG_SR_RESET] = PCF2131_SR_VAL_Clr_Pres;
+       ret = dm_i2c_write(dev, PCF2131_REG_SR_RESET, 
&buf[PCF2131_REG_SR_RESET], 1);
+       return ret;

Just "return dm_i2c_write..." is ok.

+}
+
+static int pcf2131_rtc_unlock(struct udevice *dev)
+{
+       int ret = 0;
+       uchar buf[6] = { PCF2131_REG_CTRL1 };
+
+       ret = pcf2131_rtc_read(dev, PCF2131_REG_CTRL1, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       buf[PCF2131_REG_CTRL1] &= ~PCF2131_BIT_CTRL1_STOP;
+       ret = dm_i2c_write(dev, PCF2131_REG_CTRL1, &buf[PCF2131_REG_CTRL1], 1);
+       return ret;

Ditto.

+}
+
+static int pcf2131_rtc_write(struct udevice *dev, uint offset,
+                            const u8 *buffer, uint len)
+{
+       int ret = 0;
+
+       ret = pcf2131_rtc_lock(dev);
+       if (ret < 0)
+               return ret;
+
+       ret = dm_i2c_write(dev, offset, buffer, len);
+       if (ret < 0)
+               return ret;
+
+       ret = pcf2131_rtc_unlock(dev);
+       return ret;


Ditto.

+}
+
+static int pcf2131_rtc_set(struct udevice *dev, const struct rtc_time *tm)
+{ > +       uchar buf[7] = {0};

No need init is to 0?

+       int i = 0, ret;
+
+       /* hours, minutes and seconds */
+       buf[i++] = bin2bcd(tm->tm_sec);
+       buf[i++] = bin2bcd(tm->tm_min);
+       buf[i++] = bin2bcd(tm->tm_hour);
+       buf[i++] = bin2bcd(tm->tm_mday);
+       buf[i++] = tm->tm_wday & 0x07;
+
+       /* month, 1 - 12 */
+       buf[i++] = bin2bcd(tm->tm_mon);
+
+       /* year */
+       buf[i++] = bin2bcd(tm->tm_year % 100);
+
+       ret = pcf2131_rtc_lock(dev);
+       if (ret < 0)
+               return ret;
+
+       /* write register's data */
+       ret = dm_i2c_write(dev, PCF2131_REG_SC, buf, i);
+       if (ret < 0)
+               return ret;
+
+       ret = pcf2131_rtc_unlock(dev);
+       return ret;

Just "return pfc2131_rtc_unlock..." is ok.

+}
+
+static int pcf2131_rtc_get(struct udevice *dev, struct rtc_time *tm)
+{
+       int ret = 0;
+       uchar buf[16] = { PCF2131_REG_CTRL1 };

No need initialize buf?

+
+       ret = pcf2131_rtc_read(dev, PCF2131_REG_CTRL1, buf, sizeof(buf));
+       if (ret < 0)
+               return ret;
+
+       if (buf[PCF2131_REG_CTRL3] & 0x04)
+               puts("### Warning: RTC Low Voltage - date/time not reliable\n");
+
+       tm->tm_sec  = bcd2bin(buf[PCF2131_REG_SC] & 0x7F);
+       tm->tm_min  = bcd2bin(buf[PCF2131_REG_MN] & 0x7F);
+       tm->tm_hour = bcd2bin(buf[PCF2131_REG_HR] & 0x3F);
+       tm->tm_mday = bcd2bin(buf[PCF2131_REG_DM] & 0x3F);
+       tm->tm_mon  = bcd2bin(buf[PCF2131_REG_MO] & 0x1F);
+       tm->tm_year = bcd2bin(buf[PCF2131_REG_YR]) + 1900;
+       if (tm->tm_year < 1970)
+               tm->tm_year += 100;     /* assume we are in 1970...2069 */
+       tm->tm_wday = buf[PCF2131_REG_DW] & 0x07;
+       tm->tm_yday = 0;
+       tm->tm_isdst = 0;
+
+       debug("Get DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%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 ret;
+}
+
+static int pcf2131_rtc_reset(struct udevice *dev)
+{
+       /*Doing nothing here*/
+
+       return 0;
+}
+
+static const struct rtc_ops pcf2131_rtc_ops = {
+       .get = pcf2131_rtc_get,
+       .set = pcf2131_rtc_set,
+       .reset = pcf2131_rtc_reset,
+       .read = pcf2131_rtc_read,
+       .write = pcf2131_rtc_write,
+};
+
+static const struct udevice_id pcf2131_rtc_ids[] = {
+       { .compatible = "nxp,pcf2131" },
+       { }
+};
+
+U_BOOT_DRIVER(rtc_pcf2131) = {
+       .name   = "rtc-pcf2131",
+       .id     = UCLASS_RTC,
+       .of_match = pcf2131_rtc_ids,
+       .ops    = &pcf2131_rtc_ops,
+};
--
2.37.1


Regards,
Peng.

Reply via email to