Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25888dc5 authored by Jonathan Cameron's avatar Jonathan Cameron Committed by Greg Kroah-Hartman
Browse files

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: default avatarJonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 1e3345bc
Loading
Loading
Loading
Loading
+22 −54
Original line number Diff line number Diff line
@@ -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
 * @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,28 +200,19 @@ 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,
int sca3000_read_data_short(struct sca3000_state *st,
			    u8 reg_address_high,
		      u8 **rx_p,
			    int len);

/**
@@ -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
+318 −573

File changed.

Preview size limit exceeded, changes collapsed.

+170 −82
Original line number Diff line number Diff line
@@ -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);
	}
}