MA Lite 8.1.5

Module:
* 8.1.2-simple-test1

Supported Kernel Versions:
* 3.18
* 4.4
* 4.9

Supported TDK-InvenSense Sensors:
* IAM20680

Change log:
* Timer based batch mode support for IAM20680
This commit is contained in:
Eiji Iwatsuki 2018-05-01 10:26:25 -07:00
parent a71da78c6d
commit b1c8f25f65
8 changed files with 143 additions and 19 deletions

View file

@ -19,10 +19,17 @@
* sysfs entries */
#define SUPPORT_ONLY_BASIC_FEATURES
/* Uncomment to read data registers for sensor data
* instead of FIFO */
/* Uncomment to read data registers for sensor data instead of FIFO */
//#define SENSOR_DATA_FROM_REGISTERS
/* Uncomment to enable timer based batching */
#define TIMER_BASED_BATCHING
/* Polling (batch mode) can be enabled only when FIFO read */
#if defined(SENSOR_DATA_FROM_REGISTERS)
#undef TIMER_BASED_BATCHING
#endif
/*register and associated bit definition*/
#define REG_XA_OFFS_H 0x77
#define REG_YA_OFFS_H 0x7A
@ -140,7 +147,7 @@
#define BYTES_FOR_TEMP 2
#define FIFO_COUNT_BYTE 2
#define HARDWARE_FIFO_SIZE 512
#define FIFO_SIZE (HARDWARE_FIFO_SIZE * 7 / 8)
#define FIFO_SIZE (HARDWARE_FIFO_SIZE * 7 / 10)
#define POWER_UP_TIME 100
#define REG_UP_TIME_USEC 100
#define LEFT_OVER_BYTES 128
@ -190,7 +197,7 @@ enum inv_filter_e {
#define GESTURE_ACCEL_RATE 50
#define ESI_GYRO_RATE 1000
#define MAX_FIFO_PACKET_READ 6
#define MAX_BATCH_FIFO_SIZE 896
#define MAX_BATCH_FIFO_SIZE FIFO_SIZE
#define MIN_MST_ODR_CONFIG 4
#define MAX_MST_ODR_CONFIG 5

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2017 InvenSense, Inc.
* Copyright (C) 2017-2018 InvenSense, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -172,6 +172,10 @@ static int inv_init_config(struct inv_mpu_state *st)
st->eis.count_precision = NSEC_PER_MSEC;
st->firmware = 0;
st->fifo_count_mode = BYTE_MODE;
#ifdef TIMER_BASED_BATCHING
st->batch_timeout = 0;
st->is_batch_timer_running = false;
#endif
st->eng_info[ENGINE_GYRO].base_time = NSEC_PER_SEC;
st->eng_info[ENGINE_ACCEL].base_time = NSEC_PER_SEC;

View file

@ -193,6 +193,11 @@ static int inv_process_20680_data(struct inv_mpu_state *st)
if (!pk_size)
return -EINVAL;
if (fifo_count >= (HARDWARE_FIFO_SIZE / st->batch.pk_size)) {
pr_warn("fifo overflow pkt count=%d pkt sz=%d\n", fifo_count, st->batch.pk_size);
return -EOVERFLOW;
}
fifo_count *= st->batch.pk_size;
st->fifo_count = fifo_count;
d = st->fifo_data_store;
@ -312,20 +317,24 @@ static int inv_process_20680_data(struct inv_mpu_state *st)
}
/*
* inv_read_fifo() - Transfer data from FIFO to ring buffer.
* _inv_read_fifo() - Transfer data from FIFO to ring buffer.
*/
irqreturn_t inv_read_fifo(int irq, void *dev_id)
static void _inv_read_fifo(struct inv_mpu_state *st)
{
struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;
struct iio_dev *indio_dev = iio_priv_to_dev(st);
int result;
result = wait_event_interruptible_timeout(st->wait_queue,
st->resume_state, msecs_to_jiffies(300));
if (result <= 0)
return IRQ_HANDLED;
return;
mutex_lock(&indio_dev->mlock);
#ifdef TIMER_BASED_BATCHING
if (st->batch_timeout) {
if (inv_plat_single_write(st, REG_INT_ENABLE, st->int_en))
pr_err("REG_INT_ENABLE write error\n");
}
#endif
st->wake_sensor_received = false;
result = inv_process_20680_data(st);
if (result)
@ -338,7 +347,7 @@ irqreturn_t inv_read_fifo(int irq, void *dev_id)
#else
__pm_wakeup_event(&st->wake_lock, 200); /* 200 msecs */
#endif
return IRQ_HANDLED;
return;
err_reset_fifo:
if ((!st->chip_config.gyro_enable) &&
@ -348,7 +357,7 @@ err_reset_fifo:
inv_switch_power_in_lp(st, false);
mutex_unlock(&indio_dev->mlock);
return IRQ_HANDLED;
return;
}
pr_err("error to reset fifo\n");
@ -357,10 +366,34 @@ err_reset_fifo:
inv_switch_power_in_lp(st, false);
mutex_unlock(&indio_dev->mlock);
return IRQ_HANDLED;
return;
}
irqreturn_t inv_read_fifo(int irq, void *dev_id)
{
struct inv_mpu_state *st = (struct inv_mpu_state *)dev_id;
_inv_read_fifo(st);
return IRQ_HANDLED;
}
#ifdef TIMER_BASED_BATCHING
void inv_batch_work(struct work_struct *work)
{
struct inv_mpu_state *st =
container_of(work, struct inv_mpu_state, batch_work);
struct iio_dev *indio_dev = iio_priv_to_dev(st);
mutex_lock(&indio_dev->mlock);
if (inv_plat_single_write(st, REG_INT_ENABLE, st->int_en | BIT_DATA_RDY_EN))
pr_err("REG_INT_ENABLE write error\n");
mutex_unlock(&indio_dev->mlock);
return;
}
#endif
int inv_flush_batch_data(struct iio_dev *indio_dev, int data)
{
struct inv_mpu_state *st = iio_priv(indio_dev);

View file

@ -44,6 +44,13 @@ static int inv_turn_on_fifo(struct inv_mpu_state *st)
st->gesture_int_count = WOM_DELAY_THRESHOLD;
int_en |= BIT_WOM_ALL_INT_EN;
}
#ifdef TIMER_BASED_BATCHING
if (st->chip_config.eis_enable)
int_en |= BIT_FSYNC_INT_EN;
if (!st->batch_timeout) {
int_en |= BIT_DATA_RDY_EN;
}
#else
if (st->batch.timeout) {
if(!st->batch.fifo_wm_th)
int_en = BIT_DATA_RDY_EN;
@ -52,6 +59,7 @@ static int inv_turn_on_fifo(struct inv_mpu_state *st)
if (st->chip_config.eis_enable)
int_en |= BIT_FSYNC_INT_EN;
}
#endif
if (st->sensor[SENSOR_GYRO].on)
fifo_en |= BITS_GYRO_FIFO_EN;
@ -60,6 +68,7 @@ static int inv_turn_on_fifo(struct inv_mpu_state *st)
r = inv_plat_single_write(st, REG_FIFO_EN, fifo_en);
if (r)
return r;
st->int_en = int_en;
r = inv_plat_single_write(st, REG_INT_ENABLE, int_en);
if (r)
return r;
@ -75,6 +84,19 @@ static int inv_turn_on_fifo(struct inv_mpu_state *st)
user = BIT_FIFO_EN;
#endif
r = inv_plat_single_write(st, REG_USER_CTRL, user | st->i2c_dis);
#ifdef TIMER_BASED_BATCHING
if (fifo_en && st->batch_timeout) {
if (st->is_batch_timer_running)
hrtimer_cancel(&st ->hr_batch_timer);
st->is_batch_timer_running = true;
hrtimer_start(&st ->hr_batch_timer,
ns_to_ktime(st->batch_timeout), HRTIMER_MODE_REL);
} else {
if (st->is_batch_timer_running)
hrtimer_cancel(&st ->hr_batch_timer);
st->is_batch_timer_running = false;
}
#endif
return r;
}
@ -245,6 +267,27 @@ static int inv_set_div(struct inv_mpu_state *st, int a_d, int g_d)
// 20680 does not support batching
static int inv_set_batch(struct inv_mpu_state *st)
{
#ifdef TIMER_BASED_BATCHING
u64 timeout;
int required_fifo_size;
if (st->batch.timeout) {
required_fifo_size = st->batch.timeout * st->eng_info[ENGINE_GYRO].running_rate
* st->batch.pk_size / 1000;
if (required_fifo_size > MAX_BATCH_FIFO_SIZE) {
required_fifo_size = MAX_BATCH_FIFO_SIZE;
timeout = (required_fifo_size / st->batch.pk_size) * (1000 / st->eng_info[ENGINE_GYRO].running_rate);
} else {
timeout = st->batch.timeout;
}
} else {
timeout = 1000 / st->eng_info[ENGINE_GYRO].running_rate;
}
if (timeout <= 1000 / st->eng_info[ENGINE_GYRO].running_rate)
st->batch_timeout = 0;
else
st->batch_timeout = timeout * 1000000; // ms to ns
#endif
st->batch.fifo_wm_th = 0;
return 0;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2017 InvenSense, Inc.
* Copyright (C) 2012-2018 InvenSense, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -417,6 +417,9 @@ static int inv_mpu_probe(struct i2c_client *client,
#else
pr_info("Data read from FIFO\n");
#endif
#ifdef TIMER_BASED_BATCHING
pr_info("Timer based batching\n");
#endif
return 0;
#ifdef KERNEL_VERSION_4_X

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2017 InvenSense, Inc.
* Copyright (C) 2012-2018 InvenSense, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -59,7 +59,7 @@
#include "iam20680/inv_mpu_iio_reg_20680.h"
#endif
#define INVENSENSE_DRIVER_VERSION "8.1.1-simple-test1a"
#define INVENSENSE_DRIVER_VERSION "8.1.2-simple-test1"
/* #define DEBUG */
@ -722,6 +722,12 @@ struct inv_mpu_state {
struct wake_lock wake_lock;
#else
struct wakeup_source wake_lock;
#endif
#ifdef TIMER_BASED_BATCHING
struct hrtimer hr_batch_timer;
u64 batch_timeout;
bool is_batch_timer_running;
struct work_struct batch_work;
#endif
struct i2c_client *client;
struct mpu_platform_data plat_data;
@ -1018,7 +1024,9 @@ int inv_create_dmp_sysfs(struct iio_dev *ind);
int inv_check_chip_type(struct iio_dev *indio_dev, const char *name);
int inv_write_compass_matrix(struct inv_mpu_state *st, int *adj);
irqreturn_t inv_read_fifo(int irq, void *dev_id);
#ifdef TIMER_BASED_BATCHING
void inv_batch_work(struct work_struct *work);
#endif
int inv_flush_batch_data(struct iio_dev *indio_dev, int data);
static inline int mpu_memory_write(struct inv_mpu_state *st, u8 mpu_addr,
u16 mem_addr, u32 len, u8 const *data)

View file

@ -533,6 +533,23 @@ static irqreturn_t inv_irq_handler(int irq, void *dev_id)
return IRQ_WAKE_THREAD;
}
#ifdef TIMER_BASED_BATCHING
static enum hrtimer_restart inv_batch_timer_handler(struct hrtimer *timer)
{
struct inv_mpu_state *st =
container_of(timer, struct inv_mpu_state, hr_batch_timer);
if (st->chip_config.gyro_enable || st->chip_config.accel_enable) {
hrtimer_forward_now(&st->hr_batch_timer,
ns_to_ktime(st->batch_timeout));
schedule_work(&st->batch_work);
return HRTIMER_RESTART;
}
st->is_batch_timer_running = 0;
return HRTIMER_NORESTART;
}
#endif
void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev)
{
struct inv_mpu_state *st = iio_priv(indio_dev);
@ -569,6 +586,12 @@ int inv_mpu_configure_ring(struct iio_dev *indio_dev)
struct inv_mpu_state *st = iio_priv(indio_dev);
struct iio_buffer *ring;
#ifdef TIMER_BASED_BATCHING
/* configure hrtimer */
hrtimer_init(&st->hr_batch_timer, CLOCK_BOOTTIME, HRTIMER_MODE_REL);
st->hr_batch_timer.function = inv_batch_timer_handler;
INIT_WORK(&st->batch_work, inv_batch_work);
#endif
#ifdef KERNEL_VERSION_4_X
ring = devm_iio_kfifo_allocate(st->dev);
if (!ring)

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2012-2017 InvenSense, Inc.
* Copyright (C) 2012-2018 InvenSense, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@ -271,6 +271,9 @@ static int inv_mpu_probe(struct spi_device *spi)
#else
pr_info("Data read from FIFO\n");
#endif
#ifdef TIMER_BASED_BATCHING
pr_info("Timer based batching\n");
#endif
return 0;
#ifdef KERNEL_VERSION_4_X