lsm6dsl: add pm suspend and resume to lsm6dsl

This commit implements the suspend and resume
PM API for LSM6DSL accelerometer.

Signed-off-by: Emil Lindqvist <emil@lindq.gr>
This commit is contained in:
Emil Lindqvist 2023-11-02 08:25:49 +01:00 committed by Maureen Helm
parent 8129307887
commit 8a77ad406f
2 changed files with 61 additions and 2 deletions

View File

@ -18,6 +18,7 @@
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include "lsm6dsl.h"
@ -26,7 +27,8 @@ LOG_MODULE_REGISTER(LSM6DSL, CONFIG_SENSOR_LOG_LEVEL);
static const uint16_t lsm6dsl_odr_map[] = {0, 12, 26, 52, 104, 208, 416, 833,
1666, 3332, 6664, 1};
#if defined(LSM6DSL_ACCEL_ODR_RUNTIME) || defined(LSM6DSL_GYRO_ODR_RUNTIME)
#if defined(LSM6DSL_ACCEL_ODR_RUNTIME) || defined(LSM6DSL_GYRO_ODR_RUNTIME) ||\
defined(CONFIG_PM_DEVICE)
static int lsm6dsl_freq_to_odr_val(uint16_t freq)
{
size_t i;
@ -169,6 +171,8 @@ static int lsm6dsl_gyro_set_odr_raw(const struct device *dev, uint8_t odr)
return -EIO;
}
data->gyro_freq = lsm6dsl_odr_to_freq_val(odr);
return 0;
}
@ -826,6 +830,59 @@ static int lsm6dsl_init(const struct device *dev)
return 0;
}
#ifdef CONFIG_PM_DEVICE
static int lsm6dsl_pm_action(const struct device *dev,
enum pm_device_action action)
{
struct lsm6dsl_data *data = dev->data;
int ret = -EIO;
uint8_t accel_odr = 0;
uint8_t gyro_odr = 0;
switch (action) {
case PM_DEVICE_ACTION_RESUME:
/* Restore saved ODR values */
accel_odr = lsm6dsl_freq_to_odr_val(data->accel_freq);
ret = lsm6dsl_accel_set_odr_raw(dev, accel_odr);
if (ret < 0) {
LOG_ERR("Failed to resume accelerometer");
break;
}
gyro_odr = lsm6dsl_freq_to_odr_val(data->gyro_freq);
ret = lsm6dsl_gyro_set_odr_raw(dev, gyro_odr);
if (ret < 0) {
LOG_ERR("Failed to resume gyro");
break;
}
break;
case PM_DEVICE_ACTION_SUSPEND:
/*
* Set accelerometer ODR to power-down. Don't use the direct
* function to not overwrite the saved value
*/
ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL1_XL,
LSM6DSL_MASK_CTRL1_XL_ODR_XL, 0);
if (ret < 0) {
LOG_ERR("Failed to suspend accelerometer");
break;
}
/* Set gyro ODR to power-down */
ret = data->hw_tf->update_reg(dev, LSM6DSL_REG_CTRL2_G,
LSM6DSL_MASK_CTRL2_G_ODR_G, 0);
if (ret < 0) {
LOG_ERR("Failed to suspend gyro");
break;
}
break;
default:
return -ENOTSUP;
}
return ret;
}
#endif
#if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
#warning "LSM6DSL driver enabled without any devices"
@ -837,9 +894,10 @@ static int lsm6dsl_init(const struct device *dev)
*/
#define LSM6DSL_DEVICE_INIT(inst) \
PM_DEVICE_DT_INST_DEFINE(inst, lsm6dsl_pm_action); \
SENSOR_DEVICE_DT_INST_DEFINE(inst, \
lsm6dsl_init, \
NULL, \
PM_DEVICE_DT_INST_GET(inst), \
&lsm6dsl_data_##inst, \
&lsm6dsl_config_##inst, \
POST_KERNEL, \

View File

@ -667,6 +667,7 @@ struct lsm6dsl_data {
#endif
const struct lsm6dsl_transfer_function *hw_tf;
uint16_t accel_freq;
uint16_t gyro_freq;
#ifdef CONFIG_LSM6DSL_TRIGGER
const struct device *dev;