diff mbox series

[v3,9/9] drivers: iio: imu: Add support for adis1657x family

Message ID 20240517074750.87376-10-ramona.bolboaca13@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series adis16501 and adis1657x support | expand

Commit Message

Ramona Gradinariu May 17, 2024, 7:47 a.m. UTC
Add support for ADIS1657X family devices in already exiting ADIS16475
driver.

Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
---
changes in v3:
 - changed format in sysfs_emit
 - created new function adis16575_update_msg_for_burst to make it more obvious
 that adis message is changing based on the given burst request value
 - adjusted line wrapping for adis16475_trigger_handler_with_fifo comment
 - fixed comment typo regarding watermark pin polarity
 - configured level interrupts in case device has FIFO
 drivers/iio/imu/adis16475.c | 628 ++++++++++++++++++++++++++++++++----
 1 file changed, 561 insertions(+), 67 deletions(-)

--
2.34.1

Comments

kernel test robot May 18, 2024, 6:47 a.m. UTC | #1
Hi Ramona,

kernel test robot noticed the following build errors:

[auto build test ERROR on jic23-iio/togreg]
[cannot apply to linus/master v6.9 next-20240517]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:    https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20240518/202405181400.174vWAhr-lkp@intel.com/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/202405181400.174vWAhr-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405181400.174vWAhr-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/iio/imu/adis16475.c:523:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
     523 |         &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
         |         ^
   drivers/iio/imu/adis16475.c:523:9: note: (near initialization for 'adis16475_fifo_attributes[0]')
   drivers/iio/imu/adis16475.c:524:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
     524 |         &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
         |         ^
   drivers/iio/imu/adis16475.c:524:9: note: (near initialization for 'adis16475_fifo_attributes[1]')
   drivers/iio/imu/adis16475.c:525:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
     525 |         &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
         |         ^
   drivers/iio/imu/adis16475.c:525:9: note: (near initialization for 'adis16475_fifo_attributes[2]')
   drivers/iio/imu/adis16475.c:526:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
     526 |         &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
         |         ^
   drivers/iio/imu/adis16475.c:526:9: note: (near initialization for 'adis16475_fifo_attributes[3]')
   cc1: some warnings being treated as errors


vim +523 drivers/iio/imu/adis16475.c

   514	
   515	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
   516	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
   517	static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
   518			       adis16475_get_fifo_watermark, NULL, 0);
   519	static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
   520			       adis16475_get_fifo_enabled, NULL, 0);
   521	
   522	static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
 > 523		&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
   524		&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
   525		&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
   526		&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
   527		NULL
   528	};
   529
kernel test robot May 18, 2024, 11 a.m. UTC | #2
Hi Ramona,

kernel test robot noticed the following build errors:

[auto build test ERROR on jic23-iio/togreg]
[cannot apply to linus/master v6.9 next-20240517]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
patch link:    https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
config: x86_64-allyesconfig (https://download.01.org/0day-ci/archive/20240518/202405181841.ESCYTmmL-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/202405181841.ESCYTmmL-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405181841.ESCYTmmL-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/iio/imu/adis16475.c:523:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
     523 |         &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/iio/imu/adis16475.c:524:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
     524 |         &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/iio/imu/adis16475.c:525:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
     525 |         &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/iio/imu/adis16475.c:526:2: error: incompatible pointer types initializing 'const struct iio_dev_attr *' with an expression of type 'struct attribute *' [-Werror,-Wincompatible-pointer-types]
     526 |         &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   4 errors generated.


vim +523 drivers/iio/imu/adis16475.c

   514	
   515	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
   516	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
   517	static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
   518			       adis16475_get_fifo_watermark, NULL, 0);
   519	static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
   520			       adis16475_get_fifo_enabled, NULL, 0);
   521	
   522	static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
 > 523		&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
   524		&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
   525		&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
   526		&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
   527		NULL
   528	};
   529
Jonathan Cameron May 19, 2024, 6:38 p.m. UTC | #3
On Sat, 18 May 2024 14:47:01 +0800
kernel test robot <lkp@intel.com> wrote:

> Hi Ramona,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on jic23-iio/togreg]
> [cannot apply to linus/master v6.9 next-20240517]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:    https://github.com/intel-lab-lkp/linux/commits/Ramona-Gradinariu/dt-bindings-iio-imu-Add-ADIS16501-compatibles/20240517-155051
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git togreg
> patch link:    https://lore.kernel.org/r/20240517074750.87376-10-ramona.bolboaca13%40gmail.com
> patch subject: [PATCH v3 9/9] drivers: iio: imu: Add support for adis1657x family
> config: i386-allmodconfig (https://download.01.org/0day-ci/archive/20240518/202405181400.174vWAhr-lkp@intel.com/config)
> compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240518/202405181400.174vWAhr-lkp@intel.com/reproduce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202405181400.174vWAhr-lkp@intel.com/
> 
> All errors (new ones prefixed by >>):
> 
> >> drivers/iio/imu/adis16475.c:523:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]  
>      523 |         &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
>          |         ^
>    drivers/iio/imu/adis16475.c:523:9: note: (near initialization for 'adis16475_fifo_attributes[0]')
>    drivers/iio/imu/adis16475.c:524:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
>      524 |         &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
>          |         ^
>    drivers/iio/imu/adis16475.c:524:9: note: (near initialization for 'adis16475_fifo_attributes[1]')
>    drivers/iio/imu/adis16475.c:525:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
>      525 |         &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
>          |         ^
>    drivers/iio/imu/adis16475.c:525:9: note: (near initialization for 'adis16475_fifo_attributes[2]')
>    drivers/iio/imu/adis16475.c:526:9: error: initialization of 'const struct iio_dev_attr *' from incompatible pointer type 'struct attribute *' [-Werror=incompatible-pointer-types]
>      526 |         &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
>          |         ^
>    drivers/iio/imu/adis16475.c:526:9: note: (near initialization for 'adis16475_fifo_attributes[3]')
>    cc1: some warnings being treated as errors
> 
> 
> vim +523 drivers/iio/imu/adis16475.c
> 
>    514	
>    515	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
>    516	static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
>    517	static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
>    518			       adis16475_get_fifo_watermark, NULL, 0);
>    519	static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
>    520			       adis16475_get_fifo_enabled, NULL, 0);
>    521	
>    522	static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
>  > 523		&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,  
>    524		&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
>    525		&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
>    526		&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
>    527		NULL
>    528	};
drop the dev_attr.attr parts.  This will 'work' because they are all at the start of
the containing structure, but it should be the iio_dev_attrs as in a similar
case here:
https://elixir.bootlin.com/linux/latest/source/drivers/iio/accel/adxl372.c#L1009

>    529	
>
Jonathan Cameron May 19, 2024, 6:57 p.m. UTC | #4
On Fri, 17 May 2024 10:47:50 +0300
Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:

> Add support for ADIS1657X family devices in already exiting ADIS16475
> driver.
> 
> Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>

Whilst it's not necessarily vital to support, it I'm curious about
what happens to the hardware timestamp? I thought we had one driver
still doing hardware timestamps directly to the buffer, but I can't
find it so I guess we now deal with alignment in the few devices with
this support.  The st_lsm6dsx has this sort of combining of local
and fifo timestamps for example.

As it stands I think you push the same timestamp for all scans read
from the fifo on a particular watermark interrupt?  That isn't
ideal given we should definitely be able to do better than that.

> +
> +static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> +	&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> +	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> +	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> +	&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
The autobuilder caught this one.  Drop the dev_attr.attr.

> +	NULL
> +};
> +

> +
> +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
> +	.postenable = adis16475_buffer_postenable,
> +	.postdisable = adis16475_buffer_postdisable,
> +};
> +
> +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
> +{
> +	struct adis16475 *st  = iio_priv(indio_dev);
> +	int ret;
> +	u16 wm_lvl;
> +
> +	adis_dev_lock(&st->adis);

As a follow up perhaps consider defining magic to use guard() for these as there are
enough users that will be simplified to make it worth the effort.	

> +
> +	val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
> +
> +	wm_lvl = ADIS16575_WM_LVL(val - 1);
> +	ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
> +	if (ret)
> +		goto unlock;
> +
> +	st->fifo_watermark = val;
> +
> +unlock:
> +	adis_dev_unlock(&st->adis);
> +	return ret;
> +}
> +




> @@ -1514,8 +1978,20 @@ static int adis16475_probe(struct spi_device *spi)
>  	if (ret)
>  		return ret;
> 
> -	ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
> -						 adis16475_trigger_handler);
> +	if (st->info->flags & ADIS16475_HAS_FIFO) {
> +		ret = devm_adis_setup_buffer_and_trigger_with_attrs(&st->adis, indio_dev,
> +								    adis16475_trigger_handler_with_fifo,
> +								    &adis16475_buffer_ops,
> +								    adis16475_fifo_attributes);
> +		if (ret)
> +			return ret;
blank line here.

> +		/* Update overflow behavior to always overwrite the oldest sample. */
> +		ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
> +				       ADIS16575_OVERFLOW_MASK, (u16)ADIS16575_OVERWRITE_OLDEST);
		if (ret) in here.
> +	} else {
> +		ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
> +							 adis16475_trigger_handler);
and if (ret) in here and drop the one that follows.

otherwise we end up with odd code pattern of handling one case in this scope and not
the other two.

> +	}
Nuno Sá May 21, 2024, 7:01 a.m. UTC | #5
On Sun, 2024-05-19 at 19:57 +0100, Jonathan Cameron wrote:
> On Fri, 17 May 2024 10:47:50 +0300
> Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:
> 
> > Add support for ADIS1657X family devices in already exiting ADIS16475
> > driver.
> > 
> > Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
> 
> Whilst it's not necessarily vital to support, it I'm curious about
> what happens to the hardware timestamp? I thought we had one driver
> still doing hardware timestamps directly to the buffer, but I can't
> find it so I guess we now deal with alignment in the few devices with
> this support.  The st_lsm6dsx has this sort of combining of local
> and fifo timestamps for example.
> 
> As it stands I think you push the same timestamp for all scans read
> from the fifo on a particular watermark interrupt?  That isn't
> ideal given we should definitely be able to do better than that.
> 
> > +
> > +static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
> > +	&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
> > +	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
> > +	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
> > +	&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
> The autobuilder caught this one.  Drop the dev_attr.attr.
> 
> > +	NULL
> > +};
> > +
> 
> > +
> > +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
> > +	.postenable = adis16475_buffer_postenable,
> > +	.postdisable = adis16475_buffer_postdisable,
> > +};
> > +
> > +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int
> > val)
> > +{
> > +	struct adis16475 *st  = iio_priv(indio_dev);
> > +	int ret;
> > +	u16 wm_lvl;
> > +
> > +	adis_dev_lock(&st->adis);
> 
> As a follow up perhaps consider defining magic to use guard() for these as
> there are
> enough users that will be simplified to make it worth the effort.	
> 

Already on my queue but if Ramona wants to step in, good. I already have plenty
to do :)

- Nuno Sá
>
Ramona Gradinariu May 22, 2024, 9:51 a.m. UTC | #6
On 5/19/24 21:57, Jonathan Cameron wrote:

> On Fri, 17 May 2024 10:47:50 +0300
> Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:
>
>> Add support for ADIS1657X family devices in already exiting ADIS16475
>> driver.
>>
>> Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>
> Whilst it's not necessarily vital to support, it I'm curious about
> what happens to the hardware timestamp? I thought we had one driver
> still doing hardware timestamps directly to the buffer, but I can't
> find it so I guess we now deal with alignment in the few devices with
> this support.  The st_lsm6dsx has this sort of combining of local
> and fifo timestamps for example.
>
> As it stands I think you push the same timestamp for all scans read
> from the fifo on a particular watermark interrupt?  That isn't
> ideal given we should definitely be able to do better than that.

