Message ID | 20190322204442.4035-2-ardeleanalex@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/5] iio: imu: adis16400: move trigger handler into adis16400_core | expand |
On Fri, 22 Mar 2019 22:44:39 +0200 Alexandru Ardelean <ardeleanalex@gmail.com> wrote: > From: Alexandru Ardelean <alexandru.ardelean@analog.com> > > Some variants in the ADIS16400 family support burst mode. This mechanism is > implemented in the `adis16400_buffer.c` file. > > Some variants in ADIS16480 are also adding burst mode, which is > functionally similar to ADIS16400, but with different parameters. To get > there, a `adis_burst` struct is added to parametrize certain bits of the > SPI communication to setup: the register that triggers burst-mode, and the > extra-data-length that needs be accounted for when building the bust-length > buffer. > > The trigger handler cannot be made generic, since it's very specific to > each ADIS164XX family. > > A future enhancement of this `adis_burst` mode will be the possibility to > enable/disable burst-mode. For the ADIS16400 family it's hard-coded to on > by default. But for ADIS16480 there will be a need to disable this. This sounds interesting. I'll wait to see why you need to disable it :) From what I recall there are definitely advantages to turning it off if you have a disconnected set of channels to read. Been a long time since I fired one of these up, though I think the one I have still works so I might move it into a more regular test set. > > When that will be implemented, both ADIS16400 & ADIS16480 will have the > burst-mode enable-able/disable-able. > > Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com> Applied to the togreg branch of iio.git and pushed out as testing for the autobuilders to play with it. Thanks, Jonathan > --- > drivers/iio/imu/adis16400_buffer.c | 7 +++---- > drivers/iio/imu/adis16400_core.c | 8 ++++++++ > include/linux/iio/imu/adis.h | 14 ++++++++++++++ > 3 files changed, 25 insertions(+), 4 deletions(-) > > diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c > index 268349eb51c7..199bd72348eb 100644 > --- a/drivers/iio/imu/adis16400_buffer.c > +++ b/drivers/iio/imu/adis16400_buffer.c > @@ -22,7 +22,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, > unsigned int burst_length; > u8 *tx; > > - if (st->variant->flags & ADIS16400_NO_BURST) > + if (!adis->burst || !adis->burst->en) > return adis_update_scan_mode(indio_dev, scan_mask); > > kfree(adis->xfer); > @@ -30,8 +30,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, > > /* All but the timestamp channel */ > burst_length = (indio_dev->num_channels - 1) * sizeof(u16); > - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) > - burst_length += sizeof(u16); > + burst_length += adis->burst->extra_len; > > adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); > if (!adis->xfer) > @@ -42,7 +41,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, > return -ENOMEM; > > tx = adis->buffer + burst_length; > - tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); > + tx[0] = ADIS_READ_REG(adis->burst->reg_cmd); > tx[1] = 0; > > adis->xfer[0].tx_buf = tx; > diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c > index 34d52863377a..0d799e983d74 100644 > --- a/drivers/iio/imu/adis16400_core.c > +++ b/drivers/iio/imu/adis16400_core.c > @@ -146,6 +146,11 @@ enum adis16400_chip_variant { > ADIS16448, > }; > > +static struct adis_burst adis16400_burst = { > + .en = true, > + .reg_cmd = ADIS16400_GLOB_CMD, > +}; > + > static int adis16334_get_freq(struct adis16400_state *st) > { > int ret; > @@ -973,6 +978,9 @@ static int adis16400_probe(struct spi_device *spi) > if (!(st->variant->flags & ADIS16400_NO_BURST)) { > adis16400_setup_chan_mask(st); > indio_dev->available_scan_masks = st->avail_scan_mask; > + st->adis.burst = &adis16400_burst; > + if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) > + st->adis.burst->extra_len = sizeof(u16); > } > > ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); > diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h > index cb6c3ed13459..26141ee87cfb 100644 > --- a/include/linux/iio/imu/adis.h > +++ b/include/linux/iio/imu/adis.h > @@ -21,6 +21,7 @@ > #define ADIS_REG_PAGE_ID 0x00 > > struct adis; > +struct adis_burst; > > /** > * struct adis_data - ADIS chip variant specific data > @@ -59,6 +60,7 @@ struct adis { > struct iio_trigger *trig; > > const struct adis_data *data; > + struct adis_burst *burst; > > struct mutex txrx_lock; > struct spi_message msg; > @@ -234,6 +236,18 @@ int adis_single_conversion(struct iio_dev *indio_dev, > > #ifdef CONFIG_IIO_ADIS_LIB_BUFFER > > +/** > + * struct adis_burst - ADIS data for burst transfers > + * @en burst mode enabled > + * @reg_cmd register command that triggers burst > + * @extra_len extra length to account in the SPI RX buffer > + */ > +struct adis_burst { > + bool en; > + unsigned int reg_cmd; > + unsigned int extra_len; > +}; > + > int adis_setup_buffer_and_trigger(struct adis *adis, > struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)); > void adis_cleanup_buffer_and_trigger(struct adis *adis,
diff --git a/drivers/iio/imu/adis16400_buffer.c b/drivers/iio/imu/adis16400_buffer.c index 268349eb51c7..199bd72348eb 100644 --- a/drivers/iio/imu/adis16400_buffer.c +++ b/drivers/iio/imu/adis16400_buffer.c @@ -22,7 +22,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, unsigned int burst_length; u8 *tx; - if (st->variant->flags & ADIS16400_NO_BURST) + if (!adis->burst || !adis->burst->en) return adis_update_scan_mode(indio_dev, scan_mask); kfree(adis->xfer); @@ -30,8 +30,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, /* All but the timestamp channel */ burst_length = (indio_dev->num_channels - 1) * sizeof(u16); - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) - burst_length += sizeof(u16); + burst_length += adis->burst->extra_len; adis->xfer = kcalloc(2, sizeof(*adis->xfer), GFP_KERNEL); if (!adis->xfer) @@ -42,7 +41,7 @@ int adis16400_update_scan_mode(struct iio_dev *indio_dev, return -ENOMEM; tx = adis->buffer + burst_length; - tx[0] = ADIS_READ_REG(ADIS16400_GLOB_CMD); + tx[0] = ADIS_READ_REG(adis->burst->reg_cmd); tx[1] = 0; adis->xfer[0].tx_buf = tx; diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c index 34d52863377a..0d799e983d74 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400_core.c @@ -146,6 +146,11 @@ enum adis16400_chip_variant { ADIS16448, }; +static struct adis_burst adis16400_burst = { + .en = true, + .reg_cmd = ADIS16400_GLOB_CMD, +}; + static int adis16334_get_freq(struct adis16400_state *st) { int ret; @@ -973,6 +978,9 @@ static int adis16400_probe(struct spi_device *spi) if (!(st->variant->flags & ADIS16400_NO_BURST)) { adis16400_setup_chan_mask(st); indio_dev->available_scan_masks = st->avail_scan_mask; + st->adis.burst = &adis16400_burst; + if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) + st->adis.burst->extra_len = sizeof(u16); } ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index cb6c3ed13459..26141ee87cfb 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -21,6 +21,7 @@ #define ADIS_REG_PAGE_ID 0x00 struct adis; +struct adis_burst; /** * struct adis_data - ADIS chip variant specific data @@ -59,6 +60,7 @@ struct adis { struct iio_trigger *trig; const struct adis_data *data; + struct adis_burst *burst; struct mutex txrx_lock; struct spi_message msg; @@ -234,6 +236,18 @@ int adis_single_conversion(struct iio_dev *indio_dev, #ifdef CONFIG_IIO_ADIS_LIB_BUFFER +/** + * struct adis_burst - ADIS data for burst transfers + * @en burst mode enabled + * @reg_cmd register command that triggers burst + * @extra_len extra length to account in the SPI RX buffer + */ +struct adis_burst { + bool en; + unsigned int reg_cmd; + unsigned int extra_len; +}; + int adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, irqreturn_t (*trigger_handler)(int, void *)); void adis_cleanup_buffer_and_trigger(struct adis *adis,