|
@@ -15,13 +15,49 @@
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/module.h>
|
|
|
+#include <linux/interrupt.h>
|
|
|
|
|
|
#include <linux/iio/iio.h>
|
|
|
#include <linux/iio/sysfs.h>
|
|
|
#include <linux/iio/buffer.h>
|
|
|
+#include <linux/iio/trigger_consumer.h>
|
|
|
+#include <linux/iio/triggered_buffer.h>
|
|
|
|
|
|
#include "ad7298.h"
|
|
|
|
|
|
+#define AD7298_WRITE (1 << 15) /* write to the control register */
|
|
|
+#define AD7298_REPEAT (1 << 14) /* repeated conversion enable */
|
|
|
+#define AD7298_CH(x) (1 << (13 - (x))) /* channel select */
|
|
|
+#define AD7298_TSENSE (1 << 5) /* temperature conversion enable */
|
|
|
+#define AD7298_EXTREF (1 << 2) /* external reference enable */
|
|
|
+#define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
|
|
|
+#define AD7298_PDD (1 << 0) /* partial power down enable */
|
|
|
+
|
|
|
+#define AD7298_MAX_CHAN 8
|
|
|
+#define AD7298_BITS 12
|
|
|
+#define AD7298_STORAGE_BITS 16
|
|
|
+#define AD7298_INTREF_mV 2500
|
|
|
+
|
|
|
+#define AD7298_CH_TEMP 9
|
|
|
+
|
|
|
+#define RES_MASK(bits) ((1 << (bits)) - 1)
|
|
|
+
|
|
|
+struct ad7298_state {
|
|
|
+ struct spi_device *spi;
|
|
|
+ struct regulator *reg;
|
|
|
+ unsigned ext_ref;
|
|
|
+ struct spi_transfer ring_xfer[10];
|
|
|
+ struct spi_transfer scan_single_xfer[3];
|
|
|
+ struct spi_message ring_msg;
|
|
|
+ struct spi_message scan_single_msg;
|
|
|
+ /*
|
|
|
+ * DMA (thus cache coherency maintenance) requires the
|
|
|
+ * transfer buffers to live in their own cache lines.
|
|
|
+ */
|
|
|
+ unsigned short rx_buf[12] ____cacheline_aligned;
|
|
|
+ unsigned short tx_buf[2];
|
|
|
+};
|
|
|
+
|
|
|
#define AD7298_V_CHAN(index) \
|
|
|
{ \
|
|
|
.type = IIO_VOLTAGE, \
|
|
@@ -66,6 +102,84 @@ static const struct iio_chan_spec ad7298_channels[] = {
|
|
|
IIO_CHAN_SOFT_TIMESTAMP(8),
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * ad7298_update_scan_mode() setup the spi transfer buffer for the new scan mask
|
|
|
+ **/
|
|
|
+static int ad7298_update_scan_mode(struct iio_dev *indio_dev,
|
|
|
+ const unsigned long *active_scan_mask)
|
|
|
+{
|
|
|
+ struct ad7298_state *st = iio_priv(indio_dev);
|
|
|
+ int i, m;
|
|
|
+ unsigned short command;
|
|
|
+ int scan_count;
|
|
|
+
|
|
|
+ /* Now compute overall size */
|
|
|
+ scan_count = bitmap_weight(active_scan_mask, indio_dev->masklength);
|
|
|
+
|
|
|
+ command = AD7298_WRITE | st->ext_ref;
|
|
|
+
|
|
|
+ for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
|
|
|
+ if (test_bit(i, active_scan_mask))
|
|
|
+ command |= m;
|
|
|
+
|
|
|
+ st->tx_buf[0] = cpu_to_be16(command);
|
|
|
+
|
|
|
+ /* build spi ring message */
|
|
|
+ st->ring_xfer[0].tx_buf = &st->tx_buf[0];
|
|
|
+ st->ring_xfer[0].len = 2;
|
|
|
+ st->ring_xfer[0].cs_change = 1;
|
|
|
+ st->ring_xfer[1].tx_buf = &st->tx_buf[1];
|
|
|
+ st->ring_xfer[1].len = 2;
|
|
|
+ st->ring_xfer[1].cs_change = 1;
|
|
|
+
|
|
|
+ spi_message_init(&st->ring_msg);
|
|
|
+ spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
|
|
|
+ spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
|
|
|
+
|
|
|
+ for (i = 0; i < scan_count; i++) {
|
|
|
+ st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
|
|
|
+ st->ring_xfer[i + 2].len = 2;
|
|
|
+ st->ring_xfer[i + 2].cs_change = 1;
|
|
|
+ spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
|
|
|
+ }
|
|
|
+ /* make sure last transfer cs_change is not set */
|
|
|
+ st->ring_xfer[i + 1].cs_change = 0;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ad7298_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 ad7298_trigger_handler(int irq, void *p)
|
|
|
+{
|
|
|
+ struct iio_poll_func *pf = p;
|
|
|
+ struct iio_dev *indio_dev = pf->indio_dev;
|
|
|
+ struct ad7298_state *st = iio_priv(indio_dev);
|
|
|
+ s64 time_ns = 0;
|
|
|
+ int b_sent;
|
|
|
+
|
|
|
+ b_sent = spi_sync(st->spi, &st->ring_msg);
|
|
|
+ if (b_sent)
|
|
|
+ goto done;
|
|
|
+
|
|
|
+ if (indio_dev->scan_timestamp) {
|
|
|
+ time_ns = iio_get_time_ns();
|
|
|
+ memcpy((u8 *)st->rx_buf + indio_dev->scan_bytes - sizeof(s64),
|
|
|
+ &time_ns, sizeof(time_ns));
|
|
|
+ }
|
|
|
+
|
|
|
+ iio_push_to_buffers(indio_dev, (u8 *)st->rx_buf);
|
|
|
+
|
|
|
+done:
|
|
|
+ iio_trigger_notify_done(indio_dev->trig);
|
|
|
+
|
|
|
+ return IRQ_HANDLED;
|
|
|
+}
|
|
|
+
|
|
|
static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
|
|
|
{
|
|
|
int ret;
|
|
@@ -231,7 +345,8 @@ static int __devinit ad7298_probe(struct spi_device *spi)
|
|
|
spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
|
|
|
spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
|
|
|
|
|
|
- ret = ad7298_register_ring_funcs_and_init(indio_dev);
|
|
|
+ ret = iio_triggered_buffer_setup(indio_dev, NULL,
|
|
|
+ &ad7298_trigger_handler, NULL);
|
|
|
if (ret)
|
|
|
goto error_disable_reg;
|
|
|
|
|
@@ -242,7 +357,7 @@ static int __devinit ad7298_probe(struct spi_device *spi)
|
|
|
return 0;
|
|
|
|
|
|
error_cleanup_ring:
|
|
|
- ad7298_ring_cleanup(indio_dev);
|
|
|
+ iio_triggered_buffer_cleanup(indio_dev);
|
|
|
error_disable_reg:
|
|
|
if (st->ext_ref)
|
|
|
regulator_disable(st->reg);
|
|
@@ -261,7 +376,7 @@ static int __devexit ad7298_remove(struct spi_device *spi)
|
|
|
struct ad7298_state *st = iio_priv(indio_dev);
|
|
|
|
|
|
iio_device_unregister(indio_dev);
|
|
|
- ad7298_ring_cleanup(indio_dev);
|
|
|
+ iio_triggered_buffer_cleanup(indio_dev);
|
|
|
if (st->ext_ref) {
|
|
|
regulator_disable(st->reg);
|
|
|
regulator_put(st->reg);
|