Re: [PATCH v3 3/9] iio: adc: Add support for ad4062

From: Jorge Marques
Date: Tue Dec 16 2025 - 16:41:43 EST


On Mon, Dec 08, 2025 at 10:16:35PM +0100, Jorge Marques wrote:
> On Sat, Dec 06, 2025 at 05:34:59PM +0000, Jonathan Cameron wrote:
> > On Fri, 5 Dec 2025 16:12:04 +0100
> > Jorge Marques <jorge.marques@xxxxxxxxxx> wrote:
> >
> > > The AD4060/AD4062 are versatile, 16-bit/12-bit, successive approximation
> > > register (SAR) analog-to-digital converter (ADC) with low-power and
> > > threshold monitoring modes.
> > >
> > > Signed-off-by: Jorge Marques <jorge.marques@xxxxxxxxxx>
Hi Jonathan,
> Hi Jonathan,
> ...
> Yes, and for burst avg mode, 14 bits.
> >
> > > + .storagebits = 32,
> > Given we are doing data mangling anyway why not store in a 16 bit value.
> >
> > BTW it would have been easier to spot issues with this if you'd introduced
> > the scan type stuff with the use of scans in the patch that adds buffered
> > support. So please move this stuff there.
> >
> This can be done, just note that for ad4062 in burst avg mode the
> realbits is 24 bits, so the storagebits is 32 bits only on that case
> and will requires a few conditionals to handle just this case.
>
> To not overly complicated the logic, for ad4062 I will always read
> 32-bits still. st->reg_addr_conv then takes:
> // IBI Fallback
> st->reg_addr_conv = st->chip->prod_id == 0x7C ? AD4062_REG_CONV_TRIGGER_32BITS :
> AD4062_REG_CONV_TRIGGER_16BITS;
> // GPO IRQ
> st->reg_addr_conv = st->chip->prod_id == 0x7C ? AD4062_REG_CONV_READ_32BITS :
> AD4062_REG_CONV_READ_16BITS;
>
> Then, for sample size:
> const bool is_32b = st->chip->prod_id == 0x7C;
> const size_t _sizeof = is_32b ? sizeof(st->buf.be32) : sizeof(st->buf.be16);
> instead of
> const bool is_32b = st->mode == AD4062_BURST_AVERAGING_MODE && st->chip->prod_id == 0x7C;
> const size_t _sizeof = is_32b ? sizeof(st->buf.be32) : sizeof(st->buf.be16);
> + extra st->reg_addr_conv_avg that may or may not be equal to
> st->reg_addr_conv.
>
> Note that the header section of the I3C transfer (8-bits) occurs
> at 1MHz, while the reading in 12.5MHz. I wouldn't go as far as say it is
> negligible, but for the part, protocol and software overhead, it
> wouldn't provide ground-breaking higher effective maximum
> sampling frequency.

I went back to this and now I am properly using the already set iio_get_current_scan_type
to set the appropriate sample register and storagesize (to reduce the protocol overhead).
Both methods are inline and used once, but I believe having the wrapper
methods makes things clearer.
For read_raw, I am using the non-optimized, 4 bytes trigger_conv, in the
next version.

/*
* The AD4062 in burst averaging mode increases realbits from 16-bits to
* 20-bits, increasing the storagebits from 16-bits to 32-bits.
*/
static inline size_t ad4062_sizeof_storagebits(struct ad4062_state *st)
{
const struct iio_scan_type *scan_type =
iio_get_current_scan_type(st->indio_dev, st->chip->channels);

return BITS_TO_BYTES(scan_type->storagebits);
}

/* Read registers only with realbits (no sign extension bytes) */
static inline size_t ad4062_get_conv_addr(struct ad4062_state *st, size_t _sizeof)
{
if (st->gpo_irq[1])
return _sizeof == sizeof(u32) ? AD4062_REG_CONV_READ_32BITS :
AD4062_REG_CONV_READ_16BITS;
return _sizeof == sizeof(u32) ? AD4062_REG_CONV_TRIGGER_32BITS :
AD4062_REG_CONV_TRIGGER_16BITS;
}

static int pm_ad4062_triggered_buffer_postenable(struct ad4062_state *st)
{
int ret;

PM_RUNTIME_ACQUIRE(&st->i3cdev->dev, pm);
ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
if (ret)
return ret;

if (st->wait_event)
return -EBUSY;

ret = ad4062_set_operation_mode(st, st->mode);
if (ret)
return ret;

st->conv_sizeof = ad4062_sizeof_storagebits(st);
st->conv_addr = ad4062_get_conv_addr(st, st->conv_sizeof);
...
}

Best regards,
Jorge