devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jic23@kernel.org>
To: Marcelo Schmitt <marcelo.schmitt@analog.com>
Cc: <linux-iio@vger.kernel.org>, <devicetree@vger.kernel.org>,
	<linux-doc@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<nuno.sa@analog.com>, <dlechner@baylibre.com>, <andy@kernel.org>,
	<Michael.Hennerich@analog.com>, <robh@kernel.org>,
	<krzk+dt@kernel.org>, <conor+dt@kernel.org>, <corbet@lwn.net>,
	<cosmin.tanislav@analog.com>, <marcelo.schmitt1@gmail.com>
Subject: Re: [PATCH v1 2/3] iio: adc: Initial support for AD4134
Date: Tue, 11 Nov 2025 21:11:48 +0000	[thread overview]
Message-ID: <20251111211148.322e5aaf@jic23-huawei> (raw)
In-Reply-To: <86f532ae3a9b3f122b9d5dbada9c131a0c048ca7.1762777931.git.marcelo.schmitt@analog.com>

On Mon, 10 Nov 2025 09:45:40 -0300
Marcelo Schmitt <marcelo.schmitt@analog.com> wrote:

> AD4134 is a 24-bit, 4-channel, simultaneous sampling, precision
> analog-to-digital converter (ADC). The device can be managed through SPI or
> direct control of pin logical levels (pin control mode). The AD4134 design
> also features a dedicated bus for ADC sample data output. Though, this
> initial driver for AD4134 only supports usual SPI connections.
> 
> The different wiring configurations will likely require distinct software
> to handle. So, the code specific to SPI is enclosed in ad4134-spi.c, while
> functionality that may be useful to all wiring configuration is set into
> ad4134-common.h and ad4134-common.c.

'maybe' isn't usually a justification for a split.  If that code
was on list even as an RFC before merging  I'd be fine with this, but if it is
something we might never see upstream, then squash the abstractions for
now. Those then end up being introduced as a precursor part of the patch
set that gives them a reason to exist.

> 
> Add basic support for AD4134 that allows single-shot ADC sample read.
> 
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
A few other comments inline,

Thanks, J
> diff --git a/drivers/iio/adc/ad4134-common.c b/drivers/iio/adc/ad4134-common.c
> new file mode 100644
> index 000000000000..05332a640926
> --- /dev/null
> +++ b/drivers/iio/adc/ad4134-common.c

> +
> +static const char *const ad4134_clk_sel[] = {
> +	"xtal1-xtal2", "clkin"
> +};
> +
> +static int ad4134_clock_select(struct ad4134_state *st)
> +{
> +	struct device *dev = st->dev;
> +	struct clk *sys_clk;
> +	int ret;
> +
> +	ret = device_property_match_property_string(dev, "clock-names",
> +						    ad4134_clk_sel,
> +						    ARRAY_SIZE(ad4134_clk_sel));
> +	if (ret < 0)
> +		return dev_err_probe(dev, ret, "failed to find external clock\n");
> +
> +	sys_clk = devm_clk_get_enabled(dev, ad4134_clk_sel[ret]);
> +	if (IS_ERR(sys_clk))
> +		return dev_err_probe(dev, PTR_ERR(sys_clk),
> +				     "failed to get %s external clock\n",
> +				     ad4134_clk_sel[ret]);
This is a somewhat unusual approach. More common to just trying getting
an optional clock and if that fails try the other one.

devm_clk_get_optional_enabled()


> +
> +	st->sys_clk_rate = clk_get_rate(sys_clk);
> +	if (st->sys_clk_rate != AD4134_EXT_CLOCK_MHZ)
> +		dev_warn(dev, "invalid external clock frequency %lu\n",
> +			 st->sys_clk_rate);
> +
> +	return 0;
> +}

> diff --git a/drivers/iio/adc/ad4134-common.h b/drivers/iio/adc/ad4134-common.h
> new file mode 100644
> index 000000000000..c0a553d827c9
> --- /dev/null
> +++ b/drivers/iio/adc/ad4134-common.h

> +
> +#define AD4134_CH_VREG(x)			((x) + 0x50) /* chanX virtual register */
> +#define AD4134_VREG_CH(x)			((x) - 0x50) /* chan of virtual reg X */

Add a comment or two on what virtual registers are for.

> +struct iio_scan_type ad4134_scan_types[] = {
> +	AD4134_SCAN_TYPE(16, 16),
> +	AD4134_SCAN_TYPE(16, 24),

There are no buffer in here so can type ends up meaning little.
If this eventually doesn't become useful, storage bits must be a power of 2 * 8
So can't be 24.  

> +	AD4134_SCAN_TYPE(24, 24),
> +	AD4134_SCAN_TYPE(24, 32),
> +};
> +
> +#define AD4134_CHANNEL(_index) {						\
> +	.type = IIO_VOLTAGE,							\
> +	.indexed = 1,								\
> +	.channel = (_index),							\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),				\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),			\
> +	.scan_index = (_index),							\
> +	.has_ext_scan_type = 1,							\
> +	.ext_scan_type = ad4134_scan_types,					\
> +	.num_ext_scan_type = ARRAY_SIZE(ad4134_scan_types)			\
> +}

> diff --git a/drivers/iio/adc/ad4134-spi.c b/drivers/iio/adc/ad4134-spi.c
> new file mode 100644
> index 000000000000..7d0749e5c084
> --- /dev/null
> +++ b/drivers/iio/adc/ad4134-spi.c
> @@ -0,0 +1,287 @@

