diff options
| author | Nicolin Chen <nicoleotsuka@gmail.com> | 2019-01-17 18:12:53 -0500 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2019-02-18 17:23:29 -0500 |
| commit | 43dece162de0478fee67b635916c9a901a4a47b9 (patch) | |
| tree | 2d09f806cd69588a963a6ed337e72c0f05e3580e /drivers/hwmon | |
| parent | 2e1ce20149ea3cd1cee95a07c51a5b8873c20463 (diff) | |
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 <nicoleotsuka@gmail.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
| -rw-r--r-- | drivers/hwmon/ina3221.c | 19 |
1 files changed, 19 insertions, 0 deletions
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 { | |||
| 111 | * @inputs: Array of channel input source specific structures | 111 | * @inputs: Array of channel input source specific structures |
| 112 | * @lock: mutex lock to serialize sysfs attribute accesses | 112 | * @lock: mutex lock to serialize sysfs attribute accesses |
| 113 | * @reg_config: Register value of INA3221_CONFIG | 113 | * @reg_config: Register value of INA3221_CONFIG |
| 114 | * @single_shot: running in single-shot operating mode | ||
| 114 | */ | 115 | */ |
| 115 | struct ina3221_data { | 116 | struct ina3221_data { |
| 116 | struct device *pm_dev; | 117 | struct device *pm_dev; |
| @@ -119,6 +120,8 @@ struct ina3221_data { | |||
| 119 | struct ina3221_input inputs[INA3221_NUM_CHANNELS]; | 120 | struct ina3221_input inputs[INA3221_NUM_CHANNELS]; |
| 120 | struct mutex lock; | 121 | struct mutex lock; |
| 121 | u32 reg_config; | 122 | u32 reg_config; |
| 123 | |||
| 124 | bool single_shot; | ||
| 122 | }; | 125 | }; |
| 123 | 126 | ||
| 124 | static inline bool ina3221_is_enabled(struct ina3221_data *ina, int channel) | 127 | 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) | |||
| 188 | if (!ina3221_is_enabled(ina, channel)) | 191 | if (!ina3221_is_enabled(ina, channel)) |
| 189 | return -ENODATA; | 192 | return -ENODATA; |
| 190 | 193 | ||
| 194 | /* Write CONFIG register to trigger a single-shot measurement */ | ||
| 195 | if (ina->single_shot) | ||
| 196 | regmap_write(ina->regmap, INA3221_CONFIG, | ||
| 197 | ina->reg_config); | ||
| 198 | |||
| 191 | ret = ina3221_wait_for_data(ina); | 199 | ret = ina3221_wait_for_data(ina); |
| 192 | if (ret) | 200 | if (ret) |
| 193 | return ret; | 201 | return ret; |
| @@ -232,6 +240,11 @@ static int ina3221_read_curr(struct device *dev, u32 attr, | |||
| 232 | if (!ina3221_is_enabled(ina, channel)) | 240 | if (!ina3221_is_enabled(ina, channel)) |
| 233 | return -ENODATA; | 241 | return -ENODATA; |
| 234 | 242 | ||
| 243 | /* Write CONFIG register to trigger a single-shot measurement */ | ||
| 244 | if (ina->single_shot) | ||
| 245 | regmap_write(ina->regmap, INA3221_CONFIG, | ||
| 246 | ina->reg_config); | ||
| 247 | |||
| 235 | ret = ina3221_wait_for_data(ina); | 248 | ret = ina3221_wait_for_data(ina); |
| 236 | if (ret) | 249 | if (ret) |
| 237 | return ret; | 250 | return ret; |
| @@ -614,6 +627,8 @@ static int ina3221_probe_from_dt(struct device *dev, struct ina3221_data *ina) | |||
| 614 | if (!np) | 627 | if (!np) |
| 615 | return 0; | 628 | return 0; |
| 616 | 629 | ||
| 630 | ina->single_shot = of_property_read_bool(np, "ti,single-shot"); | ||
| 631 | |||
| 617 | for_each_child_of_node(np, child) { | 632 | for_each_child_of_node(np, child) { |
| 618 | ret = ina3221_probe_child_from_dt(dev, child, ina); | 633 | ret = ina3221_probe_child_from_dt(dev, child, ina); |
| 619 | if (ret) | 634 | if (ret) |
| @@ -663,6 +678,10 @@ static int ina3221_probe(struct i2c_client *client, | |||
| 663 | /* The driver will be reset, so use reset value */ | 678 | /* The driver will be reset, so use reset value */ |
| 664 | ina->reg_config = INA3221_CONFIG_DEFAULT; | 679 | ina->reg_config = INA3221_CONFIG_DEFAULT; |
| 665 | 680 | ||
| 681 | /* Clear continuous bit to use single-shot mode */ | ||
| 682 | if (ina->single_shot) | ||
| 683 | ina->reg_config &= ~INA3221_CONFIG_MODE_CONTINUOUS; | ||
| 684 | |||
| 666 | /* Disable channels if their inputs are disconnected */ | 685 | /* Disable channels if their inputs are disconnected */ |
| 667 | for (i = 0; i < INA3221_NUM_CHANNELS; i++) { | 686 | for (i = 0; i < INA3221_NUM_CHANNELS; i++) { |
| 668 | if (ina->inputs[i].disconnected) | 687 | if (ina->inputs[i].disconnected) |
