All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Esteban Blanc" <eblanc@baylibre.com>
To: "Jonathan Cameron" <jic23@kernel.org>
Cc: "Lars-Peter Clausen" <lars@metafoo.de>,
	"Michael Hennerich" <Michael.Hennerich@analog.com>,
	"Rob Herring" <robh@kernel.org>,
	"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Nuno Sa" <nuno.sa@analog.com>,
	"Jonathan Corbet" <corbet@lwn.net>, <linux-iio@vger.kernel.org>,
	<devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	"David Lechner" <dlechner@baylibre.com>,
	<linux-doc@vger.kernel.org>
Subject: Re: [PATCH 2/6] iio: adc: ad4030: add driver for ad4030-24
Date: Tue, 27 Aug 2024 18:45:49 +0200	[thread overview]
Message-ID: <D3QUGZYL7INK.R3U3WQR0OCUS@baylibre.com> (raw)
In-Reply-To: <20240824122111.425fa689@jic23-huawei>

On Sat Aug 24, 2024 at 1:21 PM CEST, Jonathan Cameron wrote:
> On Thu, 22 Aug 2024 14:45:18 +0200
> Esteban Blanc <eblanc@baylibre.com> wrote:
>
> > This adds a new driver for the Analog Devices INC. AD4030-24 ADC.
> > 
> > The driver implements basic support for the AD4030-24 1 channel
> > differential ADC with hardware gain and offset control.
> > 
> > Signed-off-by: Esteban Blanc <eblanc@baylibre.com>
> Hi Esteban
>
> Some additional comments.  David did a good review already so
> I've tried not to duplicate too much of that.
>
> The big one in here is don't use extended_name.
> It's effectively deprecated for new drivers plus
> it would have required you add a lot of ABI docs as every
> sysfs file would have a strange name.
>
> > diff --git a/drivers/iio/adc/ad4030.c b/drivers/iio/adc/ad4030.c
> > new file mode 100644
> > index 000000000000..a981dce988e5
> > --- /dev/null
> > +++ b/drivers/iio/adc/ad4030.c
>
> > +struct ad4030_state {
> > +	struct spi_device *spi;
> > +	struct regmap *regmap;
> > +	const struct ad4030_chip_info *chip;
> > +	struct gpio_desc *cnv_gpio;
> > +	int vref_uv;
> > +	int vio_uv;
> > +	int offset_avail[3];
> > +	u32 conversion_speed_hz;
> > +	enum ad4030_out_mode mode;
> > +
> > +	/*
> > +	 * DMA (thus cache coherency maintenance) requires the transfer buffers
> > +	 * to live in their own cache lines.
> > +	 */
> > +	u8 tx_data[AD4030_SPI_MAX_XFER_LEN] __aligned(IIO_DMA_MINALIGN);
> > +	struct {
> > +		union {
> > +			u8 raw[AD4030_MAXIMUM_RX_BUFFER_SIZE];
> > +			struct {
> > +				s32 val;
> > +				u32 common;
> > +			} __packed buffered[AD4030_MAX_HARDWARE_CHANNEL_NB];
>
> David pointed out this doesn't need to be packed.
> Given you have a union here, add __beXX as needed to avoid casts below.

They also pointed out that I should reduce the size for the common field.
I was planing to use an u32 bitfield here, 8 bits for common and 24 bits for
padding. As far as I understood, the C standard is quite flexible on the
size used for bitfield, so I should probably keep the __packed, right?

> > +};
> > +
> > +#define AD4030_CHAN_CMO(_idx)  {					\
> > +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
> > +	.type = IIO_VOLTAGE,						\
> > +	.indexed = 1,							\
> > +	.channel = _idx * 2 + 2,					\
> > +	.scan_index = _idx * 2 + 1,					\
> > +	.extend_name = "Channel" #_idx " common byte part",		\
>
> We more or less never use extend name any more because it makes writing
> userspace code much harder.  Use the label callback to assign a label instead.
>
> If we were still using this, it would need to be a lot simpler than that
> and no spaces etc as it ends up int he sysfs file names.

> > +	.scan_type = {							\
> > +		.sign = 'u',						\
> > +		.storagebits = 32,					\
> > +		.realbits = 8,						\
> > +		.endianness = IIO_BE,					\
> > +	},								\
> > +}
> > +
> > +#define AD4030_CHAN_IN(_idx, _storage, _real, _shift) {			\
> > +	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),		\
> > +	.info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) |		\
> > +		BIT(IIO_CHAN_INFO_CALIBBIAS) |				\
> > +		BIT(IIO_CHAN_INFO_RAW),					\
> > +	.info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS) |	\
> > +		BIT(IIO_CHAN_INFO_CALIBSCALE),				\
> > +	.type = IIO_VOLTAGE,						\
> > +	.indexed = 1,							\
> > +	.channel = _idx * 2,						\
> > +	.channel2 = _idx * 2 + 1,					\
> > +	.scan_index = _idx * 2,						\
> > +	.extend_name = "Channel" #_idx " differential part",		\
>
> As above, no to this for same reason.
> This will generate a crazy ABI so I'm a bit surprised that didn't show
> up in your testing.  Would have needed a lot of docs even if we did
> still do things this way.

