Patch "hwmon: (ina2xx) Make calibration register value fixed" has been added to the 4.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
hwmon: (ina2xx) Make calibration register value fixed
to the 4.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
hwmon-ina2xx-make-calibration-register-value-fixed.patch
and it can be found in the queue-4.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Mon Apr 9 13:58:16 CEST 2018
From: Maciej Purski <[email protected]>
Date: Wed, 22 Nov 2017 16:32:15 +0100
Subject: hwmon: (ina2xx) Make calibration register value fixed
From: Maciej Purski <[email protected]>
[ Upstream commit 5d389b125186cf254ad5b8015763ac07c151aea4 ]
Calibration register is used for calculating current register in hardware according to datasheet:
current = shunt_volt * calib_register / 2048 (ina 226) current = shunt_volt * calib_register / 4096 (ina 219)
Fix calib_register value to 2048 for ina226 and 4096 for ina 219 in order to avoid truncation error and provide best precision allowed by shunt_voltage measurement. Make current scale value follow changes of shunt_resistor from sysfs as calib_register value is now fixed.
Power_lsb value should also follow shunt_resistor changes as stated in datasheet:power_lsb = 25 * current_lsb (ina 226)power_lsb = 20 * current_lsb (ina 219)
--- drivers/hwmon/ina2xx.c | 87 ++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 37 deletions(-)
drivers/hwmon/ina2xx.c +50 -37
@@ -95,18 +95,20 @@ enum ina2xx_ids { ina219, ina226 };struct ina2xx_config {u16 config_default; -int calibration_factor; +int calibration_value;int registers;int shunt_div;int bus_voltage_shift;int bus_voltage_lsb;/* uV */ -int power_lsb;/* uW */ +int power_lsb_factor; };struct ina2xx_data {const struct ina2xx_config *config;long rshunt; +long current_lsb_uA; +long power_lsb_uW;struct mutex config_lock;struct regmap *regmap;
@@ -116,21 +118,21 @@ struct ina2xx_data {static const struct ina2xx_config ina2xx_config[] = { [ina219] = { .config_default =INA219_CONFIG_DEFAULT , - .calibration_factor =40960000 , + .calibration_value =4096 , .registers =INA219_REGISTERS , .shunt_div =100 , .bus_voltage_shift =3 , .bus_voltage_lsb =4000 , - .power_lsb =20000 , + .power_lsb_factor =20 , }, [ina226] = { .config_default =INA226_CONFIG_DEFAULT , - .calibration_factor =5120000 , + .calibration_value =2048 , .registers =INA226_REGISTERS , .shunt_div =400 , .bus_voltage_shift =0 , .bus_voltage_lsb =1250 , - .power_lsb =25000 , + .power_lsb_factor =25 , }, };
@@ -169,12 +171,16 @@ static u16 ina226_interval_to_reg(int inreturn INA226_SHIFT_AVG (avg_bits); } +/* +* Calibration register is set to the best value, which eliminates +* truncation errors on calculating current register in hardware. +* According to datasheet (eq. 3) the best values are 2048 for +* ina226 and 4096 for ina219. They are hardcoded as calibration_value. +*/ static int ina2xx_calibrate (struct ina2xx_data *data) { -u16 val =DIV_ROUND_CLOSEST (data->config->calibration_factor, - data->rshunt); - -return regmap_write (data->regmap,INA2XX_CALIBRATION , val); +return regmap_write (data->regmap,INA2XX_CALIBRATION , + data->config->calibration_value); }/*
@@ -187,10 +193,6 @@ static int ina2xx_init(struct ina2xx_datif (ret <0 )return ret; -/* -* Set current LSB to 1mA, shunt is in uOhms -* (equation 13 in datasheet). -*/ return ina2xx_calibrate (data); }
@@ -268,15 +270,15 @@ static int ina2xx_get_value(struct ina2x val =DIV_ROUND_CLOSEST (val,1000 );break ;case INA2XX_POWER : - val = regval * data->config->power_lsb; + val = regval * data->power_lsb_uW;break ;case INA2XX_CURRENT : -/* signed register, LSB=1mA (selected), in mA */ - val = (s16 )regval; +/* signed register, result in mA */ + val = regval * data->current_lsb_uA; + val =DIV_ROUND_CLOSEST (val,1000 );break ;case INA2XX_CALIBRATION : - val =DIV_ROUND_CLOSEST (data->config->calibration_factor, - regval); + val = regval;break ;default :/* programmer goofed */
@@ -304,9 +306,32 @@ static ssize_t ina2xx_show_value(struct ina2xx_get_value(data, attr->index, regval)); } -static ssize_t ina2xx_set_shunt (struct device *dev, -struct device_attribute *da, -const char *buf,size_t count) +/* +* In order to keep calibration register value fixed, the product +* of current_lsb and shunt_resistor should also be fixed and equal +* to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order +* to keep the scale. +*/ +static int ina2xx_set_shunt (struct ina2xx_data *data,long val) +{ +unsigned int dividend =DIV_ROUND_CLOSEST (1000000000 , + data->config->shunt_div); +if (val <=0 || val > dividend) +return -EINVAL ; + +mutex_lock (&data->config_lock); + data->rshunt = val; + data->current_lsb_uA =DIV_ROUND_CLOSEST (dividend, val); + data->power_lsb_uW = data->config->power_lsb_factor * + data->current_lsb_uA; +mutex_unlock (&data->config_lock); + +return 0 ; +} + +static ssize_t ina2xx_store_shunt (struct device *dev, +struct device_attribute *da, +const char *buf,size_t count) {unsigned long val;int status;
@@ -316,18 +341,9 @@ static ssize_t ina2xx_set_shunt(struct dif (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->config_lock); - data->rshunt = val; - status =ina2xx_calibrate (data); -mutex_unlock (&data->config_lock); + status =ina2xx_set_shunt (data, val);if (status <0 )return status; -return count; }
@@ -387,7 +403,7 @@ static SENSOR_DEVICE_ATTR(power1_input,/* shunt resistance */ static SENSOR_DEVICE_ATTR(shunt_resistor, S_IRUGO | S_IWUSR, - ina2xx_show_value, ina2xx_set_shunt, + ina2xx_show_value, ina2xx_store_shunt, INA2XX_CALIBRATION);/* update interval (ina226 only) */
@@ -448,10 +464,7 @@ static int ina2xx_probe(struct i2c_clien val =INA2XX_RSHUNT_DEFAULT ; } -if (val <=0 || val > data->config->calibration_factor) -return -ENODEV ; - - data->rshunt = val; +ina2xx_set_shunt (data, val); ina2xx_regmap_config.max_register = data->config->registers;
Patches currently in stable-queue which might be from [email protected] are
queue-4.14/hwmon-ina2xx-make-calibration-register-value-fixed.patch