Currently the timestamp is added when the FIFO is read, which does not 
equal the sample time.

ADI IMU devices do not actually offer a hardware timestamp. The 
functionality is as follows:
- for internal sync / output sync / direct external sync the burst 
data returns a data counter (which increments with each sample);

- for scaled external sync the burst data returns the 'timestamp',
which contains the time associated with the last sample in each data
update relative to the most recent edge of the external clock signal.
For example, when the value in the UP_SCALE register represents a scale
factor of 20, DEC_RATE = 0, and the external SYNC rate = 100 Hz, the
following time stamp sequence results: 0LSB, 10LSB, 21LSB, 31LSB, 
41LSB, 51LSB, 61LSB, 72LSB, …, 194LSB for the 20th sample, which 
translates to 0us, 490us, …, 9510 us which is the time from the 
previous sync edge.

We can make assumptions, and try to better estimate the timestamp,
based on the sampling frequency. 
We can assume that the last sample in the FIFO was sampled when the
watermark interrupt took place, and then, based on the sample frequency
we could decrease the timestamp with the according period for each
sample.
However, I am not sure this assumption is always valid, it depends
on when the IRQ is actually handled.

I can remove the timestamp for devices which use FIFO seeing how it
does not represent the actual sample time.

>> +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
>> +	.postenable = adis16475_buffer_postenable,
>> +	.postdisable = adis16475_buffer_postdisable,
>> +};
>> +
>> +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
>> +{
>> +	struct adis16475 *st  = iio_priv(indio_dev);
>> +	int ret;
>> +	u16 wm_lvl;
>> +
>> +	adis_dev_lock(&st->adis);
> As a follow up perhaps consider defining magic to use guard() for these as there are
> enough users that will be simplified to make it worth the effort.	

I will do this in another patch series if that is alright.

>
>> +
>> +	val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
>> +
>> +	wm_lvl = ADIS16575_WM_LVL(val - 1);
>> +	ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
>> +	if (ret)
>> +		goto unlock;
>> +
>> +	st->fifo_watermark = val;
>> +
>> +unlock:
>> +	adis_dev_unlock(&st->adis);
>> +	return ret;
>> +}
>> +
Jonathan Cameron May 23, 2024, 5:11 p.m. UTC | #7
On Wed, 22 May 2024 12:51:39 +0300
Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:

> On 5/19/24 21:57, Jonathan Cameron wrote:
> 
> > On Fri, 17 May 2024 10:47:50 +0300
> > Ramona Gradinariu <ramona.bolboaca13@gmail.com> wrote:
> >  
> >> Add support for ADIS1657X family devices in already exiting ADIS16475
> >> driver.
> >>
> >> Signed-off-by: Ramona Gradinariu <ramona.bolboaca13@gmail.com>  
> > Whilst it's not necessarily vital to support, it I'm curious about
> > what happens to the hardware timestamp? I thought we had one driver
> > still doing hardware timestamps directly to the buffer, but I can't
> > find it so I guess we now deal with alignment in the few devices with
> > this support.  The st_lsm6dsx has this sort of combining of local
> > and fifo timestamps for example.
> >
> > As it stands I think you push the same timestamp for all scans read
> > from the fifo on a particular watermark interrupt?  That isn't
> > ideal given we should definitely be able to do better than that.  
> 
> Currently the timestamp is added when the FIFO is read, which does not 
> equal the sample time.
> 
> ADI IMU devices do not actually offer a hardware timestamp. The 
> functionality is as follows:
> - for internal sync / output sync / direct external sync the burst 
> data returns a data counter (which increments with each sample);
> 
> - for scaled external sync the burst data returns the 'timestamp',
> which contains the time associated with the last sample in each data
> update relative to the most recent edge of the external clock signal.
> For example, when the value in the UP_SCALE register represents a scale
> factor of 20, DEC_RATE = 0, and the external SYNC rate = 100 Hz, the
> following time stamp sequence results: 0LSB, 10LSB, 21LSB, 31LSB, 
> 41LSB, 51LSB, 61LSB, 72LSB, …, 194LSB for the 20th sample, which 
> translates to 0us, 490us, …, 9510 us which is the time from the 
> previous sync edge.

