* [PATCH RFC] rtc: m41t80: Support SMBus adapters without I2C block transfers
@ 2026-11-03 22:50 Florian Fainelli
2026-11-04 2:13 ` Maciej W. Rozycki
0 siblings, 1 reply; 2+ messages in thread
From: Florian Fainelli @ 2026-11-03 22:50 UTC (permalink / raw)
To: linux-kernel
Cc: macro, Florian Fainelli, Alexandre Belloni,
open list:REAL TIME CLOCK (RTC) SUBSYSTEM
The M41T81 on the Broadcom BCM91250E (Sentosa) is connected to the
SiByte SMBus controller. The controller supports SMBus byte and word
transactions, but not the I2C block transfers required by rtc-m41t80,
so the driver refuses to probe.
Use the I2C core's block-read emulation and provide a byte-write
fallback, retaining native block transfers when the adapter supports
them. Propagate transfer errors and reject short reads.
Individual byte or word reads do not latch the complete clock register
set. Recheck seconds after reading the time on adapters without block
reads and retry up to three times if the clock rolled over. Return
-EAGAIN if a consistent sample cannot be obtained.
Maciej W. Rozycki proposed SMBus-only support for this RTC family in
2008. The same SiByte limitation was discussed again in 2018, including
register latching, seconds rechecks and a possible regmap conversion.
This change revisits that approach using the current I2C helpers.
RTC access and date retention across a reboot were verified on a
BCM91250E. Host tests with mocked SMBus transfers covered native and
fallback paths, rollover retries, short reads and transfer errors.
Alarm operation and retention after a power-cycle were not tested.
Link: https://lkml.rescloud.iu.edu/hypermail/linux/kernel/0805.1/1778.html
Link: https://lkml.rescloud.iu.edu/1811.1/07408.html
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/rtc/rtc-m41t80.c | 65 +++++++++++++++++++++++++++++++++-------
1 file changed, 54 insertions(+), 11 deletions(-)
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index 1385cb43864b..23d02b95a606 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -188,11 +188,41 @@ static irqreturn_t m41t80_handle_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/* Some SMBus adapters only support byte and word transactions. */
+static int m41t80_read_regs(struct i2c_client *client, u8 reg, u8 len, u8 *buf)
+{
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data_or_emulated(client, reg, len, buf);
+ if (ret < 0)
+ return ret;
+
+ return ret == len ? ret : -EIO;
+}
+
+static int m41t80_write_regs(struct i2c_client *client, u8 reg, u8 len,
+ const u8 *buf)
+{
+ int i, ret;
+
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
+ return i2c_smbus_write_i2c_block_data(client, reg, len, buf);
+
+ for (i = 0; i < len; i++) {
+ ret = i2c_smbus_write_byte_data(client, reg + i, buf[i]);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf[8];
- int err, flags;
+ int err, flags, tries;
flags = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
if (flags < 0)
@@ -203,12 +233,25 @@ static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
return -EINVAL;
}
- err = i2c_smbus_read_i2c_block_data(client, M41T80_REG_SSEC,
- sizeof(buf), buf);
- if (err < 0) {
- dev_dbg(&client->dev, "Unable to read date\n");
- return err;
+ /* Byte reads do not latch the clock registers across a rollover. */
+ for (tries = 0; tries < 3; tries++) {
+ err = m41t80_read_regs(client, M41T80_REG_SSEC,
+ sizeof(buf), buf);
+ if (err < 0)
+ return err;
+
+ if (i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+ break;
+
+ err = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
+ if (err < 0)
+ return err;
+ if ((err & 0x7f) == (buf[M41T80_REG_SEC] & 0x7f))
+ break;
}
+ if (tries == 3)
+ return -EAGAIN;
tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f);
tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f);
@@ -259,7 +302,7 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *in_tm)
buf[M41T80_REG_WDAY] |= (val & 0xf0);
}
- err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_SSEC,
+ err = m41t80_write_regs(client, M41T80_REG_SSEC,
sizeof(buf), buf);
if (err < 0) {
dev_dbg(&client->dev, "Unable to write to date registers\n");
@@ -374,7 +417,7 @@ static int m41t80_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
/* Write the alarm */
- err = i2c_smbus_write_i2c_block_data(client, M41T80_REG_ALARM_MON,
+ err = m41t80_write_regs(client, M41T80_REG_ALARM_MON,
5, alarmvals);
if (err)
return err;
@@ -397,7 +440,7 @@ static int m41t80_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
u8 alarmvals[5];
int flags, ret;
- ret = i2c_smbus_read_i2c_block_data(client, M41T80_REG_ALARM_MON,
+ ret = m41t80_read_regs(client, M41T80_REG_ALARM_MON,
5, alarmvals);
if (ret != 5)
return ret < 0 ? ret : -EIO;
@@ -906,9 +949,9 @@ static int m41t80_probe(struct i2c_client *client)
struct m41t80_data *m41t80_data = NULL;
bool wakeup_source = false;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
+ if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK\n");
+ dev_err(&adapter->dev, "doesn't support I2C_FUNC_SMBUS_BYTE_DATA\n");
return -ENODEV;
}
--
2.53.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH RFC] rtc: m41t80: Support SMBus adapters without I2C block transfers
2026-11-03 22:50 [PATCH RFC] rtc: m41t80: Support SMBus adapters without I2C block transfers Florian Fainelli
@ 2026-11-04 2:13 ` Maciej W. Rozycki
0 siblings, 0 replies; 2+ messages in thread
From: Maciej W. Rozycki @ 2026-11-04 2:13 UTC (permalink / raw)
To: Florian Fainelli
Cc: linux-kernel, Alexandre Belloni,
open list:REAL TIME CLOCK (RTC) SUBSYSTEM
On Tue, 3 Nov 2026, Florian Fainelli wrote:
> Maciej W. Rozycki proposed SMBus-only support for this RTC family in
> 2008. The same SiByte limitation was discussed again in 2018, including
> register latching, seconds rechecks and a possible regmap conversion.
> This change revisits that approach using the current I2C helpers.
Thank you for following up on this. I've always meant to get back to
this stuff sometime, but given so many other outstanding matters to deal
with I am really glad to get a helpful hand.
Later I'll have a deeper look at and do some further verification of your
proposal, however meanwhile here are corresponding lore.kernel.org links
for the messages referred:
> Link: https://lkml.rescloud.iu.edu/hypermail/linux/kernel/0805.1/1778.html
Link: https://lore.kernel.org/r/Pine.LNX.4.55.0805130254420.535@cliff.in.clinika.pl/
> Link: https://lkml.rescloud.iu.edu/1811.1/07408.html
Link: https://lore.kernel.org/r/alpine.LFD.2.21.1811141234140.21654@eddie.linux-mips.org/
-- which I believe are preferable, since under our supervision.
Maciej
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-04 2:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03 22:50 [PATCH RFC] rtc: m41t80: Support SMBus adapters without I2C block transfers Florian Fainelli
2026-11-04 2:13 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®