diff options
-rw-r--r-- | Documentation/hwmon/ina3221.rst | 13 | ||||
-rw-r--r-- | drivers/hwmon/ina3221.c | 58 |
2 files changed, 63 insertions, 8 deletions
diff --git a/Documentation/hwmon/ina3221.rst b/Documentation/hwmon/ina3221.rst index 1e34abb38b59..f6007ae8f4e2 100644 --- a/Documentation/hwmon/ina3221.rst +++ b/Documentation/hwmon/ina3221.rst | |||
@@ -46,4 +46,17 @@ samples Number of samples using in the averaging mode. | |||
46 | Supports the list of number of samples: | 46 | Supports the list of number of samples: |
47 | 47 | ||
48 | 1, 4, 16, 64, 128, 256, 512, 1024 | 48 | 1, 4, 16, 64, 128, 256, 512, 1024 |
49 | |||
50 | update_interval Data conversion time in millisecond, following: | ||
51 | |||
52 | update_interval = C x S x (BC + SC) | ||
53 | |||
54 | * C: number of enabled channels | ||
55 | * S: number of samples | ||
56 | * BC: bus-voltage conversion time in millisecond | ||
57 | * SC: shunt-voltage conversion time in millisecond | ||
58 | |||
59 | Affects both Bus- and Shunt-voltage conversion time. | ||
60 | Note that setting update_interval to 0ms sets both BC | ||
61 | and SC to 140 us (minimum conversion time). | ||
49 | ======================= ======================================================= | 62 | ======================= ======================================================= |
diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 62040aac653c..e0637fed9585 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c | |||
@@ -144,19 +144,37 @@ static const int ina3221_avg_samples[] = { | |||
144 | 1, 4, 16, 64, 128, 256, 512, 1024, | 144 | 1, 4, 16, 64, 128, 256, 512, 1024, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static inline int ina3221_wait_for_data(struct ina3221_data *ina) | 147 | /* Converting update_interval in msec to conversion time in usec */ |
148 | static inline u32 ina3221_interval_ms_to_conv_time(u16 config, int interval) | ||
149 | { | ||
150 | u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK); | ||
151 | u32 samples_idx = INA3221_CONFIG_AVG(config); | ||
152 | u32 samples = ina3221_avg_samples[samples_idx]; | ||
153 | |||
154 | /* Bisect the result to Bus and Shunt conversion times */ | ||
155 | return DIV_ROUND_CLOSEST(interval * 1000 / 2, channels * samples); | ||
156 | } | ||
157 | |||
158 | /* Converting CONFIG register value to update_interval in usec */ | ||
159 | static inline u32 ina3221_reg_to_interval_us(u16 config) | ||
148 | { | 160 | { |
149 | u32 channels = hweight16(ina->reg_config & INA3221_CONFIG_CHs_EN_MASK); | 161 | u32 channels = hweight16(config & INA3221_CONFIG_CHs_EN_MASK); |
150 | u32 vbus_ct_idx = INA3221_CONFIG_VBUS_CT(ina->reg_config); | 162 | u32 vbus_ct_idx = INA3221_CONFIG_VBUS_CT(config); |
151 | u32 vsh_ct_idx = INA3221_CONFIG_VSH_CT(ina->reg_config); | 163 | u32 vsh_ct_idx = INA3221_CONFIG_VSH_CT(config); |
152 | u32 samples_idx = INA3221_CONFIG_AVG(ina->reg_config); | 164 | u32 samples_idx = INA3221_CONFIG_AVG(config); |
153 | u32 samples = ina3221_avg_samples[samples_idx]; | 165 | u32 samples = ina3221_avg_samples[samples_idx]; |
154 | u32 vbus_ct = ina3221_conv_time[vbus_ct_idx]; | 166 | u32 vbus_ct = ina3221_conv_time[vbus_ct_idx]; |
155 | u32 vsh_ct = ina3221_conv_time[vsh_ct_idx]; | 167 | u32 vsh_ct = ina3221_conv_time[vsh_ct_idx]; |
156 | u32 wait, cvrf; | ||
157 | 168 | ||
158 | /* Calculate total conversion time */ | 169 | /* Calculate total conversion time */ |
159 | wait = channels * (vbus_ct + vsh_ct) * samples; | 170 | return channels * (vbus_ct + vsh_ct) * samples; |
171 | } | ||
172 | |||
173 | static inline int ina3221_wait_for_data(struct ina3221_data *ina) | ||
174 | { | ||
175 | u32 wait, cvrf; | ||
176 | |||
177 | wait = ina3221_reg_to_interval_us(ina->reg_config); | ||
160 | 178 | ||
161 | /* Polling the CVRF bit to make sure read data is ready */ | 179 | /* Polling the CVRF bit to make sure read data is ready */ |
162 | return regmap_field_read_poll_timeout(ina->fields[F_CVRF], | 180 | return regmap_field_read_poll_timeout(ina->fields[F_CVRF], |
@@ -197,6 +215,11 @@ static int ina3221_read_chip(struct device *dev, u32 attr, long *val) | |||
197 | regval = INA3221_CONFIG_AVG(ina->reg_config); | 215 | regval = INA3221_CONFIG_AVG(ina->reg_config); |
198 | *val = ina3221_avg_samples[regval]; | 216 | *val = ina3221_avg_samples[regval]; |
199 | return 0; | 217 | return 0; |
218 | case hwmon_chip_update_interval: | ||
219 | /* Return in msec */ | ||
220 | *val = ina3221_reg_to_interval_us(ina->reg_config); | ||
221 | *val = DIV_ROUND_CLOSEST(*val, 1000); | ||
222 | return 0; | ||
200 | default: | 223 | default: |
201 | return -EOPNOTSUPP; | 224 | return -EOPNOTSUPP; |
202 | } | 225 | } |
@@ -325,6 +348,23 @@ static int ina3221_write_chip(struct device *dev, u32 attr, long val) | |||
325 | /* Update reg_config accordingly */ | 348 | /* Update reg_config accordingly */ |
326 | ina->reg_config = tmp; | 349 | ina->reg_config = tmp; |
327 | return 0; | 350 | return 0; |
351 | case hwmon_chip_update_interval: | ||
352 | tmp = ina3221_interval_ms_to_conv_time(ina->reg_config, val); | ||
353 | idx = find_closest(tmp, ina3221_conv_time, | ||
354 | ARRAY_SIZE(ina3221_conv_time)); | ||
355 | |||
356 | /* Update Bus and Shunt voltage conversion times */ | ||
357 | tmp = INA3221_CONFIG_VBUS_CT_MASK | INA3221_CONFIG_VSH_CT_MASK; | ||
358 | tmp = (ina->reg_config & ~tmp) | | ||
359 | (idx << INA3221_CONFIG_VBUS_CT_SHIFT) | | ||
360 | (idx << INA3221_CONFIG_VSH_CT_SHIFT); | ||
361 | ret = regmap_write(ina->regmap, INA3221_CONFIG, tmp); | ||
362 | if (ret) | ||
363 | return ret; | ||
364 | |||
365 | /* Update reg_config accordingly */ | ||
366 | ina->reg_config = tmp; | ||
367 | return 0; | ||
328 | default: | 368 | default: |
329 | return -EOPNOTSUPP; | 369 | return -EOPNOTSUPP; |
330 | } | 370 | } |
@@ -483,6 +523,7 @@ static umode_t ina3221_is_visible(const void *drvdata, | |||
483 | case hwmon_chip: | 523 | case hwmon_chip: |
484 | switch (attr) { | 524 | switch (attr) { |
485 | case hwmon_chip_samples: | 525 | case hwmon_chip_samples: |
526 | case hwmon_chip_update_interval: | ||
486 | return 0644; | 527 | return 0644; |
487 | default: | 528 | default: |
488 | return 0; | 529 | return 0; |
@@ -528,7 +569,8 @@ static umode_t ina3221_is_visible(const void *drvdata, | |||
528 | 569 | ||
529 | static const struct hwmon_channel_info *ina3221_info[] = { | 570 | static const struct hwmon_channel_info *ina3221_info[] = { |
530 | HWMON_CHANNEL_INFO(chip, | 571 | HWMON_CHANNEL_INFO(chip, |
531 | HWMON_C_SAMPLES), | 572 | HWMON_C_SAMPLES, |
573 | HWMON_C_UPDATE_INTERVAL), | ||
532 | HWMON_CHANNEL_INFO(in, | 574 | HWMON_CHANNEL_INFO(in, |
533 | /* 0: dummy, skipped in is_visible */ | 575 | /* 0: dummy, skipped in is_visible */ |
534 | HWMON_I_INPUT, | 576 | HWMON_I_INPUT, |