From: Hartmut Knaack <knaack.h@gmx.de>
To: Octavian Purdila <octavian.purdila@intel.com>, linux-iio@vger.kernel.org
Cc: srinivas.pandruvada@intel.com
Subject: Re: [RFC 8/8] iio: bmc150: add support for hardware fifo
Date: Mon, 24 Nov 2014 11:37:24 +0100 [thread overview]
Message-ID: <54730A64.3060003@gmx.de> (raw)
In-Reply-To: <1416246966-3083-9-git-send-email-octavian.purdila@intel.com>
Octavian Purdila schrieb am 17.11.2014 18:56:
> This patch adds support for hardware fifo. Fifo and stream mode are
> supported as well as fifo-full and fifo-watermark events.
>
> Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
> ---
> drivers/iio/accel/bmc150-accel.c | 249 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 243 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
> index 72d2dca..404cfec 100644
> --- a/drivers/iio/accel/bmc150-accel.c
> +++ b/drivers/iio/accel/bmc150-accel.c
> @@ -67,7 +67,9 @@
> #define BMC150_ACCEL_INT_MAP_0_BIT_SLOPE BIT(2)
>
> #define BMC150_ACCEL_REG_INT_MAP_1 0x1A
> -#define BMC150_ACCEL_INT_MAP_1_BIT_DATA BIT(0)
> +#define BMC150_ACCEL_INT_MAP_1_BIT_DATA BIT(0)
> +#define BMC150_ACCEL_INT_MAP_1_BIT_FWM BIT(1)
> +#define BMC150_ACCEL_INT_MAP_1_BIT_FFULL BIT(2)
>
> #define BMC150_ACCEL_REG_INT_RST_LATCH 0x21
> #define BMC150_ACCEL_INT_MODE_LATCH_RESET 0x80
> @@ -80,7 +82,9 @@
> #define BMC150_ACCEL_INT_EN_BIT_SLP_Z BIT(2)
>
> #define BMC150_ACCEL_REG_INT_EN_1 0x17
> -#define BMC150_ACCEL_INT_EN_BIT_DATA_EN BIT(4)
> +#define BMC150_ACCEL_INT_EN_BIT_DATA_EN BIT(4)
> +#define BMC150_ACCEL_INT_EN_BIT_FFULL_EN BIT(5)
> +#define BMC150_ACCEL_INT_EN_BIT_FWM_EN BIT(6)
>
> #define BMC150_ACCEL_REG_INT_OUT_CTRL 0x20
> #define BMC150_ACCEL_INT_OUT_CTRL_INT1_LVL BIT(0)
> @@ -119,6 +123,13 @@
> #define BMC150_ACCEL_AXIS_TO_REG(axis) (BMC150_ACCEL_REG_XOUT_L + (axis * 2))
> #define BMC150_AUTO_SUSPEND_DELAY_MS 2000
>
> +#define BMC150_ACCEL_REG_FIFO_STATUS 0x0E
> +#define BMC150_ACCEL_REG_FIFO_CONFIG0 0x30
> +#define BMC150_ACCEL_REG_FIFO_CONFIG1 0x3E
> +#define BMC150_ACCEL_REG_FIFO_DATA 0x3F
> +#define BMC150_ACCEL_REG_FIFO_
Something got lost here?
> +#define BMC150_ACCEL_FIFO_LENGTH 32
> +
> enum bmc150_accel_axis {
> AXIS_X,
> AXIS_Y,
> @@ -177,12 +188,13 @@ struct bmc150_accel_event {
> u32 duration;
> u32 threshold;
> } slope;
> + u8 watermark;
> };
> };
>
> -#define BMC150_ACCEL_INTERRUPTS 2
> +#define BMC150_ACCEL_INTERRUPTS 4
> #define BMC150_ACCEL_TRIGGERS 2
> -#define BMC150_ACCEL_EVENTS 1
> +#define BMC150_ACCEL_EVENTS 3
>
> struct bmc150_accel_data {
> struct i2c_client *client;
> @@ -191,6 +203,7 @@ struct bmc150_accel_data {
> struct bmc150_accel_trigger triggers[BMC150_ACCEL_TRIGGERS];
> struct bmc150_accel_event events[BMC150_ACCEL_EVENTS];
> struct mutex mutex;
> + int fifo_mode;
> s16 buffer[8];
> u8 bw_bits;
> u32 range;
> @@ -483,6 +496,18 @@ bmc150_accel_interrupts[BMC150_ACCEL_INTERRUPTS] = {
> BMC150_ACCEL_INT_EN_BIT_SLP_Y |
> BMC150_ACCEL_INT_EN_BIT_SLP_Z
> },
> + { /* fifo full interrupt */
> + .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
> + .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_FFULL,
> + .en_reg = BMC150_ACCEL_REG_INT_EN_1,
> + .en_bitmask = BMC150_ACCEL_INT_EN_BIT_FFULL_EN,
> + },
> + { /* fifo watermark interrupt */
> + .map_reg = BMC150_ACCEL_REG_INT_MAP_1,
> + .map_bitmask = BMC150_ACCEL_INT_MAP_1_BIT_FWM,
> + .en_reg = BMC150_ACCEL_REG_INT_EN_1,
> + .en_bitmask = BMC150_ACCEL_INT_EN_BIT_FWM_EN,
> + },
> };
>
> static void bmc150_accel_interrupts_setup(struct iio_dev *indio_dev,
> @@ -699,11 +724,85 @@ static int bmc150_accel_read_raw(struct iio_dev *indio_dev,
> ret = bmc150_accel_get_bw(data, val, val2);
> mutex_unlock(&data->mutex);
> return ret;
> + case IIO_CHAN_INFO_FIFO_LENGTH:
> + *val2 = 0;
> + *val = BMC150_ACCEL_FIFO_LENGTH;
> + return IIO_VAL_INT;
> default:
> return -EINVAL;
> }
> }
>
> +static int bmc150_accel_fifo_flush(struct iio_dev *indio_dev)
> +{
> + struct bmc150_accel_data *data = iio_priv(indio_dev);
> + int ret, i;
> + u8 count;
> + u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
> + u8 reg_fifo_data = BMC150_ACCEL_REG_FIFO_DATA;
> + struct i2c_msg msg[2];
> + int64_t tstamp;
> + int sample_freq = 0, sec, ms;
> +
> + ret = bmc150_accel_get_bw(data, &sec, &ms);
> + if (ret == 0)
ret can be IIO_VAL_INT_PLUS_MICRO or -EINVAL, but not 0.
> + sample_freq = sec * 1000000000 + ms * 1000;
> +
> + ret = i2c_smbus_read_byte_data(data->client,
> + BMC150_ACCEL_REG_FIFO_STATUS);
> + if (ret < 0) {
> + dev_err(&indio_dev->dev, "Error reading reg_fifo_status\n");
> + return ret;
> + }
> +
> + count = ret & 0x7F;
> +
> + i = i2c_smbus_read_byte_data(data->client,
> + BMC150_ACCEL_REG_FIFO_CONFIG1);
This read doesn't seem to serve a purpose
> + if (!count)
> + return 0;
> +
> + msg[0].addr = data->client->addr;
> + msg[0].flags = 0;
> + msg[0].buf = ®_fifo_data;
> + msg[0].len = sizeof(reg_fifo_data);
> +
> + msg[1].addr = data->client->addr;
> + msg[1].flags = I2C_M_RD;
> + msg[1].buf = (u8 *)buffer;
> + msg[1].len = count * 3 * 2;
> +
> + ret = i2c_transfer(data->client->adapter, msg, 2);
> + if (ret != 2) {
> + dev_err(&indio_dev->dev, "Error reading reg_fifo_data\n");
> + return ret;
> + }
> +
> + if (!data->timestamp)
> + data->timestamp = iio_get_time_ns();
> +
> + tstamp = data->timestamp - count * sample_freq;
> +
> + for (i = 0; i < count; i++) {
> + u16 sample[8];
> + int j, bit;
> +
> + j = 0;
> + for_each_set_bit(bit, indio_dev->buffer->scan_mask,
> + indio_dev->masklength) {
> + memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
> + }
> +
> + iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
> +
> + tstamp += sample_freq;
> + }
> +
> + data->timestamp = 0;
> +
> + return 0;
> +}
> +
> static int bmc150_accel_write_raw(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan,
> int val, int val2, long mask)
> @@ -725,6 +824,8 @@ static int bmc150_accel_write_raw(struct iio_dev *indio_dev,
> ret = bmc150_accel_set_scale(data, val2);
> mutex_unlock(&data->mutex);
> return ret;
> + case IIO_CHAN_INFO_FIFO_FLUSH:
> + return bmc150_accel_fifo_flush(indio_dev);
You may want to trigger this for specific values written to that file?
> default:
> ret = -EINVAL;
> }
> @@ -764,6 +865,22 @@ static int bmc150_accel_event_roc_read(struct bmc150_accel_event *event,
> return IIO_VAL_INT;
> }
>
> +static int bmc150_accel_event_watermark_read(struct bmc150_accel_event *event,
> + enum iio_event_info info,
> + int *val, int *val2)
> +{
> + *val2 = 0;
> + switch (info) {
> + case IIO_EV_INFO_VALUE:
> + *val = event->watermark;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + return IIO_VAL_INT;
> +}
> +
> static int bmc150_accel_read_event(struct iio_dev *indio_dev,
> const struct iio_chan_spec *chan,
> enum iio_event_type type,
> @@ -807,6 +924,38 @@ static int bmc150_accel_event_roc_write(struct bmc150_accel_event *event,
> return ret;
> }
>
> +static int bmc150_accel_event_watermark_write(struct bmc150_accel_event *event,
> + enum iio_event_info info,
> + int val, int val2)
> +{
> + struct bmc150_accel_data *data = event->data;
> + int ret;
> +
> +
> + switch (info) {
> + case IIO_EV_INFO_VALUE:
> + if (val > BMC150_ACCEL_FIFO_LENGTH) {
> + ret = -EINVAL;
> + break;
> + }
> + mutex_lock(&data->mutex);
> + ret = i2c_smbus_write_byte_data(data->client,
> + BMC150_ACCEL_REG_FIFO_CONFIG0,
> + val);
> + if (ret < 0) {
> + dev_err(&data->client->dev, "Error writing reg_fifo_config0\n");
> + break;
> + }
> + event->watermark = val;
> + mutex_unlock(&data->mutex);
> + break;
> + default:
> + ret = -EINVAL;
> + }
> +
> + return ret;
> +}
> +
> static int bmc150_accel_write_event(struct iio_dev *indio_dev,
> const struct iio_chan_spec *chan,
> enum iio_event_type type,
> @@ -900,6 +1049,76 @@ static const struct iio_event_spec bmc150_accel_events[BMC150_ACCEL_EVENTS] = {
> BIT(IIO_EV_INFO_ENABLE) |
> BIT(IIO_EV_INFO_PERIOD)
> },
> + {
> + .type = IIO_EV_TYPE_FIFO_FULL,
> + .dir = IIO_EV_DIR_RISING,
> + .mask_separate = BIT(IIO_EV_INFO_ENABLE)
> + },
> + {
> + .type = IIO_EV_TYPE_FIFO_WATERMARK,
> + .dir = IIO_EV_DIR_RISING,
> + .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
> + BIT(IIO_EV_INFO_VALUE)
> + },
> +};
> +
> +
> +static const char * const bmc150_accel_fifo_modes[] = {
> + "disabled",
> + "fifo",
> + "stream"
> +};
> +
> +static int bmc150_accel_fifo_mode_set(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + unsigned int mode)
> +{
> + struct bmc150_accel_data *data = iio_priv(indio_dev);
> + int ret;
> + u8 val;
> +
> + switch (mode) {
> + case 0:
> + val = 0;
> + break;
> + case 1:
> + val = 0x40;
> + break;
> + case 2:
> + val = 0x80;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + ret = i2c_smbus_write_byte_data(data->client,
> + BMC150_ACCEL_REG_FIFO_CONFIG1, val);
> + if (ret < 0)
> + dev_err(&indio_dev->dev, "Error writing reg_fifo_config1\n");
> +
> + data->fifo_mode = mode;
> +
> + return ret;
> +}
> +
> +static int bmc150_accel_fifo_mode_get(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan)
> +{
> + struct bmc150_accel_data *data = iio_priv(indio_dev);
> +
> + return data->fifo_mode;
> +}
> +
> +static const struct iio_enum bmc150_accel_fifo_mode_enum = {
> + .items = bmc150_accel_fifo_modes,
> + .num_items = ARRAY_SIZE(bmc150_accel_fifo_modes),
> + .set = bmc150_accel_fifo_mode_set,
> + .get = bmc150_accel_fifo_mode_get,
> +};
> +
> +static const struct iio_chan_spec_ext_info bmc150_accel_ext_info[] = {
> + IIO_FIFO_EXT_INFO(&bmc150_accel_fifo_mode_enum, IIO_SHARED_BY_TYPE),
> + {},
> };
>
> #define BMC150_ACCEL_CHANNEL(_axis, bits) { \
> @@ -908,7 +1127,9 @@ static const struct iio_event_spec bmc150_accel_events[BMC150_ACCEL_EVENTS] = {
> .channel2 = IIO_MOD_##_axis, \
> .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
> .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
> - BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
> + BIT(IIO_CHAN_INFO_FIFO_LENGTH) | \
> + BIT(IIO_CHAN_INFO_FIFO_FLUSH), \
> .scan_index = AXIS_##_axis, \
> .scan_type = { \
> .sign = 's', \
> @@ -917,7 +1138,8 @@ static const struct iio_event_spec bmc150_accel_events[BMC150_ACCEL_EVENTS] = {
> .shift = 16 - (bits), \
> }, \
> .event_spec = bmc150_accel_events, \
> - .num_event_specs = ARRAY_SIZE(bmc150_accel_events) \
> + .num_event_specs = ARRAY_SIZE(bmc150_accel_events), \
> + .ext_info = bmc150_accel_ext_info, \
> }
>
> #define BMC150_ACCEL_CHANNELS(bits) { \
> @@ -1286,6 +1508,17 @@ static struct {
> .read = bmc150_accel_event_roc_read,
> .write = bmc150_accel_event_roc_write,
> },
> + {
> + .intr = 2,
> + .type = IIO_EV_TYPE_FIFO_FULL,
> + },
> + {
> + .intr = 3,
> + .type = IIO_EV_TYPE_FIFO_WATERMARK,
> + .read = bmc150_accel_event_watermark_read,
> + .write = bmc150_accel_event_watermark_write,
> + },
> +
> };
>
> static void bmc150_accel_events_setup(struct iio_dev *indio_dev,
> @@ -1460,6 +1693,7 @@ static int bmc150_accel_resume(struct device *dev)
> mutex_lock(&data->mutex);
> if (atomic_read(&data->active_intr))
> bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
> + bmc150_accel_fifo_mode_set(indio_dev, NULL, data->fifo_mode);
> mutex_unlock(&data->mutex);
>
> return 0;
> @@ -1489,6 +1723,9 @@ static int bmc150_accel_runtime_resume(struct device *dev)
> ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
> if (ret < 0)
> return ret;
> + ret = bmc150_accel_fifo_mode_set(indio_dev, NULL, data->fifo_mode);
> + if (ret < 0)
> + return ret;
>
> sleep_val = bmc150_accel_get_startup_times(data);
> if (sleep_val < 20)
>
next prev parent reply other threads:[~2014-11-24 10:37 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-17 17:55 [RFC 0/8] iio: add support for hardware fifo Octavian Purdila
2014-11-17 17:55 ` [RFC 1/8] " Octavian Purdila
2014-11-18 13:37 ` jic23
2014-11-18 15:21 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 2/8] iio: bmc150: refactor slope duration and threshold update Octavian Purdila
2014-11-23 21:58 ` Hartmut Knaack
2014-11-23 22:16 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 3/8] iio: bmc150: refactor interrupt enabling Octavian Purdila
2014-11-23 22:02 ` Hartmut Knaack
2014-11-23 22:24 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 4/8] iio: bmc150: exit early if event / trigger state is not changed Octavian Purdila
2014-11-17 17:56 ` [RFC 5/8] iio: bmc150: introduce bmc150_accel_interrupt Octavian Purdila
2014-11-17 17:56 ` [RFC 6/8] iio: bmc150: introduce bmc150_accel_trigger Octavian Purdila
2014-11-23 23:06 ` Hartmut Knaack
2014-11-24 10:42 ` Octavian Purdila
2014-11-24 20:26 ` Hartmut Knaack
2014-11-25 16:06 ` Octavian Purdila
2014-11-17 17:56 ` [RFC 7/8] iio: bmc150: introduce bmc150_accel_event Octavian Purdila
2014-11-17 17:56 ` [RFC 8/8] iio: bmc150: add support for hardware fifo Octavian Purdila
2014-11-18 13:49 ` jic23
2014-11-18 15:31 ` Octavian Purdila
2014-11-24 10:37 ` Hartmut Knaack [this message]
2014-11-18 13:24 ` [RFC 0/8] iio: " jic23
2014-11-18 15:03 ` Octavian Purdila
2014-11-18 16:44 ` Lars-Peter Clausen
2014-11-18 17:04 ` Octavian Purdila
2014-11-18 17:23 ` Lars-Peter Clausen
2014-11-18 19:35 ` Octavian Purdila
2014-11-19 11:48 ` Lars-Peter Clausen
2014-11-19 12:33 ` Octavian Purdila
2014-12-12 12:57 ` Jonathan Cameron
2014-11-19 13:32 ` Octavian Purdila
2014-11-26 13:06 ` Octavian Purdila
2014-12-01 21:19 ` Lars-Peter Clausen
2014-12-02 9:13 ` Octavian Purdila
2014-12-12 13:10 ` Jonathan Cameron
2014-12-12 13:04 ` Jonathan Cameron
2014-12-12 12:52 ` Jonathan Cameron
2014-11-18 15:35 ` Pandruvada, Srinivas
2014-11-18 16:41 ` Lars-Peter Clausen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54730A64.3060003@gmx.de \
--to=knaack.h@gmx.de \
--cc=linux-iio@vger.kernel.org \
--cc=octavian.purdila@intel.com \
--cc=srinivas.pandruvada@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.