Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb6fee87 authored by Bingzhe Cai's avatar Bingzhe Cai
Browse files

input: sensors: add interrupt mode support for MPU6050



Add new function to configure interrupt register that allow sensor
to work on interrupt mode. When interrupt mode is enabled, sensor
can work at background and allow AP processor to sleep, it will
issue interrupt to wakeup AP processor until any preset condition is
meet.

Change-Id: I3e535af12ca200b744c9ee7a3f90a79f23640bd1
Signed-off-by: default avatarBingzhe Cai <bingzhec@codeaurora.org>
parent 08162675
Loading
Loading
Loading
Loading
+267 −58
Original line number Diff line number Diff line
@@ -47,11 +47,12 @@
#define MPU6050_GYRO_MIN_VALUE	-32768
#define MPU6050_GYRO_MAX_VALUE	32767

#define MPU6050_ACCEL_MIN_POLL_INTERVAL_MS	1
/* Limit mininum delay to 10ms as we do not need higher rate so far */
#define MPU6050_ACCEL_MIN_POLL_INTERVAL_MS	10
#define MPU6050_ACCEL_MAX_POLL_INTERVAL_MS	5000
#define MPU6050_ACCEL_DEFAULT_POLL_INTERVAL_MS	200

#define MPU6050_GYRO_MIN_POLL_INTERVAL_MS	1
#define MPU6050_GYRO_MIN_POLL_INTERVAL_MS	10
#define MPU6050_GYRO_MAX_POLL_INTERVAL_MS	5000
#define MPU6050_GYRO_DEFAULT_POLL_INTERVAL_MS	200

@@ -62,6 +63,8 @@
#define MPU6050_ACCEL_SCALE_SHIFT_2G	4
#define MPU6050_GYRO_SCALE_SHIFT_FS0	3

#define MPU6050_RESET_SLEEP_US	10

#define MPU6050_DEV_NAME_ACCEL	"MPU6050-accel"
#define MPU6050_DEV_NAME_GYRO	"gyroscope"

@@ -246,6 +249,8 @@ mpu6050_place_name2num[MPU6050_AXIS_REMAP_TAB_SZ] = {
/* Function declarations */
static void mpu6050_pinctrl_state(struct mpu6050_sensor *sensor,
			bool active);
static int mpu6050_set_drdy_int(struct mpu6050_sensor *sensor, bool on);


static int mpu6050_power_ctl(struct mpu6050_sensor *sensor, bool on)
{
@@ -551,18 +556,30 @@ static irqreturn_t mpu6050_interrupt_thread(int irq, void *data)
{
	struct mpu6050_sensor *sensor = data;

	if (sensor->cfg.accel_enable) {
		mpu6050_read_accel_data(sensor, &sensor->axis);
	mpu6050_read_gyro_data(sensor, &sensor->axis);

	input_report_abs(sensor->accel_dev, ABS_X, sensor->axis.x);
	input_report_abs(sensor->accel_dev, ABS_Y, sensor->axis.y);
	input_report_abs(sensor->accel_dev, ABS_Z, sensor->axis.z);
		mpu6050_remap_accel_data(&sensor->axis, sensor->pdata->place);
		input_report_abs(sensor->accel_dev, ABS_X,
			(sensor->axis.x >> MPU6050_ACCEL_SCALE_SHIFT_2G));
		input_report_abs(sensor->accel_dev, ABS_Y,
			(sensor->axis.y >> MPU6050_ACCEL_SCALE_SHIFT_2G));
		input_report_abs(sensor->accel_dev, ABS_Z,
			(sensor->axis.z >> MPU6050_ACCEL_SCALE_SHIFT_2G));
		input_sync(sensor->accel_dev);
	}

	if (sensor->cfg.gyro_enable) {
		mpu6050_read_gyro_data(sensor, &sensor->axis);
		mpu6050_remap_gyro_data(&sensor->axis, sensor->pdata->place);

	input_report_abs(sensor->gyro_dev, ABS_RX, sensor->axis.rx);
	input_report_abs(sensor->gyro_dev, ABS_RY, sensor->axis.ry);
	input_report_abs(sensor->gyro_dev, ABS_RZ, sensor->axis.rz);
		input_report_abs(sensor->gyro_dev, ABS_RX,
			(sensor->axis.rx >> MPU6050_GYRO_SCALE_SHIFT_FS0));
		input_report_abs(sensor->gyro_dev, ABS_RY,
			(sensor->axis.ry >> MPU6050_GYRO_SCALE_SHIFT_FS0));
		input_report_abs(sensor->gyro_dev, ABS_RZ,
			(sensor->axis.rz >> MPU6050_GYRO_SCALE_SHIFT_FS0));
		input_sync(sensor->gyro_dev);
	}

	return IRQ_HANDLED;
}
@@ -788,7 +805,7 @@ static int mpu6050_gyro_enable(struct mpu6050_sensor *sensor, bool on)
				sensor->reg.pwr_mgmt_1);
	if (ret < 0) {
		dev_err(&sensor->client->dev,
			"Fail to get sensor power state ret=%d\n", ret);
			"Fail to get sensor power state, ret=%d\n", ret);
		return ret;
	}

