From 43dece162de0478fee67b635916c9a901a4a47b9 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Thu, 17 Jan 2019 15:12:53 -0800 Subject: hwmon: (ina3221) Implement ti,single-shot DT property By default, ina3221, as a hardware monitor, continuously measures the inputs and generates corresponding data. However, for battery powered devices, this mode might be power consuming. The DT binding doc is updated with a new boolean type property to allow changing the default operating mode from consuming mode to single-shot mode, which will measure input on demand and then shut down to save power. So this patch implements the DT property accordingly. Signed-off-by: Nicolin Chen Signed-off-by: Guenter Roeck --- drivers/hwmon/ina3221.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/hwmon') diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index f157214b3b83..3626b87a5fd2 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -111,6 +111,7 @@ struct ina3221_input { * @inputs: Array of channel input source specific structures * @lock: mutex lock to serialize sysfs attribute accesses * @reg_config: Register value of INA3221_CONFIG + * @single_shot: running in single-shot operating mode */ struct ina3221_data { struct device *pm_dev; @@ -119,6 +120,8 @@ struct ina3221_data { struct ina3221_input inputs[INA3221_NUM_CHANNELS]; struct mutex lock; u32 reg_config; + + bool single_shot; }; static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) @@ -188,6 +191,11 @@ static int ina3221_read_in(struct device *dev, u32 attr, int channel, long *val) if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + /* Write CONFIG register to trigger a single-shot measurement */ + if (ina->single_shot) + regmap_write(ina->regmap, INA3221_CONFIG, + ina->reg_config); + ret = ina3221_wait_for_data(ina); if (ret) return ret; @@ -232,6 +240,11 @@ static int ina3221_read_curr(struct device *dev, u32 attr, if (!ina3221_is_enabled(ina, channel)) return -ENODATA; + /* Write CONFIG register to trigger a single-shot measurement */ + if (ina->single_shot) + regmap_write(ina->regmap, INA3221_CONFIG, + ina->reg_config); + ret = ina3221_wait_for_data(ina); if (ret) return ret; @@ -614,6 +627,8 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina) if (!np) return 0; + ina->single_shot = of_property_read_bool(np, "ti,single-shot"); + for_each_child_of_node(np, child) { ret = ina3221_probe_child_from_dt(dev, child, ina); if (ret) @@ -663,6 +678,10 @@ static int ina3221_probe(struct i2c_client *client, /* The driver will be reset, so use reset value */ ina->reg_config = INA3221_CONFIG_DEFAULT; + /* Clear continuous bit to use single-shot mode */ + if (ina->single_shot) + ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS; + /* Disable channels if their inputs are disconnected */ for (i = 0; i < INA3221_NUM_CHANNELS; i++) { if (ina->inputs[i].disconnected) -- cgit