From: David Lechner <dlechner@baylibre.com>
To: Antoniu Miclaus <antoniu.miclaus@analog.com>,
jic23@kernel.org, robh@kernel.org, conor+dt@kernel.org,
linux-iio@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v5 09/10] iio: adc: ad4080: add driver support
Date: Mon, 12 May 2025 10:09:44 -0500 [thread overview]
Message-ID: <86d73027-6ab2-4751-8839-e7905a6b4e34@baylibre.com> (raw)
In-Reply-To: <20250509105019.8887-10-antoniu.miclaus@analog.com>
On 5/9/25 5:50 AM, Antoniu Miclaus wrote:
> Add support for AD4080 high-speed, low noise, low distortion,
> 20-bit, Easy Drive, successive approximation register (SAR)
> analog-to-digital converter (ADC).
>
> Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
> ---
...
> +static const char *const ad4080_filter_type_iio_enum[] = {
> + [FILTER_NONE] = "none",
> + [SINC_1] = "sinc1",
> + [SINC_5] = "sinc5",
> + [SINC_5_COMP] = "sinc5+pf1",
> +};
> +
> +static const int ad4080_dec_rate_iio_enum[] = {
Would make more sense to call this _avail instead of _iio_enum.
> + 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
> +};
> +
> +static const char * const ad4080_power_supplies[] = {
> + "vdd33", "vdd11", "vddldo", "iovdd", "vrefin",
> +};
> +
> +struct ad4080_chip_info {
> + const char *name;
> + unsigned int product_id;
> + int num_scales;
> + const unsigned int (*scale_table)[2];
> + const struct iio_chan_spec *channels;
> + unsigned int num_channels;
> +};
> +
> +struct ad4080_state {
> + struct regmap *regmap;
> + struct clk *clk;
clk isn't used outside of probe and can be removed.
> + struct iio_backend *back;
> + const struct ad4080_chip_info *info;
> + /*
> + * Synchronize access to members the of driver state, and ensure
> + * atomicity of consecutive regmap operations.
> + */
> + struct mutex lock;
> + unsigned int num_lanes;
> + unsigned int dec_rate;
> + unsigned long clk_rate;
> + enum ad4080_filter_type filter_type;
> + bool lvds_cnv_en;
> +};
> +
...
> +static int ad4080_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long m)
> +{
> + struct ad4080_state *st = iio_priv(indio_dev);
> + unsigned int dec_rate;
> +
> + switch (m) {
> + case IIO_CHAN_INFO_SCALE:
> + return ad4080_get_scale(st, val, val2);
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + dec_rate = ad4080_get_dec_rate(indio_dev, chan);
Need to check return value for negative error code.
> + if (st->filter_type == SINC_5_COMP)
> + dec_rate *= 2;
> + if (st->filter_type)
> + *val = DIV_ROUND_CLOSEST(st->clk_rate, dec_rate);
> + else
> + *val = st->clk_rate;
> + return IIO_VAL_INT;
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
> + *val = ad4080_get_dec_rate(indio_dev, chan);
Ditto.
Also, should set *val = 1 in the case of st->filter_type == FILTER_NONE.
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int ad4080_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val, int val2, long mask)
> +{
> + switch (mask) {
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
This has no effect when st->filter_type == FILTER_NONE and should only
allow 1 in that case.
> + return ad4080_set_dec_rate(indio_dev, chan, val);
> + default:
> + return -EINVAL;
> + }
> +}
> +
...
> +static int ad4080_set_filter_type(struct iio_dev *dev,
> + const struct iio_chan_spec *chan,
> + unsigned int mode)
> +{
> + struct ad4080_state *st = iio_priv(dev);
> + unsigned int dec_rate;
> + int ret;
> +
> + guard(mutex)(&st->lock);
> +
> + dec_rate = ad4080_get_dec_rate(dev, chan);
Again, need to check for negative error code.
> +
> + if (mode >= SINC_5 && dec_rate >= 512)
> + return -EINVAL;
> +
> + ret = iio_backend_filter_type_set(st->back, mode);
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(st->regmap, AD4080_REG_FILTER_CONFIG,
> + AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
> + FIELD_PREP(AD4080_FILTER_CONFIG_FILTER_SEL_MSK,
> + mode));
> + if (ret)
> + return ret;
> +
> + st->filter_type = mode;
> +
> + return 0;
> +}
> +
> +static int ad4080_read_avail(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + const int **vals, int *type, int *length,
> + long mask)
> +{
> + switch (mask) {
> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
Would make sense to have a separate case for st->filter_type == FILTER_NONE
simialar to suggestions above. 1 is the only available value in that case.
Also, in the st->filter_type != FILTER_NONE case, would make sense to set
*length based on st->filter_type since 256 is the max value for the sinc5
filters.
> + *vals = ad4080_dec_rate_iio_enum;
> + *length = ARRAY_SIZE(ad4080_dec_rate_iio_enum);
> + *type = IIO_VAL_INT;
> + return IIO_AVAIL_LIST;
> + default:
> + return -EINVAL;
> + }
> +}
> +
...
> +
> +static int ad4080_setup(struct iio_dev *indio_dev)
> +{
> + struct ad4080_state *st = iio_priv(indio_dev);
> + struct device *dev = regmap_get_device(st->regmap);
> + unsigned int id;
> + int ret;
> +
> + ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
> + AD4080_INTERFACE_CONFIG_A_SW_RESET);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(st->regmap, AD4080_REG_INTERFACE_CONFIG_A,
> + AD4080_INTERFACE_CONFIG_A_SDO_ENABLE);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(st->regmap, AD4080_REG_CHIP_TYPE, &id);
> + if (ret)
> + return ret;
> +
> + if (id != AD4080_CHIP_ID)
> + dev_info(dev, "Unrecognized CHIP_ID 0x%X\n", id);
> +
> + ret = regmap_set_bits(st->regmap, AD4080_REG_GPIO_CONFIG_A,
> + AD4080_GPIO_CONFIG_A_GPO_1_EN);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(st->regmap, AD4080_REG_GPIO_CONFIG_B,
> + FIELD_PREP(AD4080_GPIO_CONFIG_B_GPIO_1_SEL_MSK, 3));
Would be nice to have a macro or comment to explain what 3 is here so that
we don't have to look at the datasheet to figure out that this is configuring
the pin as "Filter Result Ready (Active Low)".
I would also expect to have some devictree bindings that describe that GPIO 1
on the ADC is connected to the sync_n input of the ad408x (AXI ADC) IP block.
Or at the very least, some comments here explaining that this is the assumed
default and if we ever add another backend or someone wants to wire up a part
a bit differently, then we might need to make this more generic.
> + if (ret)
> + return ret;
> +
> + ret = iio_backend_num_lanes_set(st->back, st->num_lanes);
> + if (ret)
> + return ret;
> +
> + if (!st->lvds_cnv_en)
> + return 0;
> +
> + ret = regmap_update_bits(st->regmap,
> + AD4080_REG_ADC_DATA_INTF_CONFIG_B,
> + AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK,
> + FIELD_PREP(AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_CLK_CNT_MSK, 7));
Similar here, it looks like the 7 here is the result of some calulation
based on the external CLK signal, So I would expec to see that caluclation
done in code using st->clk_rate or explain why hard-coding 7 is OK and
how that value was calculated.
> + if (ret)
> + return ret;
> +
> + if (st->num_lanes > 1) {
> + ret = regmap_set_bits(st->regmap, AD4080_REG_ADC_DATA_INTF_CONFIG_A,
> + AD4080_ADC_DATA_INTF_CONFIG_A_SPI_LVDS_LANES);
> + if (ret)
> + return ret;
> + }
> +
> + ret = regmap_set_bits(st->regmap,
> + AD4080_REG_ADC_DATA_INTF_CONFIG_B,
> + AD4080_ADC_DATA_INTF_CONFIG_B_LVDS_CNV_EN);
> + if (ret)
> + return ret;
> +
> + return ad4080_lvds_sync_write(st);
> +}
> +
next prev parent reply other threads:[~2025-05-12 15:09 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-09 10:50 [PATCH v5 00/10] Add support for AD4080 ADC Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 01/10] iio: backend: add support for filter config Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 02/10] iio: backend: add support for data alignment Antoniu Miclaus
2025-05-12 6:53 ` Nuno Sá
2025-05-09 10:50 ` [PATCH v5 03/10] iio: backend: add support for number of lanes Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 04/10] dt-bindings: iio: adc: add ad408x axi variant Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 05/10] iio: adc: adi-axi-adc: add filter type config Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 06/10] iio: adc: adi-axi-adc: add data align process Antoniu Miclaus
2025-05-12 6:54 ` Nuno Sá
2025-05-09 10:50 ` [PATCH v5 07/10] iio: adc: adi-axi-adc: add num lanes support Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 08/10] dt-bindings: iio: adc: add ad4080 Antoniu Miclaus
2025-05-09 10:50 ` [PATCH v5 09/10] iio: adc: ad4080: add driver support Antoniu Miclaus
2025-05-12 6:59 ` Nuno Sá
2025-05-12 15:09 ` David Lechner [this message]
2025-05-09 10:50 ` [PATCH v5 10/10] Documetation: ABI: add sinc1 and sinc5+pf1 filter Antoniu Miclaus
2025-05-12 14:15 ` David Lechner
2025-05-11 14:40 ` [PATCH v5 00/10] Add support for AD4080 ADC Jonathan Cameron
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=86d73027-6ab2-4751-8839-e7905a6b4e34@baylibre.com \
--to=dlechner@baylibre.com \
--cc=antoniu.miclaus@analog.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jic23@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--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