> +
> +#include "ad4134-common.h"

> +static int ad4134_reg_write(void *context, unsigned int reg, unsigned int val)
> +{
> +	struct ad4134_state *st = context;
> +	struct spi_device *spi = to_spi_device(st->dev);
> +	struct spi_transfer xfer = {
> +		.tx_buf = st->tx_buf,
> +		.rx_buf = st->rx_buf,
> +		.len = AD4134_SPI_MAX_XFER_LEN,
> +	};
> +	int ret;
> +
> +	ad4134_prepare_spi_tx_buf(reg, val, st->tx_buf);
> +
> +	ret = spi_sync_transfer(spi, &xfer, 1);
> +	if (ret)
> +		return ret;
> +
> +	if (st->rx_buf[2] != st->tx_buf[2])
> +		dev_dbg(st->dev, "reg write CRC check failed\n");
> +
> +	return 0;
> +}
> +
> +static int ad4134_data_read(struct ad4134_state *st, unsigned int reg,
> +			    unsigned int *val)
> +{
> +	struct spi_device *spi = to_spi_device(st->dev);
> +	struct iio_scan_type *scan_type = &ad4134_scan_types[st->current_scan_type];
> +	unsigned int i;
> +	int ret;
> +
> +	/*
> +	 * Data from all four channels is serialized and output on SDO. Read
> +	 * them all but keep only the requested data.

I'm failing to spot this mode described on the datasheet.  Could you
provide a reference section?

> +	 */
> +	for (i = 0; i < ARRAY_SIZE(ad4134_chan_set); i++) {
> +		ret = spi_write_then_read(spi, NULL, 0, st->rx_buf,
> +					  BITS_TO_BYTES(scan_type->storagebits));
> +		if (ret)
> +			return ret;
> +
> +		if (i != AD4134_VREG_CH(reg))
> +			continue;
> +
> +		if (scan_type->realbits == 16)
> +			*val = get_unaligned_be16(st->rx_buf);
> +		else
> +			*val = get_unaligned_be24(st->rx_buf);
> +
> +		*val >>= scan_type->shift;
> +	}
> +
> +	return 0;
> +}
> +
> +static int ad4134_reg_read(void *context, unsigned int reg, unsigned int *val)
> +{
> +	struct ad4134_state *st = context;
> +	struct spi_device *spi = to_spi_device(st->dev);
> +	struct spi_transfer xfer = {
> +		.tx_buf = st->tx_buf,
> +		.rx_buf = st->rx_buf,
> +		.len = AD4134_SPI_MAX_XFER_LEN,
> +	};
> +	unsigned int inst;
> +	int ret;
> +
> +	if (reg >= AD4134_CH_VREG(0))
> +		return ad4134_data_read(st, reg, val);

If you are going down this path the xfer isn't used.  To avoid that being
a little confusing I'd factor out the rest of this function into a helper

> +
> +	inst = AD4134_REG_READ_MASK | reg;
> +	ad4134_prepare_spi_tx_buf(inst, 0, st->tx_buf);
> +
> +	ret = spi_sync_transfer(spi, &xfer, 1);
> +	if (ret)
> +		return ret;
> +
> +	*val = st->rx_buf[1];
> +
> +	/* Check CRC */
> +	if (st->rx_buf[2] != st->tx_buf[2])
> +		dev_dbg(st->dev, "reg read CRC check failed\n");
> +
> +	return 0;
> +}


> +
> +static const struct ad4134_bus_info ad4134_min_io_bus_info = {

given it's a mix of bus specific and other stuff, I'm not sure 
that calling this bus_info makes sense.  Maybe just ad4134_info?

> +	.chip_info = &ad4134_chip_info,
> +	.bops = &ad4134_min_io_bops,
> +};



  parent reply	other threads:[~2025-11-11 21:11 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-10 12:44 [PATCH v1 0/3] iio: adc: Add AD4134 minimum I/O support Marcelo Schmitt
2025-11-10 12:45 ` [PATCH v1 1/3] dt-bindings: iio: adc: Add AD4134 Marcelo Schmitt
2025-11-10 19:07   ` Conor Dooley
2025-11-13 21:56     ` Marcelo Schmitt
2025-11-14  1:43       ` Conor Dooley
2025-11-10 12:45 ` [PATCH v1 2/3] iio: adc: Initial support for AD4134 Marcelo Schmitt
2025-11-10 13:13   ` Andy Shevchenko
2025-11-11 21:11   ` Jonathan Cameron [this message]
2025-11-14  6:47   ` kernel test robot
2025-11-14  9:26   ` kernel test robot
2025-11-10 12:45 ` [PATCH v1 3/3] Docs: iio: Add AD4134 Marcelo Schmitt
2025-11-10 19:24   ` Randy Dunlap
2025-11-10 12:54 ` [PATCH v1 0/3] iio: adc: Add AD4134 minimum I/O support Andy Shevchenko
2025-11-10 15:43   ` Marcelo Schmitt
2025-11-10 14:48 ` Nuno Sá
2025-11-10 16:46   ` Marcelo Schmitt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251111211148.322e5aaf@jic23-huawei \
    --to=jic23@kernel.org \
    --cc=Michael.Hennerich@analog.com \
    --cc=andy@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=cosmin.tanislav@analog.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marcelo.schmitt1@gmail.com \
    --cc=marcelo.schmitt@analog.com \
    --cc=nuno.sa@analog.com \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).