diff options
author | Jonathan Cameron <jic23@cam.ac.uk> | 2011-05-18 13:41:01 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-19 23:06:13 (GMT) |
commit | 25888dc51163a566f8c8f18a84c100851d12738c (patch) | |
tree | 4fad20bf110b3423d96fe968979a04e3cf1a736a /drivers/staging/iio/accel/sca3000_ring.c | |
parent | 1e3345bc2c118c43f7f8a6db5d71c06e02b989da (diff) | |
download | linux-25888dc51163a566f8c8f18a84c100851d12738c.tar.xz |
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.c | 252 |
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 44f9a56..8efd4f0 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); + } } |