diff mbox series

[3/4] rtc: rx8025: set date in a single i2c transaction

Message ID 20210917064604.3912-4-matt@traverse.com.au
State Accepted
Commit 771fc0c0798a3c2f9d0c51cdf8f1f2eff90dbafb
Headers show
Series Add EPSON RX8035 RTC support | expand

Commit Message

Mathew McBride Sept. 17, 2021, 6:46 a.m. UTC
The RX8025/RX8035 does not like having it's time registers
set byte-by-byte in separate I2C transactions.

From the note at the top of the file, it appears
target-dependent workarounds have been used in the
past for this.

Resolve this by setting the time registers in a single
I2C transaction.

As part of this, also ensure the '24/12' flag in the RTC
is reset before writing the date (instead of after), otherwise
the RX8035 will clear the seconds and minutes registers.

Tested on Traverse Ten64 (NXP LS1088A) with RX8035.

Signed-off-by: Mathew McBride <matt@traverse.com.au>

---
 drivers/rtc/rx8025.c | 44 +++++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 21 deletions(-)

-- 
2.30.1

Comments

Tom Rini Oct. 3, 2021, 11:33 p.m. UTC | #1
On Fri, Sep 17, 2021 at 06:46:03AM +0000, Mathew McBride wrote:

> The RX8025/RX8035 does not like having it's time registers

> set byte-by-byte in separate I2C transactions.

> 

> From the note at the top of the file, it appears

> target-dependent workarounds have been used in the

> past for this.

> 

> Resolve this by setting the time registers in a single

> I2C transaction.

> 

> As part of this, also ensure the '24/12' flag in the RTC

> is reset before writing the date (instead of after), otherwise

> the RX8035 will clear the seconds and minutes registers.

> 

> Tested on Traverse Ten64 (NXP LS1088A) with RX8035.

> 

> Signed-off-by: Mathew McBride <matt@traverse.com.au>


Applied to u-boot/next, thanks!

-- 
Tom
diff mbox series

Patch

diff --git a/drivers/rtc/rx8025.c b/drivers/rtc/rx8025.c
index 09bf365f63..9423a1bb82 100644
--- a/drivers/rtc/rx8025.c
+++ b/drivers/rtc/rx8025.c
@@ -39,6 +39,7 @@  enum rx_model {
 #define RTC_DATE_REG_ADDR	0x04
 #define RTC_MON_REG_ADDR	0x05
 #define RTC_YR_REG_ADDR		0x06
+#define RTC_OFFSET_REG_ADDR	0x07
 
 #define RTC_CTL1_REG_ADDR	0x0e
 #define RTC_CTL2_REG_ADDR	0x0f
@@ -152,6 +153,19 @@  static int rx8025_rtc_get(struct udevice *dev, struct rtc_time *tmp)
  */
 static int rx8025_rtc_set(struct udevice *dev, const struct rtc_time *tmp)
 {
+	/* To work around the read/write cycle issue mentioned
+	 * at the top of this file, write all the time registers
+	 * in one I2C transaction
+	 */
+	u8 write_op[8];
+
+	/* 2412 flag must be set before doing a RTC write,
+	 * otherwise the seconds and minute register
+	 * will be cleared when the flag is set
+	 */
+	if (rtc_write(dev, RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412))
+		return -EIO;
+
 	DEBUGR("Set DATE: %4d-%02d-%02d (wday=%d)  TIME: %2d:%02d:%02d\n",
 	       tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
 	       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
@@ -159,28 +173,16 @@  static int rx8025_rtc_set(struct udevice *dev, const struct rtc_time *tmp)
 	if (tmp->tm_year < 1970 || tmp->tm_year > 2069)
 		printf("WARNING: year should be between 1970 and 2069!\n");
 
-	if (rtc_write(dev, RTC_YR_REG_ADDR, bin2bcd(tmp->tm_year % 100)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_MON_REG_ADDR, bin2bcd(tmp->tm_mon)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_DAY_REG_ADDR, bin2bcd(tmp->tm_wday)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_DATE_REG_ADDR, bin2bcd(tmp->tm_mday)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_HR_REG_ADDR, bin2bcd(tmp->tm_hour)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_MIN_REG_ADDR, bin2bcd(tmp->tm_min)))
-		return -EIO;
-
-	if (rtc_write(dev, RTC_SEC_REG_ADDR, bin2bcd(tmp->tm_sec)))
-		return -EIO;
+	write_op[RTC_SEC_REG_ADDR]  = bin2bcd(tmp->tm_sec);
+	write_op[RTC_MIN_REG_ADDR]  = bin2bcd(tmp->tm_min);
+	write_op[RTC_HR_REG_ADDR]   = bin2bcd(tmp->tm_hour);
+	write_op[RTC_DAY_REG_ADDR]	= bin2bcd(tmp->tm_wday);
+	write_op[RTC_DATE_REG_ADDR]	= bin2bcd(tmp->tm_mday);
+	write_op[RTC_MON_REG_ADDR]  = bin2bcd(tmp->tm_mon);
+	write_op[RTC_YR_REG_ADDR]	= bin2bcd(tmp->tm_year % 100);
+	write_op[RTC_OFFSET_REG_ADDR] = 0;
 
-	return rtc_write(dev, RTC_CTL1_REG_ADDR, RTC_CTL1_BIT_2412);
+	return dm_i2c_write(dev, 0, &write_op[0], 8);
 }
 
 /*