|
@@ -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);
|
|
|
|
|
@@ -131,6 +160,76 @@ static IIO_RING_ENABLE_ATTR;
|
|
|
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
|
|
@@ -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);
|
|
|
+ }
|
|
|
}
|