From: sashiko-bot@kernel.org
To: "Antoni Pokusinski" <apokusinski01@gmail.com>
Cc: linux-rtc@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
devicetree@vger.kernel.org
Subject: Re: [PATCH 3/6] rtc: abx80x: use regmap instead of I2C specific API
Date: Wed, 22 Jul 2026 20:16:45 +0000 [thread overview]
Message-ID: <20260722201646.115101F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260722195814.298552-4-apokusinski01@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Hardware unlock sequence is broken by read-modify-write inversion
- [Low] Incompatible pointer types passed to regmap_read()
--
--- Patch [3]: [PATCH 3/6] rtc: abx80x: use regmap instead of I2C specific API ---
commit 97cd1f33d168c96f848a8f59ba284bfe9c5f89fe
Author: Antoni Pokusinski <apokusinski01@gmail.com>
Date: Wed Jul 22 19:58:11 2026 +0000
rtc: abx80x: use regmap instead of I2C specific API
Rework the driver so that it uses regmap_* functions for communication
with the device instead of the i2c_smbus_* API. This way the support for
ABX81X RTCs which use SPI can be added later.
> diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
> index 9b0e1d48d9ba3..e5ba821a67689 100644
> --- a/drivers/rtc/rtc-abx80x.c
> +++ b/drivers/rtc/rtc-abx80x.c
> @@ -125,52 +126,53 @@ static struct abx80x_cap abx80x_caps[] = {
[ ... ]
> -static int abx80x_is_rc_mode(struct i2c_client *client)
> +static int abx80x_is_rc_mode(struct device *dev)
> {
> - int flags = 0;
> + struct abx80x_priv *priv = dev_get_drvdata(dev);
> + int err, flags = 0;
>
> - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS);
> - if (flags < 0) {
> - dev_err(&client->dev,
> - "Failed to read autocalibration attribute\n");
> - return flags;
> + err = regmap_read(priv->regmap, ABX8XX_REG_OSS, &flags);
[Severity: Low]
Does this pass an incompatible pointer type to regmap_read()?
The API signature of regmap_read() expects an unsigned int * for its third
argument, but the address of a local int variable (&flags) is passed here.
While this may not cause memory corruption since int and unsigned int are
the same size, it violates the function signature and generates
-Wincompatible-pointer-types warnings, which can break builds compiling with
-Werror.
> + if (err < 0) {
> + dev_err(dev, "Failed to read autocalibration attribute\n");
> + return err;
> }
[ ... ]
> @@ -259,13 +260,13 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
>
> static irqreturn_t abx80x_handle_irq(int irq, void *dev_id)
> {
> - struct i2c_client *client = dev_id;
> - struct abx80x_priv *priv = i2c_get_clientdata(client);
> + struct device *dev = dev_id;
> + struct abx80x_priv *priv = dev_get_drvdata(dev);
> struct rtc_device *rtc = priv->rtc;
> - int status;
> + int err, status;
>
> - status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
> - if (status < 0)
> + err = regmap_read(priv->regmap, ABX8XX_REG_STATUS, &status);
[Severity: Low]
Does this pass an incompatible pointer type to regmap_read()?
Similar to abx80x_is_rc_mode() above, this passes an int pointer (&status)
instead of an unsigned int pointer.
> + if (err < 0)
> return IRQ_NONE;
[ ... ]
> @@ -294,14 +294,13 @@ static int abx80x_read_alarm(struct device *dev, struct rtc_wkalrm *t)
> if (priv->irq <= 0)
> return -EINVAL;
>
> - err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ASC,
> - sizeof(buf), buf);
> + err = regmap_bulk_read(priv->regmap, ABX8XX_REG_ASC, buf, sizeof(buf));
> if (err)
> return err;
>
> - irq_mask = i2c_smbus_read_byte_data(client, ABX8XX_REG_IRQ);
> - if (irq_mask < 0)
> - return irq_mask;
> + err = regmap_read(priv->regmap, ABX8XX_REG_IRQ, &irq_mask);
[Severity: Low]
Does this pass an incompatible pointer type to regmap_read()?
This passes an int pointer (&irq_mask) instead of an unsigned int pointer.
> + if (err < 0)
> + return err;
[ ... ]
> @@ -379,22 +376,22 @@ static int abx80x_rtc_set_autocalibration(struct device *dev,
> }
>
> /* Unlock write access to Oscillator Control Register */
> - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_OSC) < 0)
> + if (abx80x_write_config_key(dev, ABX8XX_CFG_KEY_OSC) < 0)
> return -EIO;
>
> - retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags);
> + retval = regmap_write(priv->regmap, ABX8XX_REG_OSC, flags);
[Severity: High]
Does this hardware unlock sequence get broken by read-modify-write inversion?
According to the datasheet, any subsequent I2C access (read or write) resets
the configuration key to zero. If this sequence uses a read-modify-write
operation (such as regmap_write_bits()), a hardware read is performed after
the unlock key is written. This read resets the configuration key, causing the
hardware to ignore the subsequent write and breaking features like
autocalibration.
>
> return retval;
> }
>
> static int abx80x_rtc_get_autocalibration(struct device *dev)
> {
> - struct i2c_client *client = to_i2c_client(dev);
> - int flags = 0, autocalibration;
> + struct abx80x_priv *priv = dev_get_drvdata(dev);
> + int flags = 0, autocalibration, err;
>
> - flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC);
> - if (flags < 0)
> - return flags;
> + err = regmap_read(priv->regmap, ABX8XX_REG_OSC, &flags);
[Severity: Low]
Does this pass an incompatible pointer type to regmap_read()?
This passes an int pointer (&flags) instead of an unsigned int pointer.
> + if (err < 0)
> + return err;
[ ... ]
> @@ -467,10 +464,10 @@ static ssize_t oscillator_store(struct device *dev,
> flags |= (ABX8XX_OSC_OSEL);
>
> /* Unlock write access on Oscillator Control register */
> - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_OSC) < 0)
> + if (abx80x_write_config_key(dev->parent, ABX8XX_CFG_KEY_OSC) < 0)
> return -EIO;
>
> - retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags);
> + retval = regmap_write(priv->regmap, ABX8XX_REG_OSC, flags);
[Severity: High]
Does this hardware unlock sequence get broken by read-modify-write inversion?
As noted in abx80x_rtc_set_autocalibration() above, a hardware read performed
after the unlock key is written clears the key. This resets the key before the
protected write if a read-modify-write operation like regmap_write_bits() is
used.
> if (retval < 0) {
> dev_err(dev, "Failed to write Oscillator Control register\n");
[ ... ]
> @@ -513,45 +509,43 @@ static const struct attribute_group rtc_calib_attr_group = {
>
> static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled)
> {
[ ... ]
> static int abx80x_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
> {
> - struct i2c_client *client = to_i2c_client(dev);
> - int status, tmp;
> + struct abx80x_priv *priv = dev_get_drvdata(dev);
> + int err, status, tmp;
>
> switch (cmd) {
> case RTC_VL_READ:
> - status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS);
> - if (status < 0)
> - return status;
> + err = regmap_read(priv->regmap, ABX8XX_REG_STATUS, &status);
[Severity: Low]
Does this pass an incompatible pointer type to regmap_read()?
This passes an int pointer (&status) instead of an unsigned int pointer.
> + if (err < 0)
> + return err;
[ ... ]
> @@ -856,11 +898,11 @@ static int abx80x_probe(struct i2c_client *client)
> * Write the configuration key register to enable access to
> * the config2 register
> */
> - if (abx80x_write_config_key(client, ABX8XX_CFG_KEY_MISC) < 0)
> + if (abx80x_write_config_key(&client->dev, ABX8XX_CFG_KEY_MISC) < 0)
> return -EIO;
>
> - err = i2c_smbus_write_byte_data(client, ABX8XX_REG_OUT_CTRL,
> - data | ABX8XX_OUT_CTRL_EXDS);
> + err = regmap_write(regmap, ABX8XX_REG_OUT_CTRL,
> + data | ABX8XX_OUT_CTRL_EXDS);
[Severity: High]
Does this hardware unlock sequence get broken by read-modify-write inversion?
For RV1805, the key is written, but if a read-modify-write operation like
regmap_write_bits() is used here, it performs a read before writing the EXTI
disable bit. This read clears the key, leaving the write ineffective and
defeating the extra power leakage workaround.
> if (err < 0) {
> dev_err(&client->dev,
> "Unable to write output control register\n");
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260722195814.298552-1-apokusinski01@gmail.com?part=3
next prev parent reply other threads:[~2026-07-22 20:16 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-22 19:58 [PATCH 0/6] rtc: abx80x: add support for ABX81X Antoni Pokusinski
2026-07-22 19:58 ` [PATCH 1/6] dt-bindings: rtc: abx80x: document ABX81X RTCs Antoni Pokusinski
2026-07-22 20:09 ` sashiko-bot
2026-07-22 19:58 ` [PATCH 2/6] rtc: abx80x: add irq to struct abx80x_priv Antoni Pokusinski
2026-07-22 20:13 ` sashiko-bot
2026-07-22 19:58 ` [PATCH 3/6] rtc: abx80x: use regmap instead of I2C specific API Antoni Pokusinski
2026-07-22 20:16 ` sashiko-bot [this message]
2026-07-22 19:58 ` [PATCH 4/6] rtc: abx80x: replace read-modify-write pattern with regmap helpers Antoni Pokusinski
2026-07-22 20:11 ` sashiko-bot
2026-07-22 19:58 ` [PATCH 5/6] rtc: abx80x: create abx80x_i2c_probe() Antoni Pokusinski
2026-07-22 20:10 ` sashiko-bot
2026-07-22 19:58 ` [PATCH 6/6] rtc: abx80x: add support for ABX81X Antoni Pokusinski
2026-07-22 20:09 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260722201646.115101F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=alexandre.belloni@bootlin.com \
--cc=apokusinski01@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.