Browse Source

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>
Jonathan Cameron 14 years ago
parent
commit
25888dc511

+ 22 - 54
drivers/staging/iio/accel/sca3000.h

@@ -158,17 +158,17 @@
 
 /**
  * struct sca3000_state - device instance state information
- * @us: 	 		the associated spi device
- * @info: 	  		chip variant information
- * @indio_dev: 	 		device information used by the IIO core
- * @interrupt_handler_ws: 	event interrupt handler for all events
- * @last_timestamp: 		the timestamp of the last event
- * @mo_det_use_count: 		reference counter for the motion detection unit
- * @lock: 		 	lock used to protect elements of sca3000_state
- * 	 			and the underlying device state.
- * @bpse: 		 	number of bits per scan element
- * @tx: 		 	dma-able transmit buffer
- * @rx: 		 	dma-able receive buffer
+ * @us:			the associated spi device
+ * @info:			chip variant information
+ * @indio_dev:			device information used by the IIO core
+ * @interrupt_handler_ws:	event interrupt handler for all events
+ * @last_timestamp:		the timestamp of the last event
+ * @mo_det_use_count:		reference counter for the motion detection unit
+ * @lock:			lock used to protect elements of sca3000_state
+ *				and the underlying device state.
+ * @bpse:			number of bits per scan element
+ * @tx:			dma-able transmit buffer
+ * @rx:			dma-able receive buffer
  **/
 struct sca3000_state {
 	struct spi_device		*us;
@@ -179,15 +179,15 @@ struct sca3000_state {
 	int				mo_det_use_count;
 	struct mutex			lock;
 	int				bpse;
-	u8				*tx;
-	/* not used during a ring buffer read */
-	u8				*rx;
+	/* Can these share a cacheline ? */
+	u8				rx[2] ____cacheline_aligned;
+	u8				tx[6] ____cacheline_aligned;
 };
 
 /**
  * struct sca3000_chip_info - model dependent parameters
- * @name: 			model identification
- * @scale:			string containing floating point scale factor
+ * @name:			model identification
+ * @scale:			scale * 10^-6
  * @temp_output:		some devices have temperature sensors.
  * @measurement_mode_freq:	normal mode sampling frequency
  * @option_mode_1:		first optional mode. Not all models have one
@@ -200,29 +200,20 @@ struct sca3000_state {
  **/
 struct sca3000_chip_info {
 	const char		*name;
-	const char		*scale;
+	unsigned int		scale;
 	bool			temp_output;
 	int			measurement_mode_freq;
 	int			option_mode_1;
 	int			option_mode_1_freq;
 	int			option_mode_2;
 	int			option_mode_2_freq;
+	int			mot_det_mult_xz[6];
+	int			mot_det_mult_y[7];
 };
 
-/**
- * sca3000_read_data() read a series of values from the device
- * @dev:		device
- * @reg_address_high:	start address (decremented read)
- * @rx:			pointer where received data is placed. Callee
- *			responsible for freeing this.
- * @len:		number of bytes to read
- *
- * The main lock must be held.
- **/
-int sca3000_read_data(struct sca3000_state *st,
-		      u8 reg_address_high,
-		      u8 **rx_p,
-		      int len);
+int sca3000_read_data_short(struct sca3000_state *st,
+			    u8 reg_address_high,
+			    int len);
 
 /**
  * sca3000_write_reg() write a single register
@@ -233,29 +224,6 @@ int sca3000_read_data(struct sca3000_state *st,
  **/
 int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val);
 
-/* Conversion function for use with the ring buffer when in 11bit mode */
-static inline int sca3000_11bit_convert(uint8_t msb, uint8_t lsb)
-{
-	int16_t val;
-
-	val = ((lsb >> 3) & 0x1C) | (msb << 5);
-	val |= (val & (1 << 12)) ? 0xE000 : 0;
-
-	return val;
-}
-
-static inline int sca3000_13bit_convert(uint8_t msb, uint8_t lsb)
-{
-	s16 val;
-
-	val = ((lsb >> 3) & 0x1F) | (msb << 5);
-	/* sign fill */
-	val |= (val & (1 << 12)) ? 0xE000 : 0;
-
-	return val;
-}
-
-
 #ifdef CONFIG_IIO_RING_BUFFER
 /**
  * sca3000_register_ring_funcs() setup the ring state change functions

File diff suppressed because it is too large
+ 251 - 387
drivers/staging/iio/accel/sca3000_core.c


+ 170 - 82
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);
 
@@ -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);
+	}
 }

Some files were not shown because too many files changed in this diff