diff options
-rw-r--r-- | Documentation/hwmon/ina2xx | 5 | ||||
-rw-r--r-- | drivers/hwmon/ina2xx.c | 48 |
2 files changed, 49 insertions, 4 deletions
diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx index 4223c2d3b508..320dd69fb5e6 100644 --- a/Documentation/hwmon/ina2xx +++ b/Documentation/hwmon/ina2xx | |||
@@ -44,6 +44,7 @@ The INA226 monitors both a shunt voltage drop and bus supply voltage. | |||
44 | The INA230 is a high or low side current shunt and power monitor with an I2C | 44 | The INA230 is a high or low side current shunt and power monitor with an I2C |
45 | interface. The INA230 monitors both a shunt voltage drop and bus supply voltage. | 45 | interface. The INA230 monitors both a shunt voltage drop and bus supply voltage. |
46 | 46 | ||
47 | The shunt value in micro-ohms can be set via platform data or device tree. | 47 | The shunt value in micro-ohms can be set via platform data or device tree at |
48 | Please refer to the Documentation/devicetree/bindings/i2c/ina2xx.txt for bindings | 48 | compile-time or via the shunt_resistor attribute in sysfs at run-time. Please |
49 | refer to the Documentation/devicetree/bindings/i2c/ina2xx.txt for bindings | ||
49 | if the device tree is used. | 50 | if the device tree is used. |
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 3234e571805c..49537ea80748 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c | |||
@@ -115,6 +115,12 @@ static const struct ina2xx_config ina2xx_config[] = { | |||
115 | }, | 115 | }, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static int ina2xx_calibrate(struct ina2xx_data *data) | ||
119 | { | ||
120 | return i2c_smbus_write_word_swapped(data->client, INA2XX_CALIBRATION, | ||
121 | data->config->calibration_factor / data->rshunt); | ||
122 | } | ||
123 | |||
118 | /* | 124 | /* |
119 | * Initialize the configuration and calibration registers. | 125 | * Initialize the configuration and calibration registers. |
120 | */ | 126 | */ |
@@ -133,8 +139,7 @@ static int ina2xx_init(struct ina2xx_data *data) | |||
133 | * Set current LSB to 1mA, shunt is in uOhms | 139 | * Set current LSB to 1mA, shunt is in uOhms |
134 | * (equation 13 in datasheet). | 140 | * (equation 13 in datasheet). |
135 | */ | 141 | */ |
136 | return i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, | 142 | return ina2xx_calibrate(data); |
137 | data->config->calibration_factor / data->rshunt); | ||
138 | } | 143 | } |
139 | 144 | ||
140 | static int ina2xx_do_update(struct device *dev) | 145 | static int ina2xx_do_update(struct device *dev) |
@@ -231,6 +236,9 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg) | |||
231 | /* signed register, LSB=1mA (selected), in mA */ | 236 | /* signed register, LSB=1mA (selected), in mA */ |
232 | val = (s16)data->regs[reg]; | 237 | val = (s16)data->regs[reg]; |
233 | break; | 238 | break; |
239 | case INA2XX_CALIBRATION: | ||
240 | val = data->config->calibration_factor / data->regs[reg]; | ||
241 | break; | ||
234 | default: | 242 | default: |
235 | /* programmer goofed */ | 243 | /* programmer goofed */ |
236 | WARN_ON_ONCE(1); | 244 | WARN_ON_ONCE(1); |
@@ -254,6 +262,36 @@ static ssize_t ina2xx_show_value(struct device *dev, | |||
254 | ina2xx_get_value(data, attr->index)); | 262 | ina2xx_get_value(data, attr->index)); |
255 | } | 263 | } |
256 | 264 | ||
265 | static ssize_t ina2xx_set_shunt(struct device *dev, | ||
266 | struct device_attribute *da, | ||
267 | const char *buf, size_t count) | ||
268 | { | ||
269 | struct ina2xx_data *data = ina2xx_update_device(dev); | ||
270 | unsigned long val; | ||
271 | int status; | ||
272 | |||
273 | if (IS_ERR(data)) | ||
274 | return PTR_ERR(data); | ||
275 | |||
276 | status = kstrtoul(buf, 10, &val); | ||
277 | if (status < 0) | ||
278 | return status; | ||
279 | |||
280 | if (val == 0 || | ||
281 | /* Values greater than the calibration factor make no sense. */ | ||
282 | val > data->config->calibration_factor) | ||
283 | return -EINVAL; | ||
284 | |||
285 | mutex_lock(&data->update_lock); | ||
286 | data->rshunt = val; | ||
287 | status = ina2xx_calibrate(data); | ||
288 | mutex_unlock(&data->update_lock); | ||
289 | if (status < 0) | ||
290 | return status; | ||
291 | |||
292 | return count; | ||
293 | } | ||
294 | |||
257 | /* shunt voltage */ | 295 | /* shunt voltage */ |
258 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL, | 296 | static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL, |
259 | INA2XX_SHUNT_VOLTAGE); | 297 | INA2XX_SHUNT_VOLTAGE); |
@@ -270,12 +308,18 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL, | |||
270 | static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, | 308 | static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, |
271 | INA2XX_POWER); | 309 | INA2XX_POWER); |
272 | 310 | ||
311 | /* shunt resistance */ | ||
312 | static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR, | ||
313 | ina2xx_show_value, ina2xx_set_shunt, | ||
314 | INA2XX_CALIBRATION); | ||
315 | |||
273 | /* pointers to created device attributes */ | 316 | /* pointers to created device attributes */ |
274 | static struct attribute *ina2xx_attrs[] = { | 317 | static struct attribute *ina2xx_attrs[] = { |
275 | &sensor_dev_attr_in0_input.dev_attr.attr, | 318 | &sensor_dev_attr_in0_input.dev_attr.attr, |
276 | &sensor_dev_attr_in1_input.dev_attr.attr, | 319 | &sensor_dev_attr_in1_input.dev_attr.attr, |
277 | &sensor_dev_attr_curr1_input.dev_attr.attr, | 320 | &sensor_dev_attr_curr1_input.dev_attr.attr, |
278 | &sensor_dev_attr_power1_input.dev_attr.attr, | 321 | &sensor_dev_attr_power1_input.dev_attr.attr, |
322 | &sensor_dev_attr_shunt_resistor.dev_attr.attr, | ||
279 | NULL, | 323 | NULL, |
280 | }; | 324 | }; |
281 | ATTRIBUTE_GROUPS(ina2xx); | 325 | ATTRIBUTE_GROUPS(ina2xx); |