Re: [PATCH v2 1/2] iio: adis: Introduce timeouts structure

From: Jonathan Cameron
Date: Sat Jan 11 2020 - 06:35:18 EST


On Tue, 7 Jan 2020 13:17:04 +0200
Alexandru Ardelean <alexandru.ardelean@xxxxxxxxxx> wrote:

> From: Nuno SÃ <nuno.sa@xxxxxxxxxx>
>
> The adis library only allows to define a `startup_delay` which for some
> devices is enough. However, other devices define different timeouts with
> significantly different timings which could lead to devices to not wait
> enough time or to wait a lot more than necessary (which is not
> efficient). This patch introduces a new timeout struct that must be
> passed into `adis_init()`. There are mainly, for now, three timeouts
> used. This is also an introductory patch with the goal of refactoring
> `adis_initial_startup()`. New driver's (eg: adis16480, adis16460) are
> replicating code for the device initial setup. With some changes (being
> this the first one) we can pass this to `adis_initial_startup()`.
>
> Signed-off-by: Nuno SÃ <nuno.sa@xxxxxxxxxx>
> Signed-off-by: Alexandru Ardelean <alexandru.ardelean@xxxxxxxxxx>

I'm a little unsure if this is the right option long term.
You may be better off putting the _data structure as a member of
the chip info structures (using macros to handle the parts that
are reused). That would avoid either the need for memcpy or
to pass a 'per driver' part and a 'per chip_info' part into the init
function.

However, for now this is fairly clean. The best option will depend
in the long run on what else we find needs similar handling to these
timeouts.

