RE: [PATCH 5/9] iio: adc: rzt2h: implement DMA buffer support
From: Cosmin-Gabriel Tanislav
Date: Thu Sep 03 2026 - 04:01:08 EST
> From: Jonathan Cameron <jic23@xxxxxxxxxx>
> Sent: Saturday, August 29, 2026 4:21 AM
>
> > Implement buffered capture using a cyclic DMA transfer into a kfifo
> > buffer to support continuous high-rate sampling.
> >
> > On buffer enable, switch the ADC to continuous conversion mode and start
> > a cyclic DMA transfer over the active channels.
> >
> > Because the DMA controller does not support native scatter-gather, and
> > because of the cyclic DMA setup, transfers must be done in widths
> > covering all the enabled channels.
> >
> > Since DMA transfer width must be a power of two and aligned to its size,
> > cover the smallest power-of-two-aligned group of channel registers
> > spanning the enabled channels.
> >
> > Split the cyclic buffer into fixed-size periods. On each period
> > completion, bump a pending counter and wake a consumer kthread from the
> > DMA callback.
> >
> > For every completed period, gather the enabled channels out of the DMA
> > layout into the scan layout the IIO core expects and push each scan
> > with iio_push_to_buffers().
>
> Could you instead use the available_scan_masks infrastructure. bit annoying
> to specify the full list but isn't that long I think with 16 channels
>
> 16 x single
> 8 x double,
> 4 x quads
> 2 x octect
> 1 x all of them.
>
> The the IIO demux in (sits behind the push_to_buffers path if
> we have available_scan_masks set) will then deal with repacking
> the data if necessary.
>
Hi Jonathan.
There are a couple reasons why I haven't used available_scan_masks.
Our limitation is on the DMA side. It cannot do scatter-gather in a
single descriptor, and we need to copy all the channels for each
completion IRQ. This is why we have to copy all the enabled channels
in a single block, and the base address needs to have the same
alignment as the block size.
My initial naive implementation copied all 16 channels (32 bytes) all
the time, but at that size the DMAC quickly hits a wall where it doesn't
service the ADC's completion signals anymore, at ~220k requests per
second.
Optimizing the DMA window allows us to avoid losing samples when the
enabled channels are densely packed. Enabling only channel 0 and 15
still hits the DMAC performance wall though, for example.
If we were to use available_scan_masks, the ADC would have to enable the
extra channels too, since it would have no knowledge of whether a
channel is enabled legitimately or for alignment purposes. The ADC scans
each channel iteratively, not in parallel, so sampling rate would be
affected because of the extra enabled channels. Besides that, this would
be transparent to the user, but it would reuse the last set sampling
frequency values, which affect the sampling rate without the user even
knowing.
If there are any extra enabled channels, iio_demux() would have to copy
all the data again. We need to keep our own copy inside the driver to
unswap the ADC's 16-bit data registers out of each 32-bit word.
The available_scan_masks table would have to be computed at runtime
since not all instances of the ADC have 16 channels. Also the use of
devm_iio_adc_device_alloc_chaninfo_se() means that we allow gaps in the
channels themselves. scan_index is set incrementally anyway, so it can
get out of sync with the channel index, and that would need extra
handling when building the table.
Let me know what you think and what the direction should be.