I'm using ADI IIO oscilloscope to check the signals so I didn't get
impacted by the sysfs change. Anyway I will use labels.

> > +	.differential = true,						\
> > +	.scan_type = {							\
> > +		.sign = 's',						\
> > +		.storagebits = _storage,				\
> > +		.realbits = _real,					\
> > +		.shift = _shift,					\
> > +		.endianness = IIO_BE,					\
> > +	},								\
> > +}
> > +
> > +static int ad4030_spi_read(void *context, const void *reg, size_t reg_size,
> > +			   void *val, size_t val_size)
> > +{
> > +	struct ad4030_state *st = context;
> > +
> > +	struct spi_transfer xfer = {
> > +		.tx_buf = st->tx_data,
> > +		.rx_buf = st->rx_data.raw,
> > +		.len = reg_size + val_size,
> > +	};
> > +	int ret;
> > +
> > +	memcpy(st->tx_data, reg, reg_size);
> > +
> > +	/*
> > +	 * This should use spi_write_the_read but when doing so, CS never get
> > +	 * deasserted.
>
> I'm confused.  As a single transfer it won't be deasserted in the transfer
> whereas spi_write_then_read() will. So is this comment backwards or
> is it referring to something else?

So, with a single transfer (what is done now), the transfer is working
as expected: CS goes low, the data is transferred, CS goes high again.
With spi_write_then_read(), CS goes low, data is transferred but CS never
goes high again. After some time I get a timeout error in the kernel logs.

> > +static int ad4030_conversion(struct ad4030_state *st,
> > +			     const struct iio_chan_spec *chan)
> > +{
> > +	unsigned int bytes_to_read;
> > +	unsigned char byte_index;
> > +	unsigned int i;
> > +	int ret;
> > +
> > +	/* Number of bytes for one differential channel */
> > +	bytes_to_read = BITS_TO_BYTES(chan->scan_type.realbits);
> > +	/* Add one byte if we are using a differential + common byte mode */
> > +	bytes_to_read += (st->mode == AD4030_OUT_DATA_MD_24_DIFF_8_COM ||
> > +			st->mode == AD4030_OUT_DATA_MD_16_DIFF_8_COM) ? 1 : 0;
> > +	/* Mulitiply by the number of hardware channels */
> > +	bytes_to_read *= st->chip->num_channels;
> > +
> > +	gpiod_set_value_cansleep(st->cnv_gpio, 1);
> > +	ndelay(AD4030_TCNVH_NS);
> > +	gpiod_set_value_cansleep(st->cnv_gpio, 0);
> > +	ndelay(st->chip->tcyc);
> > +
> > +	ret = spi_read(st->spi, st->rx_data.raw, bytes_to_read);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (st->mode != AD4030_OUT_DATA_MD_24_DIFF_8_COM)
> > +		return 0;
> > +
> > +	byte_index = BITS_TO_BYTES(chan->scan_type.realbits);
> > +	for (i = 0; i < st->chip->num_channels; i++)
> > +		st->rx_data.buffered[i].common = ((u8 *)&st->rx_data.buffered[i].val)[byte_index];
> break line after =.
>
> When it doesn't significantly hurt readability we still try to keep to 80
> chars for IIO drivers.  People have big screens but a lot of kernel devs
> love to have lots of windows across them - or have bad eyesight due to
> years of code review!

I keep forgeting that checkpatch now defaults at 100 chars...

> > +static int ad4030_read_raw(struct iio_dev *indio_dev,
> > +			   struct iio_chan_spec const *chan, int *val,
> > +			   int *val2, long info)
> > +{
> > +	struct ad4030_state *st = iio_priv(indio_dev);
> > +	int ret;
> > +
> > +	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
> > +		switch (info) {
> > +		case IIO_CHAN_INFO_RAW:
> > +			return ad4030_single_conversion(indio_dev, chan, val);
> > +
> > +		case IIO_CHAN_INFO_SCALE:
> > +			*val = (st->vref_uv * 2) / MILLI;
> > +			*val2 = st->chip->precision_bits;
> > +			return IIO_VAL_FRACTIONAL_LOG2;
>
> No reason you can't read this whilst buffered capture in progress.
> Maybe it's not worth the effort of special casing though.
>
> It is the one thing people do read whilst doing buffered capture
> though because they didn't cache it before starting the buffer
> and it's needed for data interpretation unlike all the other controls.
>
> Maybe just do a
> 	if (info == IIO_CHAN_INFO_SCALE) {
> 	}
> block at top of function?

Good catch. I will check for IIO_CHAN_INFO_SCALE before the whole block

> > +static int ad4030_reset(struct ad4030_state *st)
> > +{
> > +	struct device *dev = &st->spi->dev;
> > +	struct gpio_desc *reset;
> > +	int ret;
> > +
> > +	/* Use GPIO if available ... */
> > +	reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> > +	if (IS_ERR(reset))
> > +		return dev_err_probe(dev, PTR_ERR(reset),
> > +				"Failed to get reset GPIO\n");
> > +
> > +	if (reset) {
> > +		ndelay(50);
> > +		gpiod_set_value_cansleep(reset, 0);
> > +	} else {
> > +		/* ... falback to software reset otherwise */
> > +		ret = ad4030_enter_config_mode(st);
> > +		if (ret)
> > +			return ret;
> > +
> > +		ret = regmap_write(st->regmap, AD4030_REG_INTERFACE_CONFIG_A,
> > +				   AD4030_REG_INTERFACE_CONFIG_A_SW_RESET);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	/* Wait for reset to complete before communicating to it */
>
> I'd rather see a reference for the value than a generic comment
> like this.  Also pull the actual value down here. Not particularly
> useful to have a define for what is a real time unless you are going
>  to have some combined docs for a bunch of timings (i.e a datasheet
> table reference)

I will put the real value in fsleep call directly. When you say "I'd
rather see a reference for the value", you ment a reference to the place
the value is defined in the datasheet, right?

> > +static int ad4030_detect_chip_info(const struct ad4030_state *st)
> > +{
> > +	unsigned int grade;
> > +	int ret;
> > +
> > +	ret = regmap_read(st->regmap, AD4030_REG_CHIP_GRADE, &grade);
> > +	if (ret)
> > +		return ret;
> > +
> > +	grade = FIELD_GET(AD4030_REG_CHIP_GRADE_MASK_CHIP_GRADE, grade);
> > +	if (grade != st->chip->grade)
> > +		return dev_err_probe(&st->spi->dev, -EINVAL,
> > +					"Unknown grade(0x%x) for %s\n", grade,
> > +					st->chip->name);
>
> Is this similar to a missmatch on a whoami value?

Yes. It also saved me multiple hours of debuging when the eval board
was not connected porperly and the SPI link was just not working.

> I.e. should we print a message and carry on in the interests of providing
> some degree of support for newer devices on older kernel?
> (fallback compatibles in DT)

Ok, let's go with a warning then.

> > +static const struct spi_device_id ad4030_id_table[] = {
> > +	{ "ad4030-24", (kernel_ulong_t)&ad4030_24_chip_info },
> > +	{}
>
> I'm going to assume you have a bunch of other parts you plan to
> support soon. Otherwise we normally don't add the chip specific
> support until it is needed.  It tends to complicate initial driver
> review a little and experience says that sometimes no other devices
> are ever added.

I'm sending the other devices in the same series (patch 4 and 5).
For the sake of reducing noise in the later patches, I've put it in
the initial driver. If you feel like I should wait and do it in the
following patch (patch 4), I can do that.

Thanks for your time,

-- 
Esteban Blanc
BayLibre

  reply	other threads:[~2024-08-27 16:45 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-22 12:45 [PATCH 0/6] iio: adc: ad4030: new driver for AD4030 and similar ADCs Esteban Blanc
2024-08-22 12:45 ` [PATCH 1/6] dt-bindings: iio: adc: add ADI ad4030, ad4630 and ad4632 Esteban Blanc
2024-08-22 15:56   ` Conor Dooley
2024-08-26  8:36   ` Krzysztof Kozlowski
2024-08-22 12:45 ` [PATCH 2/6] iio: adc: ad4030: add driver for ad4030-24 Esteban Blanc
2024-08-22 19:39   ` David Lechner
2024-08-24 10:40     ` Jonathan Cameron
2024-09-13 10:22     ` Nuno Sá
2024-09-13 12:04       ` Esteban Blanc
2024-08-24 11:21   ` Jonathan Cameron
2024-08-27 16:45     ` Esteban Blanc [this message]
2024-08-28 13:34       ` Jonathan Cameron
2024-08-22 12:45 ` [PATCH 3/6] iio: adc: ad4030: add averaging support Esteban Blanc
2024-08-22 19:41   ` David Lechner
2024-08-22 12:45 ` [PATCH 4/6] iio: adc: ad4030: add support for ad4630-24 and ad4630-16 Esteban Blanc
2024-08-22 19:43   ` David Lechner
2024-08-26  9:27   ` Jonathan Cameron
2024-09-13  9:55     ` Esteban Blanc
2024-09-13 10:18       ` Nuno Sá
2024-09-13 12:55         ` Esteban Blanc
2024-09-13 13:46           ` Nuno Sá
2024-09-14 11:25             ` Jonathan Cameron
2024-09-16  6:12               ` Nuno Sá
2024-09-17 11:19                 ` Jonathan Cameron
2024-09-17 11:19                   ` Jonathan Cameron
2024-09-17 11:21                     ` Jonathan Cameron
2024-09-16  9:19               ` Esteban Blanc
2024-09-17 11:21                 ` Jonathan Cameron
2024-09-16 13:03       ` Esteban Blanc
2024-08-22 12:45 ` [PATCH 5/6] iio: adc: ad4030: add support for ad4632-16 and ad4632-24 Esteban Blanc
2024-08-26  9:29   ` Jonathan Cameron
2024-08-22 12:45 ` [PATCH 6/6] docs: iio: ad4030: add documentation Esteban Blanc
2024-08-22 19:43   ` David Lechner
2024-08-22 15:54 ` [PATCH 0/6] iio: adc: ad4030: new driver for AD4030 and similar ADCs Conor Dooley

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=D3QUGZYL7INK.R3U3WQR0OCUS@baylibre.com \
    --to=eblanc@baylibre.com \
    --cc=Michael.Hennerich@analog.com \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=devicetree@vger.kernel.org \
    --cc=dlechner@baylibre.com \
    --cc=jic23@kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=lars@metafoo.de \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-iio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.