* Re: [PATCH v7 4/6] iio: adc: ad4691: add SPI offload support
From: Jonathan Cameron @ 2026-04-12 17:56 UTC (permalink / raw)
To: Radu Sabau via B4 Relay
Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, David Lechner,
Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Uwe Kleine-König, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Philipp Zabel,
Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
linux-pwm, linux-gpio, linux-doc
In-Reply-To: <20260409-ad4692-multichannel-sar-adc-driver-v7-4-be375d4df2c5@analog.com>
On Thu, 09 Apr 2026 18:28:25 +0300
Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org> wrote:
> From: Radu Sabau <radu.sabau@analog.com>
>
> Add SPI offload support to enable DMA-based, CPU-independent data
> acquisition using the SPI Engine offload framework.
>
> When an SPI offload is available (devm_spi_offload_get() succeeds),
> the driver registers a DMA engine IIO buffer and uses dedicated buffer
> setup operations. If no offload is available the existing software
> triggered buffer path is used unchanged.
>
> Both CNV Burst Mode and Manual Mode support offload, but use different
> trigger mechanisms:
>
> CNV Burst Mode: the SPI Engine is triggered by the ADC's DATA_READY
> signal on the GP pin specified by the trigger-source consumer reference
> in the device tree (one cell = GP pin number 0-3). For this mode the
> driver acts as both an SPI offload consumer (DMA RX stream, message
> optimization) and a trigger source provider: it registers the
> GP/DATA_READY output via devm_spi_offload_trigger_register() so the
> offload framework can match the '#trigger-source-cells' phandle and
> automatically fire the SPI Engine DMA transfer at end-of-conversion.
>
> Manual Mode: the SPI Engine is triggered by a periodic trigger at
> the configured sampling frequency. The pre-built SPI message uses
> the pipelined CNV-on-CS protocol: N+1 16-bit transfers are issued
> for N active channels (the first result is discarded as garbage from
> the pipeline flush) and the remaining N results are captured by DMA.
>
> All offload transfers use 16-bit frames (bits_per_word=16, len=2).
> The channel scan_type (storagebits=16, shift=0, IIO_BE) is shared
> between the software triggered-buffer and offload paths; no separate
> scan_type or channel array is needed for the offload case. The
> ad4691_manual_channels[] array introduced in the triggered-buffer
> commit is reused here: it hides the IIO_CHAN_INFO_OVERSAMPLING_RATIO
> attribute, which is not applicable in Manual Mode.
>
> Kconfig gains a dependency on IIO_BUFFER_DMAENGINE.
>
> Signed-off-by: Radu Sabau <radu.sabau@analog.com>
A few comments inline.
> diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c
> index 3e5caa0972eb..839ea7f44c78 100644
> --- a/drivers/iio/adc/ad4691.c
> +++ b/drivers/iio/adc/ad4691.c
> +
> +static int ad4691_cnv_burst_offload_buffer_postenable(struct iio_dev *indio_dev)
> +{
> + struct ad4691_state *st = iio_priv(indio_dev);
> + struct ad4691_offload_state *offload = st->offload;
> + struct device *dev = regmap_get_device(st->regmap);
> + struct spi_device *spi = to_spi_device(dev);
> + struct spi_offload_trigger_config config = {
> + .type = SPI_OFFLOAD_TRIGGER_DATA_READY,
> + };
> + unsigned int n_active;
> + unsigned int bit, k;
> + int ret;
> +
> + n_active = bitmap_weight(indio_dev->active_scan_mask, iio_get_masklength(indio_dev));
> +
> + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG,
> + bitmap_read(indio_dev->active_scan_mask, 0,
> + iio_get_masklength(indio_dev)));
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG,
> + ~bitmap_read(indio_dev->active_scan_mask, 0,
> + iio_get_masklength(indio_dev)) & GENMASK(15, 0));
This indent is hard to read. I would either use a local variable, or do it as
ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG,
~bitmap_read(indio_dev->active_scan_mask, 0,
iio_get_masklength(indio_dev)) &
GENMASK(15, 0));
> + if (ret)
> + return ret;
> +
> + ret = ad4691_enter_conversion_mode(st);
> + if (ret)
> + return ret;
> +
> + memset(st->scan_xfers, 0, sizeof(st->scan_xfers));
> +
> + /*
> + * Each AVG_IN register read uses two 16-bit transfers:
> + * TX: [reg_hi | 0x80, reg_lo] (address, CS stays asserted)
> + * RX: [data_hi, data_lo] (data, storagebits=16, shift=0)
> + * The state reset is also split into two 16-bit transfers
> + * (address then value) to keep bits_per_word uniform throughout.
> + */
> + k = 0;
> + iio_for_each_active_channel(indio_dev, bit) {
> + put_unaligned_be16(0x8000 | AD4691_AVG_IN(bit), offload->tx_cmd[k]);
> +
> + /* TX: address phase, CS stays asserted into data phase */
> + st->scan_xfers[2 * k].tx_buf = offload->tx_cmd[k];
> + st->scan_xfers[2 * k].len = sizeof(offload->tx_cmd[k]);
> + st->scan_xfers[2 * k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;
> +
> + /* RX: data phase, CS toggles after to delimit the next register op */
> + st->scan_xfers[2 * k + 1].len = sizeof(offload->tx_cmd[k]);
> + st->scan_xfers[2 * k + 1].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;
> + st->scan_xfers[2 * k + 1].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM;
> + st->scan_xfers[2 * k + 1].cs_change = 1;
> + k++;
> + }
> +
> + /* State reset to re-arm DATA_READY for the next scan. */
> + put_unaligned_be16(AD4691_STATE_RESET_REG, offload->tx_reset);
> + offload->tx_reset[2] = AD4691_STATE_RESET_ALL;
> +
> + st->scan_xfers[2 * k].tx_buf = offload->tx_reset;
> + st->scan_xfers[2 * k].len = sizeof(offload->tx_cmd[k]);
> + st->scan_xfers[2 * k].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;
> +
> + st->scan_xfers[2 * k + 1].tx_buf = &offload->tx_reset[2];
> + st->scan_xfers[2 * k + 1].len = sizeof(offload->tx_cmd[k]);
> + st->scan_xfers[2 * k + 1].bits_per_word = AD4691_OFFLOAD_BITS_PER_WORD;
> + st->scan_xfers[2 * k + 1].cs_change = 1;
> +
> + spi_message_init_with_transfers(&st->scan_msg, st->scan_xfers, 2 * k + 2);
> + st->scan_msg.offload = offload->spi;
> +
> + ret = spi_optimize_message(spi, &st->scan_msg);
> + if (ret)
> + goto err_exit_conversion;
> +
> + ret = ad4691_sampling_enable(st, true);
> + if (ret)
> + goto err_unoptimize;
> +
> + ret = spi_offload_trigger_enable(offload->spi, offload->trigger, &config);
> + if (ret)
> + goto err_sampling_disable;
> +
> + return 0;
> +
> +err_sampling_disable:
> + ad4691_sampling_enable(st, false);
> +err_unoptimize:
> + spi_unoptimize_message(&st->scan_msg);
> +err_exit_conversion:
> + ad4691_exit_conversion_mode(st);
> + return ret;
> +}
>
> static ssize_t sampling_frequency_store(struct device *dev,
> @@ -833,6 +1123,23 @@ static ssize_t sampling_frequency_store(struct device *dev,
> if (ret)
> return ret;
>
> + if (st->manual_mode && st->offload) {
> + struct spi_offload_trigger_config config = {
> + .type = SPI_OFFLOAD_TRIGGER_PERIODIC,
> + .periodic = { .frequency_hz = freq },
> + };
> +
> + ret = spi_offload_trigger_validate(st->offload->trigger, &config);
> + if (ret) {
> + iio_device_release_direct(indio_dev);
> + return ret;
> + }
> +
> + st->offload->trigger_hz = config.periodic.frequency_hz;
> + iio_device_release_direct(indio_dev);
This release in a different scope is a bit ugly.
Look at whether the auto cleanup approach works well here.
https://elixir.bootlin.com/linux/v7.0-rc7/source/include/linux/iio/iio.h#L767
> + return len;
> + }
> +
^ permalink raw reply
* Re: [PATCH v7 3/6] iio: adc: ad4691: add triggered buffer support
From: Jonathan Cameron @ 2026-04-12 17:47 UTC (permalink / raw)
To: Radu Sabau via B4 Relay
Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, David Lechner,
Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Uwe Kleine-König, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Philipp Zabel,
Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
linux-pwm, linux-gpio, linux-doc
In-Reply-To: <20260409-ad4692-multichannel-sar-adc-driver-v7-3-be375d4df2c5@analog.com>
On Thu, 09 Apr 2026 18:28:24 +0300
Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org> wrote:
> From: Radu Sabau <radu.sabau@analog.com>
>
> Add buffered capture support using the IIO triggered buffer framework.
>
> CNV Burst Mode: the GP pin identified by interrupt-names in the device
> tree is configured as DATA_READY output. The IRQ handler stops
> conversions and fires the IIO trigger; the trigger handler executes a
> pre-built SPI message that reads all active channels from the AVG_IN
> accumulator registers and then resets accumulator state and restarts
> conversions for the next cycle.
>
> Manual Mode: CNV is tied to SPI CS so each transfer simultaneously
> reads the previous result and starts the next conversion (pipelined
> N+1 scheme). At preenable time a pre-built, optimised SPI message of
> N+1 transfers is constructed (N channel reads plus one NOOP to drain
> the pipeline). The trigger handler executes the message in a single
> spi_sync() call and collects the results. An external trigger (e.g.
> iio-trig-hrtimer) is required to drive the trigger at the desired
> sample rate.
>
> Both modes share the same trigger handler and push a complete scan —
> one u16 slot per channel at its scan_index position, followed by a
> timestamp — to the IIO buffer via iio_push_to_buffers_with_ts().
>
> The CNV Burst Mode sampling frequency (PWM period) is exposed as a
> buffer-level attribute via IIO_DEVICE_ATTR.
>
> Signed-off-by: Radu Sabau <radu.sabau@analog.com>
A couple of minor things inline.
Thanks,
Jonathan
> diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c
> index 43bd408c3d11..3e5caa0972eb 100644
> --- a/drivers/iio/adc/ad4691.c
> +++ b/drivers/iio/adc/ad4691.c
> @@ -5,15 +5,19 @@
> */
> #include <linux/array_size.h>
> #include <linux/bitfield.h>
> -#include <linux/bitops.h>
> +#include <linux/bitmap.h>
> #include <linux/cleanup.h>
> #include <linux/delay.h>
> #include <linux/dev_printk.h>
> #include <linux/device/devres.h>
> +#include <linux/dmaengine.h>
> #include <linux/err.h>
> +#include <linux/interrupt.h>
> #include <linux/math.h>
> #include <linux/module.h>
> #include <linux/mod_devicetable.h>
> +#include <linux/property.h>
> +#include <linux/pwm.h>
> #include <linux/regmap.h>
> #include <linux/regulator/consumer.h>
> #include <linux/reset.h>
> @@ -21,7 +25,14 @@
> #include <linux/units.h>
> #include <linux/unaligned.h>
>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/buffer-dma.h>
> +#include <linux/iio/buffer-dmaengine.h>
Not yet... Only bring these headers in when you need them.
So far this is just doing normal SPI stuff.
> #include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/iio/trigger.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/iio/trigger_consumer.h>
> @@ -201,8 +245,45 @@ struct ad4691_state {
> * atomicity of consecutive SPI operations.
> */
> struct mutex lock;
> + /*
> + * Per-buffer-enable lifetime resources:
> + * Manual Mode - a pre-built SPI message that clocks out N+1
> + * transfers in one go.
> + * CNV Burst Mode - a pre-built SPI message that clocks out 2*N
> + * transfers in one go.
> + */
> + struct spi_message scan_msg;
> + /* max 16 + 1 NOOP (manual) or 2*16 + 2 (CNV burst). */
> + struct spi_transfer scan_xfers[34];
> + /*
> + * CNV burst: 16 AVG_IN addresses + state-reset address + state-reset
> + * value = 18. Manual: 16 channel cmds + 1 NOOP = 17.
> + */
> + __be16 scan_tx[18];
David raised this. As these aren't going through the regmap and are using
spi_transfers directly they need to be using DMA safe buffers.
> + /* Scan buffer: one BE16 slot per channel (rx'd directly), plus timestamp */
> + struct {
> + __be16 vals[16];
> + aligned_s64 ts;
> + } scan;
> };
> +static int ad4691_manual_buffer_preenable(struct iio_dev *indio_dev)
> +{
> + struct ad4691_state *st = iio_priv(indio_dev);
> + unsigned int n_active;
> + unsigned int n_xfers;
> + unsigned int prev_i, k, i;
> + bool first;
> + int ret;
> +
> + n_active = bitmap_weight(indio_dev->active_scan_mask, iio_get_masklength(indio_dev));
> + n_xfers = n_active + 1;
> +
> + memset(st->scan_xfers, 0, n_xfers * sizeof(st->scan_xfers[0]));
> + memset(st->scan_tx, 0, n_xfers * sizeof(st->scan_tx[0]));
> +
> + spi_message_init(&st->scan_msg);
> +
> + first = true;
> + prev_i = 0;
> + k = 0;
> + iio_for_each_active_channel(indio_dev, i) {
> + st->scan_tx[k] = cpu_to_be16(AD4691_ADC_CHAN(i));
> + st->scan_xfers[k].tx_buf = &st->scan_tx[k];
> + /*
> + * The pipeline means xfer[0] receives the residual from the
> + * previous sequence, not a valid sample for channel i. Point
> + * it at vals[i] anyway; xfer[1] (or the NOOP when only one
> + * channel is active) will overwrite that slot with the real
> + * result, so no separate dummy buffer is needed.
> + */
> + if (first) {
> + st->scan_xfers[k].rx_buf = &st->scan.vals[i];
> + first = false;
> + } else {
> + st->scan_xfers[k].rx_buf = &st->scan.vals[prev_i];
> + }
> + st->scan_xfers[k].len = sizeof(__be16);
> + st->scan_xfers[k].cs_change = 1;
> + spi_message_add_tail(&st->scan_xfers[k], &st->scan_msg);
> + prev_i = i;
> + k++;
> + }
> +
> + /* Final NOOP transfer retrieves the last channel's result. */
> + st->scan_xfers[k].tx_buf = &st->scan_tx[k]; /* scan_tx[k] == 0 == NOOP */
> + st->scan_xfers[k].rx_buf = &st->scan.vals[prev_i];
> + st->scan_xfers[k].len = sizeof(__be16);
> + spi_message_add_tail(&st->scan_xfers[k], &st->scan_msg);
> +
> + ret = spi_optimize_message(st->spi, &st->scan_msg);
> + if (ret)
See below. This matches my expectations for what to do if spi_optimize_message()
fails.
> + return ret;
> +
> + ret = ad4691_enter_conversion_mode(st);
> + if (ret) {
> + spi_unoptimize_message(&st->scan_msg);
> + return ret;
> + }
> +
> + return 0;
> +}
> +static int ad4691_cnv_burst_buffer_preenable(struct iio_dev *indio_dev)
> +{
> + struct ad4691_state *st = iio_priv(indio_dev);
> + unsigned int n_active;
> + unsigned int k, i;
> + int ret;
> +
> + n_active = bitmap_weight(indio_dev->active_scan_mask, iio_get_masklength(indio_dev));
> +
> + memset(st->scan_xfers, 0, (2 * n_active + 2) * sizeof(st->scan_xfers[0]));
> + memset(st->scan_tx, 0, (n_active + 2) * sizeof(st->scan_tx[0]));
> +
> + spi_message_init(&st->scan_msg);
> +
> + /*
> + * Each AVG_IN read needs two transfers: a 2-byte address write phase
> + * followed by a 2-byte data read phase. CS toggles between channels
> + * (cs_change=1 on the read phase of all but the last channel).
> + */
> + k = 0;
> + iio_for_each_active_channel(indio_dev, i) {
> + st->scan_tx[k] = cpu_to_be16(0x8000 | AD4691_AVG_IN(i));
> + st->scan_xfers[2 * k].tx_buf = &st->scan_tx[k];
> + st->scan_xfers[2 * k].len = sizeof(__be16);
> + spi_message_add_tail(&st->scan_xfers[2 * k], &st->scan_msg);
> + st->scan_xfers[2 * k + 1].rx_buf = &st->scan.vals[i];
> + st->scan_xfers[2 * k + 1].len = sizeof(__be16);
> + st->scan_xfers[2 * k + 1].cs_change = 1;
> + spi_message_add_tail(&st->scan_xfers[2 * k + 1], &st->scan_msg);
> + k++;
> + }
> +
> + st->scan_tx[k] = cpu_to_be16(AD4691_STATE_RESET_REG);
> + st->scan_xfers[2 * k].tx_buf = &st->scan_tx[k];
> + st->scan_xfers[2 * k].len = sizeof(__be16);
> + spi_message_add_tail(&st->scan_xfers[2 * k], &st->scan_msg);
> + st->scan_tx[k + 1] = cpu_to_be16(AD4691_STATE_RESET_ALL << 8);
> + st->scan_xfers[2 * k + 1].tx_buf = &st->scan_tx[k + 1];
> + st->scan_xfers[2 * k + 1].len = sizeof(__be16);
> + st->scan_xfers[2 * k + 1].cs_change = 1;
> + spi_message_add_tail(&st->scan_xfers[2 * k + 1], &st->scan_msg);
> +
> + ret = spi_optimize_message(st->spi, &st->scan_msg);
> + if (ret)
> + goto err_unoptimize;
I'd expect spi_optimize_message() to be side effect free if it fails.
I took a quick look at the implementation and it looks like it is..
So probably just return ret; here
That matches with the other similar flow above.
> +
> + ret = regmap_write(st->regmap, AD4691_STD_SEQ_CONFIG,
> + bitmap_read(indio_dev->active_scan_mask, 0,
> + iio_get_masklength(indio_dev)));
> + if (ret)
> + goto err_unoptimize;
> +
> + ret = regmap_write(st->regmap, AD4691_ACC_MASK_REG,
> + ~bitmap_read(indio_dev->active_scan_mask, 0,
> + iio_get_masklength(indio_dev)) & GENMASK(15, 0));
> + if (ret)
> + goto err_unoptimize;
> +
> + ret = ad4691_enter_conversion_mode(st);
> + if (ret)
> + goto err_unoptimize;
> +
> + ret = ad4691_sampling_enable(st, true);
> + if (ret)
> + goto err_exit_conv;
> +
> + enable_irq(st->irq);
> + return 0;
> +
> +err_exit_conv:
> + ad4691_exit_conversion_mode(st);
> +err_unoptimize:
> + spi_unoptimize_message(&st->scan_msg);
> + return ret;
> +}
> +static int ad4691_setup_triggered_buffer(struct iio_dev *indio_dev,
> + struct ad4691_state *st)
> +{
> + struct device *dev = regmap_get_device(st->regmap);
> + struct iio_trigger *trig;
> + unsigned int i;
> + int irq, ret;
> +
> + trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
> + indio_dev->name,
> + iio_device_id(indio_dev));
Might as well wrap this less.
> + if (!trig)
> + return -ENOMEM;
> +
^ permalink raw reply
* Re: [PATCH v7 3/6] iio: adc: ad4691: add triggered buffer support
From: Jonathan Cameron @ 2026-04-12 17:44 UTC (permalink / raw)
To: David Lechner
Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Liam Girdwood, Mark Brown, Linus Walleij,
Bartosz Golaszewski, Philipp Zabel, Jonathan Corbet, Shuah Khan,
linux-iio, devicetree, linux-kernel, linux-pwm, linux-gpio,
linux-doc
In-Reply-To: <20260412184301.05544396@jic23-huawei>
On Sun, 12 Apr 2026 18:43:01 +0100
Jonathan Cameron <jic23@kernel.org> wrote:
> On Fri, 10 Apr 2026 15:46:36 -0500
> David Lechner <dlechner@baylibre.com> wrote:
>
> > On 4/9/26 10:28 AM, Radu Sabau via B4 Relay wrote:
> > > From: Radu Sabau <radu.sabau@analog.com>
> > >
> > > Add buffered capture support using the IIO triggered buffer framework.
> > >
> >
> > ...
> >
> > > @@ -201,8 +245,45 @@ struct ad4691_state {
> > > * atomicity of consecutive SPI operations.
> > > */
> > > struct mutex lock;
> > > + /*
> > > + * Per-buffer-enable lifetime resources:
> > > + * Manual Mode - a pre-built SPI message that clocks out N+1
> > > + * transfers in one go.
> > > + * CNV Burst Mode - a pre-built SPI message that clocks out 2*N
> > > + * transfers in one go.
> > > + */
> > > + struct spi_message scan_msg;
> > > + /* max 16 + 1 NOOP (manual) or 2*16 + 2 (CNV burst). */
> > > + struct spi_transfer scan_xfers[34];
> > > + /*
> > > + * CNV burst: 16 AVG_IN addresses + state-reset address + state-reset
> > > + * value = 18. Manual: 16 channel cmds + 1 NOOP = 17.
> > > + */
> > > + __be16 scan_tx[18];
> >
> > Needs __aligned(IIO_DMA_MINALIGN) since it is used with SPI.
> As below.
> >
> > > + /* Scan buffer: one BE16 slot per channel (rx'd directly), plus timestamp */
> > > + struct {
> > > + __be16 vals[16];
> > > + aligned_s64 ts;
> > > + } scan;
> >
> > Unless it is required that all channels are always enabled:
> >
> > IIO_DECLARE_BUFFER_WITH_TS(__be16, scan_rx, 16);
> >
> > In any case, needs to be DMA-safe for SPI.
> Custom regmap that uses spi_write_then_read() for all cases so it
> should be bounced anyway.
>
> Perhaps a comment to that affect would be useful.
>
Ignore that. It's an optimized spi message. oops.
> J
>
^ permalink raw reply
* Re: [PATCH v7 3/6] iio: adc: ad4691: add triggered buffer support
From: Jonathan Cameron @ 2026-04-12 17:43 UTC (permalink / raw)
To: David Lechner
Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
Andy Shevchenko, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Uwe Kleine-König, Liam Girdwood, Mark Brown, Linus Walleij,
Bartosz Golaszewski, Philipp Zabel, Jonathan Corbet, Shuah Khan,
linux-iio, devicetree, linux-kernel, linux-pwm, linux-gpio,
linux-doc
In-Reply-To: <0f05add7-96c0-4eee-b396-d6e1be904c09@baylibre.com>
On Fri, 10 Apr 2026 15:46:36 -0500
David Lechner <dlechner@baylibre.com> wrote:
> On 4/9/26 10:28 AM, Radu Sabau via B4 Relay wrote:
> > From: Radu Sabau <radu.sabau@analog.com>
> >
> > Add buffered capture support using the IIO triggered buffer framework.
> >
>
> ...
>
> > @@ -201,8 +245,45 @@ struct ad4691_state {
> > * atomicity of consecutive SPI operations.
> > */
> > struct mutex lock;
> > + /*
> > + * Per-buffer-enable lifetime resources:
> > + * Manual Mode - a pre-built SPI message that clocks out N+1
> > + * transfers in one go.
> > + * CNV Burst Mode - a pre-built SPI message that clocks out 2*N
> > + * transfers in one go.
> > + */
> > + struct spi_message scan_msg;
> > + /* max 16 + 1 NOOP (manual) or 2*16 + 2 (CNV burst). */
> > + struct spi_transfer scan_xfers[34];
> > + /*
> > + * CNV burst: 16 AVG_IN addresses + state-reset address + state-reset
> > + * value = 18. Manual: 16 channel cmds + 1 NOOP = 17.
> > + */
> > + __be16 scan_tx[18];
>
> Needs __aligned(IIO_DMA_MINALIGN) since it is used with SPI.
As below.
>
> > + /* Scan buffer: one BE16 slot per channel (rx'd directly), plus timestamp */
> > + struct {
> > + __be16 vals[16];
> > + aligned_s64 ts;
> > + } scan;
>
> Unless it is required that all channels are always enabled:
>
> IIO_DECLARE_BUFFER_WITH_TS(__be16, scan_rx, 16);
>
> In any case, needs to be DMA-safe for SPI.
Custom regmap that uses spi_write_then_read() for all cases so it
should be bounced anyway.
Perhaps a comment to that affect would be useful.
J
^ permalink raw reply
* [PATCH] arm: dts: allwinner: t113s mangopi: enable watchdog for reboot
From: Michal Piekos @ 2026-04-12 17:42 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland
Cc: devicetree, linux-arm-kernel, linux-sunxi, linux-kernel,
Michal Piekos
Reboot hangs on MangoPi MQ-R T113s because no restart handler is
available.
Enable the SoC watchdog whose driver registers a restart handler.
Tested on MangoPi MQ-R T113s.
Signed-off-by: Michal Piekos <michal.piekos@mmpsystems.pl>
---
arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts b/arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts
index 8b3a75383816..f0232a5e903b 100644
--- a/arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts
+++ b/arch/arm/boot/dts/allwinner/sun8i-t113s-mangopi-mq-r-t113.dts
@@ -33,3 +33,7 @@ rtl8189ftv: wifi@1 {
interrupt-names = "host-wake";
};
};
+
+&wdt {
+ status = "okay";
+};
---
base-commit: f5459048c38a00fc583658d6dcd0f894aff6df8f
change-id: 20260412-t113-mangopi-reboot-hang-c9a9def82e2b
Best regards,
--
Michal Piekos <michal.piekos@mmpsystems.pl>
^ permalink raw reply related
* [PATCH v3 2/2] drm/bridge: waveshare-dsi: support DSI LCD kits with LVDS panels
From: Dmitry Baryshkov @ 2026-04-12 17:32 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg,
Joseph Guo, Marek Vasut, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec
Cc: dri-devel, devicetree, linux-kernel
In-Reply-To: <20260412-ws-lcd-v3-0-db22c2631828@oss.qualcomm.com>
Several Waveshare DSI LCD kits use LVDS panels and the ICN6202 DSI2LVDS
bridge. Support that setup by handling waveshare,dsi2lvds compatible.
The only difference with the existing waveshare,dsi2dpi is the bridge's
output type (LVDS vs DPI).
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
drivers/gpu/drm/bridge/waveshare-dsi.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/bridge/waveshare-dsi.c b/drivers/gpu/drm/bridge/waveshare-dsi.c
index 32d40414adb9..ded57f298d64 100644
--- a/drivers/gpu/drm/bridge/waveshare-dsi.c
+++ b/drivers/gpu/drm/bridge/waveshare-dsi.c
@@ -177,7 +177,7 @@ static int ws_bridge_probe(struct i2c_client *i2c)
regmap_write(ws->reg_map, 0xc2, 0x01);
regmap_write(ws->reg_map, 0xac, 0x01);
- ws->bridge.type = DRM_MODE_CONNECTOR_DPI;
+ ws->bridge.type = (uintptr_t)i2c_get_match_data(i2c);
ws->bridge.of_node = dev->of_node;
devm_drm_bridge_add(dev, &ws->bridge);
@@ -185,7 +185,8 @@ static int ws_bridge_probe(struct i2c_client *i2c)
}
static const struct of_device_id ws_bridge_of_ids[] = {
- {.compatible = "waveshare,dsi2dpi",},
+ {.compatible = "waveshare,dsi2dpi", .data = (void *)DRM_MODE_CONNECTOR_DPI, },
+ {.compatible = "waveshare,dsi2lvds", .data = (void *)DRM_MODE_CONNECTOR_LVDS, },
{ }
};
--
2.47.3
^ permalink raw reply related
* [PATCH v3 1/2] dt-bindings: display: waveshare,dsp2dpi: describe DSI2LVDS setup
From: Dmitry Baryshkov @ 2026-04-12 17:32 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg,
Joseph Guo, Marek Vasut, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec
Cc: dri-devel, devicetree, linux-kernel
In-Reply-To: <20260412-ws-lcd-v3-0-db22c2631828@oss.qualcomm.com>
Several the Waveshare DSI LCD panel kits use DSI2LVDS ICN6202 bridge
together with the LVDS panels. Define new compatible for the on-kit
bridge setup (it is not itmized and it uses Waveshare prefix since the
rest of the integration details are not known).
Note: the ICN6202 / ICN6211 bridges are completely handled by the board
itself, they should not be programmed by the host (which otherwise might
override correct params), etc. As such, it doesn't make sense to use
those in the compat strings. I consider those to be an internal detail
of the setup.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
.../devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml b/Documentation/devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml
index 3820dd7e11af..4d34a92192bf 100644
--- a/Documentation/devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml
@@ -10,11 +10,14 @@ maintainers:
- Joseph Guo <qijian.guo@nxp.com>
description:
- Waveshare bridge board is part of Waveshare panel which converts DSI to DPI.
+ Waveshare bridge board is part of Waveshare panel which converts DSI to DPI
+ or LVDS.
properties:
compatible:
- const: waveshare,dsi2dpi
+ enum:
+ - waveshare,dsi2dpi
+ - waveshare,dsi2lvds
reg:
maxItems: 1
@@ -53,7 +56,7 @@ properties:
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
- Video port for MIPI DPI output panel.
+ Video port for MIPI DPI or LVDS output to the panel.
required:
- port@0
--
2.47.3
^ permalink raw reply related
* [PATCH v3 0/2] drm/panel: simple: add Waveshare LCD panels
From: Dmitry Baryshkov @ 2026-04-12 17:32 UTC (permalink / raw)
To: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding, Sam Ravnborg,
Joseph Guo, Marek Vasut, Andrzej Hajda, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec
Cc: dri-devel, devicetree, linux-kernel
Waveshare have a serie of DSI panel kits with the DPI or LVDS panel
being attached to the DSI2DPI or DSI2LVDS bridge. Commit 80b0eb11f8e0
("dt-bindings: display: panel: Add waveshare DPI panel support")
described two of them in the bindings and commit 46be11b678e0
("drm/panel: simple: Add Waveshare 13.3" panel support") added
definitions for one of those panels. Add support for the rest of them.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Changes in v3:
- Rebased on drm-misc-next, dropping applied patches
- Link to v2: https://patch.msgid.link/20260331-ws-lcd-v2-0-a1add63b6eb6@oss.qualcomm.com
Changes in v2:
- Updated waveshare,dsi2dpi schema to implicitly mention LVDS
(Krzysztof)
- Updated commit message to explain why the ICN6202 / ICN6211 bridges
are not a part of the DT bindings.
- Link to v1: https://patch.msgid.link/20260330-ws-lcd-v1-0-309834a435c0@oss.qualcomm.com
---
Dmitry Baryshkov (2):
dt-bindings: display: waveshare,dsp2dpi: describe DSI2LVDS setup
drm/bridge: waveshare-dsi: support DSI LCD kits with LVDS panels
.../devicetree/bindings/display/bridge/waveshare,dsi2dpi.yaml | 9 ++++++---
drivers/gpu/drm/bridge/waveshare-dsi.c | 5 +++--
2 files changed, 9 insertions(+), 5 deletions(-)
---
base-commit: efcd474ed273ae7da614b30e798651c6d57d3109
change-id: 20260330-ws-lcd-b65c03c5ac17
Best regards,
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v7 2/6] iio: adc: ad4691: add initial driver for AD4691 family
From: Jonathan Cameron @ 2026-04-12 17:24 UTC (permalink / raw)
To: Radu Sabau via B4 Relay
Cc: radu.sabau, Lars-Peter Clausen, Michael Hennerich, David Lechner,
Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Uwe Kleine-König, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, Philipp Zabel,
Jonathan Corbet, Shuah Khan, linux-iio, devicetree, linux-kernel,
linux-pwm, linux-gpio, linux-doc
In-Reply-To: <20260409-ad4692-multichannel-sar-adc-driver-v7-2-be375d4df2c5@analog.com>
On Thu, 09 Apr 2026 18:28:23 +0300
Radu Sabau via B4 Relay <devnull+radu.sabau.analog.com@kernel.org> wrote:
> From: Radu Sabau <radu.sabau@analog.com>
>
> Add support for the Analog Devices AD4691 family of high-speed,
> low-power multichannel SAR ADCs: AD4691 (16-ch, 500 kSPS),
> AD4692 (16-ch, 1 MSPS), AD4693 (8-ch, 500 kSPS) and
> AD4694 (8-ch, 1 MSPS).
>
> The driver implements a custom regmap layer over raw SPI to handle the
> device's mixed 1/2/3/4-byte register widths and uses the standard IIO
> read_raw/write_raw interface for single-channel reads.
>
> The chip idles in Autonomous Mode so that single-shot read_raw can use
> the internal oscillator without disturbing the hardware configuration.
>
> Three voltage supply domains are managed: avdd (required), vio, and a
> reference supply on either the REF pin (ref-supply, external buffer)
> or the REFIN pin (refin-supply, uses the on-chip reference buffer;
> REFBUF_EN is set accordingly). Hardware reset is performed via
> the reset controller framework; a software reset through SPI_CONFIG_A
> is used as fallback when no hardware reset is available.
>
> Accumulator channel masking for single-shot reads uses ACC_MASK_REG via
> an ADDR_DESCENDING SPI write, which covers both mask bytes in a single
> 16-bit transfer.
>
> Reviewed-by: David Lechner <dlechner@baylibre.com>
> Signed-off-by: Radu Sabau <radu.sabau@analog.com>
Mostly minor stuff but the regulator bit needs another look.
> diff --git a/drivers/iio/adc/ad4691.c b/drivers/iio/adc/ad4691.c
> new file mode 100644
> index 000000000000..43bd408c3d11
> --- /dev/null
> +++ b/drivers/iio/adc/ad4691.c
> +static int ad4691_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> + struct spi_device *spi = context;
> + u8 tx[2], rx[4];
> + int ret;
> +
> + /* Set bit 15 to mark the operation as READ. */
> + put_unaligned_be16(0x8000 | reg, tx);
> +
> + switch (reg) {
> + case 0 ... AD4691_OSC_FREQ_REG:
> + case AD4691_SPARE_CONTROL ... AD4691_ACC_SAT_OVR_REG(15):
> + ret = spi_write_then_read(spi, tx, 2, rx, 1);
for tx size can use sizeof(tx)
> + if (ret)
> + return ret;
> + *val = rx[0];
> + return 0;
> + case AD4691_STD_SEQ_CONFIG:
> + case AD4691_AVG_IN(0) ... AD4691_AVG_IN(15):
> + ret = spi_write_then_read(spi, tx, 2, rx, 2);
> + if (ret)
> + return ret;
> + *val = get_unaligned_be16(rx);
> + return 0;
> + case AD4691_AVG_STS_IN(0) ... AD4691_AVG_STS_IN(15):
> + case AD4691_ACC_IN(0) ... AD4691_ACC_IN(15):
> + ret = spi_write_then_read(spi, tx, 2, rx, 3);
> + if (ret)
> + return ret;
> + *val = get_unaligned_be24(rx);
> + return 0;
> + case AD4691_ACC_STS_DATA(0) ... AD4691_ACC_STS_DATA(15):
> + ret = spi_write_then_read(spi, tx, 2, rx, 4);
> + if (ret)
> + return ret;
> + *val = get_unaligned_be32(rx);
> + return 0;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int ad4691_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> + struct spi_device *spi = context;
> + u8 tx[4];
> +
> + put_unaligned_be16(reg, tx);
> +
> + switch (reg) {
> + case 0 ... AD4691_OSC_FREQ_REG:
> + case AD4691_SPARE_CONTROL ... AD4691_ACC_MASK_REG - 1:
> + case AD4691_ACC_MASK_REG + 1 ... AD4691_GPIO_MODE2_REG:
> + if (val > 0xFF)
U8_MAX from limits.h
> + return -EINVAL;
> + tx[2] = val;
> + return spi_write_then_read(spi, tx, 3, NULL, 0);
> + case AD4691_ACC_MASK_REG:
> + case AD4691_STD_SEQ_CONFIG:
> + if (val > 0xFFFF)
U16_MAX
> + return -EINVAL;
> + put_unaligned_be16(val, &tx[2]);
> + return spi_write_then_read(spi, tx, 4, NULL, 0);
> + default:
> + return -EINVAL;
> + }
> +}
> +static int ad4691_set_sampling_freq(struct iio_dev *indio_dev, int freq)
> +{
> + struct ad4691_state *st = iio_priv(indio_dev);
> + unsigned int start = (st->info->max_rate == 1 * HZ_PER_MHZ) ? 0 : 1;
This appears in a couple of places. Maybe a little helper for
ad4691_samp_freq_array_start() would let you describe why in a comment
in a single location.
> +
> + IIO_DEV_ACQUIRE_DIRECT_MODE(indio_dev, claim);
> + if (IIO_DEV_ACQUIRE_FAILED(claim))
> + return -EBUSY;
> +
> + for (unsigned int i = start; i < ARRAY_SIZE(ad4691_osc_freqs_Hz); i++) {
> + if (ad4691_osc_freqs_Hz[i] != freq)
> + continue;
> + return regmap_update_bits(st->regmap, AD4691_OSC_FREQ_REG,
> + AD4691_OSC_FREQ_MASK, i);
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int ad4691_read_avail(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + const int **vals, int *type,
> + int *length, long mask)
> +{
> + struct ad4691_state *st = iio_priv(indio_dev);
> + unsigned int start = (st->info->max_rate == 1 * HZ_PER_MHZ) ? 0 : 1;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + *vals = &ad4691_osc_freqs_Hz[start];
> + *type = IIO_VAL_INT;
> + *length = ARRAY_SIZE(ad4691_osc_freqs_Hz) - start;
> + return IIO_AVAIL_LIST;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int ad4691_regulator_setup(struct ad4691_state *st)
> +{
> + struct device *dev = regmap_get_device(st->regmap);
> + int ret;
> +
> + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4691_supplies),
> + ad4691_supplies);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to get and enable supplies\n");
> +
> + ret = devm_regulator_get_enable(dev, "ldo-in");
> + if (ret == -ENODEV)
> + st->ldo_en = true;
This seems odd. ldo_en to me implies enabling the internal LDO, which I'd expect
to need the ldo-in supply. Anyhow - that oddity made me dig...
The datasheet is rather confusingly worded but the diagrams seem clear.
I 'think' the only time the ldo should not be enabled is when VDD = 1.8V and
LDO_IN is then tied to 0 (which maybe we represent at no ldo-in regulator?)
When ldo-in is supplied and the LDO enabled, the LDO output is tied to the VDD pin
internally. So you'd should not be feeding VDD in that case. There is a note
that says that it'll survive being also powered to 1.8V or grounded, but seems
to strongly advise against doing that.
Anyhow, what you have here and the dt-binding don't seem to align with the datasheet.
Figure 54 shows this most clearly. Your dt binding doesn't include vdd which
is also not aligning with the ad4691 datasheet on the website.
> + else if (ret)
> + return dev_err_probe(dev, ret, "Failed to get and enable LDO-IN\n");
> +
> + st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "ref");
> + if (st->vref_uV == -ENODEV) {
> + st->vref_uV = devm_regulator_get_enable_read_voltage(dev, "refin");
> + st->refbuf_en = true;
> + }
> + if (st->vref_uV < 0)
> + return dev_err_probe(dev, st->vref_uV,
> + "Failed to get reference supply\n");
> +
> + if (st->vref_uV < AD4691_VREF_uV_MIN || st->vref_uV > AD4691_VREF_uV_MAX)
> + return dev_err_probe(dev, -EINVAL,
> + "vref(%d) must be in the range [%u...%u]\n",
> + st->vref_uV, AD4691_VREF_uV_MIN,
> + AD4691_VREF_uV_MAX);
> +
> + return 0;
> +}
> +
> +static int ad4691_reset(struct ad4691_state *st)
> +{
> + struct device *dev = regmap_get_device(st->regmap);
> + struct reset_control *rst;
> +
> + rst = devm_reset_control_get_optional_exclusive(dev, NULL);
> + if (IS_ERR(rst))
> + return dev_err_probe(dev, PTR_ERR(rst), "Failed to get reset\n");
> +
> + if (rst) {
> + /*
> + * The GPIO is already asserted by reset_gpio_probe().
I thought assumption was that firmware (or driver going down) should always
leave the device in reset and hence could safely do
devm_reset_control_get_optional_exclusive_deasserted() without
the need for the dance with asserting / sleep deasserting.
More than possible I've misunderstood this bit (or we have known firmware
out there that doesn't leave this in reset - in which case good to document
that here).
I don't mind the explicit code you have, just want to understand the reasoning
a little more.
FWIW, if anyone fancies taking a look, a few of the IIO drivers could
do to use the various 'extended' devm calls rather than doing their own
handling off assert and deassert via devm_add_action_or_rest()
> + * Wait for the reset pulse width required by the chip.
> + * See datasheet Table 5.
> + */
> + fsleep(300);
> + return reset_control_deassert(rst);
> + }
> +
> + /* No hardware reset available, fall back to software reset. */
> + return regmap_write(st->regmap, AD4691_SPI_CONFIG_A_REG,
> + AD4691_SW_RESET);
> +}
> +
> +static int ad4691_config(struct ad4691_state *st)
> +{
...
> + val = FIELD_PREP(AD4691_REF_CTRL_MASK, ref_val);
> + if (st->refbuf_en)
> + val |= AD4691_REFBUF_EN;
> +
> + ret = regmap_update_bits(st->regmap, AD4691_REF_CTRL,
> + AD4691_REF_CTRL_MASK | AD4691_REFBUF_EN, val);
It doesn't hugely matter but given (at least for the AD4691) the other bits
are reserved and reset to 0 you could just write the whole thing and avoid
a bus read. Doing it like this kind of implies there is something to
preserve. I was curious what hence looked it up.
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to write REF_CTRL\n");
> +
> + ret = regmap_assign_bits(st->regmap, AD4691_DEVICE_SETUP,
> + AD4691_LDO_EN, st->ldo_en);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to write DEVICE_SETUP\n");
> +
> + /*
> + * Set the internal oscillator to the highest rate this chip supports.
> + * Index 0 (1 MHz) exceeds the 500 kHz max of AD4691/AD4693, so those
> + * chips start at index 1 (500 kHz).
> + */
> + ret = regmap_assign_bits(st->regmap, AD4691_OSC_FREQ_REG,
> + AD4691_OSC_FREQ_MASK,
Similar to above. You could simplify to a write only given rest are reserved 0 bits.
Maybe it's simpler to keep them all the same though. Up to you.
> + (st->info->max_rate == 1 * HZ_PER_MHZ) ? 0 : 1);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to write OSC_FREQ\n");
> +
> + ret = regmap_update_bits(st->regmap, AD4691_ADC_SETUP,
> + AD4691_ADC_MODE_MASK, AD4691_AUTONOMOUS_MODE);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to write ADC_SETUP\n");
> +
> + return 0;
> +}
> +
> +static int ad4691_probe(struct spi_device *spi)
> +{
> + struct device *dev = &spi->dev;
> + struct iio_dev *indio_dev;
> + struct ad4691_state *st;
> + int ret;
> +
> + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + st = iio_priv(indio_dev);
> + st->info = spi_get_device_match_data(spi);
> +
> + ret = devm_mutex_init(dev, &st->lock);
...
thanks
Jonathan
^ permalink raw reply
* Re: [PATCH v2 21/21] gpio: add GPIO controller found on Waveshare DSI TOUCH panels
From: Dmitry Baryshkov @ 2026-04-12 17:17 UTC (permalink / raw)
To: Jie Gan
Cc: Neil Armstrong, Jessica Zhang, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Cong Yang, Ondrej Jirman,
Javier Martinez Canillas, Jagan Teki, Liam Girdwood, Mark Brown,
Linus Walleij, Bartosz Golaszewski, dri-devel, devicetree,
linux-kernel, linux-gpio, Riccardo Mereu
In-Reply-To: <5d1dd70e-0300-4ca0-adb9-73f03cf4bf4d@oss.qualcomm.com>
On Sun, Apr 12, 2026 at 09:06:51AM +0800, Jie Gan wrote:
>
>
> On 4/11/2026 8:10 PM, Dmitry Baryshkov wrote:
> > The Waveshare DSI TOUCH family of panels has separate on-board GPIO
> > controller, which controls power supplies to the panel and the touch
> > screen and provides reset pins for both the panel and the touchscreen.
> > Also it provides a simple PWM controller for panel backlight. Add
> > support for this GPIO controller.
> >
> > Tested-by: Riccardo Mereu <r.mereu@arduino.cc>
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> > ---
> > drivers/gpio/Kconfig | 10 ++
> > drivers/gpio/Makefile | 1 +
> > drivers/gpio/gpio-waveshare-dsi.c | 208 ++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 219 insertions(+)
> >
> > diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> > index dbe7c6e63eab..1b210c451151 100644
> > --- a/drivers/gpio/Kconfig
> > +++ b/drivers/gpio/Kconfig
> > @@ -805,6 +805,16 @@ config GPIO_VISCONTI
> > help
> > Say yes here to support GPIO on Tohisba Visconti.
> > +config GPIO_WAVESHARE_DSI_TOUCH
> > + tristate "Waveshare GPIO controller for DSI panels"
> > + depends on BACKLIGHT_CLASS_DEVICE
> > + depends on I2C
> > + select REGMAP_I2C
> > + help
> > + Enable support for the GPIO and PWM controller found on Waveshare DSI
> > + TOUCH panel kits. It provides GPIOs (used for regulator control and
> > + resets) and backlight support.
> > +
> > config GPIO_WCD934X
> > tristate "Qualcomm Technologies Inc WCD9340/WCD9341 GPIO controller driver"
> > depends on MFD_WCD934X
> > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> > index 20d4a57afdaa..75ce89fc3b93 100644
> > --- a/drivers/gpio/Makefile
> > +++ b/drivers/gpio/Makefile
> > @@ -207,6 +207,7 @@ obj-$(CONFIG_GPIO_VIRTUSER) += gpio-virtuser.o
> > obj-$(CONFIG_GPIO_VIRTIO) += gpio-virtio.o
> > obj-$(CONFIG_GPIO_VISCONTI) += gpio-visconti.o
> > obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
> > +obj-$(CONFIG_GPIO_WAVESHARE_DSI_TOUCH) += gpio-waveshare-dsi.o
> > obj-$(CONFIG_GPIO_WCD934X) += gpio-wcd934x.o
> > obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o
> > obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o
> > diff --git a/drivers/gpio/gpio-waveshare-dsi.c b/drivers/gpio/gpio-waveshare-dsi.c
> > new file mode 100644
> > index 000000000000..f4a1d4d3b872
> > --- /dev/null
> > +++ b/drivers/gpio/gpio-waveshare-dsi.c
> > @@ -0,0 +1,208 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2024 Waveshare International Limited
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + */
> > +
> > +#include <linux/backlight.h>
> > +#include <linux/err.h>
> > +#include <linux/fb.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/regmap.h>
> > +
> > +/* I2C registers of the microcontroller. */
> > +#define REG_TP 0x94
> > +#define REG_LCD 0x95
> > +#define REG_PWM 0x96
> > +#define REG_SIZE 0x97
> > +#define REG_ID 0x98
> > +#define REG_VERSION 0x99
> > +
> > +enum {
> > + GPIO_AVDD = 0,
> > + GPIO_PANEL_RESET = 1,
> > + GPIO_BL_ENABLE = 2,
> > + GPIO_IOVCC = 4,
> > + GPIO_VCC = 8,
> > + GPIO_TS_RESET = 9,
> > +};
> > +
> > +#define NUM_GPIO 16
> > +
> > +struct waveshare_gpio {
> > + struct mutex dir_lock;
> > + struct mutex pwr_lock;
> > + struct regmap *regmap;
> > + u16 poweron_state;
> > +
> > + struct gpio_chip gc;
> > +};
> > +
> > +static const struct regmap_config waveshare_gpio_regmap_config = {
> > + .reg_bits = 8,
> > + .val_bits = 8,
> > + .max_register = REG_PWM,
>
> .max_register = REG_VERSION,
>
> check comments in probe
Yep, thanks (and for other comments too)!
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH 5/5] arm64: dts: arm: fvp-base-revc: Add FF-A notification interrupt
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>
Add an arm,ffa firmware node describing the FF-A notification
interrupt on SGI 8.
Also mark SGI 8 as donated to the non-secure world in the GICv3
node so the interrupt specifier is accepted by the donated-SGI DT
support.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
arch/arm64/boot/dts/arm/fvp-base-revc.dts | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
index 68a69f17e93d..87189b32e38d 100644
--- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts
+++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
@@ -40,6 +40,11 @@ psci {
method = "smc";
};
+ ffa {
+ compatible = "arm,ffa";
+ interrupts = <GIC_SGI 8 IRQ_TYPE_EDGE_RISING>;
+ };
+
cpus {
#address-cells = <2>;
#size-cells = <0>;
@@ -224,6 +229,7 @@ gic: interrupt-controller@2f000000 {
#interrupt-cells = <3>;
#address-cells = <2>;
#size-cells = <2>;
+ arm,secure-donated-ns-sgi-ranges = <8 1>;
ranges;
interrupt-controller;
reg = <0x0 0x2f000000 0 0x10000>, // GICD
--
2.43.0
^ permalink raw reply related
* [PATCH 4/5] firmware: arm_ffa: Use device node interrupts property for IRQ lookup
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>
Use the standard interrupts property from the arm,ffa node instead of
synthesizing a GIC mapping directly.
Requires the "arm,ffa" device node to describe exactly one interrupt,
validate that its affinity spans cpu_possible_mask so the interrupt is
per-CPU, and then cross-check the mapped hwirq against the interrupt
ID returned by FFA_FEATURES.
This removes the FF-A driver's direct arm,gic-v3 lookup and raw
irq_create_of_mapping() usage while still keeping the DT description in
sync with the firmware-reported interrupt.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 53 +++++++++++++++++++++++++++++----------
1 file changed, 40 insertions(+), 13 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index f2f94d4d533e..7a3800a55dc1 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1821,6 +1821,45 @@ static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
ffa_notification_info_get();
}
+static int ffa_dt_map_irq(int intid)
+{
+ struct device_node *ffa __free(device_node) = NULL;
+ const struct cpumask *affinity;
+ struct irq_data *irqd;
+ int count, irq;
+
+ ffa = of_find_compatible_node(NULL, NULL, "arm,ffa");
+ if (!ffa)
+ return -ENXIO;
+
+ count = of_irq_count(ffa);
+ if (count <= 0)
+ return count ? count : -ENXIO;
+
+ if (count != 1) {
+ pr_err("FF-A currently supports exactly one interrupt\n");
+ return -EINVAL;
+ }
+
+ affinity = of_irq_get_affinity(ffa, 0);
+ if (!affinity || !cpumask_equal(affinity, cpu_possible_mask)) {
+ pr_err("FF-A currently supports only SGIs/PPIs\n");
+ return -EINVAL;
+ }
+
+ irq = of_irq_get(ffa, 0);
+ if (irq <= 0)
+ return irq ? irq : -ENXIO;
+
+ irqd = irq_get_irq_data(irq);
+ if (!irqd || irqd_to_hwirq(irqd) != intid) {
+ irq_dispose_mapping(irq);
+ return -EINVAL;
+ }
+
+ return irq;
+}
+
static int ffa_irq_map(u32 id)
{
char *err_str;
@@ -1842,19 +1881,7 @@ static int ffa_irq_map(u32 id)
}
if (acpi_disabled) {
- struct of_phandle_args oirq = {};
- struct device_node *gic;
-
- /* Only GICv3 supported currently with the device tree */
- gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
- if (!gic)
- return -ENXIO;
-
- oirq.np = gic;
- oirq.args_count = 1;
- oirq.args[0] = intid;
- irq = irq_create_of_mapping(&oirq);
- of_node_put(gic);
+ irq = ffa_dt_map_irq(intid);
#ifdef CONFIG_ACPI
} else {
irq = acpi_register_gsi(NULL, intid, ACPI_EDGE_SENSITIVE,
--
2.43.0
^ permalink raw reply related
* [PATCH 3/5] dt-bindings: firmware: Add Arm FF-A binding
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>
Document the FF-A firmware device node.
Describes the "arm,ffa" compatible and requires the standard interrupts
property.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
.../devicetree/bindings/firmware/arm,ffa.yaml | 42 ++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/Documentation/devicetree/bindings/firmware/arm,ffa.yaml b/Documentation/devicetree/bindings/firmware/arm,ffa.yaml
new file mode 100644
index 000000000000..150f394b3327
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/arm,ffa.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/firmware/arm,ffa.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Arm Firmware Framework for A-profile
+
+maintainers:
+ - Sudeep Holla <sudeep.holla@kernel.org>
+
+description: |
+ Arm Firmware Framework for A-profile (FF-A) firmware device node
+ describing the notification interrupt exposed to the normal world.
+
+properties:
+ $nodename:
+ const: ffa
+
+ compatible:
+ const: arm,ffa
+
+ interrupts:
+ description:
+ Per-CPU notification interrupt used by the normal world FF-A partition.
+ maxItems: 1
+
+required:
+ - compatible
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ ffa {
+ compatible = "arm,ffa";
+ interrupts = <GIC_SGI 8 IRQ_TYPE_EDGE_RISING>;
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH 2/5] irqchip/gic-v3: Support secure-donated non-secure SGIs
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>
Parse secure-donated SGI ranges from the firmware, reject invalid
interrupt specifiers, and allow devicetree consumers to map only the
SGIs explicitly donated by the secure side to non-secure software.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
drivers/irqchip/irq-gic-v3.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 20f13b686ab2..cc7720d9fb0e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -35,6 +35,8 @@
#include <asm/smp_plat.h>
#include <asm/virt.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
#include "irq-gic-common.h"
static u8 dist_prio_irq __ro_after_init = GICV3_PRIO_IRQ;
@@ -65,6 +67,7 @@ struct gic_chip_data {
u64 flags;
bool has_rss;
unsigned int ppi_nr;
+ u16 donated_sgi_mask;
struct partition_affinity *parts;
unsigned int nr_parts;
};
@@ -95,6 +98,7 @@ static bool nmi_support_forbidden;
* with hwirq IDs, is simplified by accounting for all 16.
*/
#define SGI_NR 16
+#define GIC_SGI_IPI_NR 8
/*
* The behaviours of RPR and PMR registers differ depending on the value of
@@ -119,6 +123,74 @@ static bool nmi_support_forbidden;
*/
static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
+static bool gic_sgi_is_donated_to_ns(unsigned int sgi)
+{
+ return sgi < SGI_NR && (gic_data.donated_sgi_mask & BIT(sgi));
+}
+
+static int __init gic_of_init_donated_sgi_ranges(struct device_node *node)
+{
+ const char *propname = "arm,secure-donated-ns-sgi-ranges";
+ int count, i;
+ u32 *ranges;
+ u16 mask = 0;
+
+ count = of_property_count_u32_elems(node, propname);
+ if (count < 0) {
+ if (count == -EINVAL)
+ return 0;
+
+ pr_err("%pOF: unable to read %s\n", node, propname);
+ return count;
+ }
+
+ if (!count)
+ return 0;
+
+ if (count % 2) {
+ pr_err("%pOF: %s must contain <sgi span> pairs\n",
+ node, propname);
+ return -EINVAL;
+ }
+
+ ranges = kcalloc(count, sizeof(*ranges), GFP_KERNEL);
+ if (!ranges)
+ return -ENOMEM;
+
+ if (of_property_read_u32_array(node, propname, ranges, count)) {
+ pr_err("%pOF: unable to read %s\n", node, propname);
+ kfree(ranges);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < count; i += 2) {
+ u32 sgi = ranges[i];
+ u32 span = ranges[i + 1];
+ u32 end;
+
+ if (sgi < GIC_SGI_IPI_NR || sgi >= SGI_NR || !span || span > 8) {
+ pr_err("%pOF: invalid SGI range <%u %u> in %s\n",
+ node, sgi, span, propname);
+ kfree(ranges);
+ return -EINVAL;
+ }
+
+ end = sgi + span;
+ if (end > SGI_NR) {
+ pr_err("%pOF: SGI range <%u %u> exceeds SGI space in %s\n",
+ node, sgi, span, propname);
+ kfree(ranges);
+ return -EINVAL;
+ }
+
+ mask |= GENMASK(end - 1, sgi);
+ }
+
+ kfree(ranges);
+ gic_data.donated_sgi_mask = mask;
+ return 0;
+}
+
static u32 gic_get_pribits(void)
{
u32 pribits;
@@ -1614,6 +1686,12 @@ static int gic_irq_domain_translate(struct irq_domain *d,
case 3: /* EPPI */
*hwirq = fwspec->param[1] + EPPI_BASE_INTID;
break;
+ case GIC_SGI: /* SGI */
+ if (!gic_sgi_is_donated_to_ns(fwspec->param[1]))
+ return -EINVAL;
+
+ *hwirq = fwspec->param[1];
+ break;
case GIC_IRQ_TYPE_LPI: /* LPI */
*hwirq = fwspec->param[1];
break;
@@ -1623,6 +1701,10 @@ static int gic_irq_domain_translate(struct irq_domain *d,
*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+ if (fwspec->param[0] == GIC_SGI &&
+ *type != IRQ_TYPE_EDGE_RISING)
+ return -EINVAL;
+
/*
* Make it clear that broken DTs are... broken.
*/
@@ -2239,6 +2321,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
gic_enable_of_quirks(node, gic_quirks, &gic_data);
+ err = gic_of_init_donated_sgi_ranges(node);
+ if (err)
+ goto out_unmap_rdist;
+
err = gic_init_bases(dist_phys_base, dist_base, rdist_regs,
nr_redist_regions, redist_stride, &node->fwnode);
if (err)
--
2.43.0
^ permalink raw reply related
* [PATCH 1/5] dt-bindings: interrupt-controller: Add support for secure donated SGIs
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
In-Reply-To: <20260412-b4-ffa_ns_sgi_gicv3-v1-0-af61243eb405@kernel.org>
In GICv3, SGI security is defined by interrupt grouping and configuration
rather than by SGI number alone. Linux conventionally reserves SGIs 0-7
for non-secure internal kernel IPIs, while higher SGIs is assumed to be
owned/stolen by the Secure world unless explicitly made available.
Document secure donated SGI interrupt specifiers for the GICv3 binding.
It describes "arm,secure-donated-ns-sgi-ranges" for SGIs donated by the
secure world to non-secure software. It excludes SGIs 0-7, which are
already used by the kernel for internal IPI purposes.
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
.../bindings/interrupt-controller/arm,gic-v3.yaml | 27 +++++++++++++++++++++-
include/dt-bindings/interrupt-controller/arm-gic.h | 1 +
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
index bfd30aae682b..664727d071c9 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -45,17 +45,24 @@ description: |
The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
interrupts, 2 for interrupts in the Extended SPI range, 3 for the
- Extended PPI range. Other values are reserved for future use.
+ Extended PPI range, and 4 for SGI interrupts. Other values are
+ reserved for future use.
The 2nd cell contains the interrupt number for the interrupt type.
SPI interrupts are in the range [0-987]. PPI interrupts are in the
range [0-15]. Extended SPI interrupts are in the range [0-1023].
Extended PPI interrupts are in the range [0-127].
+ SGI interrupts are in the range [8-15] which overlaps with the SGIs
+ assigned to/reserved for the secure world but donated to the non
+ secure world to use. Refer "arm,secure-donated-ns-sgi-ranges" for
+ more details.
+
The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = edge triggered
4 = level triggered
+ SGIs are edge triggered and must be described as such.
The 4th cell is a phandle to a node describing a set of CPUs this
interrupt is affine to. The interrupt must be a PPI, and the node
@@ -136,6 +143,24 @@ description: |
- $ref: /schemas/types.yaml#/definitions/uint32
- $ref: /schemas/types.yaml#/definitions/uint64
+ arm,secure-donated-ns-sgi-ranges:
+ description:
+ A list of pairs <sgi span>, where "sgi" is the first SGI INTID of a
+ range donated by the secure side to non-secure software, and "span" is
+ the size of that range. Multiple ranges can be provided.
+
+ SGIs described by interrupt specifiers with type 4 (SGI) must fall
+ within one of these ranges. SGIs(0-7) reserved by non-secure world
+ for internal IPIs must not be listed here. "sgi" must be in the
+ range [8-15], "span" must be in the range [1-8], and the range must
+ not extend past SGI 15.
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ items:
+ - minimum: 8
+ maximum: 15
+ - minimum: 1
+ maximum: 8
+
ppi-partitions:
type: object
additionalProperties: false
diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h
index 887f53363e8a..52c2f3f090c5 100644
--- a/include/dt-bindings/interrupt-controller/arm-gic.h
+++ b/include/dt-bindings/interrupt-controller/arm-gic.h
@@ -14,6 +14,7 @@
#define GIC_PPI 1
#define GIC_ESPI 2
#define GIC_EPPI 3
+#define GIC_SGI 4
/*
* Interrupt specifier cell 2.
--
2.43.0
^ permalink raw reply related
* [PATCH 0/5] firmware/irqchip: Add FF-A DT interrupt support for donated NS SGIs
From: Sudeep Holla @ 2026-04-12 17:04 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Marc Zyngier,
devicetree, linux-kernel, linux-arm-kernel, Sudeep Holla
Hi all,
This series wires FF-A notification interrupts up through DT using the
standard interrupts property on the arm,ffa node and adds the
required GICv3 and binding support for secure-donated non-secure SGIs.
This has been long pending after the discussions here[1][2]. I have been
waiting for some ACPI story to shape up for almost an year now, but no
progress there. So posting this for now to start discussion on the approach
taken here instead of waiting for another year to sort out ACPI 😉.
It:
- documents secure-donated NS SGIs in the GIC DT binding
- teaches the GICv3 driver to accept and map those SGIs
- adds a DT binding for the arm,ffa firmware node
- updates the FF-A driver to use the arm,ffa node interrupt instead of
synthesizing its own GIC mapping
- adds an FVP DT node using SGI 8 as the FF-A notification interrupt
The FF-A DT lookup expects a single interrupt entry, verifies that it is
a per-CPU interrupt via the reported affinity mask, and cross-checks the
resolved Linux IRQ hwirq against the interrupt ID returned by
FFA_FEATURES.
[1] https://lore.kernel.org/all/86plqayvu6.wl-maz@kernel.org/
[2] https://lore.kernel.org/all/86zfpgztmt.wl-maz@kernel.org/
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
---
Sudeep Holla (5):
dt-bindings: interrupt-controller: Add support for secure donated SGIs
irqchip/gic-v3: Support secure-donated non-secure SGIs
dt-bindings: firmware: Add Arm FF-A binding
firmware: arm_ffa: Use device node interrupts property for IRQ lookup
arm64: dts: arm: fvp-base-revc: Add FF-A notification interrupt
.../devicetree/bindings/firmware/arm,ffa.yaml | 42 +++++++++++
.../bindings/interrupt-controller/arm,gic-v3.yaml | 27 ++++++-
arch/arm64/boot/dts/arm/fvp-base-revc.dts | 6 ++
drivers/firmware/arm_ffa/driver.c | 53 +++++++++----
drivers/irqchip/irq-gic-v3.c | 86 ++++++++++++++++++++++
include/dt-bindings/interrupt-controller/arm-gic.h | 1 +
6 files changed, 201 insertions(+), 14 deletions(-)
---
base-commit: f5459048c38a00fc583658d6dcd0f894aff6df8f
change-id: 20260412-b4-ffa_ns_sgi_gicv3-ede4dfe9d76e
--
Regards,
Sudeep
^ permalink raw reply
* Re: Phandles
From: Kyle Bonnici @ 2026-04-12 16:37 UTC (permalink / raw)
To: Herve Codina
Cc: devicetree-compiler@vger.kernel.org, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree@vger.kernel.org
In-Reply-To: <20260412173916.7a971a45@bootlin.com>
> On 12 Apr 2026, at 17:40, Herve Codina <herve.codina@bootlin.com> wrote:
>
> Hi Kyle,
>
> +Cc Kernel device-tree maintainers
>
> On Sun, 12 Apr 2026 13:51:35 +0000
> Kyle Bonnici <kylebonnici@hotmail.com> wrote:
>
>>> On 12 Apr 2026, at 14:51, Herve Codina <herve.codina@bootlin.com> wrote:
>>>
>>> Hi Kyle,
>>>
>>> On Sat, 11 Apr 2026 18:33:33 +0000
>>> Kyle Bonnici <kylebonnici@hotmail.com> wrote:
>>>
>>>> Hi
>>>>
>>>> I have been looking at the the code for the compiler and I am wondering which specifications marks the below properties MUST BE Nexus Properties hence the validation.
>>>>
>>>> WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
>>>> WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
>>>> WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
>>>
>>> All of those properties are defined as phandles.
>>>
>>> For instance, the 'pwms' property available in a node means the the node is
>>> a pwm consumer. It must follow the pwm consumer binding [1] and so a phandle
>>> is involved.
>>>
>>> This phandle can have arguments and the number of argument is defined by the
>>> #pwm-cells property set in the pwm provider node [2], [3].
>>>
>>> [1] https://elixir.bootlin.com/zephyr/v4.4.0-rc3/source/dts/bindings/pwm/pwm-controller.yaml
>>> [2] https://github.com/zephyrproject-rtos/zephyr/blob/main/dts/bindings/pwm/pwm-controller.yaml
>>> [3] https://elixir.bootlin.com/linux/v7.0-rc7/source/Documentation/devicetree/bindings/pwm/pwm.yaml
>>>
>>>>
>>>>
>>>> These can be found here: https://github.com/dgibson/dtc/blob/main/checks.c#L1498 this is relevant for https://github.com/zephyrproject-rtos/zephyr/issues/107066
>>>
>>> Examples provided in the zephyrproject issue link are, in my opinion, incorrect.
>>>
>>> Case 1:
>>> / {
>>> node1 {
>>> pwms = <1 &pwm0 1 20 PWM_POLARITY_NORMAL>;
>>>
>>> Here the first cell '1' is not a phandle.
>>
>> Here the compiler is making an assumption here that all `pwms` properties must be specifier properties and all use `pwm` specifier.
>
> I think the purpose of 'select: true' is to have the binding always applied:
> https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/pwm/pwm-consumer.yaml#L15
>
I’m having trouble finding where the Devicetree Specification (v0.4) mandates that all binding systems must extend dt-schema.
Since this requirement isn't explicitly in the spec, it follows that the WARNING_PROPERTY_PHANDLE_CELLS validation belongs in dt-validate rather than within dtc itself.
> If this is confirmed, DTC performs correct checks as this binding must always
> be applied and so the 'pwms' property must be a phandle-array property.
>
> Device-tree maintainers, can you confirm the purpose of 'select: true' set
> in a DT binding ?
>
> Best regards,
> Hervé
^ permalink raw reply
* [PATCH v3 1/2] arm64: dts: qcom: sdm845-google: Add dual front IMX355 cameras
From: David Heidelberg via B4 Relay @ 2026-04-12 16:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Petr Hodina, Richard Acayan, linux-arm-msm, devicetree,
linux-kernel, phone-devel, David Heidelberg
In-Reply-To: <20260412-pixel3-camera-v3-0-e26b090a6110@ixit.cz>
From: David Heidelberg <david@ixit.cz>
The Pixel 3 features two front-facing Sony IMX355 sensors with
different focal lengths (standard and wide-angle).
Both sensors are connected via CSIPHY1 and controlled over CCI I2C1,
using MCLK2 as the clock source. Describe the camera nodes and
associated resources in the device tree.
This enables support for the dual front camera configuration.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 193 ++++++++++++++++++++-
1 file changed, 192 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index 6930066857768..070023a9813ce 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sdm845.dtsi"
@@ -132,6 +133,38 @@ vreg_s4a_1p8: regulator-vreg-s4a-1p8 {
vin-supply = <&vph_pwr>;
};
+ camera_front_avdd: front-cam-avdd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "front_cam_avdd";
+
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+
+ gpios = <&tlmm 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&cam_front_avdd_default_pin>;
+ pinctrl-names = "default";
+
+ vin-supply = <&vreg_bob>;
+ };
+
+ camera_front_aux_avdd: front-cam-aux-avdd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "front_cam_aux_avdd";
+
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+
+ gpios = <&tlmm 14 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-0 = <&cam_front_aux_avdd_default_pin>;
+ pinctrl-names = "default";
+
+ vin-supply = <&vreg_bob>;
+ };
+
wcn3990-pmu {
compatible = "qcom,wcn3990-pmu";
@@ -214,6 +247,9 @@ vreg_s7a_1p025: smps7 {
regulator-max-microvolt = <1028000>;
};
+ vdda_mipi_csi0_0p9:
+ vdda_mipi_csi1_0p9:
+ vdda_mipi_csi2_0p9:
vdda_mipi_dsi0_pll:
vreg_l1a_0p875: ldo1 {
regulator-min-microvolt = <880000>;
@@ -288,6 +324,13 @@ vreg_l21a_2p95: ldo21 {
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vreg_l22a_3p3: ldo22 {
+ regulator-min-microvolt = <2864000>;
+ regulator-max-microvolt = <2864000>;
+
+ regulator-boot-on;
+ };
+
vreg_l24a_3p075: ldo24 {
regulator-min-microvolt = <3088000>;
regulator-max-microvolt = <3088000>;
@@ -319,6 +362,11 @@ vreg_l28a_3p0: ldo28 {
*/
regulator-always-on;
};
+
+ vreg_lvs1_1p8: lvs1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
};
regulators-1 {
@@ -351,6 +399,53 @@ vreg_s3c_0p6: smps3 {
};
};
+&camss {
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l26a_1p2>;
+
+ vdda-csi0-supply = <&vdda_mipi_csi0_0p9>;
+ vdda-csi1-supply = <&vdda_mipi_csi1_0p9>;
+ vdda-csi2-supply = <&vdda_mipi_csi2_0p9>;
+
+ /*
+ * MCLK2 (GPIO15) is shared between both front camera sensors.
+ * The clock is generated by CAMSS, therefore the pin is
+ * configured here rather than in individual sensor nodes.
+ */
+ pinctrl-0 = <&cam_mclk2_default>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ reg = <1>;
+ camss_endpoint1: endpoint {
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&cam_aux_front_endpoint>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ camss_endpoint2: endpoint {
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&cam_front_endpoint>;
+ };
+ };
+ };
+};
+
+&cci0_sleep {
+ /* bus has external pull-up, don't pull down */
+ bias-disable;
+};
+
&cci {
status = "okay";
};
@@ -358,7 +453,71 @@ &cci {
&cci_i2c1 {
/* actuator @0c */
- /* front camera, imx355 @1a */
+ front_cam: camera@10 {
+ compatible = "sony,imx355";
+ reg = <0x10>;
+
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ assigned-clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ /*
+ * The sensor can accept a 24 MHz clock, but 19.2 MHz has
+ * better driver compatibility.
+ */
+ assigned-clock-rates = <19200000>;
+
+ reset-gpios = <&tlmm 21 GPIO_ACTIVE_LOW>;
+
+ avdd-supply = <&camera_front_avdd>;
+ dvdd-supply = <&vreg_s3a_1p35>;
+ dovdd-supply = <&vreg_lvs1_1p8>;
+
+ pinctrl-0 = <&cam_front_reset_default_pin>;
+ pinctrl-names = "default";
+
+ rotation = <270>;
+ orientation = <0>;
+
+ port {
+ cam_front_endpoint: endpoint {
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <360000000>;
+ remote-endpoint = <&camss_endpoint2>;
+ };
+ };
+ };
+
+ front_aux_cam: camera@1a {
+ compatible = "sony,imx355";
+ reg = <0x1a>;
+
+ clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ assigned-clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
+ /*
+ * The sensor can accept a 24 MHz clock, but 19.2 MHz has
+ * better driver compatibility.
+ */
+ assigned-clock-rates = <19200000>;
+
+ reset-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
+
+ avdd-supply = <&camera_front_aux_avdd>;
+ dvdd-supply = <&vreg_s3a_1p35>;
+ dovdd-supply = <&vreg_lvs1_1p8>;
+
+ pinctrl-0 = <&cam_front_aux_reset_default_pin>;
+ pinctrl-names = "default";
+
+ rotation = <270>;
+ orientation = <0>;
+
+ port {
+ cam_aux_front_endpoint: endpoint {
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <360000000>;
+ remote-endpoint = <&camss_endpoint1>;
+ };
+ };
+ };
/* eeprom @50, at24 driver says 8K */
};
@@ -459,6 +618,38 @@ &tlmm {
gpio-reserved-ranges = < 0 4>, /* SPI (Intel MNH Pixel Visual Core) */
<81 4>; /* SPI (most likely Fingerprint Cards FPC1075) */
+ cam_front_avdd_default_pin: cam-avdd-default-pins {
+ pins = "gpio8";
+ function = "gpio";
+
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cam_front_aux_reset_default_pin: cam-front-aux-reset-default-pins {
+ pins = "gpio9";
+ function = "gpio";
+
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cam_front_aux_avdd_default_pin: cam-avdd-aux-default-pins {
+ pins = "gpio14";
+ function = "gpio";
+
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cam_front_reset_default_pin: cam-front-reset-default-pins {
+ pins = "gpio21";
+ function = "gpio";
+
+ bias-disable;
+ drive-strength = <2>;
+ };
+
touchscreen_reset: ts-reset-state {
pins = "gpio99";
function = "gpio";
--
2.53.0
^ permalink raw reply related
* [PATCH v3 0/2] Add initial dual front camera and rear flash support for Pixel 3 / 3 XL
From: David Heidelberg via B4 Relay @ 2026-04-12 16:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Petr Hodina, Richard Acayan, linux-arm-msm, devicetree,
linux-kernel, phone-devel, David Heidelberg, Dmitry Baryshkov
Describe the dual front-facing IMX355 sensors (standard and wide)
and enable the PMI8998 flash LED with hardware-accurate limits.
This brings up the basic camera topology and flash support in DT.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Changes in v3:
- Dropped cam_vio label. (Dmitry)
- Move the MCLK2 pinctrl from cameras to common camss. (Dmitry)
- Link to v2: https://lore.kernel.org/r/20260411-pixel3-camera-v2-0-41b889abb14c@ixit.cz
Changes in v2:
- leds.h include escaped the initial submission. Fixed.
- Link to v1: https://lore.kernel.org/r/20260411-pixel3-camera-v1-0-2757606515b6@ixit.cz
---
David Heidelberg (2):
arm64: dts: qcom: sdm845-google: Add dual front IMX355 cameras
arm64: dts: qcom: sdm845-google: Enable PMI8998 camera flash LED
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 207 ++++++++++++++++++++-
1 file changed, 206 insertions(+), 1 deletion(-)
---
base-commit: 66672af7a095d89f082c5327f3b15bc2f93d558e
change-id: 20260315-pixel3-camera-a9989bf589ee
Best regards,
--
David Heidelberg <david@ixit.cz>
^ permalink raw reply
* [PATCH v3 2/2] arm64: dts: qcom: sdm845-google: Enable PMI8998 camera flash LED
From: David Heidelberg via B4 Relay @ 2026-04-12 16:35 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: Petr Hodina, Richard Acayan, linux-arm-msm, devicetree,
linux-kernel, phone-devel, David Heidelberg, Dmitry Baryshkov
In-Reply-To: <20260412-pixel3-camera-v3-0-e26b090a6110@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Enable the PMI8998 flash LED block and describe the white flash LED
used for the rear camera.
Configure the LED in flash mode with hardware limits matching the
original device configuration, including maximum current and timeout.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index 070023a9813ce..e9d9842cb8674 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
#include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
@@ -596,6 +597,19 @@ &pmi8998_charger {
status = "okay";
};
+&pmi8998_flash {
+ status = "okay";
+
+ led-1 {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ led-sources = <2>;
+ led-max-microamp = <500000>;
+ flash-max-microamp = <750000>;
+ flash-max-timeout-us = <1280000>;
+ };
+};
+
&qupv3_id_0 {
status = "okay";
};
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 2/2] soc: qcom: socinfo: Add SoC ID for SM7750
From: Dmitry Baryshkov @ 2026-04-12 16:34 UTC (permalink / raw)
To: Alexander Koskovich
Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20260412-sm7550-id-v1-2-958a673ff791@pm.me>
On Sun, Apr 12, 2026 at 03:42:44PM +0000, Alexander Koskovich wrote:
> Recognize the SM7750 SoC which is an Eliza SoC variant.
>
> Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
> ---
> drivers/soc/qcom/socinfo.c | 1 +
> 1 file changed, 1 insertion(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH net-next v4 1/2] dt-bindings: net: ti: k3-am654-cpsw-nuss: Add ti,j722s-cpsw-nuss compatible
From: patchwork-bot+netdevbpf @ 2026-04-12 15:50 UTC (permalink / raw)
To: Nora Schiffer
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, nm, vigneshr,
kristo, s-vadapalli, rogerq, robh, krzk+dt, conor+dt, netdev,
devicetree, linux-kernel, linux-arm-kernel, linux
In-Reply-To: <191e9f7e3a6c14eabe891a98c5fb646766479c0a.1775558273.git.nora.schiffer@ew.tq-group.com>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Tue, 7 Apr 2026 12:48:01 +0200 you wrote:
> The J722S CPSW3G is mostly identical to the AM64's, but additionally
> supports SGMII. The AM64 compatible ti,am642-cpsw-nuss is used as a
> fallback.
>
> Signed-off-by: Nora Schiffer <nora.schiffer@ew.tq-group.com>
> ---
>
> [...]
Here is the summary with links:
- [net-next,v4,1/2] dt-bindings: net: ti: k3-am654-cpsw-nuss: Add ti,j722s-cpsw-nuss compatible
https://git.kernel.org/netdev/net-next/c/f757a2da6df5
- [net-next,v4,2/2] net: ethernet: ti: am65-cpsw: add support for J722S SoC family
https://git.kernel.org/netdev/net-next/c/436e9e48ca51
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH net-next v3 0/5] dpll: zl3073x: add ref-sync pair support
From: patchwork-bot+netdevbpf @ 2026-04-12 15:50 UTC (permalink / raw)
To: Ivan Vecera
Cc: netdev, arkadiusz.kubalewski, jiri, mschmidt, poros,
Prathosh.Satish, horms, vadim.fedorenko, linux-kernel, conor+dt,
krzk+dt, robh, devicetree, pvaanane
In-Reply-To: <20260408102716.443099-1-ivecera@redhat.com>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 8 Apr 2026 12:27:11 +0200 you wrote:
> This series adds Reference-Sync pair support to the ZL3073x DPLL driver.
> A Ref-Sync pair consists of a clock reference and a low-frequency sync
> signal (e.g. 1 PPS) where the DPLL locks to the clock reference but
> phase-aligns to the sync reference.
>
> Patches 1-3 are preparatory cleanups and helper additions:
> - Clean up esync get/set callbacks with early returns and use the
> zl3073x_out_is_ndiv() helper
> - Convert open-coded clear-and-set bitfield patterns to FIELD_MODIFY()
> - Add ref sync control and output clock type accessor helpers
>
> [...]
Here is the summary with links:
- [net-next,v3,1/5] dpll: zl3073x: clean up esync get/set and use zl3073x_out_is_ndiv()
https://git.kernel.org/netdev/net-next/c/3c8c39768b10
- [net-next,v3,2/5] dpll: zl3073x: use FIELD_MODIFY() for clear-and-set patterns
https://git.kernel.org/netdev/net-next/c/737cb6195c40
- [net-next,v3,3/5] dpll: zl3073x: add ref sync and output clock type helpers
https://git.kernel.org/netdev/net-next/c/63009eb92b0f
- [net-next,v3,4/5] dt-bindings: dpll: add ref-sync-sources property
https://git.kernel.org/netdev/net-next/c/a1a702090def
- [net-next,v3,5/5] dpll: zl3073x: add ref-sync pair support
https://git.kernel.org/netdev/net-next/c/14f269ae6998
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* [PATCH 2/2] soc: qcom: socinfo: Add SoC ID for SM7750
From: Alexander Koskovich @ 2026-04-12 15:42 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, devicetree, linux-kernel, Alexander Koskovich
In-Reply-To: <20260412-sm7550-id-v1-0-958a673ff791@pm.me>
Recognize the SM7750 SoC which is an Eliza SoC variant.
Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
---
drivers/soc/qcom/socinfo.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 8ffd903ebddb..3f67fbbcac54 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -519,6 +519,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ5424) },
{ qcom_board_id(QCM6690) },
{ qcom_board_id(QCS6690) },
+ { qcom_board_id(SM7750) },
{ qcom_board_id(SM8850) },
{ qcom_board_id(IPQ5404) },
{ qcom_board_id(QCS9100) },
--
2.53.0
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: arm: qcom,ids: Add SoC ID for SM7750
From: Alexander Koskovich @ 2026-04-12 15:42 UTC (permalink / raw)
To: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Conor Dooley
Cc: linux-arm-msm, devicetree, linux-kernel, Alexander Koskovich
In-Reply-To: <20260412-sm7550-id-v1-0-958a673ff791@pm.me>
Document the ID for SM7750, an Eliza SoC variant that can be found on
the Nothing Phone (4a) Pro.
Signed-off-by: Alexander Koskovich <akoskovich@pm.me>
---
include/dt-bindings/arm/qcom,ids.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/dt-bindings/arm/qcom,ids.h b/include/dt-bindings/arm/qcom,ids.h
index 336f7bb7188a..916f418a869e 100644
--- a/include/dt-bindings/arm/qcom,ids.h
+++ b/include/dt-bindings/arm/qcom,ids.h
@@ -290,6 +290,7 @@
#define QCOM_ID_IPQ5424 651
#define QCOM_ID_QCM6690 657
#define QCOM_ID_QCS6690 658
+#define QCOM_ID_SM7750 659
#define QCOM_ID_SM8850 660
#define QCOM_ID_IPQ5404 671
#define QCOM_ID_QCS9100 667
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox