diff mbox series

[v2] iio: filter: admv8818: Force initialization of SDO

Message ID SA1P110MB106911327A8819E9AF67E676BCE2A@SA1P110MB1069.NAMP110.PROD.OUTLOOK.COM (mailing list archive)
State New
Headers show
Series [v2] iio: filter: admv8818: Force initialization of SDO | expand

Commit Message

Sam Winchenbach Jan. 25, 2025, 2:54 p.m. UTC
When a weak pull-up is present on the SDO line, regmap_update_bits fails
to write both the SOFTRESET and SDOACTIVE bits because it incorrectly
reads them as already set.

Since the soft reset disables the SDO line, performing a
read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line
doesn't make sense. This change directly writes to the register instead
of using regmap_update_bits.

Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")

Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
---
 drivers/iio/filter/admv8818.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

Comments

Jonathan Cameron Feb. 1, 2025, 11:18 a.m. UTC | #1
On Sat, 25 Jan 2025 14:54:44 +0000
Sam Winchenbach <swinchenbach@arka.org> wrote:

> When a weak pull-up is present on the SDO line, regmap_update_bits fails
> to write both the SOFTRESET and SDOACTIVE bits because it incorrectly
> reads them as already set.

I can see this as a valid micro optimization but I'm struggling a bit
on how you can use the device if the pull up is weak enough that
you can't read data back from it. Does the reset in some way
solve that?

Having asked for the fixes tag, I'm less sure on whether this is a fix.

Antoniu, I'd also like your input on this one!

> 
> Since the soft reset disables the SDO line, performing a
> read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line
> doesn't make sense. This change directly writes to the register instead
> of using regmap_update_bits.
> 
> Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> 

No blank line here.  Fixes is part of the tags block that various scripts
scan.

> Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
> ---
>  drivers/iio/filter/admv8818.c | 14 ++++----------
>  1 file changed, 4 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> index 195e58bc4..9cd1eee84 100644
> --- a/drivers/iio/filter/admv8818.c
> +++ b/drivers/iio/filter/admv8818.c
> @@ -577,21 +577,15 @@ static int admv8818_init(struct admv8818_state *st)
>  	struct spi_device *spi = st->spi;
>  	unsigned int chip_id;
>  
> -	ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> -				 ADMV8818_SOFTRESET_N_MSK |
> -				 ADMV8818_SOFTRESET_MSK,
> -				 FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
> -				 FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
> +	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> +			   ADMV8818_SOFTRESET_N_MSK | ADMV8818_SOFTRESET_MSK);
>  	if (ret) {
>  		dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
>  		return ret;
>  	}
>  
> -	ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> -				 ADMV8818_SDOACTIVE_N_MSK |
> -				 ADMV8818_SDOACTIVE_MSK,
> -				 FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
> -				 FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
> +	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> +			   ADMV8818_SDOACTIVE_N_MSK | ADMV8818_SDOACTIVE_MSK);
>  	if (ret) {
>  		dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
>  		return ret;
Sam Winchenbach Feb. 1, 2025, 2 p.m. UTC | #2
> > When a weak pull-up is present on the SDO line, regmap_update_bits 
> > fails to write both the SOFTRESET and SDOACTIVE bits because it 
> > incorrectly reads them as already set.
> 
> I can see this as a valid micro optimization but I'm struggling a bit on how you can use the device if the pull up is weak enough that you can't read data back from it. Does the reset in some way solve that?
> 
> Having asked for the fixes tag, I'm less sure on whether this is a fix.
> 
> Antoniu, I'd also like your input on this one!
> 

On power-up the device is configured without SDO enabled. This, alone, makes the read-modify-write during initialization incorrect - It is not possible to read from the device seeing it is not driving the output.

If the SPI bus, like in our situation, has a weak pull-up the situation is compounded. When the device initializes it reads backs all 1's as part of the read-modify-write sequence, falsely determines that the soft-reset bit is already set and skips resetting the device. The next step is to enable the SDO line. It reads back all 1's, falsely determines that the SDO is enabled and then skips writing to enable it. This leaves the device in a non-functioning state.

By writing directly to register it will always perform the reset, and it will always enable SDO regardless of the invalid values read back during initialization.

> >
> > Since the soft reset disables the SDO line, performing a 
> > read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line 
> > doesn't make sense. This change directly writes to the register 
> > instead of using regmap_update_bits.
> >
> > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> >
> 
> No blank line here.  Fixes is part of the tags block that various scripts scan.

Is this the blank line after the fixes? I need to do some research to understand the tag block.

> 
> > Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
> > ---
> >  drivers/iio/filter/admv8818.c | 14 ++++----------
> >  1 file changed, 4 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/iio/filter/admv8818.c 
> > b/drivers/iio/filter/admv8818.c index 195e58bc4..9cd1eee84 100644
> > --- a/drivers/iio/filter/admv8818.c
> > +++ b/drivers/iio/filter/admv8818.c
> > @@ -577,21 +577,15 @@ static int admv8818_init(struct admv8818_state *st)
> >       struct spi_device *spi = st->spi;
> >       unsigned int chip_id;
> >
> > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > -                              ADMV8818_SOFTRESET_N_MSK |
> > -                              ADMV8818_SOFTRESET_MSK,
> > -                              FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
> > -                              FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
> > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > +                        ADMV8818_SOFTRESET_N_MSK | 
> > + ADMV8818_SOFTRESET_MSK);
> >       if (ret) {
> >               dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
> >               return ret;
> >       }
> >
> > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > -                              ADMV8818_SDOACTIVE_N_MSK |
> > -                              ADMV8818_SDOACTIVE_MSK,
> > -                              FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
> > -                              FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
> > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > +                        ADMV8818_SDOACTIVE_N_MSK | 
> > + ADMV8818_SDOACTIVE_MSK);
> >       if (ret) {
> >               dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
> >               return ret;
Jonathan Cameron Feb. 2, 2025, 3:15 p.m. UTC | #3
On Sat, 1 Feb 2025 14:00:58 +0000
Sam Winchenbach <swinchenbach@arka.org> wrote:

> > > When a weak pull-up is present on the SDO line, regmap_update_bits 
> > > fails to write both the SOFTRESET and SDOACTIVE bits because it 
> > > incorrectly reads them as already set.  
> > 
> > I can see this as a valid micro optimization but I'm struggling a bit on how you can use the device if the pull up is weak enough that you can't read data back from it. Does the reset in some way solve that?
> > 
> > Having asked for the fixes tag, I'm less sure on whether this is a fix.
> > 
> > Antoniu, I'd also like your input on this one!
> >   
> 
> On power-up the device is configured without SDO enabled. This, alone, makes the read-modify-write during initialization incorrect - It is not possible to read from the device seeing it is not driving the output.
> 
> If the SPI bus, like in our situation, has a weak pull-up the situation is compounded. When the device initializes it reads backs all 1's as part of the read-modify-write sequence, falsely determines that the soft-reset bit is already set and skips resetting the device. The next step is to enable the SDO line. It reads back all 1's, falsely determines that the SDO is enabled and then skips writing to enable it. This leaves the device in a non-functioning state.
> 
> By writing directly to register it will always perform the reset, and it will always enable SDO regardless of the invalid values read back during initialization.
Ah ok.  So it's a bug with or without appropriate pull up.
Just happens to be worse if that is missing.
> 
> > >
> > > Since the soft reset disables the SDO line, performing a 
> > > read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line 
> > > doesn't make sense. This change directly writes to the register 
> > > instead of using regmap_update_bits.
> > >
> > > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> > >  
> > 
> > No blank line here.  Fixes is part of the tags block that various scripts scan.  
> 
> Is this the blank line after the fixes? I need to do some research to understand the tag block.
Yes - The block of all tags needs to be contiguous. No blank lines.

Greg has a script that moans about this, not sure if it also runs on linux-next

Jonathan
> 
> >   
> > > Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
> > > ---
> > >  drivers/iio/filter/admv8818.c | 14 ++++----------
> > >  1 file changed, 4 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/drivers/iio/filter/admv8818.c 
> > > b/drivers/iio/filter/admv8818.c index 195e58bc4..9cd1eee84 100644
> > > --- a/drivers/iio/filter/admv8818.c
> > > +++ b/drivers/iio/filter/admv8818.c
> > > @@ -577,21 +577,15 @@ static int admv8818_init(struct admv8818_state *st)
> > >       struct spi_device *spi = st->spi;
> > >       unsigned int chip_id;
> > >
> > > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > -                              ADMV8818_SOFTRESET_N_MSK |
> > > -                              ADMV8818_SOFTRESET_MSK,
> > > -                              FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
> > > -                              FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
> > > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > +                        ADMV8818_SOFTRESET_N_MSK | 
> > > + ADMV8818_SOFTRESET_MSK);
> > >       if (ret) {
> > >               dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
> > >               return ret;
> > >       }
> > >
> > > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > -                              ADMV8818_SDOACTIVE_N_MSK |
> > > -                              ADMV8818_SDOACTIVE_MSK,
> > > -                              FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
> > > -                              FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
> > > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > +                        ADMV8818_SDOACTIVE_N_MSK | 
> > > + ADMV8818_SDOACTIVE_MSK);
> > >       if (ret) {
> > >               dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
> > >               return ret;
Miclaus, Antoniu Feb. 3, 2025, 12:14 p.m. UTC | #4
> On Sat, 25 Jan 2025 14:54:44 +0000
> Sam Winchenbach <swinchenbach@arka.org> wrote:
> 
> > When a weak pull-up is present on the SDO line, regmap_update_bits fails
> > to write both the SOFTRESET and SDOACTIVE bits because it incorrectly
> > reads them as already set.
> 
> I can see this as a valid micro optimization but I'm struggling a bit
> on how you can use the device if the pull up is weak enough that
> you can't read data back from it. Does the reset in some way
> solve that?
> 
> Having asked for the fixes tag, I'm less sure on whether this is a fix.
> 
> Antoniu, I'd also like your input on this one!
> 
Indeed, this can be considered as a "bug". I had a look over the datasheet and the SDO line is disabled by default.

So the `update_bits` doesn't quite make sense in this scenario.

> >
> > Since the soft reset disables the SDO line, performing a
> > read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO line
> > doesn't make sense. This change directly writes to the register instead
> > of using regmap_update_bits.
> >
> > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for ADMV8818")
> >
> 
> No blank line here.  Fixes is part of the tags block that various scripts
> scan.
> 
> > Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
> > ---
> >  drivers/iio/filter/admv8818.c | 14 ++++----------
> >  1 file changed, 4 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
> > index 195e58bc4..9cd1eee84 100644
> > --- a/drivers/iio/filter/admv8818.c
> > +++ b/drivers/iio/filter/admv8818.c
> > @@ -577,21 +577,15 @@ static int admv8818_init(struct admv8818_state
> *st)
> >  	struct spi_device *spi = st->spi;
> >  	unsigned int chip_id;
> >
> > -	ret = regmap_update_bits(st->regmap,
> ADMV8818_REG_SPI_CONFIG_A,
> > -				 ADMV8818_SOFTRESET_N_MSK |
> > -				 ADMV8818_SOFTRESET_MSK,
> > -
> FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
> > -				 FIELD_PREP(ADMV8818_SOFTRESET_MSK,
> 1));
> > +	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > +			   ADMV8818_SOFTRESET_N_MSK |
> ADMV8818_SOFTRESET_MSK);
> >  	if (ret) {
> >  		dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
> >  		return ret;
> >  	}
> >
> > -	ret = regmap_update_bits(st->regmap,
> ADMV8818_REG_SPI_CONFIG_A,
> > -				 ADMV8818_SDOACTIVE_N_MSK |
> > -				 ADMV8818_SDOACTIVE_MSK,
> > -
> FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
> > -				 FIELD_PREP(ADMV8818_SDOACTIVE_MSK,
> 1));
> > +	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > +			   ADMV8818_SDOACTIVE_N_MSK |
> ADMV8818_SDOACTIVE_MSK);
> >  	if (ret) {
> >  		dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
> >  		return ret;
Sam Winchenbach Feb. 3, 2025, 1:37 p.m. UTC | #5
> > > > When a weak pull-up is present on the SDO line, regmap_update_bits 
> > > > fails to write both the SOFTRESET and SDOACTIVE bits because it 
> > > > incorrectly reads them as already set.
> > >
> > > I can see this as a valid micro optimization but I'm struggling a bit on how you can use the device if the pull up is weak enough that you can't read data back from it. Does the reset in some way solve that?
> > >
> > > Having asked for the fixes tag, I'm less sure on whether this is a fix.
> > >
> > > Antoniu, I'd also like your input on this one!
> > >
> >
> > On power-up the device is configured without SDO enabled. This, alone, makes the read-modify-write during initialization incorrect - It is not possible to read from the device seeing it is not driving the output.
> >
> > If the SPI bus, like in our situation, has a weak pull-up the situation is compounded. When the device initializes it reads backs all 1's as part of the read-modify-write sequence, falsely determines that the soft-reset bit is already set and skips resetting the device. The next step is to enable the SDO line. It reads back all 1's, falsely determines that the SDO is enabled and then skips writing to enable it. This leaves the device in a non-functioning state.
> >
> > By writing directly to register it will always perform the reset, and it will always enable SDO regardless of the invalid values read back during initialization.
> Ah ok.  So it's a bug with or without appropriate pull up.
> Just happens to be worse if that is missing.
> >
> > > >
> > > > Since the soft reset disables the SDO line, performing a 
> > > > read-modify-write operation on ADI_SPI_CONFIG_A to enable the SDO 
> > > > line doesn't make sense. This change directly writes to the 
> > > > register instead of using regmap_update_bits.
> > > >
> > > > Fixes: f34fe888ad05 ("iio:filter:admv8818: add support for 
> > > > ADMV8818")
> > > >
> > >
> > > No blank line here.  Fixes is part of the tags block that various scripts scan.
> >
> > Is this the blank line after the fixes? I need to do some research to understand the tag block.
> Yes - The block of all tags needs to be contiguous. No blank lines.
> 
> Greg has a script that moans about this, not sure if it also runs on linux-next

Okay. I submitted v3 with this fix. I also setup mutt/send-email so the next time I submit a patch it won't be quite so painful.
Thank you for the guidance.

> 
> Jonathan
> >
> > >
> > > > Signed-off-by: Sam Winchenbach <swinchenbach@arka.org>
> > > > ---
> > > >  drivers/iio/filter/admv8818.c | 14 ++++----------
> > > >  1 file changed, 4 insertions(+), 10 deletions(-)
> > > >
> > > > diff --git a/drivers/iio/filter/admv8818.c 
> > > > b/drivers/iio/filter/admv8818.c index 195e58bc4..9cd1eee84 100644
> > > > --- a/drivers/iio/filter/admv8818.c
> > > > +++ b/drivers/iio/filter/admv8818.c
> > > > @@ -577,21 +577,15 @@ static int admv8818_init(struct admv8818_state *st)
> > > >       struct spi_device *spi = st->spi;
> > > >       unsigned int chip_id;
> > > >
> > > > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > > -                              ADMV8818_SOFTRESET_N_MSK |
> > > > -                              ADMV8818_SOFTRESET_MSK,
> > > > -                              FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
> > > > -                              FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
> > > > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > > +                        ADMV8818_SOFTRESET_N_MSK | 
> > > > + ADMV8818_SOFTRESET_MSK);
> > > >       if (ret) {
> > > >               dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
> > > >               return ret;
> > > >       }
> > > >
> > > > -     ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > > -                              ADMV8818_SDOACTIVE_N_MSK |
> > > > -                              ADMV8818_SDOACTIVE_MSK,
> > > > -                              FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
> > > > -                              FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
> > > > +     ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
> > > > +                        ADMV8818_SDOACTIVE_N_MSK | 
> > > > + ADMV8818_SDOACTIVE_MSK);
> > > >       if (ret) {
> > > >               dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
> > > >               return ret;
diff mbox series

Patch

diff --git a/drivers/iio/filter/admv8818.c b/drivers/iio/filter/admv8818.c
index 195e58bc4..9cd1eee84 100644
--- a/drivers/iio/filter/admv8818.c
+++ b/drivers/iio/filter/admv8818.c
@@ -577,21 +577,15 @@  static int admv8818_init(struct admv8818_state *st)
 	struct spi_device *spi = st->spi;
 	unsigned int chip_id;
 
-	ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
-				 ADMV8818_SOFTRESET_N_MSK |
-				 ADMV8818_SOFTRESET_MSK,
-				 FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |
-				 FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));
+	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
+			   ADMV8818_SOFTRESET_N_MSK | ADMV8818_SOFTRESET_MSK);
 	if (ret) {
 		dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");
 		return ret;
 	}
 
-	ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
-				 ADMV8818_SDOACTIVE_N_MSK |
-				 ADMV8818_SDOACTIVE_MSK,
-				 FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |
-				 FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));
+	ret = regmap_write(st->regmap, ADMV8818_REG_SPI_CONFIG_A,
+			   ADMV8818_SDOACTIVE_N_MSK | ADMV8818_SDOACTIVE_MSK);
 	if (ret) {
 		dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");
 		return ret;