From bd6880477a3d73270edead88f4b806504998e5d8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 01/17] staging:iio:ad7887: Preallocate sample buffer We know that the sample buffer will at most need to hold two 16 bit samples and the 64 bit aligned 64 bit timestamp. Preallocate a buffer large enough to hold this instead of allocating and freeing it each time a sample is read. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887.h | 6 ++++-- drivers/staging/iio/adc/ad7887_ring.c | 15 ++------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h index 2e09e54fc9c5..71e50925e066 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/drivers/staging/iio/adc/ad7887.h @@ -72,9 +72,11 @@ struct ad7887_state { /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. + * Buffer needs to be large enough to hold two 16 bit samples and a + * 64 bit aligned 64 bit timestamp. */ - - unsigned char data[4] ____cacheline_aligned; + unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] + ____cacheline_aligned; }; enum ad7887_supported_device_ids { diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c index b39923bbeedc..f11925e62cdc 100644 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ b/drivers/staging/iio/adc/ad7887_ring.c @@ -73,31 +73,20 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct ad7887_state *st = iio_priv(indio_dev); s64 time_ns; - __u8 *buf; int b_sent; - unsigned int bytes = bitmap_weight(indio_dev->active_scan_mask, - indio_dev->masklength) * - st->chip_info->channel[0].scan_type.storagebits / 8; - - buf = kzalloc(indio_dev->scan_bytes, GFP_KERNEL); - if (buf == NULL) - goto done; - b_sent = spi_sync(st->spi, st->ring_msg); if (b_sent) goto done; time_ns = iio_get_time_ns(); - memcpy(buf, st->data, bytes); if (indio_dev->scan_timestamp) - memcpy(buf + indio_dev->scan_bytes - sizeof(s64), + memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, buf); + iio_push_to_buffer(indio_dev->buffer, st->data); done: - kfree(buf); iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; From bf5d2613c9083b8d4f4e98f5b25553fc938b50c6 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 02/17] staging:iio:ad7887: Rework regulator handling Rework the regulator handling of the ad7887 driver to match more closely what we do for other drivers. Only request the regulator if a external reference is used, but treat it as an error if requesting the regulator fails. Also remove the possibility to specify the reference voltage via platform data and always use the regulator for this. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887.h | 3 -- drivers/staging/iio/adc/ad7887_core.c | 52 +++++++++++++-------------- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h index 71e50925e066..25d5b4008b24 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/drivers/staging/iio/adc/ad7887.h @@ -30,8 +30,6 @@ enum ad7887_channels { */ struct ad7887_platform_data { - /* External Vref voltage applied */ - u16 vref_mv; /* * AD7887: * In single channel mode en_dual = flase, AIN1/Vref pins assumes its @@ -63,7 +61,6 @@ struct ad7887_state { struct spi_device *spi; const struct ad7887_chip_info *chip_info; struct regulator *reg; - u16 int_vref_mv; struct spi_transfer xfer[4]; struct spi_message msg[3]; struct spi_message *ring_msg; diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 551790584a12..cf33ba63c6cb 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -39,7 +39,6 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, { int ret; struct ad7887_state *st = iio_priv(indio_dev); - unsigned int scale_uv; switch (m) { case IIO_CHAN_INFO_RAW: @@ -56,11 +55,18 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, RES_MASK(st->chip_info->channel[0].scan_type.realbits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - scale_uv = (st->int_vref_mv * 1000) - >> st->chip_info->channel[0].scan_type.realbits; - *val = scale_uv/1000; - *val2 = (scale_uv%1000)*1000; - return IIO_VAL_INT_PLUS_MICRO; + if (st->reg) { + *val = regulator_get_voltage(st->reg); + if (*val < 0) + return *val; + *val /= 1000; + } else { + *val = st->chip_info->int_vref_mv; + } + + *val2 = st->chip_info->channel[0].scan_type.realbits; + + return IIO_VAL_FRACTIONAL_LOG2; } return -EINVAL; } @@ -105,21 +111,24 @@ static int __devinit ad7887_probe(struct spi_device *spi) { struct ad7887_platform_data *pdata = spi->dev.platform_data; struct ad7887_state *st; - int ret, voltage_uv = 0; struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); + int ret; if (indio_dev == NULL) return -ENOMEM; st = iio_priv(indio_dev); - st->reg = regulator_get(&spi->dev, "vcc"); - if (!IS_ERR(st->reg)) { + if (!pdata || !pdata->use_onchip_ref) { + st->reg = regulator_get(&spi->dev, "vref"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_free; + } + ret = regulator_enable(st->reg); if (ret) goto error_put_reg; - - voltage_uv = regulator_get_voltage(st->reg); } st->chip_info = @@ -176,23 +185,9 @@ static int __devinit ad7887_probe(struct spi_device *spi) spi_message_init(&st->msg[AD7887_CH1]); spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (voltage_uv) - st->int_vref_mv = voltage_uv / 1000; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - indio_dev->channels = st->chip_info->channel; indio_dev->num_channels = 3; } else { - if (pdata && pdata->vref_mv) - st->int_vref_mv = pdata->vref_mv; - else if (pdata && pdata->use_onchip_ref) - st->int_vref_mv = st->chip_info->int_vref_mv; - else - dev_warn(&spi->dev, "reference voltage unspecified\n"); - indio_dev->channels = &st->chip_info->channel[1]; indio_dev->num_channels = 2; } @@ -209,11 +204,12 @@ static int __devinit ad7887_probe(struct spi_device *spi) error_unregister_ring: ad7887_ring_cleanup(indio_dev); error_disable_reg: - if (!IS_ERR(st->reg)) + if (st->reg) regulator_disable(st->reg); error_put_reg: - if (!IS_ERR(st->reg)) + if (st->reg) regulator_put(st->reg); +error_free: iio_device_free(indio_dev); return ret; @@ -226,7 +222,7 @@ static int __devexit ad7887_remove(struct spi_device *spi) iio_device_unregister(indio_dev); ad7887_ring_cleanup(indio_dev); - if (!IS_ERR(st->reg)) { + if (st->reg) { regulator_disable(st->reg); regulator_put(st->reg); } From 65dd3d3d7a9bca683599b214229c546392394622 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 03/17] staging:iio:ad7887: Squash everything into one file The recent cleanups have decimated the drivers code size by quite a bit. It is only a few hundred lines in total now and we also always build buffer support, so there really is no need to spread the driver out over multiple files. Putting everything into one file also allows to reduce the code size a bit more by removing a few lines of boilerplate code. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Makefile | 2 - .../iio/adc/{ad7887_core.c => ad7887.c} | 133 +++++++++++++++++- drivers/staging/iio/adc/ad7887.h | 66 --------- drivers/staging/iio/adc/ad7887_ring.c | 111 --------------- 4 files changed, 130 insertions(+), 182 deletions(-) rename drivers/staging/iio/adc/{ad7887_core.c => ad7887.c} (62%) delete mode 100644 drivers/staging/iio/adc/ad7887_ring.c diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index ff561c591d66..8036fd14f68a 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -17,8 +17,6 @@ ad799x-y := ad799x_core.o ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o obj-$(CONFIG_AD799X) += ad799x.o -ad7887-y := ad7887_core.o -ad7887-$(CONFIG_IIO_BUFFER) += ad7887_ring.o obj-$(CONFIG_AD7887) += ad7887.o ad7298-y := ad7298_core.o diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887.c similarity index 62% rename from drivers/staging/iio/adc/ad7887_core.c rename to drivers/staging/iio/adc/ad7887.c index cf33ba63c6cb..88ffc4620fc8 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887.c @@ -14,14 +14,140 @@ #include #include #include +#include #include #include #include +#include +#include #include "ad7887.h" +#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ +#define AD7887_DUAL (1 << 4) /* dual-channel mode */ +#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ +#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ +#define AD7887_PM_MODE1 (0) /* CS based shutdown */ +#define AD7887_PM_MODE2 (1) /* full on */ +#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ +#define AD7887_PM_MODE4 (3) /* standby mode */ + +enum ad7887_channels { + AD7887_CH0, + AD7887_CH0_CH1, + AD7887_CH1, +}; + +#define RES_MASK(bits) ((1 << (bits)) - 1) + +/** + * struct ad7887_chip_info - chip specifc information + * @int_vref_mv: the internal reference voltage + * @channel: channel specification + */ +struct ad7887_chip_info { + u16 int_vref_mv; + struct iio_chan_spec channel[3]; +}; + +struct ad7887_state { + struct spi_device *spi; + const struct ad7887_chip_info *chip_info; + struct regulator *reg; + struct spi_transfer xfer[4]; + struct spi_message msg[3]; + struct spi_message *ring_msg; + unsigned char tx_cmd_buf[8]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + * Buffer needs to be large enough to hold two 16 bit samples and a + * 64 bit aligned 64 bit timestamp. + */ + unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] + ____cacheline_aligned; +}; + +enum ad7887_supported_device_ids { + ID_AD7887 +}; + +static int ad7887_ring_preenable(struct iio_dev *indio_dev) +{ + struct ad7887_state *st = iio_priv(indio_dev); + int ret; + + ret = iio_sw_buffer_preenable(indio_dev); + if (ret < 0) + return ret; + + /* We know this is a single long so can 'cheat' */ + switch (*indio_dev->active_scan_mask) { + case (1 << 0): + st->ring_msg = &st->msg[AD7887_CH0]; + break; + case (1 << 1): + st->ring_msg = &st->msg[AD7887_CH1]; + /* Dummy read: push CH1 setting down to hardware */ + spi_sync(st->spi, st->ring_msg); + break; + case ((1 << 1) | (1 << 0)): + st->ring_msg = &st->msg[AD7887_CH0_CH1]; + break; + } + + return 0; +} + +static int ad7887_ring_postdisable(struct iio_dev *indio_dev) +{ + struct ad7887_state *st = iio_priv(indio_dev); + + /* dummy read: restore default CH0 settin */ + return spi_sync(st->spi, &st->msg[AD7887_CH0]); +} + +/** + * ad7887_trigger_handler() bh of trigger launched polling to ring buffer + * + * Currently there is no option in this driver to disable the saving of + * timestamps within the ring. + **/ +static irqreturn_t ad7887_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct ad7887_state *st = iio_priv(indio_dev); + s64 time_ns; + int b_sent; + + b_sent = spi_sync(st->spi, st->ring_msg); + if (b_sent) + goto done; + + time_ns = iio_get_time_ns(); + + if (indio_dev->scan_timestamp) + memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), + &time_ns, sizeof(time_ns)); + + iio_push_to_buffer(indio_dev->buffer, st->data); +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { + .preenable = &ad7887_ring_preenable, + .postenable = &iio_triggered_buffer_postenable, + .predisable = &iio_triggered_buffer_predisable, + .postdisable = &ad7887_ring_postdisable, +}; + static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) { int ret = spi_sync(st->spi, &st->msg[ch]); @@ -192,7 +318,8 @@ static int __devinit ad7887_probe(struct spi_device *spi) indio_dev->num_channels = 2; } - ret = ad7887_register_ring_funcs_and_init(indio_dev); + ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, + &ad7887_trigger_handler, &ad7887_ring_setup_ops); if (ret) goto error_disable_reg; @@ -202,7 +329,7 @@ static int __devinit ad7887_probe(struct spi_device *spi) return 0; error_unregister_ring: - ad7887_ring_cleanup(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); error_disable_reg: if (st->reg) regulator_disable(st->reg); @@ -221,7 +348,7 @@ static int __devexit ad7887_remove(struct spi_device *spi) struct ad7887_state *st = iio_priv(indio_dev); iio_device_unregister(indio_dev); - ad7887_ring_cleanup(indio_dev); + iio_triggered_buffer_cleanup(indio_dev); if (st->reg) { regulator_disable(st->reg); regulator_put(st->reg); diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h index 25d5b4008b24..b9078fc2aa15 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/drivers/staging/iio/adc/ad7887.h @@ -8,23 +8,6 @@ #ifndef IIO_ADC_AD7887_H_ #define IIO_ADC_AD7887_H_ -#define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ -#define AD7887_DUAL (1 << 4) /* dual-channel mode */ -#define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ -#define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ -#define AD7887_PM_MODE1 (0) /* CS based shutdown */ -#define AD7887_PM_MODE2 (1) /* full on */ -#define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ -#define AD7887_PM_MODE4 (3) /* standby mode */ - -enum ad7887_channels { - AD7887_CH0, - AD7887_CH0_CH1, - AD7887_CH1, -}; - -#define RES_MASK(bits) ((1 << (bits)) - 1) /* TODO: move this into a common header */ - /* * TODO: struct ad7887_platform_data needs to go into include/linux/iio */ @@ -46,53 +29,4 @@ struct ad7887_platform_data { bool use_onchip_ref; }; -/** - * struct ad7887_chip_info - chip specifc information - * @int_vref_mv: the internal reference voltage - * @channel: channel specification - */ - -struct ad7887_chip_info { - u16 int_vref_mv; - struct iio_chan_spec channel[3]; -}; - -struct ad7887_state { - struct spi_device *spi; - const struct ad7887_chip_info *chip_info; - struct regulator *reg; - struct spi_transfer xfer[4]; - struct spi_message msg[3]; - struct spi_message *ring_msg; - unsigned char tx_cmd_buf[8]; - - /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - * Buffer needs to be large enough to hold two 16 bit samples and a - * 64 bit aligned 64 bit timestamp. - */ - unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] - ____cacheline_aligned; -}; - -enum ad7887_supported_device_ids { - ID_AD7887 -}; - -#ifdef CONFIG_IIO_BUFFER -int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void ad7887_ring_cleanup(struct iio_dev *indio_dev); -#else /* CONFIG_IIO_BUFFER */ - -static inline int -ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_IIO_BUFFER */ #endif /* IIO_ADC_AD7887_H_ */ diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c deleted file mode 100644 index f11925e62cdc..000000000000 --- a/drivers/staging/iio/adc/ad7887_ring.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2010-2012 Analog Devices Inc. - * Copyright (C) 2008 Jonathan Cameron - * - * Licensed under the GPL-2. - * - * ad7887_ring.c - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "ad7887.h" - -/** - * ad7887_ring_preenable() setup the parameters of the ring before enabling - * - * The complex nature of the setting of the nuber of bytes per datum is due - * to this driver currently ensuring that the timestamp is stored at an 8 - * byte boundary. - **/ -static int ad7887_ring_preenable(struct iio_dev *indio_dev) -{ - struct ad7887_state *st = iio_priv(indio_dev); - int ret; - - ret = iio_sw_buffer_preenable(indio_dev); - if (ret < 0) - return ret; - - /* We know this is a single long so can 'cheat' */ - switch (*indio_dev->active_scan_mask) { - case (1 << 0): - st->ring_msg = &st->msg[AD7887_CH0]; - break; - case (1 << 1): - st->ring_msg = &st->msg[AD7887_CH1]; - /* Dummy read: push CH1 setting down to hardware */ - spi_sync(st->spi, st->ring_msg); - break; - case ((1 << 1) | (1 << 0)): - st->ring_msg = &st->msg[AD7887_CH0_CH1]; - break; - } - - return 0; -} - -static int ad7887_ring_postdisable(struct iio_dev *indio_dev) -{ - struct ad7887_state *st = iio_priv(indio_dev); - - /* dummy read: restore default CH0 settin */ - return spi_sync(st->spi, &st->msg[AD7887_CH0]); -} - -/** - * ad7887_trigger_handler() bh of trigger launched polling to ring buffer - * - * Currently there is no option in this driver to disable the saving of - * timestamps within the ring. - **/ -static irqreturn_t ad7887_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct ad7887_state *st = iio_priv(indio_dev); - s64 time_ns; - int b_sent; - - b_sent = spi_sync(st->spi, st->ring_msg); - if (b_sent) - goto done; - - time_ns = iio_get_time_ns(); - - if (indio_dev->scan_timestamp) - memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), - &time_ns, sizeof(time_ns)); - - iio_push_to_buffer(indio_dev->buffer, st->data); -done: - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = { - .preenable = &ad7887_ring_preenable, - .postenable = &iio_triggered_buffer_postenable, - .predisable = &iio_triggered_buffer_predisable, - .postdisable = &ad7887_ring_postdisable, -}; - -int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, - &ad7887_trigger_handler, &ad7887_ring_setup_ops); -} - -void ad7887_ring_cleanup(struct iio_dev *indio_dev) -{ - iio_triggered_buffer_cleanup(indio_dev); -} From 5daa751f89eb3e73424d0cb5c204f9e0bc14e25c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 04/17] staging:iio:ad7887: Use proper kernel doc Use proper kernel doc to document the platform data struct. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h index b9078fc2aa15..16c2d05e5e05 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/drivers/staging/iio/adc/ad7887.h @@ -12,21 +12,20 @@ * TODO: struct ad7887_platform_data needs to go into include/linux/iio */ + +/** + * struct ad7887_platform_data - AD7887 ADC driver platform data + * @en_dual: Whether to use dual channel mode. If set to true AIN1 becomes the + * second input channel, and Vref is internally connected to Vdd. If set to + * false the device is used in single channel mode and AIN1/Vref is used as + * VREF input. + * @use_onchip_ref: Whether to use the onchip reference. If set to true the + * internal 2.5V reference is used. If set to false a external reference is + * used. + */ struct ad7887_platform_data { - /* - * AD7887: - * In single channel mode en_dual = flase, AIN1/Vref pins assumes its - * Vref function. In dual channel mode en_dual = true, AIN1 becomes the - * second input channel, and Vref is internally connected to Vdd. - */ - bool en_dual; - /* - * AD7887: - * use_onchip_ref = true, the Vref is internally connected to the 2.500V - * Voltage reference. If use_onchip_ref = false, the reference voltage - * is supplied by AIN1/Vref - */ - bool use_onchip_ref; + bool en_dual; + bool use_onchip_ref; }; #endif /* IIO_ADC_AD7887_H_ */ From fce7c3eac7d4ca77ada5bf8332f867219fbb5068 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 05/17] staging:iio:ad7887: Allow to use internal ref in two channel mode While it is not recommended to use the internal reference in two channel mode in order to obtain optimal performance it is still possible to use it. While we are at it also get rid of the duplicate tx_cmd_buf entries. There are only two unique entries. One for channel 1 and one for channel 2. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/staging/iio/adc/ad7887.c b/drivers/staging/iio/adc/ad7887.c index 88ffc4620fc8..3ac0c305e123 100644 --- a/drivers/staging/iio/adc/ad7887.c +++ b/drivers/staging/iio/adc/ad7887.c @@ -59,7 +59,7 @@ struct ad7887_state { struct spi_transfer xfer[4]; struct spi_message msg[3]; struct spi_message *ring_msg; - unsigned char tx_cmd_buf[8]; + unsigned char tx_cmd_buf[4]; /* * DMA (thus cache coherency maintenance) requires the @@ -238,6 +238,7 @@ static int __devinit ad7887_probe(struct spi_device *spi) struct ad7887_platform_data *pdata = spi->dev.platform_data; struct ad7887_state *st; struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); + uint8_t mode; int ret; if (indio_dev == NULL) @@ -271,9 +272,13 @@ static int __devinit ad7887_probe(struct spi_device *spi) /* Setup default message */ - st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 | - ((pdata && pdata->use_onchip_ref) ? - 0 : AD7887_REF_DIS); + mode = AD7887_PM_MODE4; + if (!pdata || !pdata->use_onchip_ref) + mode |= AD7887_REF_DIS; + if (pdata && pdata->en_dual) + mode |= AD7887_DUAL; + + st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode; st->xfer[0].rx_buf = &st->data[0]; st->xfer[0].tx_buf = &st->tx_cmd_buf[0]; @@ -283,29 +288,22 @@ static int __devinit ad7887_probe(struct spi_device *spi) spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]); if (pdata && pdata->en_dual) { - st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS; - - st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; - st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL | - AD7887_REF_DIS | AD7887_PM_MODE4; + st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode; st->xfer[1].rx_buf = &st->data[0]; st->xfer[1].tx_buf = &st->tx_cmd_buf[2]; st->xfer[1].len = 2; st->xfer[2].rx_buf = &st->data[2]; - st->xfer[2].tx_buf = &st->tx_cmd_buf[4]; + st->xfer[2].tx_buf = &st->tx_cmd_buf[0]; st->xfer[2].len = 2; spi_message_init(&st->msg[AD7887_CH0_CH1]); spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]); spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]); - st->xfer[3].rx_buf = &st->data[0]; - st->xfer[3].tx_buf = &st->tx_cmd_buf[6]; + st->xfer[3].rx_buf = &st->data[2]; + st->xfer[3].tx_buf = &st->tx_cmd_buf[2]; st->xfer[3].len = 2; spi_message_init(&st->msg[AD7887_CH1]); From 98efb70adde96d86df29b4754f265b2c8bba01b2 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 06/17] staging:iio:ad7887: Use passed in chan spec in ad7887_read_raw Use the passed in chan spec in ad7887_read_raw instead of alawys using the first chan spec entry from the chip info data. Since all channels have the same shift and realbits from a functional point of view it does not matter which chan spec is used, but the patch makes the a bit more clear. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/ad7887.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/iio/adc/ad7887.c b/drivers/staging/iio/adc/ad7887.c index 3ac0c305e123..72cfe191cd83 100644 --- a/drivers/staging/iio/adc/ad7887.c +++ b/drivers/staging/iio/adc/ad7887.c @@ -177,8 +177,8 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, if (ret < 0) return ret; - *val = (ret >> st->chip_info->channel[0].scan_type.shift) & - RES_MASK(st->chip_info->channel[0].scan_type.realbits); + *val = ret >> chan->scan_type.shift; + *val &= RES_MASK(chan->scan_type.realbits); return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: if (st->reg) { @@ -190,7 +190,7 @@ static int ad7887_read_raw(struct iio_dev *indio_dev, *val = st->chip_info->int_vref_mv; } - *val2 = st->chip_info->channel[0].scan_type.realbits; + *val2 = chan->scan_type.realbits; return IIO_VAL_FRACTIONAL_LOG2; } From 4eb3ccf157639a9d9c7829de94017c46c73d9cc4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 5 Nov 2012 09:56:00 +0000 Subject: [PATCH 07/17] staging:iio: Move the ad7887 driver out of staging The driver does not expose any custom API to userspace and none of the standard static code checker tools report any issues, so move it out of staging. Signed-off-by: Lars-Peter Clausen Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 13 +++++++++++++ drivers/iio/adc/Makefile | 1 + drivers/{staging => }/iio/adc/ad7887.c | 2 +- drivers/staging/iio/adc/Kconfig | 13 ------------- drivers/staging/iio/adc/Makefile | 2 -- .../adc => include/linux/platform_data}/ad7887.h | 5 ----- 6 files changed, 15 insertions(+), 21 deletions(-) rename drivers/{staging => }/iio/adc/ad7887.c (99%) rename {drivers/staging/iio/adc => include/linux/platform_data}/ad7887.h (90%) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 492758120338..706386ba02e3 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -45,6 +45,19 @@ config AD7476 To compile this driver as a module, choose M here: the module will be called ad7476. +config AD7887 + tristate "Analog Devices AD7887 ADC driver" + depends on SPI + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for Analog Devices + AD7887 SPI analog to digital converter (ADC). + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7887. + config AT91_ADC tristate "Atmel AT91 ADC" depends on ARCH_AT91 diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 900995d5e179..034eacb8f7c9 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o obj-$(CONFIG_AD7266) += ad7266.o obj-$(CONFIG_AD7476) += ad7476.o obj-$(CONFIG_AD7791) += ad7791.o +obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o diff --git a/drivers/staging/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c similarity index 99% rename from drivers/staging/iio/adc/ad7887.c rename to drivers/iio/adc/ad7887.c index 72cfe191cd83..fd62309b4d3d 100644 --- a/drivers/staging/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -23,7 +23,7 @@ #include #include -#include "ad7887.h" +#include #define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ #define AD7887_DUAL (1 << 4) /* dual-channel mode */ diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 71a515d0a6de..eba64fb64d82 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -68,19 +68,6 @@ config AD799X_RING_BUFFER Say yes here to include ring buffer support in the AD799X ADC driver. -config AD7887 - tristate "Analog Devices AD7887 ADC driver" - depends on SPI - select IIO_BUFFER - select IIO_TRIGGERED_BUFFER - help - Say yes here to build support for Analog Devices - AD7887 SPI analog to digital converter (ADC). - If unsure, say N (but it's safe to say "Y"). - - To compile this driver as a module, choose M here: the - module will be called ad7887. - config AD7780 tristate "Analog Devices AD7780 and similar ADCs driver" depends on SPI diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index 8036fd14f68a..c56b41ee285b 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -17,8 +17,6 @@ ad799x-y := ad799x_core.o ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o obj-$(CONFIG_AD799X) += ad799x.o -obj-$(CONFIG_AD7887) += ad7887.o - ad7298-y := ad7298_core.o ad7298-$(CONFIG_IIO_BUFFER) += ad7298_ring.o obj-$(CONFIG_AD7298) += ad7298.o diff --git a/drivers/staging/iio/adc/ad7887.h b/include/linux/platform_data/ad7887.h similarity index 90% rename from drivers/staging/iio/adc/ad7887.h rename to include/linux/platform_data/ad7887.h index 16c2d05e5e05..1e06eac3174d 100644 --- a/drivers/staging/iio/adc/ad7887.h +++ b/include/linux/platform_data/ad7887.h @@ -8,11 +8,6 @@ #ifndef IIO_ADC_AD7887_H_ #define IIO_ADC_AD7887_H_ -/* - * TODO: struct ad7887_platform_data needs to go into include/linux/iio - */ - - /** * struct ad7887_platform_data - AD7887 ADC driver platform data * @en_dual: Whether to use dual channel mode. If set to true AIN1 becomes the From 84b36ce5f79c01f792c623f14e92ed86cdccb42f Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 30 Jun 2012 20:06:00 +0100 Subject: [PATCH 08/17] staging:iio: Add support for multiple buffers Route all buffer writes through the demux. Addition or removal of a buffer results in tear down and setup of all the buffers for a given device. Signed-off-by: Jonathan Cameron Tested-by: srinivas pandruvada --- drivers/iio/accel/hid-sensor-accel-3d.c | 15 +- drivers/iio/adc/ad7266.c | 3 +- drivers/iio/adc/ad7476.c | 2 +- drivers/iio/adc/ad7887.c | 2 +- drivers/iio/adc/ad_sigma_delta.c | 2 +- drivers/iio/adc/at91_adc.c | 3 +- drivers/iio/gyro/hid-sensor-gyro-3d.c | 15 +- drivers/iio/industrialio-buffer.c | 380 ++++++++++++------ drivers/iio/industrialio-core.c | 1 + drivers/iio/light/adjd_s311.c | 3 +- drivers/iio/light/hid-sensor-als.c | 15 +- drivers/iio/magnetometer/hid-sensor-magn-3d.c | 15 +- drivers/staging/iio/accel/adis16201_ring.c | 2 +- drivers/staging/iio/accel/adis16203_ring.c | 2 +- drivers/staging/iio/accel/adis16204_ring.c | 2 +- drivers/staging/iio/accel/adis16209_ring.c | 2 +- drivers/staging/iio/accel/adis16240_ring.c | 2 +- drivers/staging/iio/accel/lis3l02dq_ring.c | 2 +- drivers/staging/iio/adc/ad7298_ring.c | 2 +- drivers/staging/iio/adc/ad7606_ring.c | 2 +- drivers/staging/iio/adc/ad799x_ring.c | 2 +- drivers/staging/iio/adc/max1363_ring.c | 2 +- drivers/staging/iio/adc/mxs-lradc.c | 3 +- drivers/staging/iio/gyro/adis16260_ring.c | 2 +- drivers/staging/iio/iio_simple_dummy_buffer.c | 5 +- .../staging/iio/impedance-analyzer/ad5933.c | 4 +- drivers/staging/iio/imu/adis16400_ring.c | 5 +- drivers/staging/iio/meter/ade7758_ring.c | 2 +- include/linux/iio/buffer.h | 24 +- include/linux/iio/iio.h | 2 + 30 files changed, 313 insertions(+), 210 deletions(-) diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 314a4057879e..a95cda0e387f 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -197,21 +197,8 @@ static const struct iio_info accel_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index b11f214779a2..a6f4fc5f8201 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -91,7 +91,6 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *buffer = indio_dev->buffer; struct ad7266_state *st = iio_priv(indio_dev); int ret; @@ -99,7 +98,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p) if (ret == 0) { if (indio_dev->scan_timestamp) ((s64 *)st->data)[1] = pf->timestamp; - iio_push_to_buffer(buffer, (u8 *)st->data); + iio_push_to_buffers(indio_dev, (u8 *)st->data); } iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c index 7f2f45a0a48d..330248bfebae 100644 --- a/drivers/iio/adc/ad7476.c +++ b/drivers/iio/adc/ad7476.c @@ -76,7 +76,7 @@ static irqreturn_t ad7476_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) ((s64 *)st->data)[1] = time_ns; - iio_push_to_buffer(indio_dev->buffer, st->data); + iio_push_to_buffers(indio_dev, st->data); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c index fd62309b4d3d..81153fafac7a 100644 --- a/drivers/iio/adc/ad7887.c +++ b/drivers/iio/adc/ad7887.c @@ -134,7 +134,7 @@ static irqreturn_t ad7887_trigger_handler(int irq, void *p) memcpy(st->data + indio_dev->scan_bytes - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, st->data); + iio_push_to_buffers(indio_dev, st->data); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index 67baa1363d7a..afe6d78c8ff0 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -391,7 +391,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p) break; } - iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data); + iio_push_to_buffers(indio_dev, (uint8_t *)data); iio_trigger_notify_done(indio_dev->trig); sigma_delta->irq_dis = false; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 2e2c9a80aa37..03b85940f4ba 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -65,7 +65,6 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *idev = pf->indio_dev; struct at91_adc_state *st = iio_priv(idev); - struct iio_buffer *buffer = idev->buffer; int i, j = 0; for (i = 0; i < idev->masklength; i++) { @@ -81,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - iio_push_to_buffer(buffer, st->buffer); + iio_push_to_buffers(indio_dev, (u8 *)st->buffer); iio_trigger_notify_done(idev->trig); diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 4c56ada51c39..02ef989b830d 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -197,21 +197,8 @@ static const struct iio_info gyro_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index 722a83fd8d85..aaadd32f9f0d 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -31,6 +31,18 @@ static const char * const iio_endian_prefix[] = { [IIO_LE] = "le", }; +static bool iio_buffer_is_active(struct iio_dev *indio_dev, + struct iio_buffer *buf) +{ + struct list_head *p; + + list_for_each(p, &indio_dev->buffer_list) + if (p == &buf->buffer_list) + return true; + + return false; +} + /** * iio_buffer_read_first_n_outer() - chrdev read for buffer access * @@ -134,7 +146,7 @@ static ssize_t iio_scan_el_store(struct device *dev, if (ret < 0) return ret; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; goto error_ret; } @@ -180,12 +192,11 @@ static ssize_t iio_scan_el_ts_store(struct device *dev, return ret; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; goto error_ret; } indio_dev->buffer->scan_timestamp = state; - indio_dev->scan_timestamp = state; error_ret: mutex_unlock(&indio_dev->mlock); @@ -385,7 +396,7 @@ ssize_t iio_buffer_write_length(struct device *dev, return len; mutex_lock(&indio_dev->mlock); - if (iio_buffer_enabled(indio_dev)) { + if (iio_buffer_is_active(indio_dev, indio_dev->buffer)) { ret = -EBUSY; } else { if (buffer->access->set_length) @@ -398,102 +409,14 @@ ssize_t iio_buffer_write_length(struct device *dev, } EXPORT_SYMBOL(iio_buffer_write_length); -ssize_t iio_buffer_store_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - int ret; - bool requested_state, current_state; - int previous_mode; - struct iio_dev *indio_dev = dev_to_iio_dev(dev); - struct iio_buffer *buffer = indio_dev->buffer; - - mutex_lock(&indio_dev->mlock); - previous_mode = indio_dev->currentmode; - requested_state = !(buf[0] == '0'); - current_state = iio_buffer_enabled(indio_dev); - if (current_state == requested_state) { - printk(KERN_INFO "iio-buffer, current state requested again\n"); - goto done; - } - if (requested_state) { - if (indio_dev->setup_ops->preenable) { - ret = indio_dev->setup_ops->preenable(indio_dev); - if (ret) { - printk(KERN_ERR - "Buffer not started: " - "buffer preenable failed\n"); - goto error_ret; - } - } - if (buffer->access->request_update) { - ret = buffer->access->request_update(buffer); - if (ret) { - printk(KERN_INFO - "Buffer not started: " - "buffer parameter update failed\n"); - goto error_ret; - } - } - /* Definitely possible for devices to support both of these. */ - if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { - if (!indio_dev->trig) { - printk(KERN_INFO - "Buffer not started: no trigger\n"); - ret = -EINVAL; - goto error_ret; - } - indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; - } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) - indio_dev->currentmode = INDIO_BUFFER_HARDWARE; - else { /* should never be reached */ - ret = -EINVAL; - goto error_ret; - } - - if (indio_dev->setup_ops->postenable) { - ret = indio_dev->setup_ops->postenable(indio_dev); - if (ret) { - printk(KERN_INFO - "Buffer not started: " - "postenable failed\n"); - indio_dev->currentmode = previous_mode; - if (indio_dev->setup_ops->postdisable) - indio_dev->setup_ops-> - postdisable(indio_dev); - goto error_ret; - } - } - } else { - if (indio_dev->setup_ops->predisable) { - ret = indio_dev->setup_ops->predisable(indio_dev); - if (ret) - goto error_ret; - } - indio_dev->currentmode = INDIO_DIRECT_MODE; - if (indio_dev->setup_ops->postdisable) { - ret = indio_dev->setup_ops->postdisable(indio_dev); - if (ret) - goto error_ret; - } - } -done: - mutex_unlock(&indio_dev->mlock); - return len; - -error_ret: - mutex_unlock(&indio_dev->mlock); - return ret; -} -EXPORT_SYMBOL(iio_buffer_store_enable); - ssize_t iio_buffer_show_enable(struct device *dev, struct device_attribute *attr, char *buf) { struct iio_dev *indio_dev = dev_to_iio_dev(dev); - return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev)); + return sprintf(buf, "%d\n", + iio_buffer_is_active(indio_dev, + indio_dev->buffer)); } EXPORT_SYMBOL(iio_buffer_show_enable); @@ -537,35 +460,220 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask, return bytes; } -int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +int iio_update_buffers(struct iio_dev *indio_dev, + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer) { - struct iio_buffer *buffer = indio_dev->buffer; - dev_dbg(&indio_dev->dev, "%s\n", __func__); + int ret; + int success = 0; + struct iio_buffer *buffer; + unsigned long *compound_mask; + const unsigned long *old_mask; - /* How much space will the demuxed element take? */ - indio_dev->scan_bytes = - iio_compute_scan_bytes(indio_dev, buffer->scan_mask, - buffer->scan_timestamp); - buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes); + /* Wind down existing buffers - iff there are any */ + if (!list_empty(&indio_dev->buffer_list)) { + if (indio_dev->setup_ops->predisable) { + ret = indio_dev->setup_ops->predisable(indio_dev); + if (ret) + goto error_ret; + } + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) { + ret = indio_dev->setup_ops->postdisable(indio_dev); + if (ret) + goto error_ret; + } + } + /* Keep a copy of current setup to allow roll back */ + old_mask = indio_dev->active_scan_mask; + if (!indio_dev->available_scan_masks) + indio_dev->active_scan_mask = NULL; + + if (remove_buffer) + list_del(&remove_buffer->buffer_list); + if (insert_buffer) + list_add(&insert_buffer->buffer_list, &indio_dev->buffer_list); + + /* If no buffers in list, we are done */ + if (list_empty(&indio_dev->buffer_list)) { + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->available_scan_masks == NULL) + kfree(old_mask); + return 0; + } /* What scan mask do we actually have ?*/ - if (indio_dev->available_scan_masks) + compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), + sizeof(long), GFP_KERNEL); + if (compound_mask == NULL) { + if (indio_dev->available_scan_masks == NULL) + kfree(old_mask); + return -ENOMEM; + } + indio_dev->scan_timestamp = 0; + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + bitmap_or(compound_mask, compound_mask, buffer->scan_mask, + indio_dev->masklength); + indio_dev->scan_timestamp |= buffer->scan_timestamp; + } + if (indio_dev->available_scan_masks) { indio_dev->active_scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, indio_dev->masklength, - buffer->scan_mask); - else - indio_dev->active_scan_mask = buffer->scan_mask; - - if (indio_dev->active_scan_mask == NULL) - return -EINVAL; + compound_mask); + if (indio_dev->active_scan_mask == NULL) { + /* + * Roll back. + * Note can only occur when adding a buffer. + */ + list_del(&insert_buffer->buffer_list); + indio_dev->active_scan_mask = old_mask; + success = -EINVAL; + } + } else { + indio_dev->active_scan_mask = compound_mask; + } iio_update_demux(indio_dev); - if (indio_dev->info->update_scan_mode) - return indio_dev->info + /* Wind up again */ + if (indio_dev->setup_ops->preenable) { + ret = indio_dev->setup_ops->preenable(indio_dev); + if (ret) { + printk(KERN_ERR + "Buffer not started:" + "buffer preenable failed\n"); + goto error_remove_inserted; + } + } + indio_dev->scan_bytes = + iio_compute_scan_bytes(indio_dev, + indio_dev->active_scan_mask, + indio_dev->scan_timestamp); + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + if (buffer->access->request_update) { + ret = buffer->access->request_update(buffer); + if (ret) { + printk(KERN_INFO + "Buffer not started:" + "buffer parameter update failed\n"); + goto error_run_postdisable; + } + } + if (indio_dev->info->update_scan_mode) { + ret = indio_dev->info ->update_scan_mode(indio_dev, indio_dev->active_scan_mask); + if (ret < 0) { + printk(KERN_INFO "update scan mode failed\n"); + goto error_run_postdisable; + } + } + /* Definitely possible for devices to support both of these.*/ + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) { + if (!indio_dev->trig) { + printk(KERN_INFO "Buffer not started: no trigger\n"); + ret = -EINVAL; + /* Can only occur on first buffer */ + goto error_run_postdisable; + } + indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; + } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) { + indio_dev->currentmode = INDIO_BUFFER_HARDWARE; + } else { /* should never be reached */ + ret = -EINVAL; + goto error_run_postdisable; + } + + if (indio_dev->setup_ops->postenable) { + ret = indio_dev->setup_ops->postenable(indio_dev); + if (ret) { + printk(KERN_INFO + "Buffer not started: postenable failed\n"); + indio_dev->currentmode = INDIO_DIRECT_MODE; + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops->postdisable(indio_dev); + goto error_disable_all_buffers; + } + } + + if (indio_dev->available_scan_masks) + kfree(compound_mask); + else + kfree(old_mask); + + return success; + +error_disable_all_buffers: + indio_dev->currentmode = INDIO_DIRECT_MODE; +error_run_postdisable: + if (indio_dev->setup_ops->postdisable) + indio_dev->setup_ops->postdisable(indio_dev); +error_remove_inserted: + + if (insert_buffer) + list_del(&insert_buffer->buffer_list); + indio_dev->active_scan_mask = old_mask; + kfree(compound_mask); +error_ret: + + return ret; +} +EXPORT_SYMBOL_GPL(iio_update_buffers); + +ssize_t iio_buffer_store_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + int ret; + bool requested_state; + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct iio_buffer *pbuf = indio_dev->buffer; + bool inlist; + + ret = strtobool(buf, &requested_state); + if (ret < 0) + return ret; + + mutex_lock(&indio_dev->mlock); + + /* Find out if it is in the list */ + inlist = iio_buffer_is_active(indio_dev, pbuf); + /* Already in desired state */ + if (inlist == requested_state) + goto done; + + if (requested_state) + ret = iio_update_buffers(indio_dev, + indio_dev->buffer, NULL); + else + ret = iio_update_buffers(indio_dev, + NULL, indio_dev->buffer); + + if (ret < 0) + goto done; +done: + mutex_unlock(&indio_dev->mlock); + return (ret < 0) ? ret : len; +} +EXPORT_SYMBOL(iio_buffer_store_enable); + +int iio_sw_buffer_preenable(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + unsigned bytes; + dev_dbg(&indio_dev->dev, "%s\n", __func__); + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + if (buffer->access->set_bytes_per_datum) { + bytes = iio_compute_scan_bytes(indio_dev, + buffer->scan_mask, + buffer->scan_timestamp); + + buffer->access->set_bytes_per_datum(buffer, bytes); + } return 0; } EXPORT_SYMBOL(iio_sw_buffer_preenable); @@ -599,7 +707,11 @@ static bool iio_validate_scan_mask(struct iio_dev *indio_dev, * iio_scan_mask_set() - set particular bit in the scan mask * @buffer: the buffer whose scan mask we are interested in * @bit: the bit to be set. - **/ + * + * Note that at this point we have no way of knowing what other + * buffers might request, hence this code only verifies that the + * individual buffers request is plausible. + */ int iio_scan_mask_set(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit) { @@ -682,13 +794,12 @@ static unsigned char *iio_demux(struct iio_buffer *buffer, return buffer->demux_bounce; } -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) +static int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data) { unsigned char *dataout = iio_demux(buffer, data); return buffer->access->store_to(buffer, dataout); } -EXPORT_SYMBOL_GPL(iio_push_to_buffer); static void iio_buffer_demux_free(struct iio_buffer *buffer) { @@ -699,10 +810,26 @@ static void iio_buffer_demux_free(struct iio_buffer *buffer) } } -int iio_update_demux(struct iio_dev *indio_dev) + +int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data) +{ + int ret; + struct iio_buffer *buf; + + list_for_each_entry(buf, &indio_dev->buffer_list, buffer_list) { + ret = iio_push_to_buffer(buf, data); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(iio_push_to_buffers); + +static int iio_buffer_update_demux(struct iio_dev *indio_dev, + struct iio_buffer *buffer) { const struct iio_chan_spec *ch; - struct iio_buffer *buffer = indio_dev->buffer; int ret, in_ind = -1, out_ind, length; unsigned in_loc = 0, out_loc = 0; struct iio_demux_table *p; @@ -787,4 +914,23 @@ int iio_update_demux(struct iio_dev *indio_dev) return ret; } + +int iio_update_demux(struct iio_dev *indio_dev) +{ + struct iio_buffer *buffer; + int ret; + + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { + ret = iio_buffer_update_demux(indio_dev, buffer); + if (ret < 0) + goto error_clear_mux_table; + } + return 0; + +error_clear_mux_table: + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) + iio_buffer_demux_free(buffer); + + return ret; +} EXPORT_SYMBOL_GPL(iio_update_demux); diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index cd700368eed0..060a4045be85 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -856,6 +856,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv) return NULL; } dev_set_name(&dev->dev, "iio:device%d", dev->id); + INIT_LIST_HEAD(&dev->buffer_list); } return dev; diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c index 164b62b91a4b..36d210a06b28 100644 --- a/drivers/iio/light/adjd_s311.c +++ b/drivers/iio/light/adjd_s311.c @@ -164,7 +164,6 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adjd_s311_data *data = iio_priv(indio_dev); - struct iio_buffer *buffer = indio_dev->buffer; s64 time_ns = iio_get_time_ns(); int len = 0; int i, j = 0; @@ -187,7 +186,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64))) = time_ns; - iio_push_to_buffer(buffer, (u8 *)data->buffer); + iio_push_to_buffers(indio_dev, (u8 *)data->buffer); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 96e3691e42c4..8e1f69844eea 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -176,21 +176,8 @@ static const struct iio_info als_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index c4f0d274f577..d1b5fb74b9bf 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -198,21 +198,8 @@ static const struct iio_info magn_3d_info = { /* Function to push data to buffer */ static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len) { - struct iio_buffer *buffer = indio_dev->buffer; - int datum_sz; - dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n"); - if (!buffer) { - dev_err(&indio_dev->dev, "Buffer == NULL\n"); - return; - } - datum_sz = buffer->access->get_bytes_per_datum(buffer); - if (len > datum_sz) { - dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len, - datum_sz); - return; - } - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); } /* Callback handler to send event after all samples are received and captured */ diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c index 97c09f0c26ae..e14ca60092a2 100644 --- a/drivers/staging/iio/accel/adis16201_ring.c +++ b/drivers/staging/iio/accel/adis16201_ring.c @@ -82,7 +82,7 @@ static irqreturn_t adis16201_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c index 7507e1a04591..eba2e285c84a 100644 --- a/drivers/staging/iio/accel/adis16203_ring.c +++ b/drivers/staging/iio/accel/adis16203_ring.c @@ -81,7 +81,7 @@ static irqreturn_t adis16203_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c index 4c976bec986b..3611a13836c9 100644 --- a/drivers/staging/iio/accel/adis16204_ring.c +++ b/drivers/staging/iio/accel/adis16204_ring.c @@ -78,7 +78,7 @@ static irqreturn_t adis16204_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c index f939e29d6c82..6af9a5dbc709 100644 --- a/drivers/staging/iio/accel/adis16209_ring.c +++ b/drivers/staging/iio/accel/adis16209_ring.c @@ -78,7 +78,7 @@ static irqreturn_t adis16209_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c index caff8e25e0a2..e2ac8a8c8107 100644 --- a/drivers/staging/iio/accel/adis16240_ring.c +++ b/drivers/staging/iio/accel/adis16240_ring.c @@ -76,7 +76,7 @@ static irqreturn_t adis16240_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c index 246352716537..bc38651c315e 100644 --- a/drivers/staging/iio/accel/lis3l02dq_ring.c +++ b/drivers/staging/iio/accel/lis3l02dq_ring.c @@ -154,7 +154,7 @@ static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c index c2906a85fedb..b3dd514b9627 100644 --- a/drivers/staging/iio/adc/ad7298_ring.c +++ b/drivers/staging/iio/adc/ad7298_ring.c @@ -93,7 +93,7 @@ static irqreturn_t ad7298_trigger_handler(int irq, void *p) indio_dev->masklength); i++) buf[i] = be16_to_cpu(st->rx_buf[i]); - iio_push_to_buffer(indio_dev->buffer, (u8 *)buf); + iio_push_to_buffers(indio_dev, (u8 *)buf); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c index ba04d0ffd4f4..2b25cb07fe41 100644 --- a/drivers/staging/iio/adc/ad7606_ring.c +++ b/drivers/staging/iio/adc/ad7606_ring.c @@ -83,7 +83,7 @@ static void ad7606_poll_bh_to_ring(struct work_struct *work_s) if (indio_dev->scan_timestamp) *((s64 *)(buf + indio_dev->scan_bytes - sizeof(s64))) = time_ns; - iio_push_to_buffer(indio_dev->buffer, buf); + iio_push_to_buffers(indio_dev, buf); done: gpio_set_value(st->pdata->gpio_convst, 0); iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c index 86026d9b20bc..2c5f38475a8e 100644 --- a/drivers/staging/iio/adc/ad799x_ring.c +++ b/drivers/staging/iio/adc/ad799x_ring.c @@ -77,7 +77,7 @@ static irqreturn_t ad799x_trigger_handler(int irq, void *p) memcpy(rxbuf + indio_dev->scan_bytes - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, rxbuf); + iio_push_to_buffers(indio_dev, rxbuf); done: kfree(rxbuf); out: diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index 5f74f3b7671a..688304bdbaf0 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -80,7 +80,7 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffer(indio_dev->buffer, rxbuf); + iio_push_to_buffers(indio_dev, rxbuf); done_free: kfree(rxbuf); diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index df5bba284b73..3b467d8c5882 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c @@ -237,7 +237,6 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *iio = pf->indio_dev; struct mxs_lradc *lradc = iio_priv(iio); - struct iio_buffer *buffer = iio->buffer; const uint32_t chan_value = LRADC_CH_ACCUMULATE | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); int i, j = 0; @@ -256,7 +255,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) *timestamp = pf->timestamp; } - iio_push_to_buffer(buffer, (u8 *)lradc->buffer); + iio_push_to_buffers(iio, (u8 *)lradc->buffer); iio_trigger_notify_done(iio->trig); diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c index e294cb49736d..d6c48f850a9e 100644 --- a/drivers/staging/iio/gyro/adis16260_ring.c +++ b/drivers/staging/iio/gyro/adis16260_ring.c @@ -81,7 +81,7 @@ static irqreturn_t adis16260_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); done: diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c index 697d9700db2f..dee16f0e7570 100644 --- a/drivers/staging/iio/iio_simple_dummy_buffer.c +++ b/drivers/staging/iio/iio_simple_dummy_buffer.c @@ -46,7 +46,6 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - struct iio_buffer *buffer = indio_dev->buffer; int len = 0; u16 *data; @@ -76,7 +75,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) i < bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); i++, j++) { - j = find_next_bit(buffer->scan_mask, + j = find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, j); /* random access read from the 'device' */ data[i] = fakedata[j]; @@ -87,7 +86,7 @@ static irqreturn_t iio_simple_dummy_trigger_h(int irq, void *p) if (indio_dev->scan_timestamp) *(s64 *)((u8 *)data + ALIGN(len, sizeof(s64))) = iio_get_time_ns(); - iio_push_to_buffer(buffer, (u8 *)data); + iio_push_to_buffers(indio_dev, (u8 *)data); kfree(data); diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c index de21d47f33e9..b1fef147d5b5 100644 --- a/drivers/staging/iio/impedance-analyzer/ad5933.c +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c @@ -647,7 +647,6 @@ static void ad5933_work(struct work_struct *work) struct ad5933_state *st = container_of(work, struct ad5933_state, work.work); struct iio_dev *indio_dev = i2c_get_clientdata(st->client); - struct iio_buffer *ring = indio_dev->buffer; signed short buf[2]; unsigned char status; @@ -677,8 +676,7 @@ static void ad5933_work(struct work_struct *work) } else { buf[0] = be16_to_cpu(buf[0]); } - /* save datum to the ring */ - iio_push_to_buffer(ring, (u8 *)buf); + iio_push_to_buffers(indio_dev, (u8 *)buf); } else { /* no data available - try again later */ schedule_delayed_work(&st->work, st->poll_time_jiffies); diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c index 260bdd1a4681..d46c1e38cf7b 100644 --- a/drivers/staging/iio/imu/adis16400_ring.c +++ b/drivers/staging/iio/imu/adis16400_ring.c @@ -114,7 +114,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct adis16400_state *st = iio_priv(indio_dev); - struct iio_buffer *ring = indio_dev->buffer; int i = 0, j, ret = 0; s16 *data; @@ -148,9 +147,9 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) } } /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) + if (indio_dev->scan_timestamp) *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; - iio_push_to_buffer(ring, (u8 *) data); + iio_push_to_buffers(indio_dev, (u8 *) data); done: kfree(data); diff --git a/drivers/staging/iio/meter/ade7758_ring.c b/drivers/staging/iio/meter/ade7758_ring.c index 9e49baccf660..4552a4c7fe33 100644 --- a/drivers/staging/iio/meter/ade7758_ring.c +++ b/drivers/staging/iio/meter/ade7758_ring.c @@ -73,7 +73,7 @@ static irqreturn_t ade7758_trigger_handler(int irq, void *p) if (indio_dev->scan_timestamp) dat64[1] = pf->timestamp; - iio_push_to_buffer(indio_dev->buffer, (u8 *)dat64); + iio_push_to_buffers(indio_dev, (u8 *)dat64); iio_trigger_notify_done(indio_dev->trig); diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h index c629b3a1d9a9..027040569180 100644 --- a/include/linux/iio/buffer.h +++ b/include/linux/iio/buffer.h @@ -66,7 +66,8 @@ struct iio_buffer_access_funcs { * @stufftoread: [INTERN] flag to indicate new data. * @demux_list: [INTERN] list of operations required to demux the scan. * @demux_bounce: [INTERN] buffer for doing gather from incoming scan. - **/ + * @buffer_list: [INTERN] entry in the devices list of current buffers. + */ struct iio_buffer { int length; int bytes_per_datum; @@ -81,8 +82,21 @@ struct iio_buffer { const struct attribute_group *attrs; struct list_head demux_list; unsigned char *demux_bounce; + struct list_head buffer_list; }; +/** + * iio_update_buffers() - add or remove buffer from active list + * @indio_dev: device to add buffer to + * @insert_buffer: buffer to insert + * @remove_buffer: buffer_to_remove + * + * Note this will tear down the all buffering and build it up again + */ +int iio_update_buffers(struct iio_dev *indio_dev, + struct iio_buffer *insert_buffer, + struct iio_buffer *remove_buffer); + /** * iio_buffer_init() - Initialize the buffer structure * @buffer: buffer to be initialized @@ -115,11 +129,11 @@ int iio_scan_mask_set(struct iio_dev *indio_dev, struct iio_buffer *buffer, int bit); /** - * iio_push_to_buffer() - push to a registered buffer. - * @buffer: IIO buffer structure for device - * @data: the data to push to the buffer + * iio_push_to_buffers() - push to a registered buffer. + * @indio_dev: iio_dev structure for device. + * @data: Full scan. */ -int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data); +int iio_push_to_buffers(struct iio_dev *indio_dev, unsigned char *data); int iio_update_demux(struct iio_dev *indio_dev); diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 7806c24e5bc8..adca93a999a7 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -410,6 +410,7 @@ struct iio_buffer_setup_ops { * and owner * @event_interface: [INTERN] event chrdevs associated with interrupt lines * @buffer: [DRIVER] any buffer present + * @buffer_list: [INTERN] list of all buffers currently attached * @scan_bytes: [INTERN] num bytes captured to be fed to buffer demux * @mlock: [INTERN] lock used to prevent simultaneous device state * changes @@ -448,6 +449,7 @@ struct iio_dev { struct iio_event_interface *event_interface; struct iio_buffer *buffer; + struct list_head buffer_list; int scan_bytes; struct mutex mlock; From 0464415dd21785aa8e8b12dbc939fcb5ca52f464 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 30 Jun 2012 20:06:00 +0100 Subject: [PATCH 09/17] staging:iio:in kernel users: Add a data field for channel specific info. Used to allow information about a given channel mapping to be passed through from board files to the consumer drivers. Signed-off-by: Jonathan Cameron --- drivers/iio/inkern.c | 1 + include/linux/iio/consumer.h | 2 ++ include/linux/iio/machine.h | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index b394621d362c..d55e98fb300e 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -203,6 +203,7 @@ struct iio_channel *iio_channel_get_all(const char *name) if (name && strcmp(name, c->map->consumer_dev_name) != 0) continue; chans[mapind].indio_dev = c->indio_dev; + chans[mapind].data = c->map->consumer_data; chans[mapind].channel = iio_chan_spec_from_name(chans[mapind].indio_dev, c->map->adc_channel_label); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index e875bcf0478f..57efee63a6da 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -18,10 +18,12 @@ struct iio_chan_spec; * struct iio_channel - everything needed for a consumer to use a channel * @indio_dev: Device on which the channel exists. * @channel: Full description of the channel. + * @data: Data about the channel used by consumer. */ struct iio_channel { struct iio_dev *indio_dev; const struct iio_chan_spec *channel; + void *data; }; /** diff --git a/include/linux/iio/machine.h b/include/linux/iio/machine.h index 809a3f08d5a5..1601a2a63a72 100644 --- a/include/linux/iio/machine.h +++ b/include/linux/iio/machine.h @@ -19,11 +19,13 @@ * @consumer_dev_name: Name to uniquely identify the consumer device. * @consumer_channel: Unique name used to identify the channel on the * consumer side. + * @consumer_data: Data about the channel for use by the consumer driver. */ struct iio_map { const char *adc_channel_label; const char *consumer_dev_name; const char *consumer_channel; + void *consumer_data; }; #endif From 92d1079b281f89f1c65c6aece3cfab4fb422c797 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 30 Jun 2012 20:06:00 +0100 Subject: [PATCH 10/17] staging:iio: add a callback buffer for in kernel push interface This callback buffer is meant to be opaque to users, but basically adds a very simple pass through buffer to which data may be pushed when it is inserted into the buffer list. Signed-off-by: Jonathan Cameron --- drivers/iio/Kconfig | 6 ++ drivers/iio/Makefile | 1 + drivers/iio/buffer_cb.c | 113 +++++++++++++++++++++++++++++++++++ include/linux/iio/consumer.h | 46 ++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 drivers/iio/buffer_cb.c diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig index fc937aca71fb..65ae734c607d 100644 --- a/drivers/iio/Kconfig +++ b/drivers/iio/Kconfig @@ -20,6 +20,12 @@ config IIO_BUFFER if IIO_BUFFER +config IIO_BUFFER_CB +boolean "IIO callback buffer used for push in-kernel interfaces" + help + Should be selected by any drivers that do-inkernel push + usage. That is, those where the data is pushed to the consumer. + config IIO_KFIFO_BUF select IIO_TRIGGER tristate "Industrial I/O buffering based on kfifo" diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile index 761f2b65ac52..31d76a07ec65 100644 --- a/drivers/iio/Makefile +++ b/drivers/iio/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_IIO) += industrialio.o industrialio-y := industrialio-core.o industrialio-event.o inkern.o industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o +industrialio-$(CONFIG_IIO_BUFFER_CB) += buffer_cb.o obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o diff --git a/drivers/iio/buffer_cb.c b/drivers/iio/buffer_cb.c new file mode 100644 index 000000000000..4d40e24f3721 --- /dev/null +++ b/drivers/iio/buffer_cb.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include + +struct iio_cb_buffer { + struct iio_buffer buffer; + int (*cb)(u8 *data, void *private); + void *private; + struct iio_channel *channels; +}; + +static int iio_buffer_cb_store_to(struct iio_buffer *buffer, u8 *data) +{ + struct iio_cb_buffer *cb_buff = container_of(buffer, + struct iio_cb_buffer, + buffer); + + return cb_buff->cb(data, cb_buff->private); +} + +static struct iio_buffer_access_funcs iio_cb_access = { + .store_to = &iio_buffer_cb_store_to, +}; + +struct iio_cb_buffer *iio_channel_get_all_cb(const char *name, + int (*cb)(u8 *data, + void *private), + void *private) +{ + int ret; + struct iio_cb_buffer *cb_buff; + struct iio_dev *indio_dev; + struct iio_channel *chan; + + cb_buff = kzalloc(sizeof(*cb_buff), GFP_KERNEL); + if (cb_buff == NULL) { + ret = -ENOMEM; + goto error_ret; + } + + cb_buff->private = private; + cb_buff->cb = cb; + cb_buff->buffer.access = &iio_cb_access; + INIT_LIST_HEAD(&cb_buff->buffer.demux_list); + + cb_buff->channels = iio_channel_get_all(name); + if (IS_ERR(cb_buff->channels)) { + ret = PTR_ERR(cb_buff->channels); + goto error_free_cb_buff; + } + + indio_dev = cb_buff->channels[0].indio_dev; + cb_buff->buffer.scan_mask + = kcalloc(BITS_TO_LONGS(indio_dev->masklength), sizeof(long), + GFP_KERNEL); + if (cb_buff->buffer.scan_mask == NULL) { + ret = -ENOMEM; + goto error_release_channels; + } + chan = &cb_buff->channels[0]; + while (chan->indio_dev) { + if (chan->indio_dev != indio_dev) { + ret = -EINVAL; + goto error_release_channels; + } + set_bit(chan->channel->scan_index, + cb_buff->buffer.scan_mask); + chan++; + } + + return cb_buff; + +error_release_channels: + iio_channel_release_all(cb_buff->channels); +error_free_cb_buff: + kfree(cb_buff); +error_ret: + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(iio_channel_get_all_cb); + +int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff) +{ + return iio_update_buffers(cb_buff->channels[0].indio_dev, + &cb_buff->buffer, + NULL); +} +EXPORT_SYMBOL_GPL(iio_channel_start_all_cb); + +void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff) +{ + iio_update_buffers(cb_buff->channels[0].indio_dev, + NULL, + &cb_buff->buffer); +} +EXPORT_SYMBOL_GPL(iio_channel_stop_all_cb); + +void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buff) +{ + iio_channel_release_all(cb_buff->channels); + kfree(cb_buff); +} +EXPORT_SYMBOL_GPL(iio_channel_release_all_cb); + +struct iio_channel +*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer) +{ + return cb_buffer->channels; +} +EXPORT_SYMBOL_GPL(iio_channel_cb_get_channels); diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index 57efee63a6da..126c0a9375f2 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -61,6 +61,52 @@ struct iio_channel *iio_channel_get_all(const char *name); */ void iio_channel_release_all(struct iio_channel *chan); +struct iio_cb_buffer; +/** + * iio_channel_get_all_cb() - register callback for triggered capture + * @name: Name of client device. + * @cb: Callback function. + * @private: Private data passed to callback. + * + * NB right now we have no ability to mux data from multiple devices. + * So if the channels requested come from different devices this will + * fail. + */ +struct iio_cb_buffer *iio_channel_get_all_cb(const char *name, + int (*cb)(u8 *data, + void *private), + void *private); +/** + * iio_channel_release_all_cb() - release and unregister the callback. + * @cb_buffer: The callback buffer that was allocated. + */ +void iio_channel_release_all_cb(struct iio_cb_buffer *cb_buffer); + +/** + * iio_channel_start_all_cb() - start the flow of data through callback. + * @cb_buff: The callback buffer we are starting. + */ +int iio_channel_start_all_cb(struct iio_cb_buffer *cb_buff); + +/** + * iio_channel_stop_all_cb() - stop the flow of data through the callback. + * @cb_buff: The callback buffer we are stopping. + */ +void iio_channel_stop_all_cb(struct iio_cb_buffer *cb_buff); + +/** + * iio_channel_cb_get_channels() - get access to the underlying channels. + * @cb_buff: The callback buffer from whom we want the channel + * information. + * + * This function allows one to obtain information about the channels. + * Whilst this may allow direct reading if all buffers are disabled, the + * primary aim is to allow drivers that are consuming a channel to query + * things like scaling of the channel. + */ +struct iio_channel +*iio_channel_cb_get_channels(const struct iio_cb_buffer *cb_buffer); + /** * iio_read_channel_raw() - read from a given channel * @chan: The channel being queried. From 0d331e4fd26c6caafa27ff4048294b2bb9263b2a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 19 May 2012 15:27:51 +0100 Subject: [PATCH 11/17] staging:iio:adc:max1363 ring_sw->kfifo conversion We are moving towards scrapping ring_sw so this move is necessary. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 2 +- drivers/staging/iio/adc/max1363_ring.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index eba64fb64d82..e662a5c55b55 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -149,7 +149,7 @@ config MAX1363_RING_BUFFER bool "Maxim max1363: use ring buffer" depends on MAX1363 select IIO_BUFFER - select IIO_SW_RING + select IIO_KFIFO_BUF help Say yes here to include ring buffer support in the MAX1363 ADC driver. diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c index 688304bdbaf0..41af17b5e74f 100644 --- a/drivers/staging/iio/adc/max1363_ring.c +++ b/drivers/staging/iio/adc/max1363_ring.c @@ -16,7 +16,7 @@ #include #include -#include "../ring_sw.h" +#include #include #include "max1363.h" @@ -101,7 +101,7 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) struct max1363_state *st = iio_priv(indio_dev); int ret = 0; - indio_dev->buffer = iio_sw_rb_allocate(indio_dev); + indio_dev->buffer = iio_kfifo_allocate(indio_dev); if (!indio_dev->buffer) { ret = -ENOMEM; goto error_ret; @@ -126,7 +126,7 @@ int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) return 0; error_deallocate_sw_rb: - iio_sw_rb_free(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); error_ret: return ret; } @@ -135,5 +135,5 @@ void max1363_ring_cleanup(struct iio_dev *indio_dev) { /* ensure that the trigger has been detached */ iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->buffer); + iio_kfifo_free(indio_dev->buffer); } From b3bcbfcfece186f3a3799460aea3da30577615f9 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:10:05 +0100 Subject: [PATCH 12/17] staging:iio:adc:max1363 consolidate files. For a long while now the max1363 core has selected the buffer anyway. For a while I meant to make the separation work again, but given how long it has been it is probably time to conclude it will never happen and settle for tidying up what we have. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/Kconfig | 16 +- drivers/staging/iio/adc/Makefile | 3 - .../iio/adc/{max1363_core.c => max1363.c} | 267 +++++++++++++++++- drivers/staging/iio/adc/max1363.h | 177 ------------ drivers/staging/iio/adc/max1363_ring.c | 139 --------- 5 files changed, 269 insertions(+), 333 deletions(-) rename drivers/staging/iio/adc/{max1363_core.c => max1363.c} (83%) delete mode 100644 drivers/staging/iio/adc/max1363.h delete mode 100644 drivers/staging/iio/adc/max1363_ring.c diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index e662a5c55b55..4d348048b39d 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -133,8 +133,10 @@ config AD7280 config MAX1363 tristate "Maxim max1363 ADC driver" depends on I2C - select IIO_TRIGGER if IIO_BUFFER + select IIO_TRIGGER select MAX1363_RING_BUFFER + select IIO_BUFFER + select IIO_KFIFO_BUF help Say yes here to build support for many Maxim i2c analog to digital converters (ADC). (max1361, max1362, max1363, max1364, max1036, @@ -143,16 +145,8 @@ config MAX1363 max11602, max11603, max11604, max11605, max11606, max11607, max11608, max11609, max11610, max11611, max11612, max11613, max11614, max11615, max11616, max11617, max11644, max11645, - max11646, max11647) Provides direct access via sysfs. - -config MAX1363_RING_BUFFER - bool "Maxim max1363: use ring buffer" - depends on MAX1363 - select IIO_BUFFER - select IIO_KFIFO_BUF - help - Say yes here to include ring buffer support in the MAX1363 - ADC driver. + max11646, max11647) Provides direct access via sysfs and buffered + data via the iio dev interface. config LPC32XX_ADC tristate "NXP LPC32XX ADC" diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index c56b41ee285b..33979e62871b 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -2,9 +2,6 @@ # Makefile for industrial I/O ADC drivers # -max1363-y := max1363_core.o -max1363-y += max1363_ring.o - obj-$(CONFIG_MAX1363) += max1363.o ad7606-y := ad7606_core.o diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363.c similarity index 83% rename from drivers/staging/iio/adc/max1363_core.c rename to drivers/staging/iio/adc/max1363.c index d7b4ffcfa052..72715a4d5941 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363.c @@ -37,8 +37,152 @@ #include #include #include +#include +#include -#include "max1363.h" +#define MAX1363_SETUP_BYTE(a) ((a) | 0x80) + +/* There is a fair bit more defined here than currently + * used, but the intention is to support everything these + * chips do in the long run */ + +/* see data sheets */ +/* max1363 and max1236, max1237, max1238, max1239 */ +#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00 +#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20 +#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40 +#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60 +#define MAX1363_SETUP_POWER_UP_INT_REF 0x10 +#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00 + +/* think about includeing max11600 etc - more settings */ +#define MAX1363_SETUP_EXT_CLOCK 0x08 +#define MAX1363_SETUP_INT_CLOCK 0x00 +#define MAX1363_SETUP_UNIPOLAR 0x00 +#define MAX1363_SETUP_BIPOLAR 0x04 +#define MAX1363_SETUP_RESET 0x00 +#define MAX1363_SETUP_NORESET 0x02 +/* max1363 only - though don't care on others. + * For now monitor modes are not implemented as the relevant + * line is not connected on my test board. + * The definitions are here as I intend to add this soon. + */ +#define MAX1363_SETUP_MONITOR_SETUP 0x01 + +/* Specific to the max1363 */ +#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4)) +#define MAX1363_MON_INT_ENABLE 0x01 + +/* defined for readability reasons */ +/* All chips */ +#define MAX1363_CONFIG_BYTE(a) ((a)) + +#define MAX1363_CONFIG_SE 0x01 +#define MAX1363_CONFIG_DE 0x00 +#define MAX1363_CONFIG_SCAN_TO_CS 0x00 +#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20 +#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40 +#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60 +/* max123{6-9} only */ +#define MAX1236_SCAN_MID_TO_CHANNEL 0x40 + +/* max1363 only - merely part of channel selects or don't care for others*/ +#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18 + +#define MAX1363_CHANNEL_SEL(a) ((a) << 1) + +/* max1363 strictly 0x06 - but doesn't matter */ +#define MAX1363_CHANNEL_SEL_MASK 0x1E +#define MAX1363_SCAN_MASK 0x60 +#define MAX1363_SE_DE_MASK 0x01 + +#define MAX1363_MAX_CHANNELS 25 +/** + * struct max1363_mode - scan mode information + * @conf: The corresponding value of the configuration register + * @modemask: Bit mask corresponding to channels enabled in this mode + */ +struct max1363_mode { + int8_t conf; + DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS); +}; + +/* This must be maintained along side the max1363_mode_table in max1363_core */ +enum max1363_modes { + /* Single read of a single channel */ + _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, + /* Differential single read */ + d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, + d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, + /* Scan to channel and mid to channel where overlapping */ + s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6, + s6to7, s0to7, s6to8, s0to8, s6to9, + s0to9, s6to10, s0to10, s6to11, s0to11, + /* Differential scan to channel and mid to channel where overlapping */ + d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, + d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, + d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, + d7m6to11m10, d1m0to11m10, +}; + +/** + * struct max1363_chip_info - chip specifc information + * @name: indentification string for chip + * @bits: accuracy of the adc in bits + * @int_vref_mv: the internal reference voltage + * @info: iio core function callbacks structure + * @mode_list: array of available scan modes + * @num_modes: the number of scan modes available + * @default_mode: the scan mode in which the chip starts up + * @channel: channel specification + * @num_channels: number of channels + */ +struct max1363_chip_info { + const struct iio_info *info; + const struct iio_chan_spec *channels; + int num_channels; + const enum max1363_modes *mode_list; + enum max1363_modes default_mode; + u16 int_vref_mv; + u8 num_modes; + u8 bits; +}; + +/** + * struct max1363_state - driver instance specific data + * @client: i2c_client + * @setupbyte: cache of current device setup byte + * @configbyte: cache of current device config byte + * @chip_info: chip model specific constants, available modes etc + * @current_mode: the scan mode of this chip + * @requestedmask: a valid requested set of channels + * @reg: supply regulator + * @monitor_on: whether monitor mode is enabled + * @monitor_speed: parameter corresponding to device monitor speed setting + * @mask_high: bitmask for enabled high thresholds + * @mask_low: bitmask for enabled low thresholds + * @thresh_high: high threshold values + * @thresh_low: low threshold values + */ +struct max1363_state { + struct i2c_client *client; + u8 setupbyte; + u8 configbyte; + const struct max1363_chip_info *chip_info; + const struct max1363_mode *current_mode; + u32 requestedmask; + struct regulator *reg; + + /* Using monitor modes and buffer at the same time is + currently not supported */ + bool monitor_on; + unsigned int monitor_speed:3; + u8 mask_high; + u8 mask_low; + /* 4x unipolar first then the fours bipolar ones */ + s16 thresh_high[8]; + s16 thresh_low[8]; +}; #define MAX1363_MODE_SINGLE(_num, _mask) { \ .conf = MAX1363_CHANNEL_SEL(_num) \ @@ -148,7 +292,7 @@ static const struct max1363_mode max1363_mode_table[] = { MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000), }; -const struct max1363_mode +static const struct max1363_mode *max1363_match_mode(const unsigned long *mask, const struct max1363_chip_info *ci) { @@ -172,7 +316,7 @@ static int max1363_write_basic_config(struct i2c_client *client, return i2c_master_send(client, tx_buf, 2); } -int max1363_set_scan_mode(struct max1363_state *st) +static int max1363_set_scan_mode(struct max1363_state *st) { st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK | MAX1363_SCAN_MASK @@ -828,6 +972,21 @@ static struct attribute_group max1363_event_attribute_group = { #define MAX1363_EVENT_FUNCS \ +static int max1363_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct max1363_state *st = iio_priv(indio_dev); + + /* + * Need to figure out the current mode based upon the requested + * scan mask in iio_dev + */ + st->current_mode = max1363_match_mode(scan_mask, st->chip_info); + if (!st->current_mode) + return -EINVAL; + max1363_set_scan_mode(st); + return 0; +} static const struct iio_info max1238_info = { .read_raw = &max1363_read_raw, @@ -1269,6 +1428,108 @@ static int __devinit max1363_alloc_scan_masks(struct iio_dev *indio_dev) return 0; } + +static irqreturn_t max1363_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct max1363_state *st = iio_priv(indio_dev); + s64 time_ns; + __u8 *rxbuf; + int b_sent; + size_t d_size; + unsigned long numvals = bitmap_weight(st->current_mode->modemask, + MAX1363_MAX_CHANNELS); + + /* Ensure the timestamp is 8 byte aligned */ + if (st->chip_info->bits != 8) + d_size = numvals*2; + else + d_size = numvals; + if (indio_dev->scan_timestamp) { + d_size += sizeof(s64); + if (d_size % sizeof(s64)) + d_size += sizeof(s64) - (d_size % sizeof(s64)); + } + /* Monitor mode prevents reading. Whilst not currently implemented + * might as well have this test in here in the meantime as it does + * no harm. + */ + if (numvals == 0) + goto done; + + rxbuf = kmalloc(d_size, GFP_KERNEL); + if (rxbuf == NULL) + goto done; + if (st->chip_info->bits != 8) + b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); + else + b_sent = i2c_master_recv(st->client, rxbuf, numvals); + if (b_sent < 0) + goto done_free; + + time_ns = iio_get_time_ns(); + + if (indio_dev->scan_timestamp) + memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); + iio_push_to_buffers(indio_dev, rxbuf); + +done_free: + kfree(rxbuf); +done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static const struct iio_buffer_setup_ops max1363_ring_setup_ops = { + .postenable = &iio_triggered_buffer_postenable, + .preenable = &iio_sw_buffer_preenable, + .predisable = &iio_triggered_buffer_predisable, +}; + +static int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) +{ + struct max1363_state *st = iio_priv(indio_dev); + int ret = 0; + + indio_dev->buffer = iio_kfifo_allocate(indio_dev); + if (!indio_dev->buffer) { + ret = -ENOMEM; + goto error_ret; + } + indio_dev->pollfunc = iio_alloc_pollfunc(NULL, + &max1363_trigger_handler, + IRQF_ONESHOT, + indio_dev, + "%s_consumer%d", + st->client->name, + indio_dev->id); + if (indio_dev->pollfunc == NULL) { + ret = -ENOMEM; + goto error_deallocate_sw_rb; + } + /* Ring buffer functions - here trigger setup related */ + indio_dev->setup_ops = &max1363_ring_setup_ops; + + /* Flag that polled ring buffering is possible */ + indio_dev->modes |= INDIO_BUFFER_TRIGGERED; + + return 0; + +error_deallocate_sw_rb: + iio_kfifo_free(indio_dev->buffer); +error_ret: + return ret; +} + +static void max1363_ring_cleanup(struct iio_dev *indio_dev) +{ + /* ensure that the trigger has been detached */ + iio_dealloc_pollfunc(indio_dev->pollfunc); + iio_kfifo_free(indio_dev->buffer); +} + static int __devinit max1363_probe(struct i2c_client *client, const struct i2c_device_id *id) { diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h deleted file mode 100644 index c746918683f1..000000000000 --- a/drivers/staging/iio/adc/max1363.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef _MAX1363_H_ -#define _MAX1363_H_ - -#define MAX1363_SETUP_BYTE(a) ((a) | 0x80) - -/* There is a fair bit more defined here than currently - * used, but the intention is to support everything these - * chips do in the long run */ - -/* see data sheets */ -/* max1363 and max1236, max1237, max1238, max1239 */ -#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00 -#define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20 -#define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40 -#define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60 -#define MAX1363_SETUP_POWER_UP_INT_REF 0x10 -#define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00 - -/* think about includeing max11600 etc - more settings */ -#define MAX1363_SETUP_EXT_CLOCK 0x08 -#define MAX1363_SETUP_INT_CLOCK 0x00 -#define MAX1363_SETUP_UNIPOLAR 0x00 -#define MAX1363_SETUP_BIPOLAR 0x04 -#define MAX1363_SETUP_RESET 0x00 -#define MAX1363_SETUP_NORESET 0x02 -/* max1363 only - though don't care on others. - * For now monitor modes are not implemented as the relevant - * line is not connected on my test board. - * The definitions are here as I intend to add this soon. - */ -#define MAX1363_SETUP_MONITOR_SETUP 0x01 - -/* Specific to the max1363 */ -#define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4)) -#define MAX1363_MON_INT_ENABLE 0x01 - -/* defined for readability reasons */ -/* All chips */ -#define MAX1363_CONFIG_BYTE(a) ((a)) - -#define MAX1363_CONFIG_SE 0x01 -#define MAX1363_CONFIG_DE 0x00 -#define MAX1363_CONFIG_SCAN_TO_CS 0x00 -#define MAX1363_CONFIG_SCAN_SINGLE_8 0x20 -#define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40 -#define MAX1363_CONFIG_SCAN_SINGLE_1 0x60 -/* max123{6-9} only */ -#define MAX1236_SCAN_MID_TO_CHANNEL 0x40 - -/* max1363 only - merely part of channel selects or don't care for others*/ -#define MAX1363_CONFIG_EN_MON_MODE_READ 0x18 - -#define MAX1363_CHANNEL_SEL(a) ((a) << 1) - -/* max1363 strictly 0x06 - but doesn't matter */ -#define MAX1363_CHANNEL_SEL_MASK 0x1E -#define MAX1363_SCAN_MASK 0x60 -#define MAX1363_SE_DE_MASK 0x01 - -#define MAX1363_MAX_CHANNELS 25 -/** - * struct max1363_mode - scan mode information - * @conf: The corresponding value of the configuration register - * @modemask: Bit mask corresponding to channels enabled in this mode - */ -struct max1363_mode { - int8_t conf; - DECLARE_BITMAP(modemask, MAX1363_MAX_CHANNELS); -}; - -/* This must be maintained along side the max1363_mode_table in max1363_core */ -enum max1363_modes { - /* Single read of a single channel */ - _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, - /* Differential single read */ - d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, - d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, - /* Scan to channel and mid to channel where overlapping */ - s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6, - s6to7, s0to7, s6to8, s0to8, s6to9, - s0to9, s6to10, s0to10, s6to11, s0to11, - /* Differential scan to channel and mid to channel where overlapping */ - d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, - d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, - d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, - d7m6to11m10, d1m0to11m10, -}; - -/** - * struct max1363_chip_info - chip specifc information - * @name: indentification string for chip - * @bits: accuracy of the adc in bits - * @int_vref_mv: the internal reference voltage - * @info: iio core function callbacks structure - * @mode_list: array of available scan modes - * @num_modes: the number of scan modes available - * @default_mode: the scan mode in which the chip starts up - * @channel: channel specification - * @num_channels: number of channels - */ -struct max1363_chip_info { - const struct iio_info *info; - const struct iio_chan_spec *channels; - int num_channels; - const enum max1363_modes *mode_list; - enum max1363_modes default_mode; - u16 int_vref_mv; - u8 num_modes; - u8 bits; -}; - -/** - * struct max1363_state - driver instance specific data - * @client: i2c_client - * @setupbyte: cache of current device setup byte - * @configbyte: cache of current device config byte - * @chip_info: chip model specific constants, available modes etc - * @current_mode: the scan mode of this chip - * @requestedmask: a valid requested set of channels - * @reg: supply regulator - * @monitor_on: whether monitor mode is enabled - * @monitor_speed: parameter corresponding to device monitor speed setting - * @mask_high: bitmask for enabled high thresholds - * @mask_low: bitmask for enabled low thresholds - * @thresh_high: high threshold values - * @thresh_low: low threshold values - */ -struct max1363_state { - struct i2c_client *client; - u8 setupbyte; - u8 configbyte; - const struct max1363_chip_info *chip_info; - const struct max1363_mode *current_mode; - u32 requestedmask; - struct regulator *reg; - - /* Using monitor modes and buffer at the same time is - currently not supported */ - bool monitor_on; - unsigned int monitor_speed:3; - u8 mask_high; - u8 mask_low; - /* 4x unipolar first then the fours bipolar ones */ - s16 thresh_high[8]; - s16 thresh_low[8]; -}; - -const struct max1363_mode -*max1363_match_mode(const unsigned long *mask, - const struct max1363_chip_info *ci); - -int max1363_set_scan_mode(struct max1363_state *st); - -#ifdef CONFIG_MAX1363_RING_BUFFER -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask); -int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev); -void max1363_ring_cleanup(struct iio_dev *indio_dev); - -#else /* CONFIG_MAX1363_RING_BUFFER */ -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const long *scan_mask) -{ - return 0; -} - -static inline int -max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_MAX1363_RING_BUFFER */ -#endif /* _MAX1363_H_ */ diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c deleted file mode 100644 index 41af17b5e74f..000000000000 --- a/drivers/staging/iio/adc/max1363_ring.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2008 Jonathan Cameron - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * max1363_ring.c - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "max1363.h" - -int max1363_update_scan_mode(struct iio_dev *indio_dev, - const unsigned long *scan_mask) -{ - struct max1363_state *st = iio_priv(indio_dev); - - /* - * Need to figure out the current mode based upon the requested - * scan mask in iio_dev - */ - st->current_mode = max1363_match_mode(scan_mask, st->chip_info); - if (!st->current_mode) - return -EINVAL; - max1363_set_scan_mode(st); - return 0; -} - -static irqreturn_t max1363_trigger_handler(int irq, void *p) -{ - struct iio_poll_func *pf = p; - struct iio_dev *indio_dev = pf->indio_dev; - struct max1363_state *st = iio_priv(indio_dev); - s64 time_ns; - __u8 *rxbuf; - int b_sent; - size_t d_size; - unsigned long numvals = bitmap_weight(st->current_mode->modemask, - MAX1363_MAX_CHANNELS); - - /* Ensure the timestamp is 8 byte aligned */ - if (st->chip_info->bits != 8) - d_size = numvals*2; - else - d_size = numvals; - if (indio_dev->scan_timestamp) { - d_size += sizeof(s64); - if (d_size % sizeof(s64)) - d_size += sizeof(s64) - (d_size % sizeof(s64)); - } - /* Monitor mode prevents reading. Whilst not currently implemented - * might as well have this test in here in the meantime as it does - * no harm. - */ - if (numvals == 0) - goto done; - - rxbuf = kmalloc(d_size, GFP_KERNEL); - if (rxbuf == NULL) - goto done; - if (st->chip_info->bits != 8) - b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); - else - b_sent = i2c_master_recv(st->client, rxbuf, numvals); - if (b_sent < 0) - goto done_free; - - time_ns = iio_get_time_ns(); - - if (indio_dev->scan_timestamp) - memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); - iio_push_to_buffers(indio_dev, rxbuf); - -done_free: - kfree(rxbuf); -done: - iio_trigger_notify_done(indio_dev->trig); - - return IRQ_HANDLED; -} - -static const struct iio_buffer_setup_ops max1363_ring_setup_ops = { - .postenable = &iio_triggered_buffer_postenable, - .preenable = &iio_sw_buffer_preenable, - .predisable = &iio_triggered_buffer_predisable, -}; - -int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) -{ - struct max1363_state *st = iio_priv(indio_dev); - int ret = 0; - - indio_dev->buffer = iio_kfifo_allocate(indio_dev); - if (!indio_dev->buffer) { - ret = -ENOMEM; - goto error_ret; - } - indio_dev->pollfunc = iio_alloc_pollfunc(NULL, - &max1363_trigger_handler, - IRQF_ONESHOT, - indio_dev, - "%s_consumer%d", - st->client->name, - indio_dev->id); - if (indio_dev->pollfunc == NULL) { - ret = -ENOMEM; - goto error_deallocate_sw_rb; - } - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &max1363_ring_setup_ops; - - /* Flag that polled ring buffering is possible */ - indio_dev->modes |= INDIO_BUFFER_TRIGGERED; - - return 0; - -error_deallocate_sw_rb: - iio_kfifo_free(indio_dev->buffer); -error_ret: - return ret; -} - -void max1363_ring_cleanup(struct iio_dev *indio_dev) -{ - /* ensure that the trigger has been detached */ - iio_dealloc_pollfunc(indio_dev->pollfunc); - iio_kfifo_free(indio_dev->buffer); -} From ec44372865c0ab9dd7d816ab9734463bdb8c20d1 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:19:01 +0100 Subject: [PATCH 13/17] staging:iio:adc:max1363 drop references to 'ring' given now using a fifo Seems worth clearing the old naming out to avoid any confusion in the future. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/max1363.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/staging/iio/adc/max1363.c b/drivers/staging/iio/adc/max1363.c index 72715a4d5941..dbfdc3938064 100644 --- a/drivers/staging/iio/adc/max1363.c +++ b/drivers/staging/iio/adc/max1363.c @@ -788,7 +788,7 @@ static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) const long *modemask; if (!enabled) { - /* transition to ring capture is not currently supported */ + /* transition to buffered capture is not currently supported */ st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP; st->configbyte &= ~MAX1363_SCAN_MASK; st->monitor_on = false; @@ -1482,13 +1482,13 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p) return IRQ_HANDLED; } -static const struct iio_buffer_setup_ops max1363_ring_setup_ops = { +static const struct iio_buffer_setup_ops max1363_buffered_setup_ops = { .postenable = &iio_triggered_buffer_postenable, .preenable = &iio_sw_buffer_preenable, .predisable = &iio_triggered_buffer_predisable, }; -static int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) +static int max1363_register_buffered_funcs_and_init(struct iio_dev *indio_dev) { struct max1363_state *st = iio_priv(indio_dev); int ret = 0; @@ -1509,10 +1509,10 @@ static int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) ret = -ENOMEM; goto error_deallocate_sw_rb; } - /* Ring buffer functions - here trigger setup related */ - indio_dev->setup_ops = &max1363_ring_setup_ops; + /* Buffer functions - here trigger setup related */ + indio_dev->setup_ops = &max1363_buffered_setup_ops; - /* Flag that polled ring buffering is possible */ + /* Flag that polled buffering is possible */ indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; @@ -1523,7 +1523,7 @@ static int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) return ret; } -static void max1363_ring_cleanup(struct iio_dev *indio_dev) +static void max1363_buffer_cleanup(struct iio_dev *indio_dev) { /* ensure that the trigger has been detached */ iio_dealloc_pollfunc(indio_dev->pollfunc); @@ -1581,7 +1581,7 @@ static int __devinit max1363_probe(struct i2c_client *client, if (ret < 0) goto error_free_available_scan_masks; - ret = max1363_register_ring_funcs_and_init(indio_dev); + ret = max1363_register_buffered_funcs_and_init(indio_dev); if (ret) goto error_free_available_scan_masks; @@ -1589,7 +1589,7 @@ static int __devinit max1363_probe(struct i2c_client *client, st->chip_info->channels, st->chip_info->num_channels); if (ret) - goto error_cleanup_ring; + goto error_cleanup_buffer; if (client->irq) { ret = request_threaded_irq(st->client->irq, @@ -1600,7 +1600,7 @@ static int __devinit max1363_probe(struct i2c_client *client, indio_dev); if (ret) - goto error_uninit_ring; + goto error_uninit_buffer; } ret = iio_device_register(indio_dev); @@ -1610,10 +1610,10 @@ static int __devinit max1363_probe(struct i2c_client *client, return 0; error_free_irq: free_irq(st->client->irq, indio_dev); -error_uninit_ring: +error_uninit_buffer: iio_buffer_unregister(indio_dev); -error_cleanup_ring: - max1363_ring_cleanup(indio_dev); +error_cleanup_buffer: + max1363_buffer_cleanup(indio_dev); error_free_available_scan_masks: kfree(indio_dev->available_scan_masks); error_unregister_map: @@ -1638,7 +1638,7 @@ static int __devexit max1363_remove(struct i2c_client *client) if (client->irq) free_irq(st->client->irq, indio_dev); iio_buffer_unregister(indio_dev); - max1363_ring_cleanup(indio_dev); + max1363_buffer_cleanup(indio_dev); kfree(indio_dev->available_scan_masks); if (!IS_ERR(reg)) { regulator_disable(reg); From 2593b13a622ae99c2c7d6d8c869b59383ab70697 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:37:44 +0100 Subject: [PATCH 14/17] staging:iio:adc:max1363 make docs match the contents of max1363_chip_info Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/max1363.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/iio/adc/max1363.c b/drivers/staging/iio/adc/max1363.c index dbfdc3938064..321775327b26 100644 --- a/drivers/staging/iio/adc/max1363.c +++ b/drivers/staging/iio/adc/max1363.c @@ -127,20 +127,19 @@ enum max1363_modes { /** * struct max1363_chip_info - chip specifc information - * @name: indentification string for chip - * @bits: accuracy of the adc in bits - * @int_vref_mv: the internal reference voltage * @info: iio core function callbacks structure + * @channels: channel specification + * @num_channels: number of channels * @mode_list: array of available scan modes - * @num_modes: the number of scan modes available * @default_mode: the scan mode in which the chip starts up - * @channel: channel specification + * @int_vref_mv: the internal reference voltage * @num_channels: number of channels + * @bits: accuracy of the adc in bits */ struct max1363_chip_info { const struct iio_info *info; - const struct iio_chan_spec *channels; - int num_channels; + const struct iio_chan_spec *channels; + int num_channels; const enum max1363_modes *mode_list; enum max1363_modes default_mode; u16 int_vref_mv; From 0d9fa2ce939279ac7aab34b50b90196f8208af42 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:38:11 +0100 Subject: [PATCH 15/17] staging:iio:adc:max1363 white space cleanup Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/max1363.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/staging/iio/adc/max1363.c b/drivers/staging/iio/adc/max1363.c index 321775327b26..2f8d433413d9 100644 --- a/drivers/staging/iio/adc/max1363.c +++ b/drivers/staging/iio/adc/max1363.c @@ -765,9 +765,9 @@ static int max1363_read_event_config(struct iio_dev *indio_dev, u64 event_code) { struct max1363_state *st = iio_priv(indio_dev); - int val; int number = IIO_EVENT_CODE_EXTRACT_CHAN(event_code); + mutex_lock(&indio_dev->mlock); if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) val = (1 << number) & st->mask_low; @@ -969,8 +969,6 @@ static struct attribute_group max1363_event_attribute_group = { .name = "events", }; -#define MAX1363_EVENT_FUNCS \ - static int max1363_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { @@ -1388,8 +1386,6 @@ static const struct max1363_chip_info max1363_chip_info_tbl[] = { }, }; - - static int max1363_initial_setup(struct max1363_state *st) { st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD From b77b8f8c20c83c111050201cad1eed3a71571c35 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:39:19 +0100 Subject: [PATCH 16/17] staging:iio:adc:max1363 cleanup regulator handling. For historical reasons the regulator handling was a little clunky. This patch brings it inline with a more standard ordering wrt to allocation of the iio_device. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/adc/max1363.c | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/staging/iio/adc/max1363.c b/drivers/staging/iio/adc/max1363.c index 2f8d433413d9..1e84b5b55093 100644 --- a/drivers/staging/iio/adc/max1363.c +++ b/drivers/staging/iio/adc/max1363.c @@ -1531,28 +1531,29 @@ static int __devinit max1363_probe(struct i2c_client *client, int ret; struct max1363_state *st; struct iio_dev *indio_dev; - struct regulator *reg; - - reg = regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) { - ret = PTR_ERR(reg); - goto error_out; - } - - ret = regulator_enable(reg); - if (ret) - goto error_put_reg; indio_dev = iio_device_alloc(sizeof(struct max1363_state)); if (indio_dev == NULL) { ret = -ENOMEM; - goto error_disable_reg; + goto error_out; } + ret = iio_map_array_register(indio_dev, client->dev.platform_data); if (ret < 0) goto error_free_device; + st = iio_priv(indio_dev); - st->reg = reg; + + st->reg = regulator_get(&client->dev, "vcc"); + if (IS_ERR(st->reg)) { + ret = PTR_ERR(st->reg); + goto error_unregister_map; + } + + ret = regulator_enable(st->reg); + if (ret) + goto error_put_reg; + /* this is only used for device removal purposes */ i2c_set_clientdata(client, indio_dev); @@ -1561,7 +1562,7 @@ static int __devinit max1363_probe(struct i2c_client *client, ret = max1363_alloc_scan_masks(indio_dev); if (ret) - goto error_unregister_map; + goto error_disable_reg; /* Estabilish that the iio_dev is a child of the i2c device */ indio_dev->dev.parent = &client->dev; @@ -1613,12 +1614,12 @@ static int __devinit max1363_probe(struct i2c_client *client, kfree(indio_dev->available_scan_masks); error_unregister_map: iio_map_array_unregister(indio_dev, client->dev.platform_data); +error_disable_reg: + regulator_disable(st->reg); +error_put_reg: + regulator_put(st->reg); error_free_device: iio_device_free(indio_dev); -error_disable_reg: - regulator_disable(reg); -error_put_reg: - regulator_put(reg); error_out: return ret; } @@ -1627,7 +1628,6 @@ static int __devexit max1363_remove(struct i2c_client *client) { struct iio_dev *indio_dev = i2c_get_clientdata(client); struct max1363_state *st = iio_priv(indio_dev); - struct regulator *reg = st->reg; iio_device_unregister(indio_dev); if (client->irq) @@ -1635,9 +1635,9 @@ static int __devexit max1363_remove(struct i2c_client *client) iio_buffer_unregister(indio_dev); max1363_buffer_cleanup(indio_dev); kfree(indio_dev->available_scan_masks); - if (!IS_ERR(reg)) { - regulator_disable(reg); - regulator_put(reg); + if (!IS_ERR(st->reg)) { + regulator_disable(st->reg); + regulator_put(st->reg); } iio_map_array_unregister(indio_dev, client->dev.platform_data); iio_device_free(indio_dev); From 168c9d95a94077a42e5bf5a4a660b45ccee4fc63 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Sat, 6 Oct 2012 14:42:27 +0100 Subject: [PATCH 17/17] iio:adc:max1363 move from staging. Now this driver is using kfifo we can move it out of staging. Signed-off-by: Jonathan Cameron --- drivers/iio/adc/Kconfig | 18 ++++++++++++++++++ drivers/iio/adc/Makefile | 1 + drivers/{staging => }/iio/adc/max1363.c | 0 drivers/staging/iio/adc/Kconfig | 18 ------------------ drivers/staging/iio/adc/Makefile | 2 -- 5 files changed, 19 insertions(+), 20 deletions(-) rename drivers/{staging => }/iio/adc/max1363.c (100%) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 706386ba02e3..ef5200a6850e 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -73,4 +73,22 @@ config LP8788_ADC help Say yes here to build support for TI LP8788 ADC. +config MAX1363 + tristate "Maxim max1363 ADC driver" + depends on I2C + select IIO_TRIGGER + select MAX1363_RING_BUFFER + select IIO_BUFFER + select IIO_KFIFO_BUF + help + Say yes here to build support for many Maxim i2c analog to digital + converters (ADC). (max1361, max1362, max1363, max1364, max1036, + max1037, max1038, max1039, max1136, max1136, max1137, max1138, + max1139, max1236, max1237, max11238, max1239, max11600, max11601, + max11602, max11603, max11604, max11605, max11606, max11607, + max11608, max11609, max11610, max11611, max11612, max11613, + max11614, max11615, max11616, max11617, max11644, max11645, + max11646, max11647) Provides direct access via sysfs and buffered + data via the iio dev interface. + endmenu diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 034eacb8f7c9..54ac7bbcd01b 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_AD7791) += ad7791.o obj-$(CONFIG_AD7887) += ad7887.o obj-$(CONFIG_AT91_ADC) += at91_adc.o obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o +obj-$(CONFIG_MAX1363) += max1363.o diff --git a/drivers/staging/iio/adc/max1363.c b/drivers/iio/adc/max1363.c similarity index 100% rename from drivers/staging/iio/adc/max1363.c rename to drivers/iio/adc/max1363.c diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig index 4d348048b39d..0177f1e02300 100644 --- a/drivers/staging/iio/adc/Kconfig +++ b/drivers/staging/iio/adc/Kconfig @@ -130,24 +130,6 @@ config AD7280 To compile this driver as a module, choose M here: the module will be called ad7280a -config MAX1363 - tristate "Maxim max1363 ADC driver" - depends on I2C - select IIO_TRIGGER - select MAX1363_RING_BUFFER - select IIO_BUFFER - select IIO_KFIFO_BUF - help - Say yes here to build support for many Maxim i2c analog to digital - converters (ADC). (max1361, max1362, max1363, max1364, max1036, - max1037, max1038, max1039, max1136, max1136, max1137, max1138, - max1139, max1236, max1237, max11238, max1239, max11600, max11601, - max11602, max11603, max11604, max11605, max11606, max11607, - max11608, max11609, max11610, max11611, max11612, max11613, - max11614, max11615, max11616, max11617, max11644, max11645, - max11646, max11647) Provides direct access via sysfs and buffered - data via the iio dev interface. - config LPC32XX_ADC tristate "NXP LPC32XX ADC" depends on ARCH_LPC32XX diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile index 33979e62871b..12b4bd32437f 100644 --- a/drivers/staging/iio/adc/Makefile +++ b/drivers/staging/iio/adc/Makefile @@ -2,8 +2,6 @@ # Makefile for industrial I/O ADC drivers # -obj-$(CONFIG_MAX1363) += max1363.o - ad7606-y := ad7606_core.o ad7606-$(CONFIG_IIO_BUFFER) += ad7606_ring.o ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o