diff options
Diffstat (limited to 'drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h')
| -rw-r--r-- | drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h new file mode 100644 index 00000000000..479b9188273 --- /dev/null +++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3.h @@ -0,0 +1,296 @@ +/* + * STMicroelectronics lsm6ds3 driver + * + * Copyright 2014 STMicroelectronics Inc. + * + * Denis Ciocca <denis.ciocca@st.com> + * v. 2.1.2 + * Licensed under the GPL-2. + */ + +#ifndef ST_LSM6DS3_H +#define ST_LSM6DS3_H + +#include <linux/types.h> +#include <linux/iio/trigger.h> +#include <linux/wakelock.h> +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT +#include <linux/i2c.h> +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + +#define LSM6DS3_DEV_NAME "lsm6ds3" + +#define ST_INDIO_DEV_ACCEL 0 +#define ST_INDIO_DEV_GYRO 1 +#define ST_INDIO_DEV_SIGN_MOTION 2 +#define ST_INDIO_DEV_STEP_COUNTER 3 +#define ST_INDIO_DEV_STEP_DETECTOR 4 +#define ST_INDIO_DEV_TILT 5 +#define ST_INDIO_DEV_NUM 6 + +#define ST_INDIO_DEV_EXT0 ST_INDIO_DEV_NUM +#define ST_INDIO_DEV_EXT1 (ST_INDIO_DEV_NUM + 1) + +#define ST_LSM6DS3_ACCEL_DEPENDENCY ((1 << ST_INDIO_DEV_ACCEL) | \ + (1 << ST_INDIO_DEV_STEP_COUNTER) | \ + (1 << ST_INDIO_DEV_TILT) | \ + (1 << ST_INDIO_DEV_SIGN_MOTION) | \ + (1 << ST_INDIO_DEV_STEP_DETECTOR) | \ + (1 << ST_INDIO_DEV_EXT0) | \ + (1 << ST_INDIO_DEV_EXT1)) + +#define ST_LSM6DS3_PEDOMETER_DEPENDENCY ((1 << ST_INDIO_DEV_STEP_COUNTER) | \ + (1 << ST_INDIO_DEV_STEP_DETECTOR) | \ + (1 << ST_INDIO_DEV_SIGN_MOTION)) + +#define ST_LSM6DS3_EXTRA_DEPENDENCY ((1 << ST_INDIO_DEV_STEP_COUNTER) | \ + (1 << ST_INDIO_DEV_TILT) | \ + (1 << ST_INDIO_DEV_SIGN_MOTION) | \ + (1 << ST_INDIO_DEV_STEP_DETECTOR) | \ + (1 << ST_INDIO_DEV_EXT0) | \ + (1 << ST_INDIO_DEV_EXT1)) + +#define ST_LSM6DS3_USE_BUFFER ((1 << ST_INDIO_DEV_ACCEL) | \ + (1 << ST_INDIO_DEV_GYRO) | \ + (1 << ST_INDIO_DEV_STEP_COUNTER)) + +#define ST_LSM6DS3_EXT_SENSORS ((1 << ST_INDIO_DEV_EXT0) | \ + (1 << ST_INDIO_DEV_EXT1)) + +#ifdef CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP +#define ST_LSM6DS3_WAKE_UP_SENSORS ((1 << ST_INDIO_DEV_SIGN_MOTION) | \ + (1 << ST_INDIO_DEV_TILT)) +#else /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */ +#define ST_LSM6DS3_WAKE_UP_SENSORS ((1 << ST_INDIO_DEV_SIGN_MOTION) | \ + (1 << ST_INDIO_DEV_TILT) | \ + (1 << ST_INDIO_DEV_ACCEL) | \ + (1 << ST_INDIO_DEV_GYRO) | \ + (1 << ST_INDIO_DEV_STEP_COUNTER) | \ + (1 << ST_INDIO_DEV_STEP_DETECTOR) | \ + (1 << ST_INDIO_DEV_EXT0) | \ + (1 << ST_INDIO_DEV_EXT1)) +#endif /* CONFIG_ST_LSM6DS3_IIO_SENSORS_WAKEUP */ + +#define ST_LSM6DS3_TX_MAX_LENGTH 12 +#define ST_LSM6DS3_RX_MAX_LENGTH 8193 + +#define ST_LSM6DS3_BYTE_FOR_CHANNEL 2 +#define ST_LSM6DS3_FIFO_ELEMENT_LEN_BYTE 6 + +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT +#define ST_LSM6DS3_NUM_CLIENTS 2 +#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ +#define ST_LSM6DS3_NUM_CLIENTS 0 +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + +#define ST_LSM6DS3_LSM_CHANNELS(device_type, modif, index, mod, \ + endian, sbits, rbits, addr, s) \ +{ \ + .type = device_type, \ + .modified = modif, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = index, \ + .channel2 = mod, \ + .address = addr, \ + .scan_type = { \ + .sign = s, \ + .realbits = rbits, \ + .shift = sbits - rbits, \ + .storagebits = sbits, \ + .endianness = endian, \ + }, \ +} + +#define ST_LSM6DS3_FIFO_LENGHT() \ + IIO_DEVICE_ATTR(hw_fifo_lenght, S_IRUGO, \ + st_lsm6ds3_sysfs_get_hw_fifo_lenght, NULL, 0); + +#define ST_LSM6DS3_FIFO_FLUSH() \ + IIO_DEVICE_ATTR(flush, S_IWUSR, NULL, st_lsm6ds3_sysfs_flush_fifo, 0); + +enum fifo_mode { + BYPASS = 0, + CONTINUOS, +}; + +struct st_lsm6ds3_transfer_buffer { + struct mutex buf_lock; + u8 rx_buf[ST_LSM6DS3_RX_MAX_LENGTH]; + u8 tx_buf[ST_LSM6DS3_TX_MAX_LENGTH] ____cacheline_aligned; +}; + +enum +{ + LSM6DS3_WAKEUP_NONE = 0, + LSM6DS3_WAKEUP_TAP = 1, + LSM6DS3_WAKEUP_6D = 2, + LSM6DS3_WAKEUP_OTHER = 4 +}; + +struct lsm6ds3_data { + const char *name; + + bool reset_steps; + bool sign_motion_event_ready; + int last_wakeup_source; + int wake_lock_initialized; + struct wake_lock wlock; + u8 first_irq_from_resume; + u8 reg_read; +#define SIXD_MASK_VALID_BITS (0x3f) + u8 sixd_mask; + u8 int1_save; + + u8 *fifo_data; + u8 sensors_enabled; + u8 gyro_selftest_status; + u8 accel_selftest_status; + u8 accel_samples_in_pattern; + u8 gyro_samples_in_pattern; +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT + u8 ext0_samples_in_pattern; + u8 ext1_samples_in_pattern; +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + u8 accel_samples_to_discard; + u8 gyro_samples_to_discard; +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT + u8 ext_samples_to_discard[ST_LSM6DS3_NUM_CLIENTS]; +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + + u16 fifo_threshold; + + int irq; + + s64 timestamp; + int64_t accel_deltatime; + int64_t accel_timestamp; + int64_t gyro_deltatime; + int64_t gyro_timestamp; +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT + int64_t ext0_deltatime; + int64_t ext0_timestamp; + int64_t ext1_deltatime; + int64_t ext1_timestamp; +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + + struct work_struct data_work; + + struct device *dev; + struct iio_dev *indio_dev[ST_INDIO_DEV_NUM + ST_LSM6DS3_NUM_CLIENTS]; + struct iio_trigger *trig[ST_INDIO_DEV_NUM + ST_LSM6DS3_NUM_CLIENTS]; + struct mutex bank_registers_lock; + struct mutex fifo_lock; + +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT + struct i2c_client *master_client[ST_LSM6DS3_NUM_CLIENTS]; + struct mutex passthrough_lock; + bool ext0_available; + bool ext1_available; +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + + const struct st_lsm6ds3_transfer_function *tf; + struct st_lsm6ds3_transfer_buffer tb; +}; + +struct st_lsm6ds3_transfer_function { + int (*write) (struct lsm6ds3_data *cdata, + u8 reg_addr, int len, u8 *data, bool b_lock); + int (*read) (struct lsm6ds3_data *cdata, + u8 reg_addr, int len, u8 *data, bool b_lock); +}; + +struct lsm6ds3_sensor_data { + struct lsm6ds3_data *cdata; + + unsigned int c_odr; + unsigned int c_gain[3]; + + u8 num_data_channels; + u8 sindex; + u8 *buffer_data; +}; + +int st_lsm6ds3_write_data_with_mask(struct lsm6ds3_data *cdata, + u8 reg_addr, u8 mask, u8 data, bool b_lock); + +int st_lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq); +void st_lsm6ds3_common_remove(struct lsm6ds3_data *cdata, int irq); + +int st_lsm6ds3_set_enable(struct lsm6ds3_sensor_data *sdata, bool enable); +int st_lsm6ds3_set_axis_enable(struct lsm6ds3_sensor_data *sdata, u8 value); +int st_lsm6ds3_set_drdy_irq(struct lsm6ds3_sensor_data *sdata, bool state); +int st_lsm6ds3_set_fifo_mode(struct lsm6ds3_data *cdata, enum fifo_mode fm); +int st_lsm6ds3_reconfigure_fifo(struct lsm6ds3_data *cdata, + bool disable_irq_and_flush); + +ssize_t st_lsm6ds3_sysfs_get_hw_fifo_lenght(struct device *dev, + struct device_attribute *attr, char *buf); +ssize_t st_lsm6ds3_sysfs_flush_fifo(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size); + +#ifdef CONFIG_IIO_BUFFER +int st_lsm6ds3_allocate_rings(struct lsm6ds3_data *cdata); +void st_lsm6ds3_deallocate_rings(struct lsm6ds3_data *cdata); +int st_lsm6ds3_trig_set_state(struct iio_trigger *trig, bool state); +void st_lsm6ds3_read_fifo(struct lsm6ds3_data *cdata, bool check_fifo_len); +int st_lsm6ds3_set_fifo_decimators_and_threshold(struct lsm6ds3_data *cdata); +#define ST_LSM6DS3_TRIGGER_SET_STATE (&st_lsm6ds3_trig_set_state) +#else /* CONFIG_IIO_BUFFER */ +static inline int st_lsm6ds3_allocate_rings(struct lsm6ds3_data *cdata) +{ + return 0; +} +static inline void st_lsm6ds3_deallocate_rings(struct lsm6ds3_data *cdata) +{ +} +#define ST_LSM6DS3_TRIGGER_SET_STATE NULL +#endif /* CONFIG_IIO_BUFFER */ + +#ifdef CONFIG_IIO_TRIGGER +void st_lsm6ds3_flush_works(void); +int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata, + const struct iio_trigger_ops *trigger_ops); + +void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata); + +#else /* CONFIG_IIO_TRIGGER */ +static inline int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata, + const struct iio_trigger_ops *trigger_ops, int irq) +{ + return 0; +} +static inline void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata, + int irq) +{ + return; +} +static inline void st_lsm6ds3_flush_works() +{ + return; +} +#endif /* CONFIG_IIO_TRIGGER */ + +#ifdef CONFIG_PM +int st_lsm6ds3_common_suspend(struct lsm6ds3_data *cdata); +int st_lsm6ds3_common_resume(struct lsm6ds3_data *cdata); +#endif /* CONFIG_PM */ + +#ifdef CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT +int st_lsm6ds3_i2c_master_probe(struct lsm6ds3_data *cdata); +int st_lsm6ds3_i2c_master_exit(struct lsm6ds3_data *cdata); +int st_lsm6ds3_enable_passthrough(struct lsm6ds3_data *cdata, bool enable); +int st_lsm6ds3_enable_accel_dependency(struct lsm6ds3_sensor_data *sdata, + bool enable); +#else /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ +static inline int st_lsm6ds3_i2c_master_probe(struct lsm6ds3_data *cdata) +{ + return 0; +} +static inline int st_lsm6ds3_i2c_master_exit(struct lsm6ds3_data *cdata) +{ + return 0; +} +#endif /* CONFIG_ST_LSM6DS3_IIO_MASTER_SUPPORT */ + +#endif /* ST_LSM6DS3_H */ |