diff mbox series

rtc: abx8xx: Add support for reading RAM

Message ID 20221202153519.888910-1-sean.anderson@seco.com
State Accepted
Delegated to: Tom Rini
Headers show
Series rtc: abx8xx: Add support for reading RAM | expand

Commit Message

Sean Anderson Dec. 2, 2022, 3:35 p.m. UTC
This adds support for reading the battery-backed memory present on these
RTCs. This modifies the read/write methods to access the RAM instead of
raw register offsets. No one was using these in-tree, so we should be
fine changing them.

We use the "standard" address space window to access the RAM. The
extension RAM address register has some reserved bits, but we write the
whole thing for simplicity (as these bits default to 0).

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/rtc/abx80x.c | 68 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 17 deletions(-)

Comments

Tom Rini Jan. 12, 2023, 3:17 p.m. UTC | #1
On Fri, Dec 02, 2022 at 10:35:19AM -0500, Sean Anderson wrote:

> This adds support for reading the battery-backed memory present on these
> RTCs. This modifies the read/write methods to access the RAM instead of
> raw register offsets. No one was using these in-tree, so we should be
> fine changing them.
> 
> We use the "standard" address space window to access the RAM. The
> extension RAM address register has some reserved bits, but we write the
> whole thing for simplicity (as these bits default to 0).
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>

Applied to u-boot/master, thanks!
diff mbox series

Patch

diff --git a/drivers/rtc/abx80x.c b/drivers/rtc/abx80x.c
index 528b06cbd6..823aff03f5 100644
--- a/drivers/rtc/abx80x.c
+++ b/drivers/rtc/abx80x.c
@@ -17,6 +17,7 @@ 
 #include <i2c.h>
 #include <rtc.h>
 #include <log.h>
+#include <linux/bitfield.h>
 
 #define ABX8XX_REG_HTH		0x00
 #define ABX8XX_REG_SC		0x01
@@ -88,6 +89,16 @@ 
 #define ABX8XX_TRICKLE_STANDARD_DIODE	0x8
 #define ABX8XX_TRICKLE_SCHOTTKY_DIODE	0x4
 
+#define ABX8XX_REG_EXTRAM	0x3f
+#define ABX8XX_EXTRAM_XADS	GENMASK(1, 0)
+
+#define ABX8XX_SRAM_BASE	0x40
+#define ABX8XX_SRAM_WIN_SIZE	0x40U
+#define ABX8XX_RAM_SIZE		256
+
+#define RAM_ADDR_LOWER		GENMASK(5, 0)
+#define RAM_ADDR_UPPER		GENMASK(7, 6)
+
 static u8 trickle_resistors[] = {0, 3, 6, 11};
 
 enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
@@ -112,29 +123,52 @@  static struct abx80x_cap abx80x_caps[] = {
 	[ABX80X] = {.pn = 0}
 };
 
-static int abx80x_rtc_read8(struct udevice *dev, unsigned int reg)
+static int abx80x_rtc_xfer(struct udevice *dev, unsigned int offset,
+			   u8 *val, unsigned int bytes, bool write)
 {
-	int ret = 0;
-	u8 buf;
+	int ret;
 
-	if (reg > 0xff)
+	if (offset + bytes > ABX8XX_RAM_SIZE)
 		return -EINVAL;
 
-	ret = dm_i2c_read(dev, reg, &buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
+	while (bytes) {
+		u8 extram, reg, len, lower, upper;
 
-	return buf;
+		lower = FIELD_GET(RAM_ADDR_LOWER, offset);
+		upper = FIELD_GET(RAM_ADDR_UPPER, offset);
+		extram = FIELD_PREP(ABX8XX_EXTRAM_XADS, upper);
+		reg = ABX8XX_SRAM_BASE + lower;
+		len = min(lower + bytes, ABX8XX_SRAM_WIN_SIZE) - lower;
+
+		ret = dm_i2c_reg_write(dev, ABX8XX_REG_EXTRAM, extram);
+		if (ret)
+			return ret;
+
+		if (write)
+			ret = dm_i2c_write(dev, reg, val, len);
+		else
+			ret = dm_i2c_read(dev, reg, val, len);
+		if (ret)
+			return ret;
+
+		offset += len;
+		val += len;
+		bytes -= len;
+	}
+
+	return 0;
 }
 
-static int abx80x_rtc_write8(struct udevice *dev, unsigned int reg, int val)
+static int abx80x_rtc_read(struct udevice *dev, unsigned int offset, u8 *val,
+			   unsigned int bytes)
 {
-	u8 buf = (u8)val;
-
-	if (reg > 0xff)
-		return -EINVAL;
+	return abx80x_rtc_xfer(dev, offset, val, bytes, false);
+}
 
-	return dm_i2c_write(dev, reg, &buf, sizeof(buf));
+static int abx80x_rtc_write(struct udevice *dev, unsigned int offset,
+			    const u8 *val, unsigned int bytes)
+{
+	return abx80x_rtc_xfer(dev, offset, (u8 *)val, bytes, true);
 }
 
 static int abx80x_is_rc_mode(struct udevice *dev)
@@ -334,9 +368,9 @@  static int abx80x_rtc_reset(struct udevice *dev)
 static const struct rtc_ops abx80x_rtc_ops = {
 	.get	= abx80x_rtc_read_time,
 	.set	= abx80x_rtc_set_time,
-	.reset  = abx80x_rtc_reset,
-	.read8  = abx80x_rtc_read8,
-	.write8 = abx80x_rtc_write8
+	.reset	= abx80x_rtc_reset,
+	.read	= abx80x_rtc_read,
+	.write	= abx80x_rtc_write,
 };
 
 static int abx80x_dt_trickle_cfg(struct udevice *dev)