Release 4.7 drivers/staging/iio/accel/sca3000_ring.c
/*
* sca3000_ring.c -- support VTI sca3000 series accelerometers via SPI
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
*
*/
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
#include "../ring_hw.h"
#include "sca3000.h"
/* RFC / future work
*
* The internal ring buffer doesn't actually change what it holds depending
* on which signals are enabled etc, merely whether you can read them.
* As such the scan mode selection is somewhat different than for a software
* ring buffer and changing it actually covers any data already in the buffer.
* Currently scan elements aren't configured so it doesn't matter.
*/
static int sca3000_read_data(struct sca3000_state *st,
u8 reg_address_high,
u8 **rx_p,
int len)
{
int ret;
struct spi_transfer xfer[2] = {
{
.len = 1,
.tx_buf = st->tx,
}, {
.len = len,
}
};
*rx_p = kmalloc(len, GFP_KERNEL);
if (!*rx_p) {
ret = -ENOMEM;
goto error_ret;
}
xfer[1].rx_buf = *rx_p;
st->tx[0] = SCA3000_READ_REG(reg_address_high);
ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 150 | 94.34% | 1 | 25.00% |
lars-peter clausen | lars-peter clausen | 7 | 4.40% | 1 | 25.00% |
bhaktipriya shridhar | bhaktipriya shridhar | 1 | 0.63% | 1 | 25.00% |
ioana ciornei | ioana ciornei | 1 | 0.63% | 1 | 25.00% |
| Total | 159 | 100.00% | 4 | 100.00% |
/**
* sca3000_read_first_n_hw_rb() - main ring access, pulls data from ring
* @r: the ring
* @count: number of samples to try and pull
* @data: output the actual samples pulled from the hw ring
*
* 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.
**/
static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
size_t count, char __user *buf)
{
struct iio_hw_buffer *hw_ring = iio_to_hw_buf(r);
struct iio_dev *indio_dev = hw_ring->private;
struct sca3000_state *st = iio_priv(indio_dev);
u8 *rx;
int ret, i, num_available, num_read = 0;
int bytes_per_sample = 1;
if (st->bpse == 11)
bytes_per_sample = 2;
mutex_lock(&st->lock);
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;
num_available = st->rx[0];
/*
* num_available is the total number of samples available
* i.e. number of time points * number of channels.
*/
if (count > num_available * bytes_per_sample)
num_read = num_available * bytes_per_sample;
else
num_read = count;
ret = sca3000_read_data(st,
SCA3000_REG_ADDR_RING_OUT,
&rx, num_read);
if (ret)
goto error_ret;
for (i = 0; i < num_read / sizeof(u16); i++)
*(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i);
if (copy_to_user(buf, rx, num_read))
ret = -EFAULT;
kfree(rx);
r->stufftoread = 0;
error_ret:
mutex_unlock(&st->lock);
return ret ? ret : num_read;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 250 | 96.90% | 6 | 66.67% |
dan carpenter | dan carpenter | 5 | 1.94% | 1 | 11.11% |
manuel stahl | manuel stahl | 2 | 0.78% | 1 | 11.11% |
aybuke ozdemir | aybuke ozdemir | 1 | 0.39% | 1 | 11.11% |
| Total | 258 | 100.00% | 9 | 100.00% |
static size_t sca3000_ring_buf_data_available(struct iio_buffer *r)
{
return r->stufftoread ? r->watermark : 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
josselin costanzi | josselin costanzi | 22 | 100.00% | 2 | 100.00% |
| Total | 22 | 100.00% | 2 | 100.00% |
/**
* 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_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
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));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 115 | 99.14% | 3 | 75.00% |
lars-peter clausen | lars-peter clausen | 1 | 0.86% | 1 | 25.00% |
| Total | 116 | 100.00% | 4 | 100.00% |
/**
* 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_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
u8 val;
int ret;
mutex_lock(&st->lock);
ret = kstrtou8(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;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 158 | 94.05% | 4 | 57.14% |
manuel stahl | manuel stahl | 7 | 4.17% | 1 | 14.29% |
jingoo han | jingoo han | 2 | 1.19% | 1 | 14.29% |
lars-peter clausen | lars-peter clausen | 1 | 0.60% | 1 | 14.29% |
| Total | 168 | 100.00% | 7 | 100.00% |
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);
static ssize_t sca3000_show_buffer_scale(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct sca3000_state *st = iio_priv(indio_dev);
return sprintf(buf, "0.%06d\n", 4 * st->info->scale);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 55 | 98.21% | 5 | 83.33% |
lars-peter clausen | lars-peter clausen | 1 | 1.79% | 1 | 16.67% |
| Total | 56 | 100.00% | 6 | 100.00% |
static IIO_DEVICE_ATTR(in_accel_scale,
S_IRUGO,
sca3000_show_buffer_scale,
NULL,
0);
/*
* Ring buffer attributes
* This device is a bit unusual in that the sampling frequency and bpse
* only apply to the ring buffer. At all times full rate and accuracy
* is available via direct reading from registers.
*/
static const struct attribute *sca3000_ring_attributes[] = {
&iio_dev_attr_50_percent.dev_attr.attr,
&iio_dev_attr_75_percent.dev_attr.attr,
&iio_dev_attr_in_accel_scale.dev_attr.attr,
NULL,
};
static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev)
{
struct iio_buffer *buf;
struct iio_hw_buffer *ring;
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
if (!ring)
return NULL;
ring->private = indio_dev;
buf = &ring->buf;
buf->stufftoread = 0;
buf->length = 64;
buf->attrs = sca3000_ring_attributes;
iio_buffer_init(buf);
return buf;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 72 | 86.75% | 4 | 50.00% |
lars-peter clausen | lars-peter clausen | 7 | 8.43% | 2 | 25.00% |
ebru akagunduz | ebru akagunduz | 3 | 3.61% | 1 | 12.50% |
greg kroah-hartman | greg kroah-hartman | 1 | 1.20% | 1 | 12.50% |
| Total | 83 | 100.00% | 8 | 100.00% |
static void sca3000_ring_release(struct iio_buffer *r)
{
kfree(iio_to_hw_buf(r));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 18 | 94.74% | 3 | 75.00% |
lars-peter clausen | lars-peter clausen | 1 | 5.26% | 1 | 25.00% |
| Total | 19 | 100.00% | 4 | 100.00% |
static const struct iio_buffer_access_funcs sca3000_ring_access_funcs = {
.read_first_n = &sca3000_read_first_n_hw_rb,
.data_available = sca3000_ring_buf_data_available,
.release = sca3000_ring_release,
.modes = INDIO_BUFFER_HARDWARE,
};
int sca3000_configure_ring(struct iio_dev *indio_dev)
{
struct iio_buffer *buffer;
buffer = sca3000_rb_allocate(indio_dev);
if (!buffer)
return -ENOMEM;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
indio_dev->buffer->access = &sca3000_ring_access_funcs;
iio_device_attach_buffer(indio_dev, buffer);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 43 | 76.79% | 4 | 66.67% |
lars-peter clausen | lars-peter clausen | 12 | 21.43% | 1 | 16.67% |
cristina moraru | cristina moraru | 1 | 1.79% | 1 | 16.67% |
| Total | 56 | 100.00% | 6 | 100.00% |
void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
{
iio_buffer_put(indio_dev->buffer);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 16 | 94.12% | 2 | 66.67% |
lars-peter clausen | lars-peter clausen | 1 | 5.88% | 1 | 33.33% |
| Total | 17 | 100.00% | 3 | 100.00% |
static inline
int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->lock);
ret = sca3000_read_data_short(st, SCA3000_REG_ADDR_MODE, 1);
if (ret)
goto error_ret;
if (state) {
dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n");
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
(st->rx[0] | SCA3000_RING_BUF_ENABLE));
} else
ret = sca3000_write_reg(st,
SCA3000_REG_ADDR_MODE,
(st->rx[0] & ~SCA3000_RING_BUF_ENABLE));
error_ret:
mutex_unlock(&st->lock);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 119 | 95.20% | 3 | 75.00% |
monam agarwal | monam agarwal | 6 | 4.80% | 1 | 25.00% |
| Total | 125 | 100.00% | 4 | 100.00% |
/**
* sca3000_hw_ring_preenable() hw ring buffer preenable function
*
* Very simple enable function as the chip will allows normal reads
* during ring buffer operation so as long as it is indeed running
* before we notify the core, the precise ordering does not matter.
**/
static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev)
{
return __sca3000_hw_ring_state_set(indio_dev, 1);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 19 | 100.00% | 1 | 100.00% |
| Total | 19 | 100.00% | 1 | 100.00% |
static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
{
return __sca3000_hw_ring_state_set(indio_dev, 0);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 19 | 100.00% | 1 | 100.00% |
| Total | 19 | 100.00% | 1 | 100.00% |
static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = {
.preenable = &sca3000_hw_ring_preenable,
.postdisable = &sca3000_hw_ring_postdisable,
};
void sca3000_register_ring_funcs(struct iio_dev *indio_dev)
{
indio_dev->setup_ops = &sca3000_ring_setup_ops;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 17 | 100.00% | 2 | 100.00% |
| Total | 17 | 100.00% | 2 | 100.00% |
/**
* sca3000_ring_int_process() ring specific interrupt handling.
*
* This is only split from the main interrupt handler so as to
* reduce the amount of code if the ring buffer is not enabled.
**/
void sca3000_ring_int_process(u8 val, struct iio_buffer *ring)
{
if (val & (SCA3000_INT_STATUS_THREE_QUARTERS |
SCA3000_INT_STATUS_HALF)) {
ring->stufftoread = true;
wake_up_interruptible(&ring->pollq);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 39 | 100.00% | 3 | 100.00% |
| Total | 39 | 100.00% | 3 | 100.00% |
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
jonathan cameron | jonathan cameron | 1248 | 92.58% | 16 | 45.71% |
lars-peter clausen | lars-peter clausen | 40 | 2.97% | 6 | 17.14% |
josselin costanzi | josselin costanzi | 27 | 2.00% | 2 | 5.71% |
manuel stahl | manuel stahl | 9 | 0.67% | 1 | 2.86% |
monam agarwal | monam agarwal | 6 | 0.45% | 1 | 2.86% |
dan carpenter | dan carpenter | 5 | 0.37% | 1 | 2.86% |
tejun heo | tejun heo | 3 | 0.22% | 1 | 2.86% |
ebru akagunduz | ebru akagunduz | 3 | 0.22% | 1 | 2.86% |
jingoo han | jingoo han | 2 | 0.15% | 1 | 2.86% |
bhaktipriya shridhar | bhaktipriya shridhar | 1 | 0.07% | 1 | 2.86% |
aybuke ozdemir | aybuke ozdemir | 1 | 0.07% | 1 | 2.86% |
ioana ciornei | ioana ciornei | 1 | 0.07% | 1 | 2.86% |
cristina moraru | cristina moraru | 1 | 0.07% | 1 | 2.86% |
greg kroah-hartman | greg kroah-hartman | 1 | 0.07% | 1 | 2.86% |
| Total | 1348 | 100.00% | 35 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.