@@ -95,18 +95,20 @@ enum ina2xx_ids { ina219, ina226 };
95
95
96
96
struct ina2xx_config {
97
97
u16 config_default ;
98
- int calibration_factor ;
98
+ int calibration_value ;
99
99
int registers ;
100
100
int shunt_div ;
101
101
int bus_voltage_shift ;
102
102
int bus_voltage_lsb ; /* uV */
103
- int power_lsb ; /* uW */
103
+ int power_lsb_factor ;
104
104
};
105
105
106
106
struct ina2xx_data {
107
107
const struct ina2xx_config * config ;
108
108
109
109
long rshunt ;
110
+ long current_lsb_uA ;
111
+ long power_lsb_uW ;
110
112
struct mutex config_lock ;
111
113
struct regmap * regmap ;
112
114
@@ -116,21 +118,21 @@ struct ina2xx_data {
116
118
static const struct ina2xx_config ina2xx_config [] = {
117
119
[ina219 ] = {
118
120
.config_default = INA219_CONFIG_DEFAULT ,
119
- .calibration_factor = 40960000 ,
121
+ .calibration_value = 4096 ,
120
122
.registers = INA219_REGISTERS ,
121
123
.shunt_div = 100 ,
122
124
.bus_voltage_shift = 3 ,
123
125
.bus_voltage_lsb = 4000 ,
124
- .power_lsb = 20000 ,
126
+ .power_lsb_factor = 20 ,
125
127
},
126
128
[ina226 ] = {
127
129
.config_default = INA226_CONFIG_DEFAULT ,
128
- .calibration_factor = 5120000 ,
130
+ .calibration_value = 2048 ,
129
131
.registers = INA226_REGISTERS ,
130
132
.shunt_div = 400 ,
131
133
.bus_voltage_shift = 0 ,
132
134
.bus_voltage_lsb = 1250 ,
133
- .power_lsb = 25000 ,
135
+ .power_lsb_factor = 25 ,
134
136
},
135
137
};
136
138
@@ -169,12 +171,16 @@ static u16 ina226_interval_to_reg(int interval)
169
171
return INA226_SHIFT_AVG (avg_bits );
170
172
}
171
173
174
+ /*
175
+ * Calibration register is set to the best value, which eliminates
176
+ * truncation errors on calculating current register in hardware.
177
+ * According to datasheet (eq. 3) the best values are 2048 for
178
+ * ina226 and 4096 for ina219. They are hardcoded as calibration_value.
179
+ */
172
180
static int ina2xx_calibrate (struct ina2xx_data * data )
173
181
{
174
- u16 val = DIV_ROUND_CLOSEST (data -> config -> calibration_factor ,
175
- data -> rshunt );
176
-
177
- return regmap_write (data -> regmap , INA2XX_CALIBRATION , val );
182
+ return regmap_write (data -> regmap , INA2XX_CALIBRATION ,
183
+ data -> config -> calibration_value );
178
184
}
179
185
180
186
/*
@@ -187,10 +193,6 @@ static int ina2xx_init(struct ina2xx_data *data)
187
193
if (ret < 0 )
188
194
return ret ;
189
195
190
- /*
191
- * Set current LSB to 1mA, shunt is in uOhms
192
- * (equation 13 in datasheet).
193
- */
194
196
return ina2xx_calibrate (data );
195
197
}
196
198
@@ -268,15 +270,15 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
268
270
val = DIV_ROUND_CLOSEST (val , 1000 );
269
271
break ;
270
272
case INA2XX_POWER :
271
- val = regval * data -> config -> power_lsb ;
273
+ val = regval * data -> power_lsb_uW ;
272
274
break ;
273
275
case INA2XX_CURRENT :
274
- /* signed register, LSB=1mA (selected), in mA */
275
- val = (s16 )regval ;
276
+ /* signed register, result in mA */
277
+ val = regval * data -> current_lsb_uA ;
278
+ val = DIV_ROUND_CLOSEST (val , 1000 );
276
279
break ;
277
280
case INA2XX_CALIBRATION :
278
- val = DIV_ROUND_CLOSEST (data -> config -> calibration_factor ,
279
- regval );
281
+ val = regval ;
280
282
break ;
281
283
default :
282
284
/* programmer goofed */
@@ -304,9 +306,32 @@ static ssize_t ina2xx_show_value(struct device *dev,
304
306
ina2xx_get_value (data , attr -> index , regval ));
305
307
}
306
308
307
- static ssize_t ina2xx_set_shunt (struct device * dev ,
308
- struct device_attribute * da ,
309
- const char * buf , size_t count )
309
+ /*
310
+ * In order to keep calibration register value fixed, the product
311
+ * of current_lsb and shunt_resistor should also be fixed and equal
312
+ * to shunt_voltage_lsb = 1 / shunt_div multiplied by 10^9 in order
313
+ * to keep the scale.
314
+ */
315
+ static int ina2xx_set_shunt (struct ina2xx_data * data , long val )
316
+ {
317
+ unsigned int dividend = DIV_ROUND_CLOSEST (1000000000 ,
318
+ data -> config -> shunt_div );
319
+ if (val <= 0 || val > dividend )
320
+ return - EINVAL ;
321
+
322
+ mutex_lock (& data -> config_lock );
323
+ data -> rshunt = val ;
324
+ data -> current_lsb_uA = DIV_ROUND_CLOSEST (dividend , val );
325
+ data -> power_lsb_uW = data -> config -> power_lsb_factor *
326
+ data -> current_lsb_uA ;
327
+ mutex_unlock (& data -> config_lock );
328
+
329
+ return 0 ;
330
+ }
331
+
332
+ static ssize_t ina2xx_store_shunt (struct device * dev ,
333
+ struct device_attribute * da ,
334
+ const char * buf , size_t count )
310
335
{
311
336
unsigned long val ;
312
337
int status ;
@@ -316,18 +341,9 @@ static ssize_t ina2xx_set_shunt(struct device *dev,
316
341
if (status < 0 )
317
342
return status ;
318
343
319
- if (val == 0 ||
320
- /* Values greater than the calibration factor make no sense. */
321
- val > data -> config -> calibration_factor )
322
- return - EINVAL ;
323
-
324
- mutex_lock (& data -> config_lock );
325
- data -> rshunt = val ;
326
- status = ina2xx_calibrate (data );
327
- mutex_unlock (& data -> config_lock );
344
+ status = ina2xx_set_shunt (data , val );
328
345
if (status < 0 )
329
346
return status ;
330
-
331
347
return count ;
332
348
}
333
349
@@ -387,7 +403,7 @@ static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, ina2xx_show_value, NULL,
387
403
388
404
/* shunt resistance */
389
405
static SENSOR_DEVICE_ATTR (shunt_resistor , S_IRUGO | S_IWUSR ,
390
- ina2xx_show_value , ina2xx_set_shunt ,
406
+ ina2xx_show_value , ina2xx_store_shunt ,
391
407
INA2XX_CALIBRATION ) ;
392
408
393
409
/* update interval (ina226 only) */
@@ -448,10 +464,7 @@ static int ina2xx_probe(struct i2c_client *client,
448
464
val = INA2XX_RSHUNT_DEFAULT ;
449
465
}
450
466
451
- if (val <= 0 || val > data -> config -> calibration_factor )
452
- return - ENODEV ;
453
-
454
- data -> rshunt = val ;
467
+ ina2xx_set_shunt (data , val );
455
468
456
469
ina2xx_regmap_config .max_register = data -> config -> registers ;
457
470
0 commit comments