Provide possibility to toggle power supply to the sensor so that user can optimize their setup and not have the sensor constantly powered. Signed-off-by: Crt Mori <cmo@xxxxxxxxxxx> --- drivers/iio/temperature/mlx90632.c | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/iio/temperature/mlx90632.c b/drivers/iio/temperature/mlx90632.c index 7ee7ff8047a4..e6e5e649a9f9 100644 --- a/drivers/iio/temperature/mlx90632.c +++ b/drivers/iio/temperature/mlx90632.c @@ -18,6 +18,7 @@ #include <linux/math64.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> @@ -128,6 +129,7 @@ * calculations * @object_ambient_temperature: Ambient temperature at object (might differ of * the ambient temperature of sensor. + * @regulator: Regulator of the device */ struct mlx90632_data { struct i2c_client *client; @@ -136,6 +138,7 @@ struct mlx90632_data { u16 emissivity; u8 mtyp; u32 object_ambient_temperature; + struct regulator *regulator; }; static const struct regmap_range mlx90632_volatile_reg_range[] = { @@ -841,6 +844,37 @@ static int mlx90632_wakeup(struct mlx90632_data *data) return mlx90632_pwr_continuous(data->regmap); } +static void mlx90632_disable_regulator(void *_data) +{ + struct mlx90632_data *data = _data; + int ret; + + ret = regulator_disable(data->regulator); + if (ret < 0) + dev_err(regmap_get_device(data->regmap), + "Failed to disable power regulator: %d\n", ret); +} + +static int mlx90632_enable_regulator(struct mlx90632_data *data) +{ + int ret; + + ret = regulator_set_voltage(data->regulator, 3200000, 3600000); + if (ret < 0) { + dev_err(regmap_get_device(data->regmap), "Failed to set voltage on regulator!\n"); + return ret; + } + + ret = regulator_enable(data->regulator); + if (ret < 0) { + dev_err(regmap_get_device(data->regmap), "Failed to enable power regulator!\n"); + } else { + /* Give the device a little bit of time to start up. */ + msleep(MLX90632_SLEEP_DELAY_MS); + } + return ret; +} + static int mlx90632_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -876,6 +910,24 @@ static int mlx90632_probe(struct i2c_client *client, indio_dev->channels = mlx90632_channels; indio_dev->num_channels = ARRAY_SIZE(mlx90632_channels); + mlx90632->regulator = devm_regulator_get(&client->dev, "vdd"); + if (!IS_ERR(mlx90632->regulator)) { + ret = mlx90632_enable_regulator(mlx90632); + if (ret < 0) { + dev_err(&client->dev, "Failed to enable regulator!\n"); + return ret; + } + + ret = devm_add_action_or_reset(&client->dev, + mlx90632_disable_regulator, + mlx90632); + if (ret < 0) { + dev_err(&client->dev, "Failed to setup regulator cleanup action %d\n", + ret); + return ret; + } + } + ret = mlx90632_wakeup(mlx90632); if (ret < 0) { dev_err(&client->dev, "Wakeup failed: %d\n", ret); -- 2.34.1