Thanks for info.  I was hopeful for a real clock, but we rarely get
one (and it introduces clock drift issues anyway so they are quite
tricky to handle :(

> 
> We can make assumptions, and try to better estimate the timestamp,
> based on the sampling frequency. 
> We can assume that the last sample in the FIFO was sampled when the
> watermark interrupt took place, and then, based on the sample frequency
> we could decrease the timestamp with the according period for each
> sample.

Assume the one that corresponds to the watermark, not the last one as we
may take a while to get to processing it.

> However, I am not sure this assumption is always valid, it depends
> on when the IRQ is actually handled.
> 
> I can remove the timestamp for devices which use FIFO seeing how it
> does not represent the actual sample time.
I would do that for now as this si tricky to do well.

There are examples in tree of how to get something reasonable. 
Take a look at common/inv_sensors/inv_sensors_timestap.c
for one example

> 
> >> +static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
> >> +	.postenable = adis16475_buffer_postenable,
> >> +	.postdisable = adis16475_buffer_postdisable,
> >> +};
> >> +
> >> +static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
> >> +{
> >> +	struct adis16475 *st  = iio_priv(indio_dev);
> >> +	int ret;
> >> +	u16 wm_lvl;
> >> +
> >> +	adis_dev_lock(&st->adis);  
> > As a follow up perhaps consider defining magic to use guard() for these as there are
> > enough users that will be simplified to make it worth the effort.	  
> 
> I will do this in another patch series if that is alright.

Sure.

> 
> >  
> >> +
> >> +	val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
> >> +
> >> +	wm_lvl = ADIS16575_WM_LVL(val - 1);
> >> +	ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
> >> +	if (ret)
> >> +		goto unlock;
> >> +
> >> +	st->fifo_watermark = val;
> >> +
> >> +unlock:
> >> +	adis_dev_unlock(&st->adis);
> >> +	return ret;
> >> +}
> >> +  
>
diff mbox series

Patch

diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index c589f214259b..a1a14b0757e8 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -14,6 +14,7 @@ 
 #include <linux/iio/buffer.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/imu/adis.h>
+#include <linux/iio/sysfs.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/irq.h>
 #include <linux/lcm.h>
@@ -52,6 +53,8 @@ 
 				FIELD_PREP(ADIS16475_MSG_CTRL_DR_POL_MASK, x)
 #define ADIS16475_SYNC_MODE_MASK	GENMASK(4, 2)
 #define ADIS16475_SYNC_MODE(x)		FIELD_PREP(ADIS16475_SYNC_MODE_MASK, x)
+#define ADIS16575_SYNC_4KHZ_MASK	BIT(11)
+#define ADIS16575_SYNC_4KHZ(x)		FIELD_PREP(ADIS16575_SYNC_4KHZ_MASK, x)
 #define ADIS16475_REG_UP_SCALE		0x62
 #define ADIS16475_REG_DEC_RATE		0x64
 #define ADIS16475_REG_GLOB_CMD		0x68
@@ -65,15 +68,32 @@ 
 #define ADIS16500_BURST32_MASK		BIT(9)
 #define ADIS16500_BURST32(x)		FIELD_PREP(ADIS16500_BURST32_MASK, x)
 /* number of data elements in burst mode */
-#define ADIS16475_BURST32_MAX_DATA	32
+#define ADIS16475_BURST32_MAX_DATA_NO_TS32	32
+#define ADIS16575_BURST32_DATA_TS32		34
 #define ADIS16475_BURST_MAX_DATA	20
 #define ADIS16475_MAX_SCAN_DATA		20
 /* spi max speed in brust mode */
 #define ADIS16475_BURST_MAX_SPEED	1000000
+#define ADIS16575_BURST_MAX_SPEED	8000000
 #define ADIS16475_LSB_DEC_MASK		0
 #define ADIS16475_LSB_FIR_MASK		1
 #define ADIS16500_BURST_DATA_SEL_0_CHN_MASK	GENMASK(5, 0)
 #define ADIS16500_BURST_DATA_SEL_1_CHN_MASK	GENMASK(12, 7)
+#define ADIS16575_MAX_FIFO_WM		511UL
+#define ADIS16475_REG_FIFO_CTRL		0x5A
+#define ADIS16575_WM_LVL_MASK		GENMASK(15, 4)
+#define ADIS16575_WM_LVL(x)		FIELD_PREP(ADIS16575_WM_LVL_MASK, x)
+#define ADIS16575_WM_POL_MASK		BIT(3)
+#define ADIS16575_WM_POL(x)		FIELD_PREP(ADIS16575_WM_POL_MASK, x)
+#define ADIS16575_WM_EN_MASK		BIT(2)
+#define ADIS16575_WM_EN(x)		FIELD_PREP(ADIS16575_WM_EN_MASK, x)
+#define ADIS16575_OVERFLOW_MASK		BIT(1)
+#define ADIS16575_STOP_ENQUEUE		FIELD_PREP(ADIS16575_OVERFLOW_MASK, 0)
+#define ADIS16575_OVERWRITE_OLDEST	FIELD_PREP(ADIS16575_OVERFLOW_MASK, 1)
+#define ADIS16575_FIFO_EN_MASK		BIT(0)
+#define ADIS16575_FIFO_EN(x)		FIELD_PREP(ADIS16575_FIFO_EN_MASK, x)
+#define ADIS16575_FIFO_FLUSH_CMD	BIT(5)
+#define ADIS16575_REG_FIFO_CNT		0x3C

 enum {
 	ADIS16475_SYNC_DIRECT = 1,
@@ -95,6 +115,9 @@  struct adis16475_chip_info {
 	const char *name;
 #define ADIS16475_HAS_BURST32		BIT(0)
 #define ADIS16475_HAS_BURST_DELTA_DATA	BIT(1)
+#define ADIS16475_HAS_TIMESTAMP32	BIT(2)
+#define ADIS16475_NEEDS_BURST_REQUEST	BIT(3)
+#define ADIS16475_HAS_FIFO		BIT(4)
 	const long flags;
 	u32 num_channels;
 	u32 gyro_max_val;
@@ -116,6 +139,7 @@  struct adis16475 {
 	bool burst32;
 	unsigned long lsb_flag;
 	u16 sync_mode;
+	u16 fifo_watermark;
 	/* Alignment needed for the timestamp */
 	__be16 data[ADIS16475_MAX_SCAN_DATA] __aligned(8);
 };
@@ -442,6 +466,124 @@  static int adis16475_set_filter(struct adis16475 *st, const u32 filter)
 	return 0;
 }

+static ssize_t adis16475_get_fifo_enabled(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16475 *st = iio_priv(indio_dev);
+	int ret;
+	u16 val;
+
+	ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_FIFO_EN_MASK, val));
+}
+
+static ssize_t adis16475_get_fifo_watermark(struct device *dev,
+					    struct device_attribute *attr,
+					    char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct adis16475 *st = iio_priv(indio_dev);
+	int ret;
+	u16 val;
+
+	ret = adis_read_reg_16(&st->adis, ADIS16475_REG_FIFO_CTRL, &val);
+	if (ret)
+		return ret;
+
+	return sysfs_emit(buf, "%lu\n", FIELD_GET(ADIS16575_WM_LVL_MASK, val) + 1);
+}
+
+static ssize_t hwfifo_watermark_min_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sysfs_emit(buf, "1\n");
+}
+
+static ssize_t hwfifo_watermark_max_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	return sysfs_emit(buf, "%lu\n", ADIS16575_MAX_FIFO_WM);
+}
+
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
+static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
+		       adis16475_get_fifo_watermark, NULL, 0);
+static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
+		       adis16475_get_fifo_enabled, NULL, 0);
+
+static const struct iio_dev_attr *adis16475_fifo_attributes[] = {
+	&iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
+	&iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
+	&iio_dev_attr_hwfifo_watermark.dev_attr.attr,
+	&iio_dev_attr_hwfifo_enabled.dev_attr.attr,
+	NULL
+};
+
+static int adis16475_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct adis16475 *st = iio_priv(indio_dev);
+	struct adis *adis = &st->adis;
+
+	return adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL,
+				ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(1));
+}
+
+static int adis16475_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct adis16475 *st = iio_priv(indio_dev);
+	struct adis *adis = &st->adis;
+	int ret;
+
+	adis_dev_lock(&st->adis);
+
+	ret = __adis_update_bits(adis, ADIS16475_REG_FIFO_CTRL,
+				 ADIS16575_FIFO_EN_MASK, (u16)ADIS16575_FIFO_EN(0));
+	if (ret)
+		goto unlock;
+
+	ret = __adis_write_reg_16(adis, ADIS16475_REG_GLOB_CMD,
+				  ADIS16575_FIFO_FLUSH_CMD);
+
+unlock:
+	adis_dev_unlock(&st->adis);
+	return ret;
+}
+
+static const struct iio_buffer_setup_ops adis16475_buffer_ops = {
+	.postenable = adis16475_buffer_postenable,
+	.postdisable = adis16475_buffer_postdisable,
+};
+
+static int adis16475_set_watermark(struct iio_dev *indio_dev, unsigned int val)
+{
+	struct adis16475 *st  = iio_priv(indio_dev);
+	int ret;
+	u16 wm_lvl;
+
+	adis_dev_lock(&st->adis);
+
+	val = min_t(unsigned int, val, ADIS16575_MAX_FIFO_WM);
+
+	wm_lvl = ADIS16575_WM_LVL(val - 1);
+	ret = __adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL, ADIS16575_WM_LVL_MASK, wm_lvl);
+	if (ret)
+		goto unlock;
+
+	st->fifo_watermark = val;
+
+unlock:
+	adis_dev_unlock(&st->adis);
+	return ret;
+}
+
 static const u32 adis16475_calib_regs[] = {
 	[ADIS16475_SCAN_GYRO_X] = ADIS16475_REG_X_GYRO_BIAS_L,
 	[ADIS16475_SCAN_GYRO_Y] = ADIS16475_REG_Y_GYRO_BIAS_L,
@@ -673,6 +815,12 @@  enum adis16475_variant {
 	ADIS16507_1,
 	ADIS16507_2,
 	ADIS16507_3,
+	ADIS16575_2,
+	ADIS16575_3,
+	ADIS16576_2,
+	ADIS16576_3,
+	ADIS16577_2,
+	ADIS16577_3,
 };

 enum {
@@ -730,6 +878,12 @@  static const struct adis16475_sync adis16475_sync_mode[] = {
 	{ ADIS16475_SYNC_PULSE, 1000, 2100 },
 };

+static const struct adis16475_sync adis16575_sync_mode[] = {
+	{ ADIS16475_SYNC_OUTPUT },
+	{ ADIS16475_SYNC_DIRECT, 1900, 4100 },
+	{ ADIS16475_SYNC_SCALED, 1, 400 },
+};
+
 static const struct adis_timeout adis16475_timeouts = {
 	.reset_ms = 200,
 	.sw_reset_ms = 200,
@@ -759,7 +913,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16470, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16475_1] = {
@@ -778,7 +932,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16475_2] = {
@@ -797,7 +951,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16475_3] = {
@@ -816,7 +970,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16475, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16477_1] = {
@@ -836,7 +990,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16477_2] = {
@@ -856,7 +1010,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16477_3] = {
@@ -876,7 +1030,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16477, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16465_1] = {
@@ -895,7 +1049,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16465_2] = {
@@ -914,7 +1068,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16465_3] = {
@@ -933,7 +1087,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16465, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16467_1] = {
@@ -952,7 +1106,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16467_2] = {
@@ -971,7 +1125,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16467_3] = {
@@ -990,7 +1144,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.sync = adis16475_sync_mode,
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode),
 		.adis_data = ADIS16475_DATA(16467, &adis16475_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16500] = {
@@ -1011,7 +1165,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16500, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16501] = {
@@ -1032,7 +1186,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16501, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16505_1] = {
@@ -1053,7 +1207,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16505_2] = {
@@ -1074,7 +1228,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16505_3] = {
@@ -1095,7 +1249,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16505, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16507_1] = {
@@ -1116,7 +1270,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16507_2] = {
@@ -1137,7 +1291,7 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
 	[ADIS16507_3] = {
@@ -1158,9 +1312,153 @@  static const struct adis16475_chip_info adis16475_chip_info[] = {
 		.num_sync = ARRAY_SIZE(adis16475_sync_mode) - 1,
 		.flags = ADIS16475_HAS_BURST32 | ADIS16475_HAS_BURST_DELTA_DATA,
 		.adis_data = ADIS16475_DATA(16507, &adis1650x_timeouts,
-					    ADIS16475_BURST32_MAX_DATA,
+					    ADIS16475_BURST32_MAX_DATA_NO_TS32,
 					    ADIS16475_BURST_MAX_SPEED),
 	},
+	[ADIS16575_2] = {
+		.name = "adis16575-2",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+		.accel_max_val = 8,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(450),
+		.deltvel_max_val = 100,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16575, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
+	[ADIS16575_3] = {
+		.name = "adis16575-3",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+		.accel_max_val = 8,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+		.deltvel_max_val = 100,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16575, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
+	[ADIS16576_2] = {
+		.name = "adis16576-2",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+		.accel_max_val = 40,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(450),
+		.deltvel_max_val = 125,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16576, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
+	[ADIS16576_3] = {
+		.name = "adis16576-3",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+		.accel_max_val = 40,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+		.deltvel_max_val = 125,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16576, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
+	[ADIS16577_2] = {
+		.name = "adis16577-2",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(40 << 16),
+		.accel_max_val = 40,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(450),
+		.deltvel_max_val = 400,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16577, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
+	[ADIS16577_3] = {
+		.name = "adis16577-3",
+		.num_channels = ARRAY_SIZE(adis16477_channels),
+		.channels = adis16477_channels,
+		.gyro_max_val = 1,
+		.gyro_max_scale = IIO_RAD_TO_DEGREE(10 << 16),
+		.accel_max_val = 40,
+		.accel_max_scale = IIO_M_S_2_TO_G(32000 << 16),
+		.temp_scale = 100,
+		.deltang_max_val = IIO_DEGREE_TO_RAD(2000),
+		.deltvel_max_val = 400,
+		.int_clk = 4000,
+		.max_dec = 3999,
+		.sync = adis16575_sync_mode,
+		.num_sync = ARRAY_SIZE(adis16575_sync_mode),
+		.flags = ADIS16475_HAS_BURST32 |
+			 ADIS16475_HAS_BURST_DELTA_DATA |
+			 ADIS16475_NEEDS_BURST_REQUEST |
+			 ADIS16475_HAS_TIMESTAMP32 |
+			 ADIS16475_HAS_FIFO,
+		.adis_data = ADIS16475_DATA(16577, &adis16475_timeouts,
+					    ADIS16575_BURST32_DATA_TS32,
+					    ADIS16575_BURST_MAX_SPEED),
+	},
 };

 static int adis16475_update_scan_mode(struct iio_dev *indio_dev,
@@ -1195,15 +1493,19 @@  static const struct iio_info adis16475_info = {
 	.debugfs_reg_access = adis_debugfs_reg_access,
 };

+static const struct iio_info adis16575_info = {
+	.read_raw = &adis16475_read_raw,
+	.write_raw = &adis16475_write_raw,
+	.update_scan_mode = adis16475_update_scan_mode,
+	.debugfs_reg_access = adis_debugfs_reg_access,
+	.hwfifo_set_watermark = adis16475_set_watermark,
+};
+
 static bool adis16475_validate_crc(const u8 *buffer, u16 crc,
-				   const bool burst32)
+				   u16 burst_size, u16 start_idx)
 {
 	int i;
-	/* extra 6 elements for low gyro and accel */
-	const u16 sz = burst32 ? ADIS16475_BURST32_MAX_DATA :
-		ADIS16475_BURST_MAX_DATA;
-
-	for (i = 0; i < sz - 2; i++)
+	for (i = start_idx; i < burst_size - 2; i++)
 		crc -= buffer[i];

 	return crc == 0;
@@ -1213,10 +1515,14 @@  static void adis16475_burst32_check(struct adis16475 *st)
 {
 	int ret;
 	struct adis *adis = &st->adis;
+	u8 timestamp32 = 0;

 	if (!(st->info->flags & ADIS16475_HAS_BURST32))
 		return;

+	if (st->info->flags & ADIS16475_HAS_TIMESTAMP32)
+		timestamp32 = 1;
+
 	if (st->lsb_flag && !st->burst32) {
 		const u16 en = ADIS16500_BURST32(1);

@@ -1230,9 +1536,12 @@  static void adis16475_burst32_check(struct adis16475 *st)
 		/*
 		 * In 32-bit mode we need extra 2 bytes for all gyro
 		 * and accel channels.
+		 * If the device has 32-bit timestamp value we need 2 extra
+		 * bytes for it.
 		 */
-		adis->burst_extra_len = 6 * sizeof(u16);
-		adis->xfer[1].len += 6 * sizeof(u16);
+		adis->burst_extra_len = (6 + timestamp32) * sizeof(u16);
+		adis->xfer[1].len += (6 + timestamp32) * sizeof(u16);
+
 		dev_dbg(&adis->spi->dev, "Enable burst32 mode, xfer:%d",
 			adis->xfer[1].len);

@@ -1248,7 +1557,7 @@  static void adis16475_burst32_check(struct adis16475 *st)

 		/* Remove the extra bits */
 		adis->burst_extra_len = 0;
-		adis->xfer[1].len -= 6 * sizeof(u16);
+		adis->xfer[1].len -= (6 + timestamp32) * sizeof(u16);
 		dev_dbg(&adis->spi->dev, "Disable burst32 mode, xfer:%d\n",
 			adis->xfer[1].len);
 	}
@@ -1263,20 +1572,30 @@  static int adis16475_push_single_sample(struct iio_poll_func *pf)
 	__be16 *buffer;
 	u16 crc;
 	bool valid;
+	u8 crc_offset = 9;
+	u16 burst_size = ADIS16475_BURST_MAX_DATA;
+	u16 start_idx = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 2 : 0;
+
 	/* offset until the first element after gyro and accel */
 	const u8 offset = st->burst32 ? 13 : 7;

+	if (st->burst32) {
+		crc_offset = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ? 16 : 15;
+		burst_size = (st->info->flags & ADIS16475_HAS_TIMESTAMP32) ?
+			     ADIS16575_BURST32_DATA_TS32 : ADIS16475_BURST32_MAX_DATA_NO_TS32;
+	}
+
 	ret = spi_sync(adis->spi, &adis->msg);
 	if (ret)
-		goto check_burst32;
+		return ret;

 	buffer = adis->buffer;

-	crc = be16_to_cpu(buffer[offset + 2]);
-	valid = adis16475_validate_crc(adis->buffer, crc, st->burst32);
+	crc = be16_to_cpu(buffer[crc_offset]);
+	valid = adis16475_validate_crc(adis->buffer, crc, burst_size, start_idx);
 	if (!valid) {
 		dev_err(&adis->spi->dev, "Invalid crc\n");
-		goto check_burst32;
+		return ret;
 	}

 	for_each_set_bit(bit, indio_dev->active_scan_mask,
@@ -1337,22 +1656,123 @@  static int adis16475_push_single_sample(struct iio_poll_func *pf)
 	}

 	iio_push_to_buffers_with_timestamp(indio_dev, st->data, pf->timestamp);
-check_burst32:
+
+	return 0;
+}
+
+static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adis16475 *st = iio_priv(indio_dev);
+
+	adis16475_push_single_sample(pf);
 	/*
 	 * We only check the burst mode at the end of the current capture since
 	 * it takes a full data ready cycle for the device to update the burst
 	 * array.
 	 */
 	adis16475_burst32_check(st);
-	return ret;
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
 }

-static irqreturn_t adis16475_trigger_handler(int irq, void *p)
+/*
+ * This function updates the first tx byte from the adis message based on the
+ * given burst request.
+ */
+static void adis16575_update_msg_for_burst(struct adis *adis, u8 burst_req)
+{
+	unsigned int burst_max_length;
+	u8 *tx;
+
+	if (adis->data->burst_max_len)
+		burst_max_length = adis->data->burst_max_len;
+	else
+		burst_max_length = adis->data->burst_len + adis->burst_extra_len;
+
+	tx = adis->buffer + burst_max_length;
+	tx[0] = ADIS_READ_REG(burst_req);
+}
+
+static int adis16575_custom_burst_read(struct iio_poll_func *pf, u8 burst_req)
+{
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adis16475 *st = iio_priv(indio_dev);
+	struct adis *adis = &st->adis;
+
+	adis16575_update_msg_for_burst(adis, burst_req);
+
+	if (burst_req)
+		return spi_sync(adis->spi, &adis->msg);
+
+	return adis16475_push_single_sample(pf);
+}
+
+/*
+ * This handler is meant to be used for devices which support burst readings
+ * from FIFO (namely devices from adis1657x family).
+ * In order to pop the FIFO the 0x68 0x00 FIFO pop burst request has to be sent.
+ * If the previous device command was not a FIFO pop burst request, the FIFO pop
+ * burst request will simply pop the FIFO without returning valid data.
+ * For the nth consecutive burst request, thedevice will send the data popped
+ * with the (n-1)th consecutive burst request.
+ * In order to read the data which was popped previously, without popping the
+ * FIFO, the 0x00 0x00 burst request has to be sent.
+ * If after a 0x68 0x00 FIFO pop burst request, there is any other device access
+ * different from a 0x68 0x00 or a 0x00 0x00 burst request, the FIFO data popped
+ * previously will be lost.
+ */
+static irqreturn_t adis16475_trigger_handler_with_fifo(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adis16475 *st = iio_priv(indio_dev);
+	struct adis *adis = &st->adis;
+	int ret;
+	u16 fifo_cnt, i;

-	adis16475_push_single_sample(pf);
+	adis_dev_lock(&st->adis);
+
+	ret = __adis_read_reg_16(adis, ADIS16575_REG_FIFO_CNT, &fifo_cnt);
+	if (ret)
+		goto unlock;
+
+	/*
+	 * If no sample is available, nothing can be read. This can happen if
+	 * a the used trigger has a higher frequency than the selected sample rate.
+	 */
+	if (!fifo_cnt)
+		goto unlock;
+
+	/*
+	 * First burst request - FIFO pop: popped data will be returned in the
+	 * next burst request.
+	 */
+	ret = adis16575_custom_burst_read(pf, adis->data->burst_reg_cmd);
+	if (ret)
+		goto unlock;
+
+	for (i = 0; i < fifo_cnt - 1; i++) {
+		ret = adis16475_push_single_sample(pf);
+		if (ret)
+			goto unlock;
+	}
+
+	/* FIFO read without popping */
+	ret = adis16575_custom_burst_read(pf, 0);
+	if (ret)
+		goto unlock;
+
+unlock:
+	/*
+	 * We only check the burst mode at the end of the current capture since
+	 * reading data from registers will impact the FIFO reading.
+	 */
+	adis16475_burst32_check(st);
+	adis_dev_unlock(&st->adis);
 	iio_trigger_notify_done(indio_dev->trig);

 	return IRQ_HANDLED;
@@ -1366,6 +1786,14 @@  static int adis16475_config_sync_mode(struct adis16475 *st)
 	u32 sync_mode;
 	u16 max_sample_rate = st->info->int_clk + 100;

+	/* if available, enable 4khz internal clock */
+	if (st->info->int_clk == 4000) {
+		ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+					 ADIS16575_SYNC_4KHZ_MASK, (u16)ADIS16575_SYNC_4KHZ(1));
+		if (ret)
+			return ret;
+	}
+
 	/* default to internal clk */
 	st->clk_freq = st->info->int_clk * 1000;

@@ -1443,34 +1871,67 @@  static int adis16475_config_irq_pin(struct adis16475 *st)
 	u8 polarity;
 	struct spi_device *spi = st->adis.spi;

-	/*
-	 * It is possible to configure the data ready polarity. Furthermore, we
-	 * need to update the adis struct if we want data ready as active low.
-	 */
 	irq_type = irq_get_trigger_type(spi->irq);
-	if (irq_type == IRQ_TYPE_EDGE_RISING) {
-		polarity = 1;
-		st->adis.irq_flag = IRQF_TRIGGER_RISING;
-	} else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
-		polarity = 0;
-		st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+
+	if (st->info->flags & ADIS16475_HAS_FIFO) {
+		/*
+		 * It is possible to configure the fifo watermark pin polarity.
+		 * Furthermore, we need to update the adis struct if we want the
+		 * watermark pin active low.
+		 */
+		if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
+			polarity = 1;
+			st->adis.irq_flag = IRQF_TRIGGER_HIGH;
+		} else if (irq_type == IRQ_TYPE_LEVEL_LOW) {
+			polarity = 0;
+			st->adis.irq_flag = IRQF_TRIGGER_LOW;
+		} else {
+			dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+				irq_type);
+			return -EINVAL;
+		}
+
+		/* Configure the watermark pin polarity. */
+		ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+				       ADIS16575_WM_POL_MASK, (u16)ADIS16575_WM_POL(polarity));
+		if (ret)
+			return ret;
+
+		/* Enable watermark interrupt pin. */
+		ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+				       ADIS16575_WM_EN_MASK, (u16)ADIS16575_WM_EN(1));
+		if (ret)
+			return ret;
+
 	} else {
-		dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
-			irq_type);
-		return -EINVAL;
-	}
+		/*
+		 * It is possible to configure the data ready polarity. Furthermore, we
+		 * need to update the adis struct if we want data ready as active low.
+		 */
+		if (irq_type == IRQ_TYPE_EDGE_RISING) {
+			polarity = 1;
+			st->adis.irq_flag = IRQF_TRIGGER_RISING;
+		} else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
+			polarity = 0;
+			st->adis.irq_flag = IRQF_TRIGGER_FALLING;
+		} else {
+			dev_err(&spi->dev, "Invalid interrupt type 0x%x specified\n",
+				irq_type);
+			return -EINVAL;
+		}

-	val = ADIS16475_MSG_CTRL_DR_POL(polarity);
-	ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
-				 ADIS16475_MSG_CTRL_DR_POL_MASK, val);
-	if (ret)
-		return ret;
-	/*
-	 * There is a delay writing to any bits written to the MSC_CTRL
-	 * register. It should not be bigger than 200us, so 250 should be more
-	 * than enough!
-	 */
-	usleep_range(250, 260);
+		val = ADIS16475_MSG_CTRL_DR_POL(polarity);
+		ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+					 ADIS16475_MSG_CTRL_DR_POL_MASK, val);
+		if (ret)
+			return ret;
+		/*
+		 * There is a delay writing to any bits written to the MSC_CTRL
+		 * register. It should not be bigger than 200us, so 250 should be more
+		 * than enough!
+		 */
+		usleep_range(250, 260);
+	}

 	return 0;
 }
@@ -1499,7 +1960,10 @@  static int adis16475_probe(struct spi_device *spi)
 	indio_dev->name = st->info->name;
 	indio_dev->channels = st->info->channels;
 	indio_dev->num_channels = st->info->num_channels;
-	indio_dev->info = &adis16475_info;
+	if (st->info->flags & ADIS16475_HAS_FIFO)
+		indio_dev->info = &adis16575_info;
+	else
+		indio_dev->info = &adis16475_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;

 	ret = __adis_initial_startup(&st->adis);
@@ -1514,8 +1978,20 @@  static int adis16475_probe(struct spi_device *spi)
 	if (ret)
 		return ret;

-	ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
-						 adis16475_trigger_handler);
+	if (st->info->flags & ADIS16475_HAS_FIFO) {
+		ret = devm_adis_setup_buffer_and_trigger_with_attrs(&st->adis, indio_dev,
+								    adis16475_trigger_handler_with_fifo,
+								    &adis16475_buffer_ops,
+								    adis16475_fifo_attributes);
+		if (ret)
+			return ret;
+		/* Update overflow behavior to always overwrite the oldest sample. */
+		ret = adis_update_bits(&st->adis, ADIS16475_REG_FIFO_CTRL,
+				       ADIS16575_OVERFLOW_MASK, (u16)ADIS16575_OVERWRITE_OLDEST);
+	} else {
+		ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev,
+							 adis16475_trigger_handler);
+	}
 	if (ret)
 		return ret;

@@ -1571,6 +2047,18 @@  static const struct of_device_id adis16475_of_match[] = {
 		.data = &adis16475_chip_info[ADIS16507_2] },
 	{ .compatible = "adi,adis16507-3",
 		.data = &adis16475_chip_info[ADIS16507_3] },
+	{ .compatible = "adi,adis16575-2",
+		.data = &adis16475_chip_info[ADIS16575_2] },
+	{ .compatible = "adi,adis16575-3",
+		.data = &adis16475_chip_info[ADIS16575_3] },
+	{ .compatible = "adi,adis16576-2",
+		.data = &adis16475_chip_info[ADIS16576_2] },
+	{ .compatible = "adi,adis16576-3",
+		.data = &adis16475_chip_info[ADIS16576_3] },
+	{ .compatible = "adi,adis16577-2",
+		.data = &adis16475_chip_info[ADIS16577_2] },
+	{ .compatible = "adi,adis16577-3",
+		.data = &adis16475_chip_info[ADIS16577_3] },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, adis16475_of_match);
@@ -1597,6 +2085,12 @@  static const struct spi_device_id adis16475_ids[] = {
 	{ "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] },
 	{ "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] },
 	{ "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] },
+	{ "adis16575-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_2] },
+	{ "adis16575-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16575_3] },
+	{ "adis16576-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_2] },
+	{ "adis16576-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16576_3] },
+	{ "adis16577-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_2] },
+	{ "adis16577-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16577_3] },
 	{ }
 };
 MODULE_DEVICE_TABLE(spi, adis16475_ids);