Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 338004
b: refs/heads/master
c: aacff89
h: refs/heads/master
v: v3
  • Loading branch information
Lars-Peter Clausen authored and Jonathan Cameron committed Nov 19, 2012
1 parent aa0dc47 commit 22be2bd
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 49 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a458c55c107c5e467ab5b7e471f77ec5868afcb9
refs/heads/master: aacff892cbd5c6b1904a3906219548a65018d750
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/accel/adis16201_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ static const struct iio_chan_spec adis16201_channels[] = {
static const struct iio_info adis16201_info = {
.read_raw = &adis16201_read_raw,
.write_raw = &adis16201_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/accel/adis16203_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static const struct iio_chan_spec adis16203_channels[] = {
static const struct iio_info adis16203_info = {
.read_raw = &adis16203_read_raw,
.write_raw = &adis16203_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/accel/adis16204_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ static const struct iio_chan_spec adis16204_channels[] = {
static const struct iio_info adis16204_info = {
.read_raw = &adis16204_read_raw,
.write_raw = &adis16204_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/accel/adis16209_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
static const struct iio_info adis16209_info = {
.read_raw = &adis16209_read_raw,
.write_raw = &adis16209_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/accel/adis16240_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ static const struct iio_info adis16240_info = {
.attrs = &adis16240_attribute_group,
.read_raw = &adis16240_read_raw,
.write_raw = &adis16240_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/staging/iio/gyro/adis16260_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ static const struct iio_info adis16260_info = {
.attrs = &adis16260_attribute_group,
.read_raw = &adis16260_read_raw,
.write_raw = &adis16260_write_raw,
.update_scan_mode = adis_update_scan_mode,
.driver_module = THIS_MODULE,
};

Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/staging/iio/imu/adis.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
.sign = 'u', \
.realbits = (bits), \
.storagebits = 16, \
.endianness = IIO_BE, \
}, \
}

Expand All @@ -109,6 +110,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
.sign = 'u', \
.realbits = (bits), \
.storagebits = 16, \
.endianness = IIO_BE, \
}, \
}

Expand All @@ -125,6 +127,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
.sign = 's', \
.realbits = (bits), \
.storagebits = 16, \
.endianness = IIO_BE, \
}, \
}

Expand All @@ -150,6 +153,9 @@ void adis_cleanup_buffer_and_trigger(struct adis *adis,
int adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev);
void adis_remove_trigger(struct adis *adis);

int adis_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask);

#else /* CONFIG_IIO_BUFFER */

static inline int adis_setup_buffer_and_trigger(struct adis *adis,
Expand All @@ -173,6 +179,8 @@ static inline void adis_remove_trigger(struct adis *adis)
{
}

#define adis_update_scan_mode NULL

#endif /* CONFIG_IIO_BUFFER */

#endif
114 changes: 66 additions & 48 deletions trunk/drivers/staging/iio/imu/adis_buffer.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* Common library for ADIS16XXX devices
*
* Copyright 2012 Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* Licensed under the GPL-2 or later.
*/

#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
Expand All @@ -12,73 +21,80 @@

#include "adis.h"

#define ADIS_MAX_OUTPUTS 12

static int adis_read_buffer_data(struct adis *adis, struct iio_dev *indio_dev)
int adis_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
int n_outputs = indio_dev->num_channels;
struct spi_transfer xfers[ADIS_MAX_OUTPUTS + 1];
struct spi_message msg;
int ret;
int i;

mutex_lock(&adis->txrx_lock);

spi_message_init(&msg);

memset(xfers, 0, sizeof(xfers));
for (i = 0; i <= n_outputs; i++) {
xfers[i].bits_per_word = 8;
xfers[i].cs_change = 1;
xfers[i].len = 2;
xfers[i].delay_usecs = adis->data->read_delay;
if (i < n_outputs) {
xfers[i].tx_buf = adis->tx + 2 * i;
adis->tx[2 * i] = indio_dev->channels[i].address;
adis->tx[2 * i + 1] = 0;
}
if (i >= 1)
xfers[i].rx_buf = adis->rx + 2 * (i - 1);
spi_message_add_tail(&xfers[i], &msg);
}
struct adis *adis = iio_device_get_drvdata(indio_dev);
const struct iio_chan_spec *chan;
unsigned int scan_count;
unsigned int i, j;
__be16 *tx, *rx;

ret = spi_sync(adis->spi, &msg);
if (ret)
dev_err(&adis->spi->dev, "Failed to read data: %d", ret);
kfree(adis->xfer);
kfree(adis->buffer);

mutex_unlock(&adis->txrx_lock);
scan_count = indio_dev->scan_bytes / 2;

return ret;
adis->xfer = kcalloc(scan_count + 1, sizeof(*adis->xfer), GFP_KERNEL);
if (!adis->xfer)
return -ENOMEM;

adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;

rx = adis->buffer;
tx = rx + indio_dev->scan_bytes;

spi_message_init(&adis->msg);

for (j = 0; j <= scan_count; j++) {
adis->xfer[j].bits_per_word = 8;
if (j != scan_count)
adis->xfer[j].cs_change = 1;
adis->xfer[j].len = 2;
adis->xfer[j].delay_usecs = adis->data->read_delay;
if (j < scan_count)
adis->xfer[j].tx_buf = &tx[j];
if (j >= 1)
adis->xfer[j].rx_buf = &rx[j - 1];
spi_message_add_tail(&adis->xfer[j], &adis->msg);
}

chan = indio_dev->channels;
for (i = 0; i < indio_dev->num_channels; i++, chan++) {
if (!test_bit(chan->scan_index, scan_mask))
continue;
*tx++ = cpu_to_be16(chan->address << 8);
}

return 0;
}
EXPORT_SYMBOL_GPL(adis_update_scan_mode);

static irqreturn_t adis_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct adis *adis = iio_device_get_drvdata(indio_dev);
u16 *data;
int i = 0;
int ret;

data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
if (data == NULL) {
dev_err(&adis->spi->dev, "Failed to allocate memory.");
if (!adis->buffer)
return -ENOMEM;
}

if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)
&& adis_read_buffer_data(adis, indio_dev) >= 0)
for (; i < bitmap_weight(indio_dev->active_scan_mask,
indio_dev->masklength); i++)
data[i] = be16_to_cpup((__be16 *)&(adis->rx[i*2]));
ret = spi_sync(adis->spi, &adis->msg);
if (ret)
dev_err(&adis->spi->dev, "Failed to read data: %d", ret);

/* Guaranteed to be aligned with 8 byte boundary */
if (indio_dev->scan_timestamp)
*((s64 *)(PTR_ALIGN(data, sizeof(s64)))) = pf->timestamp;
if (indio_dev->scan_timestamp) {
void *b = adis->buffer + indio_dev->scan_bytes - sizeof(s64);
*(s64 *)b = pf->timestamp;
}

iio_push_to_buffers(indio_dev, (u8 *)data);
iio_push_to_buffers(indio_dev, adis->buffer);

iio_trigger_notify_done(indio_dev->trig);
kfree(data);

return IRQ_HANDLED;
}
Expand Down Expand Up @@ -137,6 +153,8 @@ void adis_cleanup_buffer_and_trigger(struct adis *adis,
{
if (adis->spi->irq)
adis_remove_trigger(adis);
kfree(adis->buffer);
kfree(adis->xfer);
iio_triggered_buffer_cleanup(indio_dev);
}
EXPORT_SYMBOL_GPL(adis_cleanup_buffer_and_trigger);

0 comments on commit 22be2bd

Please sign in to comment.