As such.. Applied to the togreg branch of iio.git and pushed out as
testing for the autobuilders to poke at it.
> ---
>
> Changelog v1 - v2:
> * rework patch to remove manual assignments for adis16136, adis16400,
> adis16480 and do memcpy() from the static adis_data
>
>
> drivers/iio/accel/adis16201.c | 7 +++
> drivers/iio/accel/adis16209.c | 7 +++
> drivers/iio/gyro/adis16136.c | 40 ++++++++++++++++-
> drivers/iio/gyro/adis16260.c | 7 +++
> drivers/iio/imu/adis.c | 18 ++++++--
> drivers/iio/imu/adis16400.c | 63 ++++++++++++++++++++++++++-
> drivers/iio/imu/adis16460.c | 7 +++
> drivers/iio/imu/adis16480.c | 58 +++++++++++++++++++++++-
> drivers/staging/iio/accel/adis16203.c | 7 +++
> drivers/staging/iio/accel/adis16240.c | 7 +++
> include/linux/iio/imu/adis.h | 13 ++++++
> 11 files changed, 227 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c
> index c4810c73b2a2..c92d22387b01 100644
> --- a/drivers/iio/accel/adis16201.c
> +++ b/drivers/iio/accel/adis16201.c
> @@ -233,6 +233,12 @@ static const char * const adis16201_status_error_msgs[] = {
> [ADIS16201_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
> };
>
> +static const struct adis_timeout adis16201_timeouts = {
> + .reset_ms = ADIS16201_STARTUP_DELAY_MS,
> + .sw_reset_ms = ADIS16201_STARTUP_DELAY_MS,
> + .self_test_ms = ADIS16201_STARTUP_DELAY_MS,
> +};
> +
> static const struct adis_data adis16201_data = {
> .read_delay = 20,
> .msc_ctrl_reg = ADIS16201_MSC_CTRL_REG,
> @@ -242,6 +248,7 @@ static const struct adis_data adis16201_data = {
> .self_test_mask = ADIS16201_MSC_CTRL_SELF_TEST_EN,
> .self_test_no_autoclear = true,
> .startup_delay = ADIS16201_STARTUP_DELAY_MS,
> + .timeouts = &adis16201_timeouts,
>
> .status_error_msgs = adis16201_status_error_msgs,
> .status_error_mask = BIT(ADIS16201_DIAG_STAT_SPI_FAIL_BIT) |
> diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c
> index 98d77af8a2b0..f5a78fc11919 100644
> --- a/drivers/iio/accel/adis16209.c
> +++ b/drivers/iio/accel/adis16209.c
> @@ -243,6 +243,12 @@ static const char * const adis16209_status_error_msgs[] = {
> [ADIS16209_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
> };
>
> +static const struct adis_timeout adis16209_timeouts = {
> + .reset_ms = ADIS16209_STARTUP_DELAY_MS,
> + .self_test_ms = ADIS16209_STARTUP_DELAY_MS,
> + .sw_reset_ms = ADIS16209_STARTUP_DELAY_MS,
> +};
> +
> static const struct adis_data adis16209_data = {
> .read_delay = 30,
> .msc_ctrl_reg = ADIS16209_MSC_CTRL_REG,
> @@ -252,6 +258,7 @@ static const struct adis_data adis16209_data = {
> .self_test_mask = ADIS16209_MSC_CTRL_SELF_TEST_EN,
> .self_test_no_autoclear = true,
> .startup_delay = ADIS16209_STARTUP_DELAY_MS,
> + .timeouts = &adis16209_timeouts,
>
> .status_error_msgs = adis16209_status_error_msgs,
> .status_error_mask = BIT(ADIS16209_STAT_SELFTEST_FAIL_BIT) |
> diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
> index f10c4f173898..dc91d8df7697 100644
> --- a/drivers/iio/gyro/adis16136.c
> +++ b/drivers/iio/gyro/adis16136.c
> @@ -59,6 +59,7 @@
> struct adis16136_chip_info {
> unsigned int precision;
> unsigned int fullscale;
> + const struct adis_timeout *timeouts;
> };
>
> struct adis16136 {
> @@ -490,30 +491,63 @@ enum adis16136_id {
> ID_ADIS16137,
> };
>
> +static const struct adis_timeout adis16133_timeouts = {
> + .reset_ms = 75,
> + .sw_reset_ms = 75,
> + .self_test_ms = 50,
> +};
> +
> +static const struct adis_timeout adis16136_timeouts = {
> + .reset_ms = 128,
> + .sw_reset_ms = 75,
> + .self_test_ms = 245,
> +};
> +
> static const struct adis16136_chip_info adis16136_chip_info[] = {
> [ID_ADIS16133] = {
> .precision = IIO_DEGREE_TO_RAD(1200),
> .fullscale = 24000,
> + .timeouts = &adis16133_timeouts,
> },
> [ID_ADIS16135] = {
> .precision = IIO_DEGREE_TO_RAD(300),
> .fullscale = 24000,
> + .timeouts = &adis16133_timeouts,
> },
> [ID_ADIS16136] = {
> .precision = IIO_DEGREE_TO_RAD(450),
> .fullscale = 24623,
> + .timeouts = &adis16136_timeouts,
> },
> [ID_ADIS16137] = {
> .precision = IIO_DEGREE_TO_RAD(1000),
> .fullscale = 24609,
> + .timeouts = &adis16136_timeouts,
> },
> };
>
> +static struct adis_data *adis16136_adis_data_alloc(struct adis16136 *st,
> + struct device *dev)
> +{
> + struct adis_data *data;
> +
> + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL);
> + if (!data)
> + return ERR_PTR(-ENOMEM);
> +
> + memcpy(data, &adis16136_data, sizeof(*data));
> +
> + data->timeouts = st->chip_info->timeouts;
> +
> + return data;
> +}
> +
> static int adis16136_probe(struct spi_device *spi)
> {
> const struct spi_device_id *id = spi_get_device_id(spi);
> struct adis16136 *adis16136;
> struct iio_dev *indio_dev;
> + const struct adis_data *adis16136_data;
> int ret;
>
> indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16136));
> @@ -532,7 +566,11 @@ static int adis16136_probe(struct spi_device *spi)
> indio_dev->info = &adis16136_info;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> - ret = adis_init(&adis16136->adis, indio_dev, spi, &adis16136_data);
> + adis16136_data = adis16136_adis_data_alloc(adis16136, &spi->dev);
> + if (IS_ERR(adis16136_data))
> + return PTR_ERR(adis16136_data);
> +
> + ret = adis_init(&adis16136->adis, indio_dev, spi, adis16136_data);
> if (ret)
> return ret;
>
> diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
> index 726a0aa321a8..0e3a66a7726d 100644
> --- a/drivers/iio/gyro/adis16260.c
> +++ b/drivers/iio/gyro/adis16260.c
> @@ -332,6 +332,12 @@ static const char * const adis1620_status_error_msgs[] = {
> [ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
> };
>
> +static const struct adis_timeout adis16260_timeouts = {
> + .reset_ms = ADIS16260_STARTUP_DELAY,
> + .sw_reset_ms = ADIS16260_STARTUP_DELAY,
> + .self_test_ms = ADIS16260_STARTUP_DELAY,
> +};
> +
> static const struct adis_data adis16260_data = {
> .write_delay = 30,
> .read_delay = 30,
> @@ -341,6 +347,7 @@ static const struct adis_data adis16260_data = {
>
> .self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
> .startup_delay = ADIS16260_STARTUP_DELAY,
> + .timeouts = &adis16260_timeouts,
>
> .status_error_msgs = adis1620_status_error_msgs,
> .status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
> diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
> index c53f3ed3cb97..3e12ad4b71ba 100644
> --- a/drivers/iio/imu/adis.c
> +++ b/drivers/iio/imu/adis.c
> @@ -317,19 +317,25 @@ EXPORT_SYMBOL_GPL(__adis_check_status);
> int __adis_reset(struct adis *adis)
> {
> int ret;
> + const struct adis_timeout *timeouts = adis->data->timeouts;
>
> ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,
> ADIS_GLOB_CMD_SW_RESET);
> - if (ret)
> + if (ret) {
> dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
> + return ret;
> + }
>
> - return ret;
> + msleep(timeouts->sw_reset_ms);
> +
> + return 0;
> }
> EXPORT_SYMBOL_GPL(__adis_reset);
>
> static int adis_self_test(struct adis *adis)
> {
> int ret;
> + const struct adis_timeout *timeouts = adis->data->timeouts;
>
> ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg,
> adis->data->self_test_mask);
> @@ -339,7 +345,7 @@ static int adis_self_test(struct adis *adis)
> return ret;
> }
>
> - msleep(adis->data->startup_delay);
> + msleep(timeouts->self_test_ms);
>
> ret = __adis_check_status(adis);
>
> @@ -368,7 +374,6 @@ int adis_initial_startup(struct adis *adis)
> if (ret) {
> dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n");
> __adis_reset(adis);
> - msleep(adis->data->startup_delay);
> ret = adis_self_test(adis);
> if (ret) {
> dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n");
> @@ -444,6 +449,11 @@ EXPORT_SYMBOL_GPL(adis_single_conversion);
> int adis_init(struct adis *adis, struct iio_dev *indio_dev,
> struct spi_device *spi, const struct adis_data *data)
> {
> + if (!data || !data->timeouts) {
> + dev_err(&spi->dev, "No config data or timeouts not defined!\n");
> + return -EINVAL;
> + }
> +
> mutex_init(&adis->state_lock);
> adis->spi = spi;
> adis->data = data;
> diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
> index 662cb5367c11..51b1ec23b8ef 100644
> --- a/drivers/iio/imu/adis16400.c
> +++ b/drivers/iio/imu/adis16400.c
> @@ -156,6 +156,7 @@ struct adis16400_state;
>
> struct adis16400_chip_info {
> const struct iio_chan_spec *channels;
> + const struct adis_timeout *timeouts;
> const int num_channels;
> const long flags;
> unsigned int gyro_scale_micro;
> @@ -929,6 +930,36 @@ static const struct iio_chan_spec adis16334_channels[] = {
> IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
> };
>
> +static const struct adis_timeout adis16300_timeouts = {
> + .reset_ms = ADIS16400_STARTUP_DELAY,
> + .sw_reset_ms = ADIS16400_STARTUP_DELAY,
> + .self_test_ms = ADIS16400_STARTUP_DELAY,
> +};
> +
> +static const struct adis_timeout adis16362_timeouts = {
> + .reset_ms = 130,
> + .sw_reset_ms = 130,
> + .self_test_ms = 12,
> +};
> +
> +static const struct adis_timeout adis16400_timeouts = {
> + .reset_ms = 170,
> + .sw_reset_ms = 170,
> + .self_test_ms = 12,
> +};
> +
> +static const struct adis_timeout adis16445_timeouts = {
> + .reset_ms = 55,
> + .sw_reset_ms = 55,
> + .self_test_ms = 16,
> +};
> +
> +static const struct adis_timeout adis16448_timeouts = {
> + .reset_ms = 90,
> + .sw_reset_ms = 90,
> + .self_test_ms = 45,
> +};
> +
> static struct adis16400_chip_info adis16400_chips[] = {
> [ADIS16300] = {
> .channels = adis16300_channels,
> @@ -941,6 +972,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16300_timeouts,
> },
> [ADIS16334] = {
> .channels = adis16334_channels,
> @@ -964,6 +996,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16300_timeouts,
> },
> [ADIS16360] = {
> .channels = adis16350_channels,
> @@ -976,6 +1009,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16300_timeouts,
> },
> [ADIS16362] = {
> .channels = adis16350_channels,
> @@ -988,6 +1022,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16362_timeouts,
> },
> [ADIS16364] = {
> .channels = adis16350_channels,
> @@ -1000,6 +1035,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16362_timeouts,
> },
> [ADIS16367] = {
> .channels = adis16350_channels,
> @@ -1012,6 +1048,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16300_timeouts,
> },
> [ADIS16400] = {
> .channels = adis16400_channels,
> @@ -1023,6 +1060,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
> .set_freq = adis16400_set_freq,
> .get_freq = adis16400_get_freq,
> + .timeouts = &adis16400_timeouts,
> },
> [ADIS16445] = {
> .channels = adis16445_channels,
> @@ -1036,6 +1074,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
> .set_freq = adis16334_set_freq,
> .get_freq = adis16334_get_freq,
> + .timeouts = &adis16445_timeouts,
> },
> [ADIS16448] = {
> .channels = adis16448_channels,
> @@ -1049,6 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
> .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
> .set_freq = adis16334_set_freq,
> .get_freq = adis16334_get_freq,
> + .timeouts = &adis16448_timeouts,
> }
> };
>
> @@ -1120,11 +1160,28 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st)
> }
> }
>
> +static struct adis_data *adis16400_adis_data_alloc(struct adis16400_state *st,
> + struct device *dev)
> +{
> + struct adis_data *data;
> +
> + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL);
> + if (!data)
> + return ERR_PTR(-ENOMEM);
> +
> + memcpy(data, &adis16400_data, sizeof(*data));
> +
> + data->timeouts = st->variant->timeouts;
> +
> + return data;
> +}
> +
> static int adis16400_probe(struct spi_device *spi)
> {
> struct adis16400_state *st;
> struct iio_dev *indio_dev;
> int ret;
> + const struct adis_data *adis16400_data;
>
> indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
> if (indio_dev == NULL)
> @@ -1151,7 +1208,11 @@ static int adis16400_probe(struct spi_device *spi)
> st->adis.burst->extra_len = sizeof(u16);
> }
>
> - ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data);
> + adis16400_data = adis16400_adis_data_alloc(st, &spi->dev);
> + if (IS_ERR(adis16400_data))
> + return PTR_ERR(adis16400_data);
> +
> + ret = adis_init(&st->adis, indio_dev, spi, adis16400_data);
> if (ret)
> return ret;
>
> diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
> index b55812521537..9539cfe4a259 100644
> --- a/drivers/iio/imu/adis16460.c
> +++ b/drivers/iio/imu/adis16460.c
> @@ -383,6 +383,12 @@ static const char * const adis16460_status_error_msgs[] = {
> [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure",
> };
>
> +static const struct adis_timeout adis16460_timeouts = {
> + .reset_ms = 225,
> + .sw_reset_ms = 225,
> + .self_test_ms = 10,
> +};
> +
> static const struct adis_data adis16460_data = {
> .diag_stat_reg = ADIS16460_REG_DIAG_STAT,
> .glob_cmd_reg = ADIS16460_REG_GLOB_CMD,
> @@ -398,6 +404,7 @@ static const struct adis_data adis16460_data = {
> BIT(ADIS16460_DIAG_STAT_SPI_COMM) |
> BIT(ADIS16460_DIAG_STAT_FLASH_UPT),
> .enable_irq = adis16460_enable_irq,
> + .timeouts = &adis16460_timeouts,
> };
>
> static int adis16460_probe(struct spi_device *spi)
> diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
> index f73094e8d35d..f0ad7ce64861 100644
> --- a/drivers/iio/imu/adis16480.c
> +++ b/drivers/iio/imu/adis16480.c
> @@ -138,6 +138,7 @@ struct adis16480_chip_info {
> unsigned int max_dec_rate;
> const unsigned int *filter_freqs;
> bool has_pps_clk_mode;
> + const struct adis_timeout *timeouts;
> };
>
> enum adis16480_int_pin {
> @@ -794,6 +795,30 @@ enum adis16480_variant {
> ADIS16497_3,
> };
>
> +static const struct adis_timeout adis16485_timeouts = {
> + .reset_ms = 560,
> + .sw_reset_ms = 120,
> + .self_test_ms = 12,
> +};
> +
> +static const struct adis_timeout adis16480_timeouts = {
> + .reset_ms = 560,
> + .sw_reset_ms = 560,
> + .self_test_ms = 12,
> +};
> +
> +static const struct adis_timeout adis16495_timeouts = {
> + .reset_ms = 170,
> + .sw_reset_ms = 130,
> + .self_test_ms = 40,
> +};
> +
> +static const struct adis_timeout adis16495_1_timeouts = {
> + .reset_ms = 250,
> + .sw_reset_ms = 210,
> + .self_test_ms = 20,
> +};
> +
> static const struct adis16480_chip_info adis16480_chip_info[] = {
> [ADIS16375] = {
> .channels = adis16485_channels,
> @@ -812,6 +837,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .int_clk = 2460000,
> .max_dec_rate = 2048,
> .filter_freqs = adis16480_def_filter_freqs,
> + .timeouts = &adis16485_timeouts,
> },
> [ADIS16480] = {
> .channels = adis16480_channels,
> @@ -824,6 +850,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .int_clk = 2460000,
> .max_dec_rate = 2048,
> .filter_freqs = adis16480_def_filter_freqs,
> + .timeouts = &adis16480_timeouts,
> },
> [ADIS16485] = {
> .channels = adis16485_channels,
> @@ -836,6 +863,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .int_clk = 2460000,
> .max_dec_rate = 2048,
> .filter_freqs = adis16480_def_filter_freqs,
> + .timeouts = &adis16485_timeouts,
> },
> [ADIS16488] = {
> .channels = adis16480_channels,
> @@ -848,6 +876,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .int_clk = 2460000,
> .max_dec_rate = 2048,
> .filter_freqs = adis16480_def_filter_freqs,
> + .timeouts = &adis16485_timeouts,
> },
> [ADIS16495_1] = {
> .channels = adis16485_channels,
> @@ -861,6 +890,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> [ADIS16495_2] = {
> .channels = adis16485_channels,
> @@ -874,6 +904,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> [ADIS16495_3] = {
> .channels = adis16485_channels,
> @@ -887,6 +918,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> [ADIS16497_1] = {
> .channels = adis16485_channels,
> @@ -900,6 +932,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> [ADIS16497_2] = {
> .channels = adis16485_channels,
> @@ -913,6 +946,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> [ADIS16497_3] = {
> .channels = adis16485_channels,
> @@ -926,6 +960,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = {
> .max_dec_rate = 4250,
> .filter_freqs = adis16495_def_filter_freqs,
> .has_pps_clk_mode = true,
> + .timeouts = &adis16495_1_timeouts,
> },
> };
>
> @@ -1195,9 +1230,26 @@ static int adis16480_get_ext_clocks(struct adis16480 *st)
> return 0;
> }
>
> +static struct adis_data *adis16480_adis_data_alloc(struct adis16480 *st,
> + struct device *dev)
> +{
> + struct adis_data *data;
> +
> + data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL);
> + if (!data)
> + return ERR_PTR(-ENOMEM);
> +
> + memcpy(data, &adis16480_data, sizeof(*data));
> +
> + data->timeouts = st->chip_info->timeouts;
> +
> + return data;
> +}
> +
> static int adis16480_probe(struct spi_device *spi)
> {
> const struct spi_device_id *id = spi_get_device_id(spi);
> + const struct adis_data *adis16480_data;
> struct iio_dev *indio_dev;
> struct adis16480 *st;
> int ret;
> @@ -1218,7 +1270,11 @@ static int adis16480_probe(struct spi_device *spi)
> indio_dev->info = &adis16480_info;
> indio_dev->modes = INDIO_DIRECT_MODE;
>
> - ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data);
> + adis16480_data = adis16480_adis_data_alloc(st, &spi->dev);
> + if (IS_ERR(adis16480_data))
> + return PTR_ERR(adis16480_data);
> +
> + ret = adis_init(&st->adis, indio_dev, spi, adis16480_data);
> if (ret)
> return ret;
>
> diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c
> index 39687139a7d3..3d706ee02df0 100644
> --- a/drivers/staging/iio/accel/adis16203.c
> +++ b/drivers/staging/iio/accel/adis16203.c
> @@ -237,6 +237,12 @@ static const char * const adis16203_status_error_msgs[] = {
> [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V",
> };
>
> +static const struct adis_timeout adis16203_timeouts = {
> + .reset_ms = ADIS16203_STARTUP_DELAY,
> + .sw_reset_ms = ADIS16203_STARTUP_DELAY,
> + .self_test_ms = ADIS16203_STARTUP_DELAY
> +};
> +
> static const struct adis_data adis16203_data = {
> .read_delay = 20,
> .msc_ctrl_reg = ADIS16203_MSC_CTRL,
> @@ -246,6 +252,7 @@ static const struct adis_data adis16203_data = {
> .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN,
> .self_test_no_autoclear = true,
> .startup_delay = ADIS16203_STARTUP_DELAY,
> + .timeouts = &adis16203_timeouts,
>
> .status_error_msgs = adis16203_status_error_msgs,
> .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) |
> diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c
> index 794f063e6c86..d4848ef78c75 100644
> --- a/drivers/staging/iio/accel/adis16240.c
> +++ b/drivers/staging/iio/accel/adis16240.c
> @@ -359,6 +359,12 @@ static const char * const adis16240_status_error_msgs[] = {
> [ADIS16240_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.225V",
> };
>
> +static const struct adis_timeout adis16240_timeouts = {
> + .reset_ms = ADIS16240_STARTUP_DELAY,
> + .sw_reset_ms = ADIS16240_STARTUP_DELAY,
> + .self_test_ms = ADIS16240_STARTUP_DELAY,
> +};
> +
> static const struct adis_data adis16240_data = {
> .write_delay = 35,
> .read_delay = 35,
> @@ -369,6 +375,7 @@ static const struct adis_data adis16240_data = {
> .self_test_mask = ADIS16240_MSC_CTRL_SELF_TEST_EN,
> .self_test_no_autoclear = true,
> .startup_delay = ADIS16240_STARTUP_DELAY,
> + .timeouts = &adis16240_timeouts,
>
> .status_error_msgs = adis16240_status_error_msgs,
> .status_error_mask = BIT(ADIS16240_DIAG_STAT_PWRON_FAIL_BIT) |
> diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h
> index 4b5bc0e06e69..853dc8c8365c 100644
> --- a/include/linux/iio/imu/adis.h
> +++ b/include/linux/iio/imu/adis.h
> @@ -22,6 +22,17 @@
> struct adis;
> struct adis_burst;
>
> +/**
> + * struct adis_timeouts - ADIS chip variant timeouts
> + * @reset_ms - Wait time after rst pin goes inactive
> + * @sw_reset_ms - Wait time after sw reset command
> + * @self_test_ms - Wait time after self test command
> + */
> +struct adis_timeout {
> + u16 reset_ms;
> + u16 sw_reset_ms;
> + u16 self_test_ms;
> +};
> /**
> * struct adis_data - ADIS chip variant specific data
> * @read_delay: SPI delay for read operations in us
> @@ -32,6 +43,7 @@ struct adis_burst;
> * @diag_stat_reg: Register address of the DIAG_STAT register
> * @status_error_msgs: Array of error messgaes
> * @status_error_mask:
> + * @timeouts: Chip specific delays
> */
> struct adis_data {
> unsigned int read_delay;
> @@ -45,6 +57,7 @@ struct adis_data {
> unsigned int self_test_mask;
> bool self_test_no_autoclear;
> unsigned int startup_delay;
> + const struct adis_timeout *timeouts;
>
> const char * const *status_error_msgs;
> unsigned int status_error_mask;