summaryrefslogtreecommitdiff
path: root/drivers/staging/iio/accel/sca3000_ring.c
diff options
context:
space:
mode:
authorJonathan Cameron <jic23@cam.ac.uk>2011-05-18 14:41:01 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-19 16:06:13 -0700
commit25888dc51163a566f8c8f18a84c100851d12738c (patch)
tree4fad20bf110b3423d96fe968979a04e3cf1a736a /drivers/staging/iio/accel/sca3000_ring.c
parent1e3345bc2c118c43f7f8a6db5d71c06e02b989da (diff)
staging:iio:sca3000 extract old event handling and move to poll for events from buffer
Fairly substantial rewrite as the code had bitrotted. A rethink is needed for how to handle variable types in the new chan_spec world. This patch restores sca3000 buffer usage to a working state. V3: Rebase fixups. V2: Move to new version of IIO_CHAN macro Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/iio/accel/sca3000_ring.c')
-rw-r--r--drivers/staging/iio/accel/sca3000_ring.c252
1 files changed, 170 insertions, 82 deletions
diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c
index 44f9a56b8f8b..8efd4f0144be 100644
--- a/drivers/staging/iio/accel/sca3000_ring.c
+++ b/drivers/staging/iio/accel/sca3000_ring.c
@@ -17,6 +17,8 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
#include "../iio.h"
#include "../sysfs.h"
@@ -34,6 +36,44 @@
* Currently scan elements aren't configured so it doesn't matter.
*/
+static int sca3000_read_data(struct sca3000_state *st,
+ uint8_t reg_address_high,
+ u8 **rx_p,
+ int len)
+{
+ int ret;
+ struct spi_message msg;
+ struct spi_transfer xfer[2] = {
+ {
+ .len = 1,
+ .tx_buf = st->tx,
+ }, {
+ .len = len,
+ }
+ };
+ *rx_p = kmalloc(len, GFP_KERNEL);
+ if (*rx_p == NULL) {
+ ret = -ENOMEM;
+ goto error_ret;
+ }
+ xfer[1].rx_buf = *rx_p;
+ st->tx[0] = SCA3000_READ_REG(reg_address_high);
+ spi_message_init(&msg);
+ spi_message_add_tail(&xfer[0], &msg);
+ spi_message_add_tail(&xfer[1], &msg);
+ ret = spi_sync(st->us, &msg);
+ if (ret) {
+ dev_err(get_device(&st->us->dev), "problem reading register");
+ goto error_free_rx;
+ }
+
+ return 0;
+error_free_rx:
+ kfree(*rx_p);
+error_ret:
+ return ret;
+}
+
/**
* sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring
* @r: the ring
@@ -45,8 +85,6 @@
* Currently does not provide timestamps. As the hardware doesn't add them they
* can only be inferred approximately from ring buffer events such as 50% full
* and knowledge of when buffer was last emptied. This is left to userspace.
- *
- * Temporarily deliberately broken.
**/
static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r,
size_t count, char __user *buf,
@@ -56,54 +94,45 @@ static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r,
struct iio_dev *indio_dev = hw_ring->private;
struct sca3000_state *st = indio_dev->dev_data;
u8 *rx;
- s16 *samples;
int ret, i, num_available, num_read = 0;
int bytes_per_sample = 1;
- u8 *datas;
- u8 **data = &datas;
if (st->bpse == 11)
bytes_per_sample = 2;
mutex_lock(&st->lock);
- /* Check how much data is available:
- * RFC: Implement an ioctl to not bother checking whether there
- * is enough data in the ring? Afterall, if we are responding
- * to an interrupt we have a minimum content guaranteed so it
- * seems slight silly to waste time checking it is there.
- */
- ret = sca3000_read_data(st,
- SCA3000_REG_ADDR_BUF_COUNT,
- &rx, 1);
+ if (count % bytes_per_sample) {
+ ret = -EINVAL;
+ goto error_ret;
+ }
+
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1);
if (ret)
goto error_ret;
else
- num_available = rx[1];
- /* num_available is the total number of samples available
+ num_available = st->rx[0];
+ /*
+ * num_available is the total number of samples available
* i.e. number of time points * number of channels.
*/
- kfree(rx);
if (count > num_available * bytes_per_sample)
num_read = num_available*bytes_per_sample;
else
- num_read = count - (count % (bytes_per_sample));
+ num_read = count;
- /* Avoid the read request byte */
- *dead_offset = 1;
ret = sca3000_read_data(st,
SCA3000_REG_ADDR_RING_OUT,
- data, num_read);
-
- /* Convert byte order and shift to default resolution */
- if (st->bpse == 11) {
- samples = (s16*)(*data+1);
- for (i = 0; i < (num_read/2); i++) {
- samples[i] = be16_to_cpup(
- (__be16 *)&(samples[i]));
- samples[i] >>= 3;
- }
- }
+ &rx, num_read);
+ if (ret)
+ goto error_ret;
+
+ for (i = 0; i < num_read; i++)
+ *(((u16 *)rx) + i) = be16_to_cpup((u16 *)rx + i);
+ if (copy_to_user(buf, rx, num_read))
+ ret = -EFAULT;
+ kfree(rx);
+ r->stufftoread = 0;
error_ret:
mutex_unlock(&st->lock);
@@ -132,6 +161,76 @@ static IIO_RING_BYTES_PER_DATUM_ATTR;
static IIO_RING_LENGTH_ATTR;
/**
+ * sca3000_query_ring_int() is the hardware ring status interrupt enabled
+ **/
+static ssize_t sca3000_query_ring_int(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ int ret, val;
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct sca3000_state *st = indio_dev->dev_data;
+
+ mutex_lock(&st->lock);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
+ val = st->rx[0];
+ mutex_unlock(&st->lock);
+ if (ret)
+ return ret;
+
+ return sprintf(buf, "%d\n", !!(val & this_attr->address));
+}
+
+/**
+ * sca3000_set_ring_int() set state of ring status interrupt
+ **/
+static ssize_t sca3000_set_ring_int(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct sca3000_state *st = indio_dev->dev_data;
+ struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+ long val;
+ int ret;
+
+ mutex_lock(&st->lock);
+ ret = strict_strtol(buf, 10, &val);
+ if (ret)
+ goto error_ret;
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_INT_MASK, 1);
+ if (ret)
+ goto error_ret;
+ if (val)
+ ret = sca3000_write_reg(st,
+ SCA3000_REG_ADDR_INT_MASK,
+ st->rx[0] | this_attr->address);
+ else
+ ret = sca3000_write_reg(st,
+ SCA3000_REG_ADDR_INT_MASK,
+ st->rx[0] & ~this_attr->address);
+error_ret:
+ mutex_unlock(&st->lock);
+
+ return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(50_percent, S_IRUGO | S_IWUSR,
+ sca3000_query_ring_int,
+ sca3000_set_ring_int,
+ SCA3000_INT_MASK_RING_HALF);
+
+static IIO_DEVICE_ATTR(75_percent, S_IRUGO | S_IWUSR,
+ sca3000_query_ring_int,
+ sca3000_set_ring_int,
+ SCA3000_INT_MASK_RING_THREE_QUARTER);
+
+
+/**
* sca3000_show_ring_bpse() -sysfs function to query bits per sample from ring
* @dev: ring buffer device
* @attr: this device attribute
@@ -142,20 +241,18 @@ static ssize_t sca3000_show_ring_bpse(struct device *dev,
char *buf)
{
int len = 0, ret;
- u8 *rx;
struct iio_ring_buffer *ring = dev_get_drvdata(dev);
struct iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- if (rx[1] & SCA3000_RING_BUF_8BIT)
+ if (st->rx[0] & SCA3000_RING_BUF_8BIT)
len = sprintf(buf, "s8/8\n");
else
len = sprintf(buf, "s11/16\n");
- kfree(rx);
error_ret:
mutex_unlock(&st->lock);
@@ -178,20 +275,19 @@ static ssize_t sca3000_store_ring_bpse(struct device *dev,
struct iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data;
int ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
- if (strncmp(buf, "s8/8", 4) == 0) {
+ if (sysfs_streq(buf, "s8/8")) {
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] | SCA3000_RING_BUF_8BIT);
+ st->rx[0] | SCA3000_RING_BUF_8BIT);
st->bpse = 8;
- } else if (strncmp(buf, "s11/16", 5) == 0) {
+ } else if (sysfs_streq(buf, "s11/16")) {
ret = sca3000_write_reg(st, SCA3000_REG_ADDR_MODE,
- rx[1] & ~SCA3000_RING_BUF_8BIT);
+ st->rx[0] & ~SCA3000_RING_BUF_8BIT);
st->bpse = 11;
} else
ret = -EINVAL;
@@ -201,32 +297,22 @@ error_ret:
return ret ? ret : len;
}
-static IIO_SCAN_EL_C(accel_x, 0, 0, NULL);
-static IIO_SCAN_EL_C(accel_y, 1, 0, NULL);
-static IIO_SCAN_EL_C(accel_z, 2, 0, NULL);
-static IIO_CONST_ATTR(accel_type_available, "s8/8 s11/16");
-static IIO_DEVICE_ATTR(accel_type,
- S_IRUGO | S_IWUSR,
- sca3000_show_ring_bpse,
- sca3000_store_ring_bpse,
- 0);
+static ssize_t sca3000_show_buffer_scale(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+ struct iio_dev *indio_dev = ring->indio_dev;
+ struct sca3000_state *st = indio_dev->dev_data;
-static struct attribute *sca3000_scan_el_attrs[] = {
- &iio_scan_el_accel_x.dev_attr.attr,
- &iio_const_attr_accel_x_index.dev_attr.attr,
- &iio_scan_el_accel_y.dev_attr.attr,
- &iio_const_attr_accel_y_index.dev_attr.attr,
- &iio_scan_el_accel_z.dev_attr.attr,
- &iio_const_attr_accel_z_index.dev_attr.attr,
- &iio_const_attr_accel_type_available.dev_attr.attr,
- &iio_dev_attr_accel_type.dev_attr.attr,
- NULL
-};
+ return sprintf(buf, "0.%06d\n", 4*st->info->scale);
+}
-static struct attribute_group sca3000_scan_el_group = {
- .attrs = sca3000_scan_el_attrs,
- .name = "scan_elements",
-};
+static IIO_DEVICE_ATTR(accel_scale,
+ S_IRUGO,
+ sca3000_show_buffer_scale,
+ NULL,
+ 0);
/*
* Ring buffer attributes
@@ -238,6 +324,9 @@ static struct attribute *sca3000_ring_attributes[] = {
&dev_attr_length.attr,
&dev_attr_bytes_per_datum.attr,
&dev_attr_enable.attr,
+ &iio_dev_attr_50_percent.dev_attr.attr,
+ &iio_dev_attr_75_percent.dev_attr.attr,
+ &iio_dev_attr_accel_scale.dev_attr.attr,
NULL,
};
@@ -263,11 +352,12 @@ static struct iio_ring_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
ring = kzalloc(sizeof *ring, GFP_KERNEL);
if (!ring)
return NULL;
+
ring->private = indio_dev;
buf = &ring->buf;
+ buf->stufftoread = 0;
iio_ring_buffer_init(buf, indio_dev);
buf->dev.type = &sca3000_ring_type;
- device_initialize(&buf->dev);
buf->dev.parent = &indio_dev->dev;
dev_set_drvdata(&buf->dev, (void *)buf);
@@ -287,10 +377,14 @@ int sca3000_configure_ring(struct iio_dev *indio_dev)
return -ENOMEM;
indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER;
- indio_dev->ring->scan_el_attrs = &sca3000_scan_el_group;
indio_dev->ring->access.read_first_n = &sca3000_read_first_n_hw_rb;
indio_dev->ring->access.get_length = &sca3000_ring_get_length;
- indio_dev->ring->access.get_bytes_per_datum = &sca3000_ring_get_bytes_per_datum;
+ indio_dev->ring->access.get_bytes_per_datum =
+ &sca3000_ring_get_bytes_per_datum;
+
+ iio_scan_mask_set(indio_dev->ring, 0);
+ iio_scan_mask_set(indio_dev->ring, 1);
+ iio_scan_mask_set(indio_dev->ring, 2);
return 0;
}
@@ -305,22 +399,20 @@ int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = indio_dev->dev_data;
int ret;
- u8 *rx;
mutex_lock(&st->lock);
- ret = sca3000_read_data(st, SCA3000_REG_ADDR_MODE, &rx, 1);
+ ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
if (state) {
printk(KERN_INFO "supposedly enabling ring buffer\n");
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
- (rx[1] | SCA3000_RING_BUF_ENABLE));
+ (st->rx[0] | SCA3000_RING_BUF_ENABLE));
} else
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
- (rx[1] & ~SCA3000_RING_BUF_ENABLE));
- kfree(rx);
+ (st->rx[0] & ~SCA3000_RING_BUF_ENABLE));
error_ret:
mutex_unlock(&st->lock);
@@ -357,13 +449,9 @@ void sca3000_register_ring_funcs(struct iio_dev *indio_dev)
**/
void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring)
{
- /*
- if (val & SCA3000_INT_STATUS_THREE_QUARTERS)
- iio_push_ring_event(ring,
- IIO_EVENT_CODE_RING_75_FULL,
- 0);
- else if (val & SCA3000_INT_STATUS_HALF)
- iio_push_ring_event(ring,
- IIO_EVENT_CODE_RING_50_FULL, 0);
- */
+ if (val & (SCA3000_INT_STATUS_THREE_QUARTERS |
+ SCA3000_INT_STATUS_HALF)) {
+ ring->stufftoread = true;
+ wake_up_interruptible(&ring->pollq);
+ }
}