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:
Родитель
1e3345bc2c
Коммит
25888dc511
|
@ -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
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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);
|
||||
&rx, num_read);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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,33 +297,23 @@ 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,
|
||||
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;
|
||||
|
||||
return sprintf(buf, "0.%06d\n", 4*st->info->scale);
|
||||
}
|
||||
|
||||
static IIO_DEVICE_ATTR(accel_scale,
|
||||
S_IRUGO,
|
||||
sca3000_show_buffer_scale,
|
||||
NULL,
|
||||
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
|
||||
* 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_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);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче