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>
This commit is contained in:
Jonathan Cameron 2011-05-18 14:41:01 +01:00 committed by Greg Kroah-Hartman
parent 1e3345bc2c
commit 25888dc511
3 changed files with 514 additions and 713 deletions

View file

@ -158,17 +158,17 @@
/** /**
* struct sca3000_state - device instance state information * struct sca3000_state - device instance state information
* @us: the associated spi device * @us: the associated spi device
* @info: chip variant information * @info: chip variant information
* @indio_dev: device information used by the IIO core * @indio_dev: device information used by the IIO core
* @interrupt_handler_ws: event interrupt handler for all events * @interrupt_handler_ws: event interrupt handler for all events
* @last_timestamp: the timestamp of the last event * @last_timestamp: the timestamp of the last event
* @mo_det_use_count: reference counter for the motion detection unit * @mo_det_use_count: reference counter for the motion detection unit
* @lock: lock used to protect elements of sca3000_state * @lock: lock used to protect elements of sca3000_state
* and the underlying device state. * and the underlying device state.
* @bpse: number of bits per scan element * @bpse: number of bits per scan element
* @tx: dma-able transmit buffer * @tx: dma-able transmit buffer
* @rx: dma-able receive buffer * @rx: dma-able receive buffer
**/ **/
struct sca3000_state { struct sca3000_state {
struct spi_device *us; struct spi_device *us;
@ -179,15 +179,15 @@ struct sca3000_state {
int mo_det_use_count; int mo_det_use_count;
struct mutex lock; struct mutex lock;
int bpse; int bpse;
u8 *tx; /* Can these share a cacheline ? */
/* not used during a ring buffer read */ u8 rx[2] ____cacheline_aligned;
u8 *rx; u8 tx[6] ____cacheline_aligned;
}; };
/** /**
* struct sca3000_chip_info - model dependent parameters * struct sca3000_chip_info - model dependent parameters
* @name: model identification * @name: model identification
* @scale: string containing floating point scale factor * @scale: scale * 10^-6
* @temp_output: some devices have temperature sensors. * @temp_output: some devices have temperature sensors.
* @measurement_mode_freq: normal mode sampling frequency * @measurement_mode_freq: normal mode sampling frequency
* @option_mode_1: first optional mode. Not all models have one * @option_mode_1: first optional mode. Not all models have one
@ -200,29 +200,20 @@ struct sca3000_state {
**/ **/
struct sca3000_chip_info { struct sca3000_chip_info {
const char *name; const char *name;
const char *scale; unsigned int scale;
bool temp_output; bool temp_output;
int measurement_mode_freq; int measurement_mode_freq;
int option_mode_1; int option_mode_1;
int option_mode_1_freq; int option_mode_1_freq;
int option_mode_2; int option_mode_2;
int option_mode_2_freq; int option_mode_2_freq;
int mot_det_mult_xz[6];
int mot_det_mult_y[7];
}; };
/** int sca3000_read_data_short(struct sca3000_state *st,
* sca3000_read_data() read a series of values from the device u8 reg_address_high,
* @dev: device int len);
* @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);
/** /**
* sca3000_write_reg() write a single register * 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); 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 #ifdef CONFIG_IIO_RING_BUFFER
/** /**
* sca3000_register_ring_funcs() setup the ring state change functions * sca3000_register_ring_funcs() setup the ring state change functions

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include "../iio.h" #include "../iio.h"
#include "../sysfs.h" #include "../sysfs.h"
@ -34,6 +36,44 @@
* Currently scan elements aren't configured so it doesn't matter. * 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 * sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring
* @r: the ring * @r: the ring
@ -45,8 +85,6 @@
* Currently does not provide timestamps. As the hardware doesn't add them they * 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 * 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. * 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, static int sca3000_read_first_n_hw_rb(struct iio_ring_buffer *r,
size_t count, char __user *buf, 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 iio_dev *indio_dev = hw_ring->private;
struct sca3000_state *st = indio_dev->dev_data; struct sca3000_state *st = indio_dev->dev_data;
u8 *rx; u8 *rx;
s16 *samples;
int ret, i, num_available, num_read = 0; int ret, i, num_available, num_read = 0;
int bytes_per_sample = 1; int bytes_per_sample = 1;
u8 *datas;
u8 **data = &datas;
if (st->bpse == 11) if (st->bpse == 11)
bytes_per_sample = 2; bytes_per_sample = 2;
mutex_lock(&st->lock); mutex_lock(&st->lock);
/* Check how much data is available: if (count % bytes_per_sample) {
* RFC: Implement an ioctl to not bother checking whether there ret = -EINVAL;
* is enough data in the ring? Afterall, if we are responding goto error_ret;
* 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_short(st, SCA3000_REG_ADDR_BUF_COUNT, 1);
ret = sca3000_read_data(st,
SCA3000_REG_ADDR_BUF_COUNT,
&rx, 1);
if (ret) if (ret)
goto error_ret; goto error_ret;
else else
num_available = rx[1]; num_available = st->rx[0];
/* num_available is the total number of samples available /*
* num_available is the total number of samples available
* i.e. number of time points * number of channels. * i.e. number of time points * number of channels.
*/ */
kfree(rx);
if (count > num_available * bytes_per_sample) if (count > num_available * bytes_per_sample)
num_read = num_available*bytes_per_sample; num_read = num_available*bytes_per_sample;
else else
num_read = count - (count % (bytes_per_sample)); num_read = count;
/* Avoid the read request byte */
*dead_offset = 1;
ret = sca3000_read_data(st, ret = sca3000_read_data(st,
SCA3000_REG_ADDR_RING_OUT, SCA3000_REG_ADDR_RING_OUT,
data, num_read); &rx, num_read);
if (ret)
goto error_ret;
/* Convert byte order and shift to default resolution */ for (i = 0; i < num_read; i++)
if (st->bpse == 11) { *(((u16 *)rx) + i) = be16_to_cpup((u16 *)rx + i);
samples = (s16*)(*data+1);
for (i = 0; i < (num_read/2); i++) {
samples[i] = be16_to_cpup(
(__be16 *)&(samples[i]));
samples[i] >>= 3;
}
}
if (copy_to_user(buf, rx, num_read))
ret = -EFAULT;
kfree(rx);
r->stufftoread = 0;
error_ret: error_ret:
mutex_unlock(&st->lock); mutex_unlock(&st->lock);
@ -131,6 +160,76 @@ static IIO_RING_ENABLE_ATTR;
static IIO_RING_BYTES_PER_DATUM_ATTR; static IIO_RING_BYTES_PER_DATUM_ATTR;
static IIO_RING_LENGTH_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 * sca3000_show_ring_bpse() -sysfs function to query bits per sample from ring
* @dev: ring buffer device * @dev: ring buffer device
@ -142,20 +241,18 @@ static ssize_t sca3000_show_ring_bpse(struct device *dev,
char *buf) char *buf)
{ {
int len = 0, ret; int len = 0, ret;
u8 *rx;
struct iio_ring_buffer *ring = dev_get_drvdata(dev); struct iio_ring_buffer *ring = dev_get_drvdata(dev);
struct iio_dev *indio_dev = ring->indio_dev; struct iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data; struct sca3000_state *st = indio_dev->dev_data;
mutex_lock(&st->lock); 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) if (ret)
goto error_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"); len = sprintf(buf, "s8/8\n");
else else
len = sprintf(buf, "s11/16\n"); len = sprintf(buf, "s11/16\n");
kfree(rx);
error_ret: error_ret:
mutex_unlock(&st->lock); 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 iio_dev *indio_dev = ring->indio_dev;
struct sca3000_state *st = indio_dev->dev_data; struct sca3000_state *st = indio_dev->dev_data;
int ret; int ret;
u8 *rx;
mutex_lock(&st->lock); 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) if (ret)
goto error_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, 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; 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, 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; st->bpse = 11;
} else } else
ret = -EINVAL; ret = -EINVAL;
@ -201,33 +297,23 @@ error_ret:
return ret ? ret : len; return ret ? ret : len;
} }
static IIO_SCAN_EL_C(accel_x, 0, 0, NULL); static ssize_t sca3000_show_buffer_scale(struct device *dev,
static IIO_SCAN_EL_C(accel_y, 1, 0, NULL); struct device_attribute *attr,
static IIO_SCAN_EL_C(accel_z, 2, 0, NULL); char *buf)
static IIO_CONST_ATTR(accel_type_available, "s8/8 s11/16"); {
static IIO_DEVICE_ATTR(accel_type, struct iio_ring_buffer *ring = dev_get_drvdata(dev);
S_IRUGO | S_IWUSR, struct iio_dev *indio_dev = ring->indio_dev;
sca3000_show_ring_bpse, struct sca3000_state *st = indio_dev->dev_data;
sca3000_store_ring_bpse,
return sprintf(buf, "0.%06d\n", 4*st->info->scale);
}
static IIO_DEVICE_ATTR(accel_scale,
S_IRUGO,
sca3000_show_buffer_scale,
NULL,
0); 0);
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
};
static struct attribute_group sca3000_scan_el_group = {
.attrs = sca3000_scan_el_attrs,
.name = "scan_elements",
};
/* /*
* Ring buffer attributes * Ring buffer attributes
* This device is a bit unusual in that the sampling frequency and bpse * This device is a bit unusual in that the sampling frequency and bpse
@ -238,6 +324,9 @@ static struct attribute *sca3000_ring_attributes[] = {
&dev_attr_length.attr, &dev_attr_length.attr,
&dev_attr_bytes_per_datum.attr, &dev_attr_bytes_per_datum.attr,
&dev_attr_enable.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, NULL,
}; };
@ -263,11 +352,12 @@ static struct iio_ring_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
ring = kzalloc(sizeof *ring, GFP_KERNEL); ring = kzalloc(sizeof *ring, GFP_KERNEL);
if (!ring) if (!ring)
return NULL; return NULL;
ring->private = indio_dev; ring->private = indio_dev;
buf = &ring->buf; buf = &ring->buf;
buf->stufftoread = 0;
iio_ring_buffer_init(buf, indio_dev); iio_ring_buffer_init(buf, indio_dev);
buf->dev.type = &sca3000_ring_type; buf->dev.type = &sca3000_ring_type;
device_initialize(&buf->dev);
buf->dev.parent = &indio_dev->dev; buf->dev.parent = &indio_dev->dev;
dev_set_drvdata(&buf->dev, (void *)buf); dev_set_drvdata(&buf->dev, (void *)buf);
@ -287,10 +377,14 @@ int sca3000_configure_ring(struct iio_dev *indio_dev)
return -ENOMEM; return -ENOMEM;
indio_dev->modes |= INDIO_RING_HARDWARE_BUFFER; 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.read_first_n = &sca3000_read_first_n_hw_rb;
indio_dev->ring->access.get_length = &sca3000_ring_get_length; 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; 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; struct sca3000_state *st = indio_dev->dev_data;
int ret; int ret;
u8 *rx;
mutex_lock(&st->lock); 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) if (ret)
goto error_ret; goto error_ret;
if (state) { if (state) {
printk(KERN_INFO "supposedly enabling ring buffer\n"); printk(KERN_INFO "supposedly enabling ring buffer\n");
ret = sca3000_write_reg(st, ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE, SCA3000_REG_ADDR_MODE,
(rx[1] | SCA3000_RING_BUF_ENABLE)); (st->rx[0] | SCA3000_RING_BUF_ENABLE));
} else } else
ret = sca3000_write_reg(st, ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE, SCA3000_REG_ADDR_MODE,
(rx[1] & ~SCA3000_RING_BUF_ENABLE)); (st->rx[0] & ~SCA3000_RING_BUF_ENABLE));
kfree(rx);
error_ret: error_ret:
mutex_unlock(&st->lock); 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) void sca3000_ring_int_process(u8 val, struct iio_ring_buffer *ring)
{ {
/* if (val & (SCA3000_INT_STATUS_THREE_QUARTERS |
if (val & SCA3000_INT_STATUS_THREE_QUARTERS) SCA3000_INT_STATUS_HALF)) {
iio_push_ring_event(ring, ring->stufftoread = true;
IIO_EVENT_CODE_RING_75_FULL, wake_up_interruptible(&ring->pollq);
0); }
else if (val & SCA3000_INT_STATUS_HALF)
iio_push_ring_event(ring,
IIO_EVENT_CODE_RING_50_FULL, 0);
*/
} }