@@ -805,11 +822,37 @@ static int mpu6050_gyro_enable(struct mpu6050_sensor *sensor, bool on)
				sensor->reg.pwr_mgmt_1, data);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail to set sensor power state ret=%d\n", ret);
				"Fail to set sensor power state, ret=%d\n",
				ret);
			return ret;
		}

		if (!sensor->cfg.int_enabled) {
			ret = mpu6050_set_drdy_int(sensor, true);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to enable interrupt mode for gyro, ret=%d\n",
					ret);
				return ret;
			}
			enable_irq(sensor->client->irq);
			sensor->cfg.int_enabled = true;
		}

		sensor->cfg.enable = 1;
	} else {
		if (sensor->cfg.int_enabled && !sensor->cfg.accel_enable) {
			ret = mpu6050_set_drdy_int(sensor, false);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to disable interrupt mode for gyro, ret=%d\n",
					ret);
				return ret;
			}
			disable_irq(sensor->client->irq);
			sensor->cfg.int_enabled = false;
		}

		ret = mpu6050_switch_engine(sensor, false,
			BIT_PWR_GYRO_STBY_MASK);
		if (ret)
@@ -821,7 +864,7 @@ static int mpu6050_gyro_enable(struct mpu6050_sensor *sensor, bool on)
					sensor->reg.pwr_mgmt_1, data);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to set sensor power state ret=%d\n",
					"Fail to set sensor power state, ret=%d\n",
					ret);
				return ret;
			}
@@ -840,11 +883,25 @@ static int mpu6050_restore_context(struct mpu6050_sensor *sensor)
	struct mpu_reg_map *reg;
	struct i2c_client *client;
	int ret;
	u8 data;
	u8 data, pwr_ctrl;

	client = sensor->client;
	reg = &sensor->reg;

	/* Save power state and wakeup device from sleep */
	ret = i2c_smbus_read_byte_data(client, reg->pwr_mgmt_1);
	if (ret < 0) {
		dev_err(&client->dev, "read power ctrl failed.\n");
		goto exit;
	}
	pwr_ctrl = (u8)ret;

	ret = i2c_smbus_write_byte_data(client, reg->pwr_mgmt_1,
		BIT_WAKEUP_AFTER_RESET);
	if (ret < 0) {
		dev_err(&client->dev, "wakeup sensor failed.\n");
		goto exit;
	}
	ret = i2c_smbus_write_byte_data(client, reg->gyro_config,
			sensor->cfg.fsr << GYRO_CONFIG_FSR_SHIFT);
	if (ret < 0) {
@@ -898,9 +955,23 @@ static int mpu6050_restore_context(struct mpu6050_sensor *sensor)
	}

	ret = i2c_smbus_write_byte_data(client, reg->sample_rate_div,
			ODR_DLPF_ENA / INIT_FIFO_RATE - 1);
			sensor->cfg.rate_div);
	if (ret < 0) {
		dev_err(&client->dev, "set lpa_freq failed.\n");
		dev_err(&client->dev, "set sample_rate_div failed.\n");
		goto exit;
	}

	ret = i2c_smbus_write_byte_data(client, reg->int_pin_cfg,
			sensor->cfg.int_pin_cfg);
	if (ret < 0) {
		dev_err(&client->dev, "set int_pin_cfg failed.\n");
		goto exit;
	}

	ret = i2c_smbus_write_byte_data(client, reg->pwr_mgmt_1,
		pwr_ctrl);
	if (ret < 0) {
		dev_err(&client->dev, "Write saved power state failed.\n");
		goto exit;
	}

@@ -941,7 +1012,7 @@ static void mpu6050_reset_chip(struct mpu6050_sensor *sensor)
			break;
		}

		msleep(MPU6050_RESET_WAIT_MS);
		usleep(MPU6050_RESET_SLEEP_US);
	}

exit:
@@ -980,8 +1051,6 @@ static int mpu6050_gyro_set_enable(struct mpu6050_sensor *sensor, bool enable)
		if (sensor->use_poll)
			schedule_delayed_work(&sensor->gyro_poll_work,
				msecs_to_jiffies(sensor->gyro_poll_ms));
		else
			enable_irq(sensor->client->irq);
	} else {
		ret = mpu6050_gyro_enable(sensor, false);
		if (ret) {
@@ -992,8 +1061,6 @@ static int mpu6050_gyro_set_enable(struct mpu6050_sensor *sensor, bool enable)
		}
		if (sensor->use_poll)
			cancel_delayed_work_sync(&sensor->gyro_poll_work);
		else
			disable_irq(sensor->client->irq);

	}

@@ -1002,9 +1069,109 @@ exit:
	return ret;
}

/*
  * Configure the sensor interrupt register that allow sensor to
  * issue interrupt for each new sensor event.
  */
static int mpu6050_set_drdy_int(struct mpu6050_sensor *sensor, bool on)
{
	int ret;
	u8 data;

	if (sensor->cfg.is_asleep)
		return -EINVAL;

	if (on) {
		ret = i2c_smbus_read_byte_data(sensor->client,
					sensor->reg.int_enable);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail read interrupt mode. ret=%d\n", ret);
			return ret;
		}

		data = (u8)ret;
		data |= BIT_DATA_RDY_EN;
		ret = i2c_smbus_write_byte_data(sensor->client,
				sensor->reg.int_enable, data);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail to set interrupt. ret=%d\n", ret);
			return ret;
		}
	} else {
		ret = i2c_smbus_read_byte_data(sensor->client,
					sensor->reg.int_enable);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail read interrupt mode. ret=%d\n", ret);
			return ret;
		}

		data = (u8)ret;
		data &= ~BIT_DATA_RDY_EN;
		ret = i2c_smbus_write_byte_data(sensor->client,
				sensor->reg.int_enable, data);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail to set interrupt. ret=%d\n", ret);
			return ret;
		}
	}
	return 0;
}

/* Update sensor sample rate divider upon accel and gyro polling rate. */
static int mpu6050_config_sample_rate(struct mpu6050_sensor *sensor)
{
	int ret;
	u32 delay_ms;
	u8 div;

	if (sensor->cfg.is_asleep)
		return -EINVAL;

	if (sensor->accel_poll_ms <= sensor->gyro_poll_ms)
		delay_ms = sensor->accel_poll_ms;
	else
		delay_ms = sensor->gyro_poll_ms;

	/* Sample_rate = internal_ODR/(1+SMPLRT_DIV) */
	if ((sensor->cfg.lpf != MPU_DLPF_256HZ_NOLPF2) &&
		(sensor->cfg.lpf != MPU_DLPF_RESERVED)) {
		if (delay_ms > DELAY_MS_MAX_DLPF)
			delay_ms = DELAY_MS_MAX_DLPF;
		if (delay_ms < DELAY_MS_MIN_DLPF)
			delay_ms = DELAY_MS_MIN_DLPF;

		div = (u8)(((ODR_DLPF_ENA * delay_ms) / MSEC_PER_SEC) - 1);
	} else {
		if (delay_ms > DELAY_MS_MAX_NODLPF)
			delay_ms = DELAY_MS_MAX_NODLPF;
		if (delay_ms < DELAY_MS_MIN_NODLPF)
			delay_ms = DELAY_MS_MIN_NODLPF;
		div = (u8)(((ODR_DLPF_DIS * delay_ms) / MSEC_PER_SEC) - 1);
	}

	ret = i2c_smbus_write_byte_data(sensor->client,
		sensor->reg.sample_rate_div, div);
	if (ret < 0) {
		dev_err(&sensor->client->dev,
				"Update sample rate divdier fail, ret=%d\n",
				ret);
		return ret;
	}

	sensor->cfg.rate_div = div;

	return 0;
}

static int mpu6050_gyro_set_poll_delay(struct mpu6050_sensor *sensor,
					unsigned long delay)
{
	int ret;

	mutex_lock(&sensor->op_lock);
	if (delay < MPU6050_GYRO_MIN_POLL_INTERVAL_MS)
		delay = MPU6050_GYRO_MIN_POLL_INTERVAL_MS;
@@ -1016,6 +1183,11 @@ static int mpu6050_gyro_set_poll_delay(struct mpu6050_sensor *sensor,
		cancel_delayed_work_sync(&sensor->gyro_poll_work);
		schedule_delayed_work(&sensor->gyro_poll_work,
				msecs_to_jiffies(sensor->gyro_poll_ms));
	} else {
		ret = mpu6050_config_sample_rate(sensor);
		if (ret < 0)
			dev_err(&sensor->client->dev,
				"Unable to set polling delay for gyro!\n");
	}
	mutex_unlock(&sensor->op_lock);
	return 0;
@@ -1150,7 +1322,7 @@ static int mpu6050_accel_enable(struct mpu6050_sensor *sensor, bool on)
				sensor->reg.pwr_mgmt_1);
	if (ret < 0) {
		dev_err(&sensor->client->dev,
			"Fail to get sensor power state ret=%d\n", ret);
			"Fail to get sensor power state, ret=%d\n", ret);
		return ret;
	}

@@ -1167,11 +1339,37 @@ static int mpu6050_accel_enable(struct mpu6050_sensor *sensor, bool on)
				sensor->reg.pwr_mgmt_1, data);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail to set sensor power state ret=%d\n", ret);
				"Fail to set sensor power state, ret=%d\n",
				ret);
			return ret;
		}

		if (!sensor->cfg.int_enabled) {
			ret = mpu6050_set_drdy_int(sensor, true);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to enable interrupt mode for accel, ret=%d\n",
					ret);
				return ret;
			}
			enable_irq(sensor->client->irq);
			sensor->cfg.int_enabled = true;
		}

		sensor->cfg.enable = 1;
	} else {
		if (sensor->cfg.int_enabled && !sensor->cfg.gyro_enable) {
			ret = mpu6050_set_drdy_int(sensor, false);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to disable interrupt mode for accel, ret=%d\n",
					ret);
				return ret;
			}
			disable_irq(sensor->client->irq);
			sensor->cfg.int_enabled = false;
		}

		ret = mpu6050_switch_engine(sensor, false,
			BIT_PWR_ACCEL_STBY_MASK);
		if (ret)
