Commit 92e7407a authored by Jean-Baptiste Maneyrol's avatar Jean-Baptiste Maneyrol Committed by Jonathan Cameron

iio: imu: inv_mpu6050: rewrite power and engine management

Rewrite clock management to use automatic clock switching
present since MPU6500.
Sensors engine management can now turn on or off a batch of
sensors which simplifies usage a lot.
Temperature sensor is now turned on/off depending on usage.
Signed-off-by: default avatarJean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 398da994
This diff is collapsed.
...@@ -83,11 +83,22 @@ enum inv_devices { ...@@ -83,11 +83,22 @@ enum inv_devices {
INV_NUM_PARTS INV_NUM_PARTS
}; };
/* chip sensors mask: accelerometer, gyroscope, temperature, magnetometer */
#define INV_MPU6050_SENSOR_ACCL BIT(0)
#define INV_MPU6050_SENSOR_GYRO BIT(1)
#define INV_MPU6050_SENSOR_TEMP BIT(2)
#define INV_MPU6050_SENSOR_MAGN BIT(3)
/** /**
* struct inv_mpu6050_chip_config - Cached chip configuration data. * struct inv_mpu6050_chip_config - Cached chip configuration data.
* @clk: selected chip clock
* @fsr: Full scale range. * @fsr: Full scale range.
* @lpf: Digital low pass filter frequency. * @lpf: Digital low pass filter frequency.
* @accl_fs: accel full scale range. * @accl_fs: accel full scale range.
* @accl_en: accel engine enabled
* @gyro_en: gyro engine enabled
* @temp_en: temperature sensor enabled
* @magn_en: magn engine (i2c master) enabled
* @accl_fifo_enable: enable accel data output * @accl_fifo_enable: enable accel data output
* @gyro_fifo_enable: enable gyro data output * @gyro_fifo_enable: enable gyro data output
* @temp_fifo_enable: enable temp data output * @temp_fifo_enable: enable temp data output
...@@ -95,9 +106,14 @@ enum inv_devices { ...@@ -95,9 +106,14 @@ enum inv_devices {
* @divider: chip sample rate divider (sample rate divider - 1) * @divider: chip sample rate divider (sample rate divider - 1)
*/ */
struct inv_mpu6050_chip_config { struct inv_mpu6050_chip_config {
unsigned int clk:3;
unsigned int fsr:2; unsigned int fsr:2;
unsigned int lpf:3; unsigned int lpf:3;
unsigned int accl_fs:2; unsigned int accl_fs:2;
unsigned int accl_en:1;
unsigned int gyro_en:1;
unsigned int temp_en:1;
unsigned int magn_en:1;
unsigned int accl_fifo_enable:1; unsigned int accl_fifo_enable:1;
unsigned int gyro_fifo_enable:1; unsigned int gyro_fifo_enable:1;
unsigned int temp_fifo_enable:1; unsigned int temp_fifo_enable:1;
...@@ -262,6 +278,7 @@ struct inv_mpu6050_state { ...@@ -262,6 +278,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_PWR_MGMT_1 0x6B #define INV_MPU6050_REG_PWR_MGMT_1 0x6B
#define INV_MPU6050_BIT_H_RESET 0x80 #define INV_MPU6050_BIT_H_RESET 0x80
#define INV_MPU6050_BIT_SLEEP 0x40 #define INV_MPU6050_BIT_SLEEP 0x40
#define INV_MPU6050_BIT_TEMP_DIS 0x08
#define INV_MPU6050_BIT_CLK_MASK 0x7 #define INV_MPU6050_BIT_CLK_MASK 0x7
#define INV_MPU6050_REG_PWR_MGMT_2 0x6C #define INV_MPU6050_REG_PWR_MGMT_2 0x6C
...@@ -292,7 +309,9 @@ struct inv_mpu6050_state { ...@@ -292,7 +309,9 @@ struct inv_mpu6050_state {
/* delay time in milliseconds */ /* delay time in milliseconds */
#define INV_MPU6050_POWER_UP_TIME 100 #define INV_MPU6050_POWER_UP_TIME 100
#define INV_MPU6050_TEMP_UP_TIME 100 #define INV_MPU6050_TEMP_UP_TIME 100
#define INV_MPU6050_SENSOR_UP_TIME 30 #define INV_MPU6050_ACCEL_UP_TIME 20
#define INV_MPU6050_GYRO_UP_TIME 35
#define INV_MPU6050_GYRO_DOWN_TIME 150
/* delay time in microseconds */ /* delay time in microseconds */
#define INV_MPU6050_REG_UP_TIME_MIN 5000 #define INV_MPU6050_REG_UP_TIME_MIN 5000
...@@ -417,7 +436,8 @@ enum inv_mpu6050_clock_sel_e { ...@@ -417,7 +436,8 @@ enum inv_mpu6050_clock_sel_e {
irqreturn_t inv_mpu6050_read_fifo(int irq, void *p); irqreturn_t inv_mpu6050_read_fifo(int irq, void *p);
int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type); int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev, int irq_type);
int inv_reset_fifo(struct iio_dev *indio_dev); int inv_reset_fifo(struct iio_dev *indio_dev);
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask); int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
unsigned int mask);
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val); int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on); int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
int inv_mpu_acpi_create_mux_client(struct i2c_client *client); int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
......
...@@ -316,9 +316,9 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) ...@@ -316,9 +316,9 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
* *
* Returns 0 on success, a negative error code otherwise * Returns 0 on success, a negative error code otherwise
*/ */
int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val) int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
{ {
unsigned int user_ctrl, status; unsigned int status;
__be16 data; __be16 data;
uint8_t addr; uint8_t addr;
unsigned int freq_hz, period_ms; unsigned int freq_hz, period_ms;
...@@ -350,16 +350,14 @@ int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val) ...@@ -350,16 +350,14 @@ int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val)
freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX; freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
period_ms = 1000 / freq_hz; period_ms = 1000 / freq_hz;
/* start i2c master, wait for xfer, stop */ ret = inv_mpu6050_switch_engine(st, true, INV_MPU6050_SENSOR_MAGN);
user_ctrl = st->chip_config.user_ctrl | INV_MPU6050_BIT_I2C_MST_EN;
ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl);
if (ret) if (ret)
return ret; return ret;
/* need to wait 2 periods + half-period margin */ /* need to wait 2 periods + half-period margin */
msleep(period_ms * 2 + period_ms / 2); msleep(period_ms * 2 + period_ms / 2);
user_ctrl = st->chip_config.user_ctrl;
ret = regmap_write(st->map, st->reg->user_ctrl, user_ctrl); ret = inv_mpu6050_switch_engine(st, false, INV_MPU6050_SENSOR_MAGN);
if (ret) if (ret)
return ret; return ret;
......
...@@ -31,6 +31,6 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate); ...@@ -31,6 +31,6 @@ int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate);
int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st); int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st);
int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val); int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val);
#endif /* INV_MPU_MAGN_H_ */ #endif /* INV_MPU_MAGN_H_ */
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
#include "inv_mpu_iio.h" #include "inv_mpu_iio.h"
static void inv_scan_query_mpu6050(struct iio_dev *indio_dev) static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
unsigned int mask;
st->chip_config.gyro_fifo_enable = st->chip_config.gyro_fifo_enable =
test_bit(INV_MPU6050_SCAN_GYRO_X, test_bit(INV_MPU6050_SCAN_GYRO_X,
...@@ -27,17 +28,28 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev) ...@@ -27,17 +28,28 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev)
st->chip_config.temp_fifo_enable = st->chip_config.temp_fifo_enable =
test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask); test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask);
mask = 0;
if (st->chip_config.gyro_fifo_enable)
mask |= INV_MPU6050_SENSOR_GYRO;
if (st->chip_config.accl_fifo_enable)
mask |= INV_MPU6050_SENSOR_ACCL;
if (st->chip_config.temp_fifo_enable)
mask |= INV_MPU6050_SENSOR_TEMP;
return mask;
} }
static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev) static unsigned int inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
unsigned int mask;
inv_scan_query_mpu6050(indio_dev); mask = inv_scan_query_mpu6050(indio_dev);
/* no magnetometer if i2c auxiliary bus is used */ /* no magnetometer if i2c auxiliary bus is used */
if (st->magn_disabled) if (st->magn_disabled)
return; return mask;
st->chip_config.magn_fifo_enable = st->chip_config.magn_fifo_enable =
test_bit(INV_MPU9X50_SCAN_MAGN_X, test_bit(INV_MPU9X50_SCAN_MAGN_X,
...@@ -46,9 +58,13 @@ static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev) ...@@ -46,9 +58,13 @@ static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev)
indio_dev->active_scan_mask) || indio_dev->active_scan_mask) ||
test_bit(INV_MPU9X50_SCAN_MAGN_Z, test_bit(INV_MPU9X50_SCAN_MAGN_Z,
indio_dev->active_scan_mask); indio_dev->active_scan_mask);
if (st->chip_config.magn_fifo_enable)
mask |= INV_MPU6050_SENSOR_MAGN;
return mask;
} }
static void inv_scan_query(struct iio_dev *indio_dev) static unsigned int inv_scan_query(struct iio_dev *indio_dev)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
...@@ -92,62 +108,40 @@ static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st) ...@@ -92,62 +108,40 @@ static unsigned int inv_compute_skip_samples(const struct inv_mpu6050_state *st)
static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
{ {
struct inv_mpu6050_state *st = iio_priv(indio_dev); struct inv_mpu6050_state *st = iio_priv(indio_dev);
uint8_t d; unsigned int scan;
int result; int result;
scan = inv_scan_query(indio_dev);
if (enable) { if (enable) {
result = inv_mpu6050_set_power_itg(st, true); result = inv_mpu6050_set_power_itg(st, true);
if (result) if (result)
return result; return result;
inv_scan_query(indio_dev); result = inv_mpu6050_switch_engine(st, true, scan);
if (st->chip_config.gyro_fifo_enable) { if (result)
result = inv_mpu6050_switch_engine(st, true, goto error_power_off;
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result)
goto error_power_off;
}
if (st->chip_config.accl_fifo_enable) {
result = inv_mpu6050_switch_engine(st, true,
INV_MPU6050_BIT_PWR_ACCL_STBY);
if (result)
goto error_gyro_off;
}
if (st->chip_config.magn_fifo_enable) {
d = st->chip_config.user_ctrl |
INV_MPU6050_BIT_I2C_MST_EN;
result = regmap_write(st->map, st->reg->user_ctrl, d);
if (result)
goto error_accl_off;
st->chip_config.user_ctrl = d;
}
st->skip_samples = inv_compute_skip_samples(st); st->skip_samples = inv_compute_skip_samples(st);
result = inv_reset_fifo(indio_dev); result = inv_reset_fifo(indio_dev);
if (result) if (result)
goto error_magn_off; goto error_sensors_off;
} else { } else {
result = regmap_write(st->map, st->reg->fifo_en, 0); result = regmap_write(st->map, st->reg->fifo_en, 0);
if (result) if (result)
goto error_magn_off; goto error_fifo_off;
result = regmap_write(st->map, st->reg->int_enable, 0); result = regmap_write(st->map, st->reg->int_enable, 0);
if (result) if (result)
goto error_magn_off; goto error_fifo_off;
d = st->chip_config.user_ctrl & ~INV_MPU6050_BIT_I2C_MST_EN;
result = regmap_write(st->map, st->reg->user_ctrl, d);
if (result)
goto error_magn_off;
st->chip_config.user_ctrl = d;
result = inv_mpu6050_switch_engine(st, false, /* restore user_ctrl for disabling FIFO reading */
INV_MPU6050_BIT_PWR_ACCL_STBY); result = regmap_write(st->map, st->reg->user_ctrl,
st->chip_config.user_ctrl);
if (result) if (result)
goto error_accl_off; goto error_sensors_off;
result = inv_mpu6050_switch_engine(st, false, result = inv_mpu6050_switch_engine(st, false, scan);
INV_MPU6050_BIT_PWR_GYRO_STBY);
if (result) if (result)
goto error_gyro_off; goto error_power_off;
result = inv_mpu6050_set_power_itg(st, false); result = inv_mpu6050_set_power_itg(st, false);
if (result) if (result)
...@@ -156,18 +150,11 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable) ...@@ -156,18 +150,11 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
return 0; return 0;
error_magn_off: error_fifo_off:
/* always restore user_ctrl to disable fifo properly */ /* always restore user_ctrl to disable fifo properly */
st->chip_config.user_ctrl &= ~INV_MPU6050_BIT_I2C_MST_EN;
regmap_write(st->map, st->reg->user_ctrl, st->chip_config.user_ctrl); regmap_write(st->map, st->reg->user_ctrl, st->chip_config.user_ctrl);
error_accl_off: error_sensors_off:
if (st->chip_config.accl_fifo_enable) inv_mpu6050_switch_engine(st, false, scan);
inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_ACCL_STBY);
error_gyro_off:
if (st->chip_config.gyro_fifo_enable)
inv_mpu6050_switch_engine(st, false,
INV_MPU6050_BIT_PWR_GYRO_STBY);
error_power_off: error_power_off:
inv_mpu6050_set_power_itg(st, false); inv_mpu6050_set_power_itg(st, false);
return result; return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment