This patch adds event support for iio st_accel driver. Signed-off-by: Lukasz Czerwinski <l.czerwinski@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- .../bindings/iio/accelerometer/st_accel.txt | 1 + drivers/iio/accel/st_accel_core.c | 149 ++++++++++++++++++++ 2 files changed, 150 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/accelerometer/st_accel.txt b/Documentation/devicetree/bindings/iio/accelerometer/st_accel.txt index 9eab7d9..f461a77 100644 --- a/Documentation/devicetree/bindings/iio/accelerometer/st_accel.txt +++ b/Documentation/devicetree/bindings/iio/accelerometer/st_accel.txt @@ -21,6 +21,7 @@ Optional properties: - interrupt-parent : phandle to the interrupt map subnode - interrupts : interrupt mapping for st_accel interrupt sources: 0: INT1 irq_data_ready + 1: INT2 irq_event - irq-map : irq sub-node defining interrupt map (all properties listed below are required): - #interrupt-cells : should be 1 diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 385cd86..983e8c4 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -19,6 +19,7 @@ #include <linux/gpio.h> #include <linux/irq.h> #include <linux/iio/iio.h> +#include <linux/iio/events.h> #include <linux/iio/sysfs.h> #include <linux/iio/trigger.h> #include <linux/iio/buffer.h> @@ -68,6 +69,20 @@ #define ST_ACCEL_1_DRDY_IRQ_INT1_MASK 0x10 #define ST_ACCEL_1_DRDY_IRQ_INT2_MASK 0x08 #define ST_ACCEL_1_MULTIREAD_BIT true +#define ST_ACCEL_1_EVENT_IRQ_ADDR 0x22 +#define ST_ACCEL_1_EVENT_IRQ_MASK 0x40 +#define ST_ACCEL_1_EVENT_CTRL_REG 0x30 +#define ST_ACCEL_1_EVENT_CTRL_MASK 0xc0 +#define ST_ACCEL_1_EVENT_CTRL_DEFAULT_VAL 0x01 +#define ST_ACCEL_1_THS_REG 0x32 +#define ST_ACCEL_1_EVENT_STATUS_REG 0x31 +#define ST_ACCEL_1_EVENT_STATUS_REG_MASK 0x7f +#define ST_ACCEL_1_INT1_XL 0 +#define ST_ACCEL_1_INT1_XH 1 +#define ST_ACCEL_1_INT1_YL 2 +#define ST_ACCEL_1_INT1_YH 3 +#define ST_ACCEL_1_INT1_ZL 4 +#define ST_ACCEL_1_INT1_ZH 5 /* CUSTOM VALUES FOR SENSOR 2 */ #define ST_ACCEL_2_WAI_EXP 0x32 @@ -93,6 +108,20 @@ #define ST_ACCEL_2_DRDY_IRQ_INT1_MASK 0x02 #define ST_ACCEL_2_DRDY_IRQ_INT2_MASK 0x10 #define ST_ACCEL_2_MULTIREAD_BIT true +#define ST_ACCEL_2_EVENT_IRQ_ADDR 0x22 +#define ST_ACCEL_2_EVENT_IRQ_MASK 0x01 +#define ST_ACCEL_2_EVENT_CTRL_REG 0x30 +#define ST_ACCEL_2_EVENT_CTRL_MASK 0xc0 +#define ST_ACCEL_2_EVENT_CTRL_DEFAULT_VAL 0x01 +#define ST_ACCEL_2_THS_REG 0x32 +#define ST_ACCEL_2_EVENT_STATUS_REG 0x31 +#define ST_ACCEL_2_EVENT_STATUS_REG_MASK 0x7f +#define ST_ACCEL_2_INT1_XL 0 +#define ST_ACCEL_2_INT1_XH 1 +#define ST_ACCEL_2_INT1_YL 2 +#define ST_ACCEL_2_INT1_YH 3 +#define ST_ACCEL_2_INT1_ZL 4 +#define ST_ACCEL_2_INT1_ZH 5 /* CUSTOM VALUES FOR SENSOR 3 */ #define ST_ACCEL_3_WAI_EXP 0x40 @@ -129,6 +158,20 @@ #define ST_ACCEL_3_IG1_EN_MASK 0x08 #define ST_ACCEL_3_MULTIREAD_BIT false +#define ST_SENSORS_LSM_ACCEL_EVENT(ch, mod, dir, bit_pos, ths_reg) \ +{ \ + .bit = bit_pos,\ + .chan = ch, \ + .chan_type = IIO_ACCEL, \ + .modifier = mod, \ + .event_type = IIO_EV_TYPE_THRESH, \ + .direction = dir, \ + .event_ths_reg = { \ + .addr = ths_reg, \ + .mask = 0x7f, \ + }, \ +} + static const struct iio_chan_spec st_accel_12bit_channels[] = { ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), @@ -232,6 +275,46 @@ static const struct st_sensors st_accel_sensors[] = { }, .multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT, .bootime = 2, + .event_irq = { + .addr = ST_ACCEL_1_EVENT_IRQ_ADDR, + .mask = ST_ACCEL_1_EVENT_IRQ_MASK, + .event_count = 6, + .ctrl_reg = { + .addr = ST_ACCEL_1_EVENT_CTRL_REG, + .mask = ST_ACCEL_1_EVENT_CTRL_MASK, + .val = ST_ACCEL_1_EVENT_CTRL_DEFAULT_VAL, + }, + .status_reg = { + .addr = ST_ACCEL_1_EVENT_STATUS_REG, + .mask = ST_ACCEL_1_EVENT_STATUS_REG_MASK, + }, + .events = { + ST_SENSORS_LSM_ACCEL_EVENT(0, IIO_MOD_X, + IIO_EV_DIR_FALLING, + ST_ACCEL_1_INT1_XL, + ST_ACCEL_1_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(0, IIO_MOD_X, + IIO_EV_DIR_RISING, + ST_ACCEL_1_INT1_XH, + ST_ACCEL_1_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(1, IIO_MOD_Y, + IIO_EV_DIR_FALLING, + ST_ACCEL_1_INT1_YL, + ST_ACCEL_1_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(1, IIO_MOD_Y, + IIO_EV_DIR_RISING, + ST_ACCEL_1_INT1_YH, + ST_ACCEL_1_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(2, IIO_MOD_Z, + IIO_EV_DIR_FALLING, + ST_ACCEL_1_INT1_ZL, + ST_ACCEL_1_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(2, IIO_MOD_Z, + IIO_EV_DIR_RISING, + ST_ACCEL_1_INT1_ZH, + ST_ACCEL_1_THS_REG), + }, + }, }, { .wai = ST_ACCEL_2_WAI_EXP, @@ -294,6 +377,47 @@ static const struct st_sensors st_accel_sensors[] = { }, .multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT, .bootime = 2, + .event_irq = { + .addr = ST_ACCEL_2_EVENT_IRQ_ADDR, + .mask = ST_ACCEL_2_EVENT_IRQ_MASK, + .event_count = 6, + .ctrl_reg = { + .addr = ST_ACCEL_2_EVENT_CTRL_REG, + .mask = ST_ACCEL_2_EVENT_CTRL_MASK, + .val = ST_ACCEL_2_EVENT_CTRL_DEFAULT_VAL, + }, + .status_reg = { + .addr = ST_ACCEL_2_EVENT_STATUS_REG, + .mask = ST_ACCEL_2_EVENT_STATUS_REG_MASK, + }, + .events = { + ST_SENSORS_LSM_ACCEL_EVENT(0, IIO_MOD_X, + IIO_EV_DIR_FALLING, + ST_ACCEL_2_INT1_XL, + ST_ACCEL_2_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(0, IIO_MOD_X, + IIO_EV_DIR_RISING, + ST_ACCEL_2_INT1_XH, + ST_ACCEL_2_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(1, IIO_MOD_Y, + IIO_EV_DIR_FALLING, + ST_ACCEL_2_INT1_YL, + ST_ACCEL_2_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(1, IIO_MOD_Y, + IIO_EV_DIR_RISING, + ST_ACCEL_2_INT1_YH, + ST_ACCEL_2_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(2, IIO_MOD_Z, + IIO_EV_DIR_FALLING, + ST_ACCEL_2_INT1_ZL, + ST_ACCEL_2_THS_REG), + ST_SENSORS_LSM_ACCEL_EVENT(2, IIO_MOD_Z, + IIO_EV_DIR_RISING, + ST_ACCEL_2_INT1_ZH, + ST_ACCEL_2_THS_REG), + }, + }, + }, { .wai = ST_ACCEL_3_WAI_EXP, @@ -437,6 +561,10 @@ static const struct iio_info accel_info = { .attrs = &st_accel_attribute_group, .read_raw = &st_accel_read_raw, .write_raw = &st_accel_write_raw, + .read_event_value = &st_sensors_read_event_value, + .write_event_value = &st_sensors_write_event_value, + .read_event_config = &st_sensors_read_event_config, + .write_event_config = &st_sensors_write_event_config, }; #ifdef CONFIG_IIO_TRIGGER @@ -452,6 +580,7 @@ static const struct iio_trigger_ops st_accel_trigger_ops = { int st_accel_common_probe(struct iio_dev *indio_dev) { int err; + int i; struct st_sensor_data *adata = iio_priv(indio_dev); indio_dev->modes = INDIO_DIRECT_MODE; @@ -489,6 +618,20 @@ int st_accel_common_probe(struct iio_dev *indio_dev) goto st_accel_probe_trigger_error; } + if (adata->get_irq_event(indio_dev) > 0) { + err = st_sensors_request_event_irq(indio_dev); + if (err < 0) + goto st_accel_request_irq_event_error; + + for (i = 0; i < indio_dev->num_channels; i++) + adata->sensor->ch[i].event_mask = + ST_SENSORS_LSM_EVENTS_MASK; + + err = st_sensors_enable_events(indio_dev); + if (err < 0) + goto st_accel_enable_events_error; + } + err = iio_device_register(indio_dev); if (err) goto st_accel_device_register_error; @@ -496,6 +639,10 @@ int st_accel_common_probe(struct iio_dev *indio_dev) return err; st_accel_device_register_error: +st_accel_enable_events_error: + if (adata->get_irq_event(indio_dev) > 0) + free_irq(adata->get_irq_event(indio_dev), indio_dev); +st_accel_request_irq_event_error: if (adata->get_irq_data_ready(indio_dev) > 0) st_sensors_deallocate_trigger(indio_dev); st_accel_probe_trigger_error: @@ -515,6 +662,8 @@ void st_accel_common_remove(struct iio_dev *indio_dev) st_sensors_deallocate_trigger(indio_dev); st_accel_deallocate_ring(indio_dev); } + if (adata->get_irq_event(indio_dev) > 0) + free_irq(adata->get_irq_event(indio_dev), indio_dev); iio_device_free(indio_dev); } EXPORT_SYMBOL(st_accel_common_remove); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html