The SPI transfers for AD4020, AD4021, and AD4022 have slightly different
timing specifications. Use device specific timing constraints to set SPI
transfer parameters.
Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
---
drivers/iio/adc/ad4000.c | 50 ++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
index 21731c4d31ee..68ac77494263 100644
--- a/drivers/iio/adc/ad4000.c
+++ b/drivers/iio/adc/ad4000.c
@@ -35,10 +35,6 @@
#define AD4000_SCALE_OPTIONS 2
-#define AD4000_TQUIET1_NS 190
-#define AD4000_TQUIET2_NS 60
-#define AD4000_TCONV_NS 320
-
#define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \
{ \
.type = IIO_VOLTAGE, \
@@ -122,10 +118,30 @@ static const int ad4000_gains[] = {
454, 909, 1000, 1900,
};
+struct ad4000_time_spec {
+ int t_conv_ns;
+ int t_quiet2_ns;
+};
+
+/*
+ * Same timing specifications for all of AD4000, AD4001, ..., AD4008, AD4010,
+ * ADAQ4001, and ADAQ4003.
+ */
+static const struct ad4000_time_spec ad4000_t_spec = {
+ .t_conv_ns = 320,
+ .t_quiet2_ns = 60,
+};
+
+static const struct ad4000_time_spec ad4020_t_spec = {
+ .t_conv_ns = 350,
+ .t_quiet2_ns = 60,
+};
+
struct ad4000_chip_info {
const char *dev_name;
struct iio_chan_spec chan_spec[2];
struct iio_chan_spec reg_access_chan_spec[2];
+ const struct ad4000_time_spec *time_spec;
bool has_hardware_gain;
};
@@ -133,90 +149,105 @@ static const struct ad4000_chip_info ad4000_chip_info = {
.dev_name = "ad4000",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4001_chip_info = {
.dev_name = "ad4001",
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4002_chip_info = {
.dev_name = "ad4002",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4003_chip_info = {
.dev_name = "ad4003",
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4004_chip_info = {
.dev_name = "ad4004",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4005_chip_info = {
.dev_name = "ad4005",
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4006_chip_info = {
.dev_name = "ad4006",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4007_chip_info = {
.dev_name = "ad4007",
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4008_chip_info = {
.dev_name = "ad4008",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 16, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4010_chip_info = {
.dev_name = "ad4010",
.chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 0),
.reg_access_chan_spec = AD4000_PSEUDO_DIFF_CHANNELS('u', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4011_chip_info = {
.dev_name = "ad4011",
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
+ .time_spec = &ad4000_t_spec,
};
static const struct ad4000_chip_info ad4020_chip_info = {
.dev_name = "ad4020",
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
+ .time_spec = &ad4020_t_spec,
};
static const struct ad4000_chip_info ad4021_chip_info = {
.dev_name = "ad4021",
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
+ .time_spec = &ad4020_t_spec,
};
static const struct ad4000_chip_info ad4022_chip_info = {
.dev_name = "ad4022",
.chan_spec = AD4000_DIFF_CHANNELS('s', 20, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 20, 1),
+ .time_spec = &ad4020_t_spec,
};
static const struct ad4000_chip_info adaq4001_chip_info = {
.dev_name = "adaq4001",
.chan_spec = AD4000_DIFF_CHANNELS('s', 16, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 16, 1),
+ .time_spec = &ad4000_t_spec,
.has_hardware_gain = true,
};
@@ -224,6 +255,7 @@ static const struct ad4000_chip_info adaq4003_chip_info = {
.dev_name = "adaq4003",
.chan_spec = AD4000_DIFF_CHANNELS('s', 18, 0),
.reg_access_chan_spec = AD4000_DIFF_CHANNELS('s', 18, 1),
+ .time_spec = &ad4000_t_spec,
.has_hardware_gain = true,
};
@@ -238,6 +270,7 @@ struct ad4000_state {
bool span_comp;
u16 gain_milli;
int scale_tbl[AD4000_SCALE_OPTIONS][2];
+ const struct ad4000_time_spec *time_spec;
/*
* DMA (thus cache coherency maintenance) requires the transfer buffers
@@ -502,16 +535,15 @@ static const struct iio_info ad4000_info = {
static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st,
const struct iio_chan_spec *chan)
{
- unsigned int cnv_pulse_time = AD4000_TCONV_NS;
struct spi_transfer *xfers = st->xfers;
xfers[0].cs_change = 1;
- xfers[0].cs_change_delay.value = cnv_pulse_time;
+ xfers[0].cs_change_delay.value = st->time_spec->t_conv_ns;
xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
xfers[1].rx_buf = &st->scan.data;
xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits);
- xfers[1].delay.value = AD4000_TQUIET2_NS;
+ xfers[1].delay.value = st->time_spec->t_quiet2_ns;
xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS;
spi_message_init_with_transfers(&st->msg, st->xfers, 2);
@@ -529,7 +561,6 @@ static int ad4000_prepare_3wire_mode_message(struct ad4000_state *st,
static int ad4000_prepare_4wire_mode_message(struct ad4000_state *st,
const struct iio_chan_spec *chan)
{
- unsigned int cnv_to_sdi_time = AD4000_TCONV_NS;
struct spi_transfer *xfers = st->xfers;
/*
@@ -537,7 +568,7 @@ static int ad4000_prepare_4wire_mode_message(struct ad4000_state *st,
* going low.
*/
xfers[0].cs_off = 1;
- xfers[0].delay.value = cnv_to_sdi_time;
+ xfers[0].delay.value = st->time_spec->t_conv_ns;
xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
xfers[1].rx_buf = &st->scan.data;
@@ -576,6 +607,7 @@ static int ad4000_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
st->spi = spi;
+ st->time_spec = chip->time_spec;
ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4000_power_supplies),
ad4000_power_supplies);
--
2.45.2
On 11/14/24 5:51 PM, Marcelo Schmitt wrote:
> The SPI transfers for AD4020, AD4021, and AD4022 have slightly different
> timing specifications. Use device specific timing constraints to set SPI
> transfer parameters.
>
> Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> ---
> drivers/iio/adc/ad4000.c | 50 ++++++++++++++++++++++++++++++++--------
> 1 file changed, 41 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
> index 21731c4d31ee..68ac77494263 100644
> --- a/drivers/iio/adc/ad4000.c
> +++ b/drivers/iio/adc/ad4000.c
> @@ -35,10 +35,6 @@
>
> #define AD4000_SCALE_OPTIONS 2
>
> -#define AD4000_TQUIET1_NS 190
> -#define AD4000_TQUIET2_NS 60
> -#define AD4000_TCONV_NS 320
We are removing 3 but only adding 2 in the struct below?
If one of these was unused, best to mention it in the commit message.
> -
> #define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \
> { \
> .type = IIO_VOLTAGE, \
> @@ -122,10 +118,30 @@ static const int ad4000_gains[] = {
> 454, 909, 1000, 1900,
> };
>
> +struct ad4000_time_spec {
> + int t_conv_ns;
> + int t_quiet2_ns;
> +};
> +
> +/*
> + * Same timing specifications for all of AD4000, AD4001, ..., AD4008, AD4010,
> + * ADAQ4001, and ADAQ4003.
> + */
> +static const struct ad4000_time_spec ad4000_t_spec = {
> + .t_conv_ns = 320,
> + .t_quiet2_ns = 60,
> +};
> +
> +static const struct ad4000_time_spec ad4020_t_spec = {
> + .t_conv_ns = 350,
> + .t_quiet2_ns = 60,
> +};
t_quiet2_ns is the same in both cases, so do we actually need to
add it here instead of using a common macro? Or if it is for future
differences, mention that in the commit message.
On 11/15, David Lechner wrote:
> On 11/14/24 5:51 PM, Marcelo Schmitt wrote:
> > The SPI transfers for AD4020, AD4021, and AD4022 have slightly different
> > timing specifications. Use device specific timing constraints to set SPI
> > transfer parameters.
> >
> > Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> > ---
> > drivers/iio/adc/ad4000.c | 50 ++++++++++++++++++++++++++++++++--------
> > 1 file changed, 41 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
> > index 21731c4d31ee..68ac77494263 100644
> > --- a/drivers/iio/adc/ad4000.c
> > +++ b/drivers/iio/adc/ad4000.c
> > @@ -35,10 +35,6 @@
> >
> > #define AD4000_SCALE_OPTIONS 2
> >
> > -#define AD4000_TQUIET1_NS 190
> > -#define AD4000_TQUIET2_NS 60
> > -#define AD4000_TCONV_NS 320
>
> We are removing 3 but only adding 2 in the struct below?
>
> If one of these was unused, best to mention it in the commit message.
One of them was unused (AD4000_TQUIET1_NS IRCC).
Sure, will add a comment about it in the commit body.
>
> > -
> > #define __AD4000_DIFF_CHANNEL(_sign, _real_bits, _storage_bits, _reg_access) \
> > { \
> > .type = IIO_VOLTAGE, \
> > @@ -122,10 +118,30 @@ static const int ad4000_gains[] = {
> > 454, 909, 1000, 1900,
> > };
> >
> > +struct ad4000_time_spec {
> > + int t_conv_ns;
> > + int t_quiet2_ns;
> > +};
> > +
> > +/*
> > + * Same timing specifications for all of AD4000, AD4001, ..., AD4008, AD4010,
> > + * ADAQ4001, and ADAQ4003.
> > + */
> > +static const struct ad4000_time_spec ad4000_t_spec = {
> > + .t_conv_ns = 320,
> > + .t_quiet2_ns = 60,
> > +};
> > +
> > +static const struct ad4000_time_spec ad4020_t_spec = {
> > + .t_conv_ns = 350,
> > + .t_quiet2_ns = 60,
> > +};
>
> t_quiet2_ns is the same in both cases, so do we actually need to
> add it here instead of using a common macro? Or if it is for future
> differences, mention that in the commit message.
Okay, will add a macro for setting ad4000_time_spec. My plan is to also add a
t_quiet1_ns filed which will be needed for offloading support.
t_quiet1_ns will also differ between AD4000 and AD4020.
© 2016 - 2026 Red Hat, Inc.