{128, "MPU6515"},
};
+/* define INV_REG_NUM_MAX the max register unmbers of all sensor type */
+#define INV_REG_NUM_MAX 128
+static u8 inv_reg_data[128] = {0};
+/**
+ * inv_reg_store() - Register store for hw poweroff.
+ */
+int inv_reg_store(struct inv_mpu_iio_s *st)
+{
+ int ii;
+ char data;
+
+ if (!st->chip_config.enable)
+ st->set_power_state(st, true);
+ for (ii = 0; ii < st->hw->num_reg; ii++) {
+ /* don't read fifo r/w register */
+ if (ii == st->reg.fifo_r_w)
+ data = 0;
+ else
+ inv_plat_read(st, ii, 1, &data);
+ inv_reg_data[ii] = data;
+ }
+ if (!st->chip_config.enable)
+ st->set_power_state(st, false);
+
+ return 0;
+}
+
+/**
+ * inv_reg_recover() - Register recover for hw poweroff.
+ */
+int inv_reg_recover(struct inv_mpu_iio_s *st)
+{
+ int ii;
+ char data;
+
+ if (!st->chip_config.enable)
+ st->set_power_state(st, true);
+ for (ii = 0; ii < st->hw->num_reg; ii++) {
+ data = inv_reg_data[ii];
+ /* don't write fifo r/w register */
+ if (ii == st->reg.fifo_r_w)
+ continue;
+ else
+ inv_plat_single_write(st, ii, data);
+ }
+ if (!st->chip_config.enable)
+ st->set_power_state(st, false);
+
+ return 0;
+}
+
static void inv_setup_reg(struct inv_reg_map_s *reg)
{
reg->sample_rate_div = REG_SAMPLE_RATE_DIV;
int orig_x, orig_y, orig_z;
int i;
struct device_node *np = client->dev.of_node;
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct inv_mpu_iio_s *st = iio_priv(indio_dev);
unsigned long irq_flags;
int irq_pin;
int gpio_pin;
int debug;
+ int hw_pwoff;
gpio_pin = of_get_named_gpio_flags(np, "irq-gpio", 0, (enum of_gpio_flags *)&irq_flags);
gpio_request(gpio_pin, "mpu6500");
mpu_data.orientation[i] = -1;
}
+ ret = of_property_read_u32(np, "support-hw-poweroff", &hw_pwoff);
+ if (ret != 0) {
+ st->support_hw_poweroff = 0;
+ }
+ st->support_hw_poweroff = hw_pwoff;
+
ret = of_property_read_u32(np, "mpu-debug", &debug);
if (ret != 0) {
dev_err(&client->dev, "get mpu-debug error\n");
st->client = client;
st->sl_handle = client->adapter;
st->i2c_addr = client->addr;
+ i2c_set_clientdata(client, indio_dev);
if (client->dev.of_node) {
result = of_inv_parse_platform_data(client, &st->plat_data);
if (result)
}
/* Make state variables available to all _show and _store functions. */
- i2c_set_clientdata(client, indio_dev);
indio_dev->dev.parent = &client->dev;
if (!strcmp(id->name, "mpu6xxx"))
indio_dev->name = st->name;
#ifdef CONFIG_PM
static int inv_mpu_resume(struct device *dev)
{
- struct inv_mpu_iio_s *st =
- iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+ int result;
+
pr_debug("%s inv_mpu_resume\n", st->hw->name);
- return st->set_power_state(st, true);
+
+ if (st->support_hw_poweroff) {
+ mutex_lock(&indio_dev->mlock);
+ /* reset to make sure previous state are not there */
+ result = inv_plat_single_write(st, st->reg.pwr_mgmt_1, BIT_H_RESET);
+ if (result) {
+ pr_err("%s, reset failed\n", __func__);
+ goto rw_err;
+ }
+ msleep(POWER_UP_TIME);
+ /* toggle power state */
+ result = st->set_power_state(st, false);
+ if (result) {
+ pr_err("%s, set_power_state false failed\n", __func__);
+ goto rw_err;
+ }
+ result = st->set_power_state(st, true);
+ if (result) {
+ pr_err("%s, set_power_state true failed\n", __func__);
+ goto rw_err;
+ }
+ result = inv_plat_single_write(st, st->reg.user_ctrl, st->i2c_dis);
+ if (result) {
+ pr_err("%s, set user_ctrl failed\n", __func__);
+ goto rw_err;
+ }
+ inv_reg_recover(st);
+ mutex_unlock(&indio_dev->mlock);
+ } else {
+ result = st->set_power_state(st, true);
+ }
+ return result;
+
+rw_err:
+ mutex_unlock(&indio_dev->mlock);
+ return result;
}
static int inv_mpu_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct inv_mpu_iio_s *st = iio_priv(indio_dev);
- int result;
+ int result = 0;
pr_debug("%s inv_mpu_suspend\n", st->hw->name);
+
mutex_lock(&indio_dev->mlock);
- result = 0;
+ if (st->support_hw_poweroff)
+ inv_reg_store(st);
if ((!st->chip_config.dmp_on) ||
(!st->chip_config.enable) ||
(!st->chip_config.dmp_event_int_on))
signed short hid_temperature;
u64 hid_timestamp;
int use_hid;
+ int support_hw_poweroff;
int accel_bias[3];
int gyro_bias[3];
short raw_gyro[3];
struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count);
-
+int inv_reg_store(struct inv_mpu_iio_s *st);
+int inv_reg_recover(struct inv_mpu_iio_s *st);
int inv_mpu_configure_ring(struct iio_dev *indio_dev);
int inv_mpu_probe_trigger(struct iio_dev *indio_dev);
void inv_mpu_unconfigure_ring(struct iio_dev *indio_dev);
u32 orientation[9];
int orig_x, orig_y, orig_z;
int i;
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct inv_mpu_iio_s *st = iio_priv(indio_dev);
struct device_node *np = spi->dev.of_node;
unsigned long irq_flags;
int irq_pin;
int gpio_pin;
int debug;
+ int hw_pwoff;
gpio_pin = of_get_named_gpio_flags(np, "irq-gpio", 0, (enum of_gpio_flags *)&irq_flags);
gpio_request(gpio_pin, "mpu6500");
mpu_data.orientation[i] = -1;
}
+ ret = of_property_read_u32(np, "support-hw-poweroff", &hw_pwoff);
+ if (ret != 0) {
+ st->support_hw_poweroff = 0;
+ }
+ st->support_hw_poweroff = hw_pwoff;
+
ret = of_property_read_u32(np, "mpu-debug", &debug);
if (ret != 0) {
dev_err(&spi->dev, "get mpu-debug error\n");
goto out_no_free;
}
st = iio_priv(indio_dev);
+ spi_set_drvdata(spi, indio_dev);
if (spi->dev.of_node) {
result = of_inv_parse_platform_data(spi, &st->plat_data);
if (result)
*(struct mpu_platform_data *)dev_get_platdata(&spi->dev);
/* Make state variables available to all _show and _store functions. */
- spi_set_drvdata(spi, indio_dev);
indio_dev->dev.parent = &spi->dev;
st->dev = &spi->dev;
st->irq = spi->irq;
#ifdef CONFIG_PM
static int inv_mpu_resume(struct device *dev)
{
- struct inv_mpu_iio_s *st =
- iio_priv(spi_get_drvdata(to_spi_device(dev)));
+ struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
+ struct inv_mpu_iio_s *st = iio_priv(indio_dev);
+ int result;
+
pr_debug("%s inv_mpu_resume\n", st->hw->name);
- return st->set_power_state(st, true);
+
+ if (st->support_hw_poweroff) {
+ mutex_lock(&indio_dev->mlock);
+ /* reset to make sure previous state are not there */
+ result = inv_plat_single_write(st, st->reg.pwr_mgmt_1, BIT_H_RESET);
+ if (result) {
+ pr_err("%s, reset failed\n", __func__);
+ goto rw_err;
+ }
+ msleep(POWER_UP_TIME);
+ /* toggle power state */
+ result = st->set_power_state(st, false);
+ if (result) {
+ pr_err("%s, set_power_state false failed\n", __func__);
+ goto rw_err;
+ }
+ result = st->set_power_state(st, true);
+ if (result) {
+ pr_err("%s, set_power_state true failed\n", __func__);
+ goto rw_err;
+ }
+ result = inv_plat_single_write(st, st->reg.user_ctrl, st->i2c_dis);
+ if (result) {
+ pr_err("%s, set user_ctrl failed\n", __func__);
+ goto rw_err;
+ }
+ inv_reg_recover(st);
+ mutex_unlock(&indio_dev->mlock);
+ } else {
+ result = st->set_power_state(st, true);
+ }
+ return result;
+
+rw_err:
+ mutex_unlock(&indio_dev->mlock);
+ return result;
}
static int inv_mpu_suspend(struct device *dev)
{
struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
struct inv_mpu_iio_s *st = iio_priv(indio_dev);
- int result;
+ int result = 0;
pr_debug("%s inv_mpu_suspend\n", st->hw->name);
+
mutex_lock(&indio_dev->mlock);
- result = 0;
+ if (st->support_hw_poweroff)
+ inv_reg_store(st);
if ((!st->chip_config.dmp_on) ||
(!st->chip_config.enable) ||
(!st->chip_config.dmp_event_int_on))