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