android_kernel_samsung_msm8976/drivers/iio/imu/st_lsm6ds3.h

258 lines
6.4 KiB
C

/*
* STMicroelectronics lsm6ds3 driver
*
* Copyright 2014 STMicroelectronics Inc.
*
* Denis Ciocca <denis.ciocca@st.com>
* v. 1.1.2
* Licensed under the GPL-2.
*/
#ifndef ST_LSM6DS3_H
#define ST_LSM6DS3_H
#include <linux/types.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/iio/trigger.h>
#define LSM6DS3_HRTIMER_TRIGGER 1
#define LSM6DS3_SMART_ALERT LSM6DS3_HRTIMER_TRIGGER
#if (LSM6DS3_SMART_ALERT > 0)
#include <linux/wakelock.h>
#endif
#define LSM6DS3_DEV_NAME "lsm6ds3"
#define VENDOR_NAME "STM"
#define MODULE_NAME_ACC "accelerometer_sensor"
#define MODULE_NAME_GYRO "gyro_sensor"
#define CALIBRATION_FILE_PATH "/efs/FactoryApp/accel_calibration_data"
#define GYRO_CALIBRATION_FILE_PATH "/efs/FactoryApp/gyro_cal_data"
#define CALIBRATION_DATA_AMOUNT 20
#define MAX_ACCEL_1G 8192
#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_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))
#define ST_LSM6DS3_STEP_COUNTER_DEPENDENCY \
((1 << ST_INDIO_DEV_STEP_COUNTER) | \
(1 << ST_INDIO_DEV_SIGN_MOTION) | \
(1 << ST_INDIO_DEV_STEP_DETECTOR))
#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))
#define ST_LSM6DS3_USE_BUFFER ((1 << ST_INDIO_DEV_ACCEL) | \
(1 << ST_INDIO_DEV_GYRO) | \
(1 << ST_INDIO_DEV_STEP_COUNTER))
#define ST_LSM6DS3_TX_MAX_LENGTH 12
#define ST_LSM6DS3_RX_MAX_LENGTH 4097
#define ST_LSM6DS3_NUMBER_DATA_CHANNELS 3
#define ST_LSM6DS3_BYTE_FOR_CHANNEL 2
#define ST_LSM6DS3_LSM_CHANNELS(device_type, index, mod, endian, bits, addr) \
{ \
.type = device_type, \
.modified = 1, \
.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 = bits, \
.shift = 16 - bits, \
.storagebits = 16, \
.endianness = endian, \
}, \
}
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;
};
struct st_lsm6ds3_transfer_function {
int (*write) (struct st_lsm6ds3_transfer_buffer *tb,
struct device *dev, u8 reg_addr, int len, u8 *data);
int (*read) (struct st_lsm6ds3_transfer_buffer *tb,
struct device *dev, u8 reg_addr, int len, u8 *data);
};
struct lsm6ds3_steps {
bool new_steps;
u16 steps;
struct hrtimer hr_timer;
ktime_t ktime;
s64 last_step_timestamp;
};
struct lsm6ds3_data {
const char *name;
u8 drdy_int_pin;
u8 sensors_enabled;
u8 gyro_module;
u16 gyro_selftest_delta[3];
u8 gyro_selftest_status;
u8 accel_selftest_status;
bool patch_feature;
bool sign_motion_event_ready;
int err_count;
int irq;
int irq_gpio;
s16 accel_data[3];
s16 gyro_data[3];
s16 accel_cal_data[3];
s16 gyro_cal_data[3];
s8 orientation[9];
int64_t timestamp;
struct work_struct data_work;
struct device *dev;
struct device *acc_factory_dev;
struct device *gyro_factory_dev;
struct iio_dev *indio_dev[ST_INDIO_DEV_NUM];
struct iio_trigger *trig[ST_INDIO_DEV_NUM];
struct lsm6ds3_steps step_c;
const struct st_lsm6ds3_transfer_function *tf;
struct st_lsm6ds3_transfer_buffer tb;
#if (LSM6DS3_SMART_ALERT > 0)
struct delayed_work sa_irq_work;
struct wake_lock sa_wake_lock;
int sa_irq_state;
int sa_flag;
#endif
struct regulator *reg_vio;
struct i2c_client *client;
u8 odr;
bool skip_gyro_data;
int skip_gyro_cnt;
int states;
};
struct lsm6ds3_sensor_data {
struct lsm6ds3_data *cdata;
unsigned int c_odr;
unsigned int c_gain;
unsigned int bandwidth;
int poll_delay;
int lpf_on;
u8 sindex;
u8 *buffer_data;
int st_mode;
int64_t old_timestamp;
#if (LSM6DS3_HRTIMER_TRIGGER > 0)
struct hrtimer hr_timer;
ktime_t ktime;
int hr_timer_en;
struct workqueue_struct *tmr_wq;
struct work_struct tmr_work;
#endif
};
int st_lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq);
void st_lsm6ds3_common_remove(struct lsm6ds3_data *cdata, int irq);
void st_lsm6ds3_common_shutdown(struct lsm6ds3_data *cdata);
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);
void st_lsm6ds3_set_irq(struct lsm6ds3_data *cdata, bool enable);
#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);
#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
int st_lsm6ds3_allocate_triggers(struct lsm6ds3_data *cdata,
const struct iio_trigger_ops *trigger_ops, int irq);
void st_lsm6ds3_deallocate_triggers(struct lsm6ds3_data *cdata, int irq);
#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;
}
#endif /* CONFIG_IIO_TRIGGER */
static inline s64 st_lsm6ds3_iio_get_boottime_ns(void)
{
struct timespec ts;
ts = ktime_to_timespec(ktime_get_boottime());
return timespec_to_ns(&ts);
}
#ifdef CONFIG_PM
int st_lsm6ds3_common_suspend(struct lsm6ds3_data *cdata);
int st_lsm6ds3_common_resume(struct lsm6ds3_data *cdata);
#endif /* CONFIG_PM */
#if (LSM6DS3_HRTIMER_TRIGGER > 0)
void st_lsm6ds3_poll_work_acc(struct work_struct *data_work);
void st_lsm6ds3_poll_work_gyr(struct work_struct *data_work);
#endif
int st_lsm6ds3_acc_open_calibration(struct lsm6ds3_data *cdata);
int st_lsm6ds3_gyro_open_calibration(struct lsm6ds3_data *cdata);
#endif /* ST_LSM6DS3_H */