* [PATCH 1/5] iio: adc: ad9467: support multiple channels calibration
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
@ 2024-07-04 9:25 ` Nuno Sa
2024-07-06 11:16 ` Jonathan Cameron
2024-07-04 9:25 ` [PATCH 2/5] iio: adc: ad9467: add new chip_info variables Nuno Sa
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Nuno Sa @ 2024-07-04 9:25 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
The calibration process mixes the support for calibrating multiple
channels with only having one channel. Some paths do have 'num_channels'
into account while others don't.
As of now, the driver only supports devices with one channel so the
above is not really a problem. That said, we'll add support for devices
with more than one channel, hence let's properly make the calibration
process to work with it.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/ad9467.c | 117 ++++++++++++++++++++++++++++++-----------------
1 file changed, 76 insertions(+), 41 deletions(-)
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 41c1b519c573..1d8270a5bccb 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -352,6 +352,34 @@ static int ad9467_outputmode_set(struct ad9467_state *st, unsigned int mode)
AN877_ADC_TRANSFER_SYNC);
}
+static int ad9467_testmode_set(struct ad9467_state *st, unsigned int chan,
+ unsigned int test_mode)
+{
+ int ret;
+
+ if (st->info->num_channels > 1) {
+ /* so that the test mode is only applied to one channel */
+ ret = ad9467_spi_write(st, AN877_ADC_REG_CHAN_INDEX, BIT(chan));
+ if (ret)
+ return ret;
+ }
+
+ ret = ad9467_spi_write(st, AN877_ADC_REG_TEST_IO, test_mode);
+ if (ret)
+ return ret;
+
+ if (st->info->num_channels > 1) {
+ /* go to default state where all channels get write commands */
+ ret = ad9467_spi_write(st, AN877_ADC_REG_CHAN_INDEX,
+ GENMASK(st->info->num_channels - 1, 0));
+ if (ret)
+ return ret;
+ }
+
+ return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER,
+ AN877_ADC_TRANSFER_SYNC);
+}
+
static int ad9647_calibrate_prepare(struct ad9467_state *st)
{
struct iio_backend_data_fmt data = {
@@ -360,32 +388,30 @@ static int ad9647_calibrate_prepare(struct ad9467_state *st)
unsigned int c;
int ret;
- ret = ad9467_spi_write(st, AN877_ADC_REG_TEST_IO,
- AN877_ADC_TESTMODE_PN9_SEQ);
- if (ret)
- return ret;
-
- ret = ad9467_spi_write(st, AN877_ADC_REG_TRANSFER,
- AN877_ADC_TRANSFER_SYNC);
- if (ret)
- return ret;
-
ret = ad9467_outputmode_set(st, st->info->default_output_mode);
if (ret)
return ret;
for (c = 0; c < st->info->num_channels; c++) {
+ ret = ad9467_testmode_set(st, c, AN877_ADC_TESTMODE_PN9_SEQ);
+ if (ret)
+ return ret;
+
ret = iio_backend_data_format_set(st->back, c, &data);
if (ret)
return ret;
+
+ ret = iio_backend_test_pattern_set(st->back, c,
+ IIO_BACKEND_ADI_PRBS_9A);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_chan_enable(st->back, c);
+ if (ret)
+ return ret;
}
- ret = iio_backend_test_pattern_set(st->back, 0,
- IIO_BACKEND_ADI_PRBS_9A);
- if (ret)
- return ret;
-
- return iio_backend_chan_enable(st->back, 0);
+ return 0;
}
static int ad9647_calibrate_polarity_set(struct ad9467_state *st,
@@ -468,38 +494,32 @@ static int ad9647_calibrate_stop(struct ad9467_state *st)
unsigned int c, mode;
int ret;
- ret = iio_backend_chan_disable(st->back, 0);
- if (ret)
- return ret;
-
- ret = iio_backend_test_pattern_set(st->back, 0,
- IIO_BACKEND_NO_TEST_PATTERN);
- if (ret)
- return ret;
-
for (c = 0; c < st->info->num_channels; c++) {
+ ret = iio_backend_chan_disable(st->back, c);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_test_pattern_set(st->back, c,
+ IIO_BACKEND_NO_TEST_PATTERN);
+ if (ret)
+ return ret;
+
ret = iio_backend_data_format_set(st->back, c, &data);
if (ret)
return ret;
+
+ ret = ad9467_testmode_set(st, c, AN877_ADC_TESTMODE_OFF);
+ if (ret)
+ return ret;
}
mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
- ret = ad9467_outputmode_set(st, mode);
- if (ret)
- return ret;
-
- ret = ad9467_spi_write(st, AN877_ADC_REG_TEST_IO,
- AN877_ADC_TESTMODE_OFF);
- if (ret)
- return ret;
-
- return ad9467_spi_write(st, AN877_ADC_REG_TRANSFER,
- AN877_ADC_TRANSFER_SYNC);
+ return ad9467_outputmode_set(st, mode);
}
static int ad9467_calibrate(struct ad9467_state *st)
{
- unsigned int point, val, inv_val, cnt, inv_cnt = 0;
+ unsigned int point, val, inv_val, cnt, inv_cnt = 0, c;
/*
* Half of the bitmap is for the inverted signal. The number of test
* points is the same though...
@@ -526,11 +546,26 @@ static int ad9467_calibrate(struct ad9467_state *st)
if (ret)
return ret;
- ret = iio_backend_chan_status(st->back, 0, &stat);
- if (ret)
- return ret;
+ for (c = 0; c < st->info->num_channels; c++) {
+ ret = iio_backend_chan_status(st->back, c, &stat);
+ if (ret)
+ return ret;
- __assign_bit(point + invert * test_points, st->calib_map, stat);
+ /*
+ * A point is considered valid if all channels report no
+ * error. If one reports an error, then we consider the
+ * point as invalid and we can break the loop right away.
+ */
+ if (stat) {
+ dev_dbg(dev, "Invalid point(%u, inv:%u) for CH:%u\n",
+ point, invert, c);
+ break;
+ }
+
+ if (c == st->info->num_channels - 1)
+ __clear_bit(point + invert * test_points,
+ st->calib_map);
+ }
}
if (!invert) {
--
2.45.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 1/5] iio: adc: ad9467: support multiple channels calibration
2024-07-04 9:25 ` [PATCH 1/5] iio: adc: ad9467: support multiple channels calibration Nuno Sa
@ 2024-07-06 11:16 ` Jonathan Cameron
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2024-07-06 11:16 UTC (permalink / raw)
To: Nuno Sa
Cc: linux-iio, devicetree, Lars-Peter Clausen, Michael Hennerich,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
On Thu, 4 Jul 2024 11:25:21 +0200
Nuno Sa <nuno.sa@analog.com> wrote:
> The calibration process mixes the support for calibrating multiple
> channels with only having one channel. Some paths do have 'num_channels'
> into account while others don't.
>
> As of now, the driver only supports devices with one channel so the
> above is not really a problem. That said, we'll add support for devices
> with more than one channel, hence let's properly make the calibration
> process to work with it.
>
> Signed-off-by: Nuno Sa <nuno.sa@analog.com>
Hi Nuno,
Not suggesting you change it here, but one place where I think
the existing code readability could be improved.
> static int ad9467_calibrate(struct ad9467_state *st)
> {
> - unsigned int point, val, inv_val, cnt, inv_cnt = 0;
> + unsigned int point, val, inv_val, cnt, inv_cnt = 0, c;
Comment on existing code. I'm not keen on mix of assignment and non
assignment in a single line of local variable declarations.
It can get hard to spot what is assigned!
> /*
> * Half of the bitmap is for the inverted signal. The number of test
> * points is the same though...
> @@ -526,11 +546,26 @@ static int ad9467_calibrate(struct ad9467_state *st)
> if (ret)
> return ret;
>
> - ret = iio_backend_chan_status(st->back, 0, &stat);
> - if (ret)
> - return ret;
> + for (c = 0; c < st->info->num_channels; c++) {
> + ret = iio_backend_chan_status(st->back, c, &stat);
> + if (ret)
> + return ret;
>
> - __assign_bit(point + invert * test_points, st->calib_map, stat);
> + /*
> + * A point is considered valid if all channels report no
> + * error. If one reports an error, then we consider the
> + * point as invalid and we can break the loop right away.
> + */
> + if (stat) {
> + dev_dbg(dev, "Invalid point(%u, inv:%u) for CH:%u\n",
> + point, invert, c);
> + break;
> + }
> +
> + if (c == st->info->num_channels - 1)
> + __clear_bit(point + invert * test_points,
> + st->calib_map);
> + }
> }
>
> if (!invert) {
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/5] iio: adc: ad9467: add new chip_info variables
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
2024-07-04 9:25 ` [PATCH 1/5] iio: adc: ad9467: support multiple channels calibration Nuno Sa
@ 2024-07-04 9:25 ` Nuno Sa
2024-07-04 9:25 ` [PATCH 3/5] iio: adc: ad9467: don't allow reading vref if not available Nuno Sa
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Nuno Sa @ 2024-07-04 9:25 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Add new variables to the per chip info structure:
* test_points: Number of valid test points for calibration;
* has_dco_invert: Supports inverting DCO (Data clock output) polarity;
* dco_en: Specicic mask to enable DCO delays.
This is in preparation for supporting new parts with subtle differences
in how to configure the hardware.
Note that with the new test_points variable, we also add a new
calib_map_size to 'struct ad9467_state' so we know our map size
depending on how many test points we have and if we can run the
calibration in the inverted state or not.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/ad9467.c | 38 +++++++++++++++++++++++++++++---------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 1d8270a5bccb..077c3a594bfc 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -105,6 +105,8 @@
#define AD9467_REG_VREF_MASK 0x0F
#define AD9647_MAX_TEST_POINTS 32
+#define AD9467_CAN_INVERT(st) \
+ (!(st)->info->has_dco || (st)->info->has_dco_invert)
struct ad9467_chip_info {
const char *name;
@@ -117,8 +119,11 @@ struct ad9467_chip_info {
unsigned int default_output_mode;
unsigned int vref_mask;
unsigned int num_lanes;
+ unsigned int dco_en;
+ unsigned int test_points;
/* data clock output */
bool has_dco;
+ bool has_dco_invert;
};
struct ad9467_state {
@@ -138,6 +143,8 @@ struct ad9467_state {
* at the io delay control section.
*/
DECLARE_BITMAP(calib_map, AD9647_MAX_TEST_POINTS * 2);
+ /* number of bits of the map */
+ unsigned int calib_map_size;
struct gpio_desc *pwrdown_gpio;
/* ensure consistent state obtained on multiple related accesses */
struct mutex lock;
@@ -256,6 +263,7 @@ static const struct ad9467_chip_info ad9467_chip_tbl = {
.num_scales = ARRAY_SIZE(ad9467_scale_table),
.channels = ad9467_channels,
.num_channels = ARRAY_SIZE(ad9467_channels),
+ .test_points = AD9647_MAX_TEST_POINTS,
.default_output_mode = AD9467_DEF_OUTPUT_MODE,
.vref_mask = AD9467_REG_VREF_MASK,
.num_lanes = 8,
@@ -269,6 +277,7 @@ static const struct ad9467_chip_info ad9434_chip_tbl = {
.num_scales = ARRAY_SIZE(ad9434_scale_table),
.channels = ad9434_channels,
.num_channels = ARRAY_SIZE(ad9434_channels),
+ .test_points = AD9647_MAX_TEST_POINTS,
.default_output_mode = AD9434_DEF_OUTPUT_MODE,
.vref_mask = AD9434_REG_VREF_MASK,
.num_lanes = 6,
@@ -282,9 +291,11 @@ static const struct ad9467_chip_info ad9265_chip_tbl = {
.num_scales = ARRAY_SIZE(ad9265_scale_table),
.channels = ad9467_channels,
.num_channels = ARRAY_SIZE(ad9467_channels),
+ .test_points = AD9647_MAX_TEST_POINTS,
.default_output_mode = AD9265_DEF_OUTPUT_MODE,
.vref_mask = AD9265_REG_VREF_MASK,
.has_dco = true,
+ .has_dco_invert = true,
};
static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
@@ -468,7 +479,7 @@ static int ad9467_calibrate_apply(struct ad9467_state *st, unsigned int val)
if (st->info->has_dco) {
ret = ad9467_spi_write(st, AN877_ADC_REG_OUTPUT_DELAY,
- val);
+ val | st->info->dco_en);
if (ret)
return ret;
@@ -524,14 +535,14 @@ static int ad9467_calibrate(struct ad9467_state *st)
* Half of the bitmap is for the inverted signal. The number of test
* points is the same though...
*/
- unsigned int test_points = AD9647_MAX_TEST_POINTS;
+ unsigned int test_points = st->info->test_points;
unsigned long sample_rate = clk_get_rate(st->clk);
struct device *dev = &st->spi->dev;
bool invert = false, stat;
int ret;
/* all points invalid */
- bitmap_fill(st->calib_map, BITS_PER_TYPE(st->calib_map));
+ bitmap_fill(st->calib_map, st->calib_map_size);
ret = ad9647_calibrate_prepare(st);
if (ret)
@@ -541,7 +552,7 @@ static int ad9467_calibrate(struct ad9467_state *st)
if (ret)
return ret;
- for (point = 0; point < test_points; point++) {
+ for (point = 0; point < st->info->test_points; point++) {
ret = ad9467_calibrate_apply(st, point);
if (ret)
return ret;
@@ -576,8 +587,13 @@ static int ad9467_calibrate(struct ad9467_state *st)
* a row.
*/
if (cnt < 3) {
- invert = true;
- goto retune;
+ if (AD9467_CAN_INVERT(st)) {
+ invert = true;
+ goto retune;
+ }
+
+ if (!cnt)
+ return -EIO;
}
} else {
inv_cnt = ad9467_find_optimal_point(st->calib_map, test_points,
@@ -802,7 +818,7 @@ static ssize_t ad9467_dump_calib_table(struct file *file,
size_t count, loff_t *ppos)
{
struct ad9467_state *st = file->private_data;
- unsigned int bit, size = BITS_PER_TYPE(st->calib_map);
+ unsigned int bit;
/* +2 for the newline and +1 for the string termination */
unsigned char map[AD9647_MAX_TEST_POINTS * 2 + 3];
ssize_t len = 0;
@@ -811,8 +827,8 @@ static ssize_t ad9467_dump_calib_table(struct file *file,
if (*ppos)
goto out_read;
- for (bit = 0; bit < size; bit++) {
- if (bit == size / 2)
+ for (bit = 0; bit < st->calib_map_size; bit++) {
+ if (AD9467_CAN_INVERT(st) && bit == st->calib_map_size / 2)
len += scnprintf(map + len, sizeof(map) - len, "\n");
len += scnprintf(map + len, sizeof(map) - len, "%c",
@@ -861,6 +877,10 @@ static int ad9467_probe(struct spi_device *spi)
if (!st->info)
return -ENODEV;
+ st->calib_map_size = st->info->test_points;
+ if (AD9467_CAN_INVERT(st))
+ st->calib_map_size *= 2;
+
st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");
if (IS_ERR(st->clk))
return PTR_ERR(st->clk);
--
2.45.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH 3/5] iio: adc: ad9467: don't allow reading vref if not available
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
2024-07-04 9:25 ` [PATCH 1/5] iio: adc: ad9467: support multiple channels calibration Nuno Sa
2024-07-04 9:25 ` [PATCH 2/5] iio: adc: ad9467: add new chip_info variables Nuno Sa
@ 2024-07-04 9:25 ` Nuno Sa
2024-07-06 11:20 ` Jonathan Cameron
2024-07-04 9:25 ` [PATCH 4/5] dt-bindings: adc: ad9467: support new parts Nuno Sa
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Nuno Sa @ 2024-07-04 9:25 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
If there's only one possible scale, there's no way to change the Vref
select in the device so avoid reading the register in ad9467_get_scale().
In this case, it makes no sense to provide the .read_available()
callback nor allowing for writing the scale attribute.
Note this is in preparation for supporting a new device that only has
one possible scale.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/ad9467.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 077c3a594bfc..d06a5fcc4ee8 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -231,14 +231,14 @@ static void __ad9467_get_scale(struct ad9467_state *st, int index,
*val2 = tmp % 1000000;
}
-#define AD9467_CHAN(_chan, _si, _bits, _sign) \
+#define AD9467_CHAN(_chan, avai_mask, _si, _bits, _sign) \
{ \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _chan, \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type_available = avai_mask, \
.scan_index = _si, \
.scan_type = { \
.sign = _sign, \
@@ -248,11 +248,11 @@ static void __ad9467_get_scale(struct ad9467_state *st, int index,
}
static const struct iio_chan_spec ad9434_channels[] = {
- AD9467_CHAN(0, 0, 12, 's'),
+ AD9467_CHAN(0, BIT(IIO_CHAN_INFO_SCALE), 0, 12, 's'),
};
static const struct iio_chan_spec ad9467_channels[] = {
- AD9467_CHAN(0, 0, 16, 's'),
+ AD9467_CHAN(0, BIT(IIO_CHAN_INFO_SCALE), 0, 16, 's'),
};
static const struct ad9467_chip_info ad9467_chip_tbl = {
@@ -301,9 +301,13 @@ static const struct ad9467_chip_info ad9265_chip_tbl = {
static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
{
const struct ad9467_chip_info *info = st->info;
- unsigned int i, vref_val;
+ unsigned int i = 0, vref_val;
int ret;
+ /* nothing to read if we only have one possible scale */
+ if (info->num_scales == 1)
+ goto out_get_scale;
+
ret = ad9467_spi_read(st, AN877_ADC_REG_VREF);
if (ret < 0)
return ret;
@@ -318,6 +322,7 @@ static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
if (i == info->num_scales)
return -ERANGE;
+out_get_scale:
__ad9467_get_scale(st, i, val, val2);
return IIO_VAL_INT_PLUS_MICRO;
@@ -332,6 +337,8 @@ static int ad9467_set_scale(struct ad9467_state *st, int val, int val2)
if (val != 0)
return -EINVAL;
+ if (info->num_scales == 1)
+ return -EOPNOTSUPP;
for (i = 0; i < info->num_scales; i++) {
__ad9467_get_scale(st, i, &scale_val[0], &scale_val[1]);
@@ -730,7 +737,7 @@ static int ad9467_update_scan_mode(struct iio_dev *indio_dev,
return 0;
}
-static const struct iio_info ad9467_info = {
+static struct iio_info ad9467_info = {
.read_raw = ad9467_read_raw,
.write_raw = ad9467_write_raw,
.update_scan_mode = ad9467_update_scan_mode,
@@ -905,6 +912,8 @@ static int ad9467_probe(struct spi_device *spi)
return -ENODEV;
}
+ if (st->info->num_scales > 1)
+ ad9467_info.read_avail = ad9467_read_avail;
indio_dev->name = st->info->name;
indio_dev->channels = st->info->channels;
indio_dev->num_channels = st->info->num_channels;
--
2.45.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 3/5] iio: adc: ad9467: don't allow reading vref if not available
2024-07-04 9:25 ` [PATCH 3/5] iio: adc: ad9467: don't allow reading vref if not available Nuno Sa
@ 2024-07-06 11:20 ` Jonathan Cameron
0 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2024-07-06 11:20 UTC (permalink / raw)
To: Nuno Sa
Cc: linux-iio, devicetree, Lars-Peter Clausen, Michael Hennerich,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
On Thu, 4 Jul 2024 11:25:23 +0200
Nuno Sa <nuno.sa@analog.com> wrote:
> If there's only one possible scale, there's no way to change the Vref
> select in the device so avoid reading the register in ad9467_get_scale().
> In this case, it makes no sense to provide the .read_available()
> callback nor allowing for writing the scale attribute.
>
> Note this is in preparation for supporting a new device that only has
> one possible scale.
>
> Signed-off-by: Nuno Sa <nuno.sa@analog.com>
Trivial comment inline. If nothing else comes up I might just tweak it
whilst applying.
>
> static const struct ad9467_chip_info ad9467_chip_tbl = {
> @@ -301,9 +301,13 @@ static const struct ad9467_chip_info ad9265_chip_tbl = {
> static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
> {
> const struct ad9467_chip_info *info = st->info;
> - unsigned int i, vref_val;
> + unsigned int i = 0, vref_val;
This time it's in new code.
unsigned int vref_val;
unsigned int i = 0;
preferred so the assignment isn't burried.
> int ret;
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/5] dt-bindings: adc: ad9467: support new parts
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
` (2 preceding siblings ...)
2024-07-04 9:25 ` [PATCH 3/5] iio: adc: ad9467: don't allow reading vref if not available Nuno Sa
@ 2024-07-04 9:25 ` Nuno Sa
2024-07-04 14:23 ` Krzysztof Kozlowski
2024-07-04 9:25 ` [PATCH 5/5] iio: " Nuno Sa
2024-07-06 11:30 ` [PATCH 0/5] iio: adc: ad9467: support new devices Jonathan Cameron
5 siblings, 1 reply; 10+ messages in thread
From: Nuno Sa @ 2024-07-04 9:25 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Add support for new devices:
* Analog Devices AD9652 16-bit 310 MSPS ADC;
* Analog Devices AD9643 14-Bit, 170/210/250 MSPS ADC;
* Analog Devices AD9649 14-bit 20/40/65/80 MSPS ADC.
Note all these parts have subtle differences in their programming model
(different scales, number of channels, etc..) so fallbacks are not
possible.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
index eecd5fbab695..2606c0c5dfc6 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
@@ -28,6 +28,9 @@ properties:
- adi,ad9265
- adi,ad9434
- adi,ad9467
+ - adi,ad9643
+ - adi,ad9649
+ - adi,ad9652
reg:
maxItems: 1
--
2.45.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 4/5] dt-bindings: adc: ad9467: support new parts
2024-07-04 9:25 ` [PATCH 4/5] dt-bindings: adc: ad9467: support new parts Nuno Sa
@ 2024-07-04 14:23 ` Krzysztof Kozlowski
0 siblings, 0 replies; 10+ messages in thread
From: Krzysztof Kozlowski @ 2024-07-04 14:23 UTC (permalink / raw)
To: Nuno Sa, linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
On 04/07/2024 11:25, Nuno Sa wrote:
> Add support for new devices:
> * Analog Devices AD9652 16-bit 310 MSPS ADC;
> * Analog Devices AD9643 14-Bit, 170/210/250 MSPS ADC;
> * Analog Devices AD9649 14-bit 20/40/65/80 MSPS ADC.
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/5] iio: adc: ad9467: support new parts
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
` (3 preceding siblings ...)
2024-07-04 9:25 ` [PATCH 4/5] dt-bindings: adc: ad9467: support new parts Nuno Sa
@ 2024-07-04 9:25 ` Nuno Sa
2024-07-06 11:30 ` [PATCH 0/5] iio: adc: ad9467: support new devices Jonathan Cameron
5 siblings, 0 replies; 10+ messages in thread
From: Nuno Sa @ 2024-07-04 9:25 UTC (permalink / raw)
To: linux-iio, devicetree
Cc: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Add support for new devices:
* Analog Devices AD9652 16-bit 310 MSPS ADC;
* Analog Devices AD9643 14-Bit, 170/210/250 MSPS ADC;
* Analog Devices AD9649 14-bit 20/40/65/80 MSPS ADC.
Signed-off-by: Nuno Sa <nuno.sa@analog.com>
---
drivers/iio/adc/ad9467.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index d06a5fcc4ee8..b07c83efc39a 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -104,6 +104,27 @@
#define AD9467_DEF_OUTPUT_MODE 0x08
#define AD9467_REG_VREF_MASK 0x0F
+/*
+ * Analog Devices AD9643 14-Bit, 170/210/250 MSPS ADC
+ */
+
+#define CHIPID_AD9643 0x82
+#define AD9643_REG_VREF_MASK 0x1F
+
+/*
+ * Analog Devices AD9652 16-bit 310 MSPS ADC
+ */
+
+#define CHIPID_AD9652 0xC1
+#define AD9652_REG_VREF_MASK 0xC0
+
+/*
+ * Analog Devices AD9649 14-bit 20/40/65/80 MSPS ADC
+ */
+
+#define CHIPID_AD9649 0x6F
+#define AD9649_TEST_POINTS 8
+
#define AD9647_MAX_TEST_POINTS 32
#define AD9467_CAN_INVERT(st) \
(!(st)->info->has_dco || (st)->info->has_dco_invert)
@@ -218,6 +239,24 @@ static const unsigned int ad9467_scale_table[][2] = {
{2300, 8}, {2400, 9}, {2500, 10},
};
+static const unsigned int ad9643_scale_table[][2] = {
+ {2087, 0x0F}, {2065, 0x0E}, {2042, 0x0D}, {2020, 0x0C}, {1997, 0x0B},
+ {1975, 0x0A}, {1952, 0x09}, {1930, 0x08}, {1907, 0x07}, {1885, 0x06},
+ {1862, 0x05}, {1840, 0x04}, {1817, 0x03}, {1795, 0x02}, {1772, 0x01},
+ {1750, 0x00}, {1727, 0x1F}, {1704, 0x1E}, {1681, 0x1D}, {1658, 0x1C},
+ {1635, 0x1B}, {1612, 0x1A}, {1589, 0x19}, {1567, 0x18}, {1544, 0x17},
+ {1521, 0x16}, {1498, 0x15}, {1475, 0x14}, {1452, 0x13}, {1429, 0x12},
+ {1406, 0x11}, {1383, 0x10},
+};
+
+static const unsigned int ad9649_scale_table[][2] = {
+ {2000, 0},
+};
+
+static const unsigned int ad9652_scale_table[][2] = {
+ {1250, 0}, {1125, 1}, {1200, 2}, {1250, 3}, {1000, 5},
+};
+
static void __ad9467_get_scale(struct ad9467_state *st, int index,
unsigned int *val, unsigned int *val2)
{
@@ -255,6 +294,20 @@ static const struct iio_chan_spec ad9467_channels[] = {
AD9467_CHAN(0, BIT(IIO_CHAN_INFO_SCALE), 0, 16, 's'),
};
+static const struct iio_chan_spec ad9643_channels[] = {
+ AD9467_CHAN(0, BIT(IIO_CHAN_INFO_SCALE), 0, 14, 's'),
+ AD9467_CHAN(1, BIT(IIO_CHAN_INFO_SCALE), 1, 14, 's'),
+};
+
+static const struct iio_chan_spec ad9649_channels[] = {
+ AD9467_CHAN(0, 0, 0, 14, 's'),
+};
+
+static const struct iio_chan_spec ad9652_channels[] = {
+ AD9467_CHAN(0, BIT(IIO_CHAN_INFO_SCALE), 0, 16, 's'),
+ AD9467_CHAN(1, BIT(IIO_CHAN_INFO_SCALE), 1, 16, 's'),
+};
+
static const struct ad9467_chip_info ad9467_chip_tbl = {
.name = "ad9467",
.id = CHIPID_AD9467,
@@ -298,6 +351,48 @@ static const struct ad9467_chip_info ad9265_chip_tbl = {
.has_dco_invert = true,
};
+static const struct ad9467_chip_info ad9643_chip_tbl = {
+ .name = "ad9643",
+ .id = CHIPID_AD9643,
+ .max_rate = 250000000UL,
+ .scale_table = ad9643_scale_table,
+ .num_scales = ARRAY_SIZE(ad9643_scale_table),
+ .channels = ad9643_channels,
+ .num_channels = ARRAY_SIZE(ad9643_channels),
+ .test_points = AD9647_MAX_TEST_POINTS,
+ .vref_mask = AD9643_REG_VREF_MASK,
+ .has_dco = true,
+ .has_dco_invert = true,
+ .dco_en = AN877_ADC_DCO_DELAY_ENABLE,
+};
+
+static const struct ad9467_chip_info ad9649_chip_tbl = {
+ .name = "ad9649",
+ .id = CHIPID_AD9649,
+ .max_rate = 80000000UL,
+ .scale_table = ad9649_scale_table,
+ .num_scales = ARRAY_SIZE(ad9649_scale_table),
+ .channels = ad9649_channels,
+ .num_channels = ARRAY_SIZE(ad9649_channels),
+ .test_points = AD9649_TEST_POINTS,
+ .has_dco = true,
+ .has_dco_invert = true,
+ .dco_en = AN877_ADC_DCO_DELAY_ENABLE,
+};
+
+static const struct ad9467_chip_info ad9652_chip_tbl = {
+ .name = "ad9652",
+ .id = CHIPID_AD9652,
+ .max_rate = 310000000UL,
+ .scale_table = ad9652_scale_table,
+ .num_scales = ARRAY_SIZE(ad9652_scale_table),
+ .channels = ad9652_channels,
+ .num_channels = ARRAY_SIZE(ad9652_channels),
+ .test_points = AD9647_MAX_TEST_POINTS,
+ .vref_mask = AD9652_REG_VREF_MASK,
+ .has_dco = true,
+};
+
static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
{
const struct ad9467_chip_info *info = st->info;
@@ -948,6 +1043,9 @@ static const struct of_device_id ad9467_of_match[] = {
{ .compatible = "adi,ad9265", .data = &ad9265_chip_tbl, },
{ .compatible = "adi,ad9434", .data = &ad9434_chip_tbl, },
{ .compatible = "adi,ad9467", .data = &ad9467_chip_tbl, },
+ { .compatible = "adi,ad9643", .data = &ad9643_chip_tbl, },
+ { .compatible = "adi,ad9649", .data = &ad9649_chip_tbl, },
+ { .compatible = "adi,ad9652", .data = &ad9652_chip_tbl, },
{}
};
MODULE_DEVICE_TABLE(of, ad9467_of_match);
@@ -956,6 +1054,9 @@ static const struct spi_device_id ad9467_ids[] = {
{ "ad9265", (kernel_ulong_t)&ad9265_chip_tbl },
{ "ad9434", (kernel_ulong_t)&ad9434_chip_tbl },
{ "ad9467", (kernel_ulong_t)&ad9467_chip_tbl },
+ { "ad9643", (kernel_ulong_t)&ad9643_chip_tbl },
+ { "ad9649", (kernel_ulong_t)&ad9649_chip_tbl, },
+ { "ad9652", (kernel_ulong_t)&ad9652_chip_tbl, },
{}
};
MODULE_DEVICE_TABLE(spi, ad9467_ids);
--
2.45.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH 0/5] iio: adc: ad9467: support new devices
2024-07-04 9:25 [PATCH 0/5] iio: adc: ad9467: support new devices Nuno Sa
` (4 preceding siblings ...)
2024-07-04 9:25 ` [PATCH 5/5] iio: " Nuno Sa
@ 2024-07-06 11:30 ` Jonathan Cameron
5 siblings, 0 replies; 10+ messages in thread
From: Jonathan Cameron @ 2024-07-06 11:30 UTC (permalink / raw)
To: Nuno Sa
Cc: linux-iio, devicetree, Lars-Peter Clausen, Michael Hennerich,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
On Thu, 4 Jul 2024 11:25:20 +0200
Nuno Sa <nuno.sa@analog.com> wrote:
> This series adds support for more devices:
> * Analog Devices AD9652 16-bit 310 MSPS ADC;
> * Analog Devices AD9643 14-Bit, 170/210/250 MSPS ADC;
> * Analog Devices AD9649 14-bit 20/40/65/80 MSPS ADC.
>
> The first pacthes are just in preparation to make adding the new devices
patches..
> straightforward.
Applied with the minor tweak mentioned in thread to patch 3.
Applied for now to the testing branch of iio.git which I'll rebase and
push out as togreg after 6.11-rc1 is available.
Thanks,
Jonathan
>
> ---
> Nuno Sa (5):
> iio: adc: ad9467: support multiple channels calibration
> iio: adc: ad9467: add new chip_info variables
> iio: adc: ad9467: don't allow reading vref if not available
> dt-bindings: adc: ad9467: support new parts
> iio: adc: ad9467: support new parts
>
> .../devicetree/bindings/iio/adc/adi,ad9467.yaml | 3 +
> drivers/iio/adc/ad9467.c | 277 ++++++++++++++++-----
> 2 files changed, 224 insertions(+), 56 deletions(-)
> ---
> base-commit: 7db8a847f98caae68c70bdab9ba92d1af38e5656
> change-id: 20240620-dev-iio-ad9467-new-devs-f30e5536220f
> --
>
> Thanks!
> - Nuno Sá
>
^ permalink raw reply [flat|nested] 10+ messages in thread