Re: [PATCH 3/6] rtc: abx80x: use regmap instead of I2C specific API

Antoni Pokusinski <[email protected]> Thu, 23 Jul 2026 19:45:05 +0200
Newsgroups org.kernel.vger.linux-rtc,dev.linux.lists.sashiko-reviews,org.kernel.vger.linux-devicetree
Message-ID <amJSJYp8xECJ4Hx9@antoniarch>
On Wed, Jul 22, 2026 at 08:16:45PM +0000, [email protected] wrote:
> 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 <[email protected]>
> 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.
>
I don't think it matters in all these cases, but I could make
these values unsigned int just to maintain the pointer type
compatibility.

> > +	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.
>
I see no issue here. The datasheet clearly states that
"CONFKEY is reset to 0x00 on any register **write**". I experienced no
issues with the current version of the driver when testing it on AB1815 hardware.

(this comment also applies to the other read-modify-write "bug" reports by
sashiko in this patch series)