From: Jonathan Cameron <jic23-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
To: Lukasz Czerwinski
<l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>,
jic23-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org
Cc: denis.ciocca-qxv4g6HH51o@public.gmane.org,
linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [RFC v2 PATCH 06/14] iio: st_common: Add threshold events support
Date: Tue, 01 Oct 2013 17:09:14 +0100 [thread overview]
Message-ID: <524AF3AA.9060801@kernel.org> (raw)
In-Reply-To: <1380299538-22047-7-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
On 09/27/13 17:32, Lukasz Czerwinski wrote:
> This patch adds threshold events support for the ST common
> library.
>
> Signed-off-by: Lukasz Czerwinski <l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Signed-off-by: Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Hi Lukasz,
Note that we are moving over to a more adaptable way of event registration.
This driver will need updating to match that, but this review is conducted
against the old method.
If you are happy to do the update, that's great. If not such is life and
someone else will have to pick it up before we can drop the old method.
A few minor bits inline.
> ---
> drivers/iio/common/st_sensors/st_sensors_core.c | 209 ++++++++++++++++++++++-
> include/linux/iio/common/st_sensors.h | 74 ++++++++
> 2 files changed, 282 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
> index 697b16d..98fb425 100644
> --- a/drivers/iio/common/st_sensors/st_sensors_core.c
> +++ b/drivers/iio/common/st_sensors/st_sensors_core.c
> @@ -13,7 +13,9 @@
> #include <linux/slab.h>
> #include <linux/delay.h>
> #include <linux/iio/iio.h>
> +#include <linux/iio/events.h>
> #include <asm/unaligned.h>
> +#include <linux/interrupt.h>
>
> #include <linux/iio/common/st_sensors.h>
>
> @@ -339,7 +341,12 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
>
> *val = *val >> ch->scan_type.shift;
>
> - err = st_sensors_set_enable(indio_dev, false);
> + /*
> + * When events are enabled sensor should be always enabled.
> + * It prevents unnecessary sensor off.
> + */
> + if (!sdata->events_flag)
> + err = st_sensors_set_enable(indio_dev, false);
> }
> out:
> mutex_unlock(&indio_dev->mlock);
> @@ -465,6 +472,206 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
> }
> EXPORT_SYMBOL(st_sensors_sysfs_scale_avail);
>
This should get simpler after Lars' series but will still be a little
ugly. Ah well, only occurs in relatively slow paths.
> +static struct st_sensor_event *st_sensor_find_event_data(struct
> + st_sensor_data * sdata, u64 event_code)
> +{
> + int mod = IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code);
> + int chan_type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event_code);
> + int type = IIO_EVENT_CODE_EXTRACT_TYPE(event_code);
> + int dir = IIO_EVENT_CODE_EXTRACT_DIR(event_code);
> + struct st_sensor_event_irq *irq = &sdata->sensor->event_irq;
> + struct st_sensor_event *event;
> + int i;
> +
If either of these two tests fails and you get here, hasn't
something gone horribly wrong?
> + if (!irq)
> + return NULL;
> +
> + if (irq->event_count == 0)
> + return NULL;
> +
> + for (i = 0; i < irq->event_count; i++) {
> + event = &irq->events[i];
> +
> + if (event->modifier == mod &&
> + event->chan_type == chan_type &&
> + event->event_type == type &&
> + event->direction == dir)
> + return event;
> + }
> + return NULL;
> +}
> +
> +int st_sensors_read_event_config(struct iio_dev *indio_dev,
> + u64 event_code)
> +{
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event *event =
> + st_sensor_find_event_data(sdata, event_code);
> +
> + if (!event || !sdata->events_enabled)
> + return -EINVAL;
> +
> + return (bool)(sdata->events_flag & (1 << event->bit));
> +}
> +EXPORT_SYMBOL(st_sensors_read_event_config);
> +
> +int st_sensors_write_event_config(struct iio_dev *indio_dev,
> + u64 event_code,
> + int state)
> +{
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event *event =
> + st_sensor_find_event_data(sdata, event_code);
> + int unsigned mask;
> + int err;
> +
> + if (!event | !sdata->events_enabled)
> + return -EINVAL;
> +
> + mutex_lock(&indio_dev->mlock);
> +
> + mask = (1 << event->bit);
> + err = st_sensors_write_data_with_mask(indio_dev,
> + sdata->sensor->event_irq.ctrl_reg.addr,
> + mask, (bool)state);
> + if (err < 0)
> + goto exit;
> +
> + if (state)
> + sdata->events_flag |= mask;
> + else
> + sdata->events_flag &= ~mask;
> +
> + err = st_sensors_set_enable(indio_dev, (bool)sdata->events_flag);
> +
> +exit:
> + mutex_unlock(&indio_dev->mlock);
> + return err;
> +}
> +EXPORT_SYMBOL(st_sensors_write_event_config);
> +
> +int st_sensors_read_event_value(struct iio_dev *indio_dev,
> + u64 event_code,
> + int *val)
> +{
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event *event =
> + st_sensor_find_event_data(sdata, event_code);
> + u8 byte;
> + int err;
> +
> + if (!event | !sdata->events_enabled)
> + return -EINVAL;
> +
> + mutex_lock(&indio_dev->mlock);
> +
> + err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
> + event->event_ths_reg.addr, &byte);
> + if (!err)
> + *val = byte;
> +
> + mutex_unlock(&indio_dev->mlock);
> + return err;
> +}
> +EXPORT_SYMBOL(st_sensors_read_event_value);
> +
> +int st_sensors_write_event_value(struct iio_dev *indio_dev,
> + u64 event_code,
> + int val)
> +{
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event *event =
> + st_sensor_find_event_data(sdata, event_code);
> + int err;
> +
> + if (!event | !sdata->events_enabled)
> + return -EINVAL;
> +
> + mutex_lock(&indio_dev->mlock);
> +
> + err = st_sensors_write_data_with_mask(indio_dev,
> + event->event_ths_reg.addr,
> + event->event_ths_reg.mask,
> + (u8)val);
> +
> + mutex_unlock(&indio_dev->mlock);
> +
> + return err;
> +}
> +EXPORT_SYMBOL(st_sensors_write_event_value);
> +
> +static irqreturn_t st_sensor_event_handler(int irq, void *private)
> +{
> + struct iio_dev *indio_dev = private;
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event_irq *irq_data =
> + &sdata->sensor->event_irq;
> + struct st_sensor_event *event;
> + s64 timestamp = iio_get_time_ns();
> + u8 status, mask, i;
> + int err = -EIO;
> +
I'm a little worried by this. How would we ever get here
without sdata pointing anywhere? If this is dropped,
remember to drop the -EIO above as well.
> + if (sdata)
> + err = sdata->tf->read_byte(&sdata->tb,
> + sdata->dev,
> + irq_data->status_reg.addr,
> + &status);
> +
> + if (err < 0)
return IRQ_HANDLED;
> + goto exit;
> +
> + for (i = 0; i < irq_data->event_count; i++) {
> + event = &irq_data->events[i];
> + mask = (1 << event->bit);
> + if (status & mask)
> + iio_push_event(indio_dev,
> + IIO_MOD_EVENT_CODE(event->chan_type,
> + 0,
> + event->modifier,
> + event->event_type,
> + event->direction),
> + timestamp);
> + }
> +
> +exit:
> + return IRQ_HANDLED;
> +}
> +
> +int st_sensors_request_event_irq(struct iio_dev *indio_dev)
> +{
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> +
> + return request_threaded_irq(sdata->get_irq_event(indio_dev),
> + NULL,
> + st_sensor_event_handler,
> + IRQF_TRIGGER_RISING | IRQF_ONESHOT,
Naming wise, the device name is a bit generic, perhaps
have -event on the end?
Also, for symmetry I'd normally expect to see a matching
st_sensors_free_event_irq.
Clearly it would be trivial, but it make the code more
'obviously' right which is always a good thing.
> + dev_name(&indio_dev->dev),
> + indio_dev);
> +}
> +
> +int st_sensors_enable_events(struct iio_dev *indio_dev)
> +{
> + int err;
> + struct st_sensor_data *sdata = iio_priv(indio_dev);
> + struct st_sensor_event_irq *irq = &sdata->sensor->event_irq;
> +
> + err = st_sensors_write_data_with_mask(indio_dev,
> + irq->addr,
> + irq->mask,
> + 1);
> +
> + if (err < 0)
return err; is cleaner here rather than the goto given
there is no cleaning up to do.
> + goto error;
> +
> + err = st_sensors_write_data_with_mask(indio_dev,
> + irq->ctrl_reg.addr,
> + irq->ctrl_reg.mask,
> + irq->ctrl_reg.val);
> +error:
> + return err;
> +}
> +EXPORT_SYMBOL(st_sensors_enable_events);
> +
> MODULE_AUTHOR("Denis Ciocca <denis.ciocca-qxv4g6HH51o@public.gmane.org>");
> MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
> MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
> index 3f4a0f7..178dec8 100644
> --- a/include/linux/iio/common/st_sensors.h
> +++ b/include/linux/iio/common/st_sensors.h
> @@ -14,6 +14,7 @@
> #include <linux/i2c.h>
> #include <linux/spi/spi.h>
> #include <linux/irqreturn.h>
> +#include <linux/iio/events.h>
> #include <linux/iio/trigger.h>
> #include <linux/bitops.h>
> #include <linux/regulator/consumer.h>
> @@ -25,6 +26,7 @@
>
> #define ST_SENSORS_ODR_LIST_MAX 10
> #define ST_SENSORS_FULLSCALE_AVL_MAX 10
> +#define ST_SENSORS_EVENTS_MAX 10
>
> #define ST_SENSORS_NUMBER_ALL_CHANNELS 4
> #define ST_SENSORS_ENABLE_ALL_AXIS 0x07
> @@ -47,6 +49,10 @@
> #define ST_SENSORS_DRDY_IRQ_NAME "drdy-int"
> #define ST_SENSORS_EVENT_IRQ_NAME "event-int"
>
> +#define ST_SENSORS_LSM_EVENT_MASK \
> + (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
> + IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
> +
> #define ST_SENSORS_LSM_CHANNELS(device_type, mask, index, mod, \
> ch2, s, endian, rbits, sbits, addr) \
> { \
> @@ -63,6 +69,7 @@
> .storagebits = sbits, \
> .endianness = endian, \
> }, \
> + .event_mask = ST_SENSORS_LSM_EVENT_MASK, \
> }
>
> #define ST_SENSOR_DEV_ATTR_SAMP_FREQ() \
> @@ -114,6 +121,12 @@ struct st_sensor_fullscale {
> struct st_sensor_fullscale_avl fs_avl[ST_SENSORS_FULLSCALE_AVL_MAX];
> };
>
> +struct st_sensor_register {
> + u8 addr;
> + u8 mask;
> + u8 val;
> +};
> +
> /**
> * struct st_sensor_bdu - ST sensor device block data update
> * @addr: address of the register.
> @@ -144,6 +157,46 @@ struct st_sensor_data_ready_irq {
> };
>
> /**
> + * struct st_sensor_event - event data.
> + * @bit: position of bit in status register related to event
> + * @chan: channel number.
> + * @chan_type: channel type.
> + * @modifier: modifier for the channel.
> + * @event_type: type of the event.
> + * @direction: direction of the event.
> + * @event_ths_reg: represents the threshold
> + * register of event.
> + */
> +struct st_sensor_event {
> + u8 bit;
The approach used in Lars' new approach to the
event callbacks makes this simpler by using
a pointer to the relevant channel. Otherwise
this is very similar which should make lifte
easy when converting over.
> + enum iio_chan_type chan_type;
> + enum iio_modifier modifier;
> + enum iio_event_type event_type;
> + enum iio_event_direction direction;
> + struct st_sensor_register event_ths_reg;
> +};
> +
> +/**
> + * struct st_sensor_event_irq -ST sensor event interrupt.
> + * @addr: address of the interrupt register.
> + * @mask: mask to write on/off value.
> + * @event_count: number of events declared in @events array.
> + * @ctrl_reg: represents the control register
> + * of event system
> + * @status_reg: status register of event subsystem.
> + * @events array: driver events declared by user
> + */
> +struct st_sensor_event_irq {
> + u8 addr;
> + u8 mask;
> + u8 event_count;
> + struct st_sensor_register ctrl_reg;
> + struct st_sensor_register status_reg;
> + struct st_sensor_event events[ST_SENSORS_EVENTS_MAX];
> +};
> +
One blank line is all that is needed here.
> +
> +/**
> * struct st_sensor_transfer_buffer - ST sensor device I/O buffer
> * @buf_lock: Mutex to protect rx and tx buffers.
> * @tx_buf: Buffer used by SPI transfer function to send data to the sensors.
> @@ -184,6 +237,7 @@ struct st_sensor_transfer_function {
> * @fs: Full scale register and full scale list available.
> * @bdu: Block data update register.
> * @drdy_irq: Data ready register of the sensor.
> + * @event_irq: Event register of the sensor.
> * @multi_read_bit: Use or not particular bit for [I2C/SPI] multi-read.
> * @bootime: samples to discard when sensor passing from power-down to power-up.
> */
> @@ -198,6 +252,7 @@ struct st_sensors {
> struct st_sensor_fullscale fs;
> struct st_sensor_bdu bdu;
> struct st_sensor_data_ready_irq drdy_irq;
> + struct st_sensor_event_irq event_irq;
> bool multi_read_bit;
> unsigned int bootime;
> };
> @@ -212,9 +267,11 @@ struct st_sensors {
> * @vdd_io: Pointer to sensor's Vdd-IO power supply
> * @enabled: Status of the sensor (false->off, true->on).
> * @multiread_bit: Use or not particular bit for [I2C/SPI] multiread.
> + * @events_enable: Status of the sensor events (false->off, true->on).
> * @buffer_data: Data used by buffer part.
> * @odr: Output data rate of the sensor [Hz].
> * num_data_channels: Number of data channels used in buffer.
> + * @events_flag: Data used by event part.
> * @irq_map: Container of mapped IRQs.
> * @drdy_int_pin: Redirect DRDY on pin 1 (1) or pin 2 (2).
> * @get_irq_data_ready: Function to get the IRQ used for data ready signal.
> @@ -232,11 +289,13 @@ struct st_sensor_data {
>
> bool enabled;
> bool multiread_bit;
> + bool events_enabled;
>
> char *buffer_data;
>
> unsigned int odr;
> unsigned int num_data_channels;
> + unsigned int events_flag;
> unsigned int irq_map[ST_SENSORS_INT_MAX];
>
> u8 drdy_int_pin;
> @@ -302,4 +361,19 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
> ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
> struct device_attribute *attr, char *buf);
>
> +int st_sensors_read_event_config(struct iio_dev *indio_dev,
> + u64 event_code);
> +
> +int st_sensors_write_event_config(struct iio_dev *indio_dev,
> + u64 event_code, int state);
> +
> +int st_sensors_read_event_value(struct iio_dev *indio_dev,
> + u64 event_code, int *val);
> +
> +int st_sensors_write_event_value(struct iio_dev *indio_dev,
> + u64 event_code, int val);
> +
> +int st_sensors_request_event_irq(struct iio_dev *indio_dev);
> +
> +int st_sensors_enable_events(struct iio_dev *indio_dev);
> #endif /* ST_SENSORS_H */
>
next prev parent reply other threads:[~2013-10-01 16:09 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-27 16:32 [RFC v2 PATCH 00/14] iio: STMicroelectronics DT and event support Lukasz Czerwinski
[not found] ` <1380299538-22047-1-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-09-27 16:32 ` [RFC v2 PATCH 01/14] iio: st_common: New interrupt interface Lukasz Czerwinski
[not found] ` <1380299538-22047-2-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 15:34 ` Jonathan Cameron
[not found] ` <524AEB97.1090806-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-10-01 16:22 ` Jonathan Cameron
2013-10-21 11:59 ` Mark Rutland
2013-10-21 11:48 ` Mark Rutland
2013-09-27 16:32 ` [RFC v2 PATCH 02/14] iio: st_accel: Add dt bindings Lukasz Czerwinski
[not found] ` <1380299538-22047-3-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 15:40 ` Jonathan Cameron
[not found] ` <524AED0A.6030707-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-10-21 11:37 ` Mark Rutland
2013-09-27 16:32 ` [RFC v2 PATCH 03/14] iio: st_gyro: " Lukasz Czerwinski
2013-09-27 16:32 ` [RFC v2 PATCH 04/14] iio: st_mang: " Lukasz Czerwinski
2013-09-27 16:32 ` [RFC v2 PATCH 05/14] iio: st_pressure: " Lukasz Czerwinski
2013-09-27 16:32 ` [RFC v2 PATCH 06/14] iio: st_common: Add threshold events support Lukasz Czerwinski
[not found] ` <1380299538-22047-7-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 16:09 ` Jonathan Cameron [this message]
2013-09-27 16:32 ` [RFC v2 PATCH 07/14] iio: st_accel: Add event subsystem to st_accel driver Lukasz Czerwinski
[not found] ` <1380299538-22047-8-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 16:17 ` Jonathan Cameron
2013-09-27 16:32 ` [RFC v2 PATCH 08/14] iio: iio_magn: Add event ops Lukasz Czerwinski
[not found] ` <1380299538-22047-9-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 16:21 ` Jonathan Cameron
2013-09-27 16:32 ` [RFC v2 PATCH 09/14] iio: st_gyro: " Lukasz Czerwinski
2013-09-27 16:32 ` [RFC v2 PATCH 10/14] iio: iio_press: " Lukasz Czerwinski
2013-09-27 16:32 ` [RFC v2 PATCH 11/14] Documentation: Add st_magn binding documentation Lukasz Czerwinski
[not found] ` <1380299538-22047-12-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-01 16:29 ` Jonathan Cameron
[not found] ` <524AF86D.7010200-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-10-01 15:49 ` Rob Herring
[not found] ` <524AEEFC.8010201-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2013-10-22 6:55 ` Lee Jones
2013-10-21 11:16 ` Mark Rutland
2013-09-27 16:32 ` [RFC v2 PATCH 12/14] Documentation: Add st_gyro " Lukasz Czerwinski
[not found] ` <1380299538-22047-13-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-21 11:19 ` Mark Rutland
2013-09-27 16:32 ` [RFC v2 PATCH 13/14] Documentation: Add st_pressure " Lukasz Czerwinski
[not found] ` <1380299538-22047-14-git-send-email-l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-10-21 11:23 ` Mark Rutland
2013-09-27 16:32 ` [RFC v2 PATCH 14/14] Documentation: Add st_accel " Lukasz Czerwinski
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=524AF3AA.9060801@kernel.org \
--to=jic23-dgejt+ai2ygdnm+yrofe0a@public.gmane.org \
--cc=denis.ciocca-qxv4g6HH51o@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=jic23-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org \
--cc=l.czerwinski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org \
--cc=lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=linux-iio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).