Commit 8a5fc795 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Guenter Roeck

hwmon: (ina2xx) make shunt resistance configurable at run-time

The shunt resistance can only be set via platform_data or device tree. This
isn't suitable for devices in which the shunt resistance can change/isn't
known at boot-time.

Add a sysfs attribute that allows to read and set the shunt resistance.
Signed-off-by: default avatarBartosz Golaszewski <bgolaszewski@baylibre.com>
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent e7947040
...@@ -44,6 +44,7 @@ The INA226 monitors both a shunt voltage drop and bus supply voltage. ...@@ -44,6 +44,7 @@ The INA226 monitors both a shunt voltage drop and bus supply voltage.
The INA230 is a high or low side current shunt and power monitor with an I2C The INA230 is a high or low side current shunt and power monitor with an I2C
interface. The INA230 monitors both a shunt voltage drop and bus supply voltage. interface. The INA230 monitors both a shunt voltage drop and bus supply voltage.
The shunt value in micro-ohms can be set via platform data or device tree. The shunt value in micro-ohms can be set via platform data or device tree at
Please refer to the Documentation/devicetree/bindings/i2c/ina2xx.txt for bindings compile-time or via the shunt_resistor attribute in sysfs at run-time. Please
refer to the Documentation/devicetree/bindings/i2c/ina2xx.txt for bindings
if the device tree is used. if the device tree is used.
...@@ -115,6 +115,12 @@ static const struct ina2xx_config ina2xx_config[] = { ...@@ -115,6 +115,12 @@ static const struct ina2xx_config ina2xx_config[] = {
}, },
}; };
static int ina2xx_calibrate(struct ina2xx_data *data)
{
return i2c_smbus_write_word_swapped(data->client, INA2XX_CALIBRATION,
data->config->calibration_factor / data->rshunt);
}
/* /*
* Initialize the configuration and calibration registers. * Initialize the configuration and calibration registers.
*/ */
...@@ -133,8 +139,7 @@ static int ina2xx_init(struct ina2xx_data *data) ...@@ -133,8 +139,7 @@ static int ina2xx_init(struct ina2xx_data *data)
* Set current LSB to 1mA, shunt is in uOhms * Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet). * (equation 13 in datasheet).
*/ */
return i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, return ina2xx_calibrate(data);
data->config->calibration_factor / data->rshunt);
} }
static int ina2xx_do_update(struct device *dev) static int ina2xx_do_update(struct device *dev)
...@@ -231,6 +236,9 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg) ...@@ -231,6 +236,9 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
/* signed register, LSB=1mA (selected), in mA */ /* signed register, LSB=1mA (selected), in mA */
val = (s16)data->regs[reg]; val = (s16)data->regs[reg];
break; break;
case INA2XX_CALIBRATION:
val = data->config->calibration_factor / data->regs[reg];
break;
default: default:
/* programmer goofed */ /* programmer goofed */
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
...@@ -254,6 +262,36 @@ static ssize_t ina2xx_show_value(struct device *dev, ...@@ -254,6 +262,36 @@ static ssize_t ina2xx_show_value(struct device *dev,
ina2xx_get_value(data, attr->index)); ina2xx_get_value(data, attr->index));
} }
static ssize_t ina2xx_set_shunt(struct device *dev,
struct device_attribute *da,
const char *buf, size_t count)
{
struct ina2xx_data *data = ina2xx_update_device(dev);
unsigned long val;
int status;
if (IS_ERR(data))
return PTR_ERR(data);
status = kstrtoul(buf, 10, &val);
if (status < 0)
return status;
if (val == 0 ||
/* Values greater than the calibration factor make no sense. */
val > data->config->calibration_factor)
return -EINVAL;
mutex_lock(&data->update_lock);
data->rshunt = val;
status = ina2xx_calibrate(data);
mutex_unlock(&data->update_lock);
if (status < 0)
return status;
return count;
}
/* shunt voltage */ /* shunt voltage */
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL, static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_SHUNT_VOLTAGE); INA2XX_SHUNT_VOLTAGE);
...@@ -270,12 +308,18 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL, ...@@ -270,12 +308,18 @@ static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ina2xx_show_value, NULL,
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL, static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
INA2XX_POWER); INA2XX_POWER);
/* shunt resistance */
static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR,
ina2xx_show_value, ina2xx_set_shunt,
INA2XX_CALIBRATION);
/* pointers to created device attributes */ /* pointers to created device attributes */
static struct attribute *ina2xx_attrs[] = { static struct attribute *ina2xx_attrs[] = {
&sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr,
&sensor_dev_attr_curr1_input.dev_attr.attr, &sensor_dev_attr_curr1_input.dev_attr.attr,
&sensor_dev_attr_power1_input.dev_attr.attr, &sensor_dev_attr_power1_input.dev_attr.attr,
&sensor_dev_attr_shunt_resistor.dev_attr.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(ina2xx); ATTRIBUTE_GROUPS(ina2xx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment