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

Commit 89dff3d2 authored by Bingzhe Cai's avatar Bingzhe Cai
Browse files

input: sensors: recovery MPU6050 bad power state



MPU6050 sensor requires Vdd power on before Vio, it may enter
bad power state if this power on sequence does not satisfied.
As MPU6050 share power rails with other devices, this power on
sequence is not guaranteed.
Reset the sensor when system back form sleep and retain the sensor
power to recover the sensor from bad power state.

Change-Id: I3e39174cafe31645e92e13cb1647834ee47add3d
Signed-off-by: default avatarBingzhe Cai <bingzhec@codeaurora.org>
parent ef9db122
Loading
Loading
Loading
Loading
+54 −31
Original line number Diff line number Diff line
@@ -891,6 +891,44 @@ exit:
	return ret;
}

/**
 * mpu6050_reset_chip - reset chip to default state
 */
static void mpu6050_reset_chip(struct mpu6050_sensor *sensor)
{
	struct i2c_client *client;
	int ret, i;

	client = sensor->client;

	ret = i2c_smbus_write_byte_data(client, sensor->reg.pwr_mgmt_1,
			BIT_RESET_ALL);
	if (ret < 0) {
		dev_err(&client->dev, "Reset chip fail!\n");
		goto exit;
	}
	for (i = 0; i < MPU6050_RESET_RETRY_CNT; i++) {
		ret = i2c_smbus_read_byte_data(sensor->client,
					sensor->reg.pwr_mgmt_1);
		if (ret < 0) {
			dev_err(&sensor->client->dev,
				"Fail to get reset state ret=%d\n", ret);
			goto exit;
		}

		if ((ret & BIT_H_RESET) == 0) {
			dev_dbg(&sensor->client->dev,
				"Chip reset success! i=%d\n", i);
			break;
		}

		msleep(MPU6050_RESET_WAIT_MS);
	}

exit:
	return;
}

static int mpu6050_gyro_set_enable(struct mpu6050_sensor *sensor, bool enable)
{
	int ret = 0;
@@ -938,14 +976,6 @@ static int mpu6050_gyro_set_enable(struct mpu6050_sensor *sensor, bool enable)
		else
			disable_irq(sensor->client->irq);

		if (!sensor->cfg.enable) {
			ret = mpu6050_power_ctl(sensor, false);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Failed to set power off mpu6050");
				goto exit;
			}
		}
	}

exit:
@@ -1194,14 +1224,6 @@ static int mpu6050_accel_set_enable(struct mpu6050_sensor *sensor, bool enable)
			goto exit;
		}

		if (!sensor->cfg.enable) {
			ret = mpu6050_power_ctl(sensor, false);
			if (ret < 0) {
				dev_err(&sensor->client->dev,
					"Failed to set power off mpu6050");
				goto exit;
			}
		}
	}

exit:
@@ -1983,15 +2005,12 @@ static int mpu6050_suspend(struct device *dev)
			cancel_delayed_work_sync(&sensor->accel_poll_work);
	}


	if (sensor->cfg.enable) {
	mpu6050_set_power_mode(sensor, false);
	ret = mpu6050_power_ctl(sensor, false);
	if (ret < 0) {
		dev_err(&client->dev, "Power off mpu6050 failed\n");
		goto exit;
	}
	}

	dev_dbg(&client->dev, "suspended\n");

@@ -2013,20 +2032,24 @@ static int mpu6050_resume(struct device *dev)
	struct mpu6050_sensor *sensor = i2c_get_clientdata(client);
	int ret = 0;

	if (sensor->cfg.enable) {
	/* Keep sensor power on to prevent  */
	ret = mpu6050_power_ctl(sensor, true);
	if (ret < 0) {
			dev_err(&client->dev, "Power off mpu6050 failed\n");
		dev_err(&client->dev, "Power on mpu6050 failed\n");
		goto exit;
	}
	/* Reset sensor to recovery from unexpect state */
	mpu6050_reset_chip(sensor);

	if (sensor->cfg.enable) {
		ret = mpu6050_restore_context(sensor);
		if (ret < 0) {
			dev_err(&client->dev, "Failed to restore context\n");
			goto exit;
		}

		mpu6050_set_power_mode(sensor, true);
	} else {
		mpu6050_set_power_mode(sensor, false);
	}

	if (sensor->cfg.gyro_enable) {
+7 −2
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@
#define BIT_SLEEP		0x40
#define BIT_CYCLE		0x20
#define BIT_CLK_MASK		0x7
#define BIT_RESET_ALL		0xCF

#define REG_PWR_MGMT_2		0x6C
#define BIT_PWR_ACCEL_STBY_MASK	0x38
@@ -88,6 +89,10 @@
/* initial configure */
#define INIT_FIFO_RATE		50

/* chip reset wait */
#define MPU6050_RESET_RETRY_CNT	10
#define MPU6050_RESET_WAIT_MS	20

enum mpu_device_id {
	MPU6050_ID = 0x68,
	MPU6500_ID = 0x70,