@@ -1184,7 +1382,7 @@ static int mpu6050_accel_enable(struct mpu6050_sensor *sensor, bool on)
					sensor->reg.pwr_mgmt_1, data);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Fail to set sensor power state ret=%d\n",
					"Fail to set sensor power state for accel, ret=%d\n",
					ret);
				return ret;
			}
@@ -1227,13 +1425,9 @@ static int mpu6050_accel_set_enable(struct mpu6050_sensor *sensor, bool enable)
		if (sensor->use_poll)
			schedule_delayed_work(&sensor->accel_poll_work,
				msecs_to_jiffies(sensor->accel_poll_ms));
		else
			enable_irq(sensor->client->irq);
	} else {
		if (sensor->use_poll)
			cancel_delayed_work_sync(&sensor->accel_poll_work);
		else
			disable_irq(sensor->client->irq);

		ret = mpu6050_accel_enable(sensor, false);
		if (ret) {
@@ -1253,7 +1447,6 @@ exit:
static int mpu6050_accel_set_poll_delay(struct mpu6050_sensor *sensor,
					unsigned long delay)
{
	u8 divider;
	int ret;

	mutex_lock(&sensor->op_lock);
@@ -1262,18 +1455,17 @@ static int mpu6050_accel_set_poll_delay(struct mpu6050_sensor *sensor,
	if (delay > MPU6050_ACCEL_MAX_POLL_INTERVAL_MS)
		delay = MPU6050_ACCEL_MAX_POLL_INTERVAL_MS;

	if (sensor->accel_poll_ms != delay) {
		/* Output frequency divider. and set timer delay */
		divider = ODR_DLPF_ENA / INIT_FIFO_RATE - 1;
		ret = i2c_smbus_write_byte_data(sensor->client,
				sensor->reg.sample_rate_div, divider);
		if (ret == 0)
	sensor->accel_poll_ms = delay;
	}

	if (sensor->use_poll) {
		cancel_delayed_work_sync(&sensor->accel_poll_work);
		schedule_delayed_work(&sensor->accel_poll_work,
				msecs_to_jiffies(sensor->accel_poll_ms));
	} else {
		ret = mpu6050_config_sample_rate(sensor);
		if (ret < 0)
			dev_err(&sensor->client->dev,
				"Unable to set polling delay for accel!\n");
	}
	mutex_unlock(&sensor->op_lock);
	return 0;
@@ -1495,6 +1687,7 @@ static void setup_mpu6050_reg(struct mpu_reg_map *reg)
	reg->raw_gyro		= REG_RAW_GYRO;
	reg->raw_accel		= REG_RAW_ACCEL;
	reg->temperature	= REG_TEMPERATURE;
	reg->int_pin_cfg	= REG_INT_PIN_CFG;
	reg->int_enable		= REG_INT_ENABLE;
	reg->int_status		= REG_INT_STATUS;
	reg->pwr_mgmt_1		= REG_PWR_MGMT_1;
@@ -1565,6 +1758,7 @@ static int mpu6050_init_config(struct mpu6050_sensor *sensor)
	struct mpu_reg_map *reg;
	struct i2c_client *client;
	s32 ret;
	u8 data;

	if (sensor->cfg.is_asleep)
		return -EINVAL;
@@ -1572,24 +1766,15 @@ static int mpu6050_init_config(struct mpu6050_sensor *sensor)
	reg = &sensor->reg;
	client = sensor->client;

	/* reset device*/
	ret = i2c_smbus_write_byte_data(client,
		reg->pwr_mgmt_1, BIT_H_RESET);
	mpu6050_reset_chip(sensor);

	memset(&sensor->cfg, 0, sizeof(struct mpu_chip_config));

	/* Wake up from sleep */
	ret = i2c_smbus_write_byte_data(client, reg->pwr_mgmt_1,
		BIT_WAKEUP_AFTER_RESET);
	if (ret < 0)
		return ret;
	do {
		usleep(10);
		/* check reset complete */
		ret = i2c_smbus_read_byte_data(client,
			reg->pwr_mgmt_1);
		if (ret < 0) {
			dev_err(&client->dev,
				"Failed to read reset status ret =%d\n",
				ret);
			return ret;
		}
	} while (ret & BIT_H_RESET);
	memset(&sensor->cfg, 0, sizeof(struct mpu_chip_config));

	/* Gyro full scale range configure */
	ret = i2c_smbus_write_byte_data(client, reg->gyro_config,
@@ -1603,11 +1788,11 @@ static int mpu6050_init_config(struct mpu6050_sensor *sensor)
		return ret;
	sensor->cfg.lpf = MPU_DLPF_42HZ;

	ret = i2c_smbus_write_byte_data(client, reg->sample_rate_div,
					ODR_DLPF_ENA / INIT_FIFO_RATE - 1);
	data = (u8)(ODR_DLPF_ENA / INIT_FIFO_RATE - 1);
	ret = i2c_smbus_write_byte_data(client, reg->sample_rate_div, data);
	if (ret < 0)
		return ret;
	sensor->cfg.fifo_rate = INIT_FIFO_RATE;
	sensor->cfg.rate_div = data;

	ret = i2c_smbus_write_byte_data(client, reg->accel_config,
		(ACCEL_FS_02G << ACCL_CONFIG_FSR_SHIFT));
@@ -1615,6 +1800,29 @@ static int mpu6050_init_config(struct mpu6050_sensor *sensor)
		return ret;
	sensor->cfg.accel_fs = ACCEL_FS_02G;

	if ((sensor->pdata->int_flags & IRQF_TRIGGER_FALLING) ||
		(sensor->pdata->int_flags & IRQF_TRIGGER_LOW))
		data = BIT_INT_CFG_DEFAULT | BIT_INT_ACTIVE_LOW;
	else
		data = BIT_INT_CFG_DEFAULT;
	ret = i2c_smbus_write_byte_data(client, reg->int_pin_cfg, data);
	if (ret < 0)
		return ret;
	sensor->cfg.int_pin_cfg = data;

	/* Put sensor into sleep mode */
	ret = i2c_smbus_read_byte_data(client,
		sensor->reg.pwr_mgmt_1);
	if (ret < 0)
		return ret;

	data = (u8)ret;
	data |=  BIT_SLEEP;
	ret = i2c_smbus_write_byte_data(client,
		sensor->reg.pwr_mgmt_1, data);
	if (ret < 0)
		return ret;

	sensor->cfg.gyro_enable = 0;
	sensor->cfg.gyro_fifo_enable = 0;
	sensor->cfg.accel_enable = 0;
@@ -1926,6 +2134,7 @@ static int mpu6050_probe(struct i2c_client *client,
			client->irq = 0;
			goto err_free_gpio;
		}
		/* Disable interrupt until event is enabled */
		disable_irq(client->irq);
	} else {
		sensor->use_poll = 1;
+38 −11
Original line number Diff line number Diff line
@@ -32,6 +32,14 @@
#define BIT_ACCEL_OUT		0x08
#define BITS_GYRO_OUT		0x70

#define REG_INT_PIN_CFG		0x37
#define BIT_INT_ACTIVE_LOW	0x80
#define BIT_INT_OPEN_DRAIN	0x40
#define BIT_INT_LATCH_EN	0x20
#define BIT_INT_RD_CLR		0x10
#define BIT_I2C_BYPASS_EN	0x02
#define BIT_INT_CFG_DEFAULT	(BIT_INT_LATCH_EN | BIT_INT_RD_CLR)

#define REG_INT_ENABLE		0x38
#define BIT_DATA_RDY_EN		0x01
#define BIT_DMP_INT_EN		0x02
@@ -40,10 +48,12 @@
#define BIT_6500_WOM_EN		0x40

#define REG_DMP_INT_STATUS	0x39

#define REG_INT_STATUS		0x3A
#define BIT_MOT_INT		0x40
#define BIT_DATA_RDY_INT	0x01
#define BIT_DMP_INT_INT		0x02
#define BIT_ZMOT_INT		0x20
#define BIT_MOT_INT		0x40
#define BIT_6500_WOM_INT	0x40

#define REG_RAW_ACCEL		0x3B
#define REG_TEMPERATURE		0x41
@@ -62,8 +72,9 @@
#define BIT_H_RESET		0x80
#define BIT_SLEEP		0x40
#define BIT_CYCLE		0x20
#define BIT_CLK_MASK		0x7
#define BIT_CLK_MASK		0x07
#define BIT_RESET_ALL		0xCF
#define BIT_WAKEUP_AFTER_RESET	0x00

#define REG_PWR_MGMT_2		0x6C
#define BIT_PWR_ACCEL_STBY_MASK	0x38
@@ -74,9 +85,20 @@
#define REG_FIFO_R_W		0x74
#define REG_WHOAMI		0x75

#define SAMPLE_DIV_MAX		0xFF
#define ODR_DLPF_DIS		8000
#define ODR_DLPF_ENA		1000

/* Min delay = MSEC_PER_SEC/ODR_DLPF_ENA */
/* Max delay = MSEC_PER_SEC/(ODR_DLPF_ENA/SAMPLE_DIV_MAX+1) */
#define DELAY_MS_MIN_DLPF	1
#define DELAY_MS_MAX_DLPF	256

/* Min delay = MSEC_PER_SEC/ODR_DLPF_DIS and round up to 1*/
/* Max delay = MSEC_PER_SEC/(ODR_DLPF_DIS/SAMPLE_DIV_MAX+1) */
#define DELAY_MS_MIN_NODLPF	1
#define DELAY_MS_MAX_NODLPF	32

/* device bootup time in millisecond */
#define POWER_UP_TIME_MS	100
/* delay to wait gyro engine stable in millisecond */
@@ -149,9 +171,10 @@ enum inv_devices {
 *  @accel_config:	accel config register
 *  @fifo_count_h:	Upper byte of FIFO count.
 *  @fifo_r_w:	FIFO register.
 *  @raw_gyro		Address of first gyro register.
 *  @raw_accl		Address of first accel register.
 *  @temperature	temperature register
 *  @raw_gyro:	Address of first gyro register.
 *  @raw_accl:	Address of first accel register.
 *  @temperature:	temperature register.
 *  @int_pin_cfg:	Interrupt pin and I2C bypass configuration.
 *  @int_enable:	Interrupt enable register.
 *  @int_status:	Interrupt flags.
 *  @pwr_mgmt_1:	Controls chip's power state and clock source.
@@ -169,6 +192,7 @@ struct mpu_reg_map {
	u8 raw_gyro;
	u8 raw_accel;
	u8 temperature;
	u8 int_pin_cfg;
	u8 int_enable;
	u8 int_status;
	u8 pwr_mgmt_1;
@@ -189,8 +213,9 @@ struct mpu_reg_map {
 *  @lpa_mod:		low power mode.
 *  @tap_on:		tap on/off.
 *  @flick_int_on:		flick interrupt on/off.
 *  @int_enabled:		interrupt is enabled.
 *  @lpa_freq:		low power frequency
 *  @fifo_rate:		FIFO update rate.
 *  @rate_div:		Sampling rate divider.
 */
struct mpu_chip_config {
	u32 fsr:2;
@@ -205,8 +230,10 @@ struct mpu_chip_config {
	u32 lpa_mode:1;
	u32 tap_on:1;
	u32 flick_int_on:1;
	u32 int_enabled:1;
	u8 int_pin_cfg;
	u16 lpa_freq;
	u16 fifo_rate;
	u16 rate_div;
};