63
63
#define dP_ACC_100 0x1900
64
64
#define dP_ACC_200 0x3200
65
65
66
+ #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */
67
+
66
68
struct max17042_chip {
67
69
struct i2c_client * client ;
68
70
struct regmap * regmap ;
@@ -85,10 +87,94 @@ static enum power_supply_property max17042_battery_props[] = {
85
87
POWER_SUPPLY_PROP_CHARGE_FULL ,
86
88
POWER_SUPPLY_PROP_CHARGE_COUNTER ,
87
89
POWER_SUPPLY_PROP_TEMP ,
90
+ POWER_SUPPLY_PROP_TEMP_ALERT_MIN ,
91
+ POWER_SUPPLY_PROP_TEMP_ALERT_MAX ,
92
+ POWER_SUPPLY_PROP_TEMP_MIN ,
93
+ POWER_SUPPLY_PROP_TEMP_MAX ,
94
+ POWER_SUPPLY_PROP_HEALTH ,
88
95
POWER_SUPPLY_PROP_CURRENT_NOW ,
89
96
POWER_SUPPLY_PROP_CURRENT_AVG ,
90
97
};
91
98
99
+ static int max17042_get_temperature (struct max17042_chip * chip , int * temp )
100
+ {
101
+ int ret ;
102
+ u32 data ;
103
+ struct regmap * map = chip -> regmap ;
104
+
105
+ ret = regmap_read (map , MAX17042_TEMP , & data );
106
+ if (ret < 0 )
107
+ return ret ;
108
+
109
+ * temp = data ;
110
+ /* The value is signed. */
111
+ if (* temp & 0x8000 ) {
112
+ * temp = (0x7fff & ~* temp ) + 1 ;
113
+ * temp *= -1 ;
114
+ }
115
+
116
+ /* The value is converted into deci-centigrade scale */
117
+ /* Units of LSB = 1 / 256 degree Celsius */
118
+ * temp = * temp * 10 / 256 ;
119
+ return 0 ;
120
+ }
121
+
122
+ static int max17042_get_battery_health (struct max17042_chip * chip , int * health )
123
+ {
124
+ int temp , vavg , vbatt , ret ;
125
+ u32 val ;
126
+
127
+ ret = regmap_read (chip -> regmap , MAX17042_AvgVCELL , & val );
128
+ if (ret < 0 )
129
+ goto health_error ;
130
+
131
+ /* bits [0-3] unused */
132
+ vavg = val * 625 / 8 ;
133
+ /* Convert to millivolts */
134
+ vavg /= 1000 ;
135
+
136
+ ret = regmap_read (chip -> regmap , MAX17042_VCELL , & val );
137
+ if (ret < 0 )
138
+ goto health_error ;
139
+
140
+ /* bits [0-3] unused */
141
+ vbatt = val * 625 / 8 ;
142
+ /* Convert to millivolts */
143
+ vbatt /= 1000 ;
144
+
145
+ if (vavg < chip -> pdata -> vmin ) {
146
+ * health = POWER_SUPPLY_HEALTH_DEAD ;
147
+ goto out ;
148
+ }
149
+
150
+ if (vbatt > chip -> pdata -> vmax + MAX17042_VMAX_TOLERANCE ) {
151
+ * health = POWER_SUPPLY_HEALTH_OVERVOLTAGE ;
152
+ goto out ;
153
+ }
154
+
155
+ ret = max17042_get_temperature (chip , & temp );
156
+ if (ret < 0 )
157
+ goto health_error ;
158
+
159
+ if (temp <= chip -> pdata -> temp_min ) {
160
+ * health = POWER_SUPPLY_HEALTH_COLD ;
161
+ goto out ;
162
+ }
163
+
164
+ if (temp >= chip -> pdata -> temp_max ) {
165
+ * health = POWER_SUPPLY_HEALTH_OVERHEAT ;
166
+ goto out ;
167
+ }
168
+
169
+ * health = POWER_SUPPLY_HEALTH_GOOD ;
170
+
171
+ out :
172
+ return 0 ;
173
+
174
+ health_error :
175
+ return ret ;
176
+ }
177
+
92
178
static int max17042_get_property (struct power_supply * psy ,
93
179
enum power_supply_property psp ,
94
180
union power_supply_propval * val )
@@ -181,19 +267,34 @@ static int max17042_get_property(struct power_supply *psy,
181
267
val -> intval = data * 1000 / 2 ;
182
268
break ;
183
269
case POWER_SUPPLY_PROP_TEMP :
184
- ret = regmap_read (map , MAX17042_TEMP , & data );
270
+ ret = max17042_get_temperature (chip , & val -> intval );
271
+ if (ret < 0 )
272
+ return ret ;
273
+ break ;
274
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN :
275
+ ret = regmap_read (map , MAX17042_TALRT_Th , & data );
276
+ if (ret < 0 )
277
+ return ret ;
278
+ /* LSB is Alert Minimum. In deci-centigrade */
279
+ val -> intval = (data & 0xff ) * 10 ;
280
+ break ;
281
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX :
282
+ ret = regmap_read (map , MAX17042_TALRT_Th , & data );
283
+ if (ret < 0 )
284
+ return ret ;
285
+ /* MSB is Alert Maximum. In deci-centigrade */
286
+ val -> intval = (data >> 8 ) * 10 ;
287
+ break ;
288
+ case POWER_SUPPLY_PROP_TEMP_MIN :
289
+ val -> intval = chip -> pdata -> temp_min ;
290
+ break ;
291
+ case POWER_SUPPLY_PROP_TEMP_MAX :
292
+ val -> intval = chip -> pdata -> temp_max ;
293
+ break ;
294
+ case POWER_SUPPLY_PROP_HEALTH :
295
+ ret = max17042_get_battery_health (chip , & val -> intval );
185
296
if (ret < 0 )
186
297
return ret ;
187
-
188
- val -> intval = data ;
189
- /* The value is signed. */
190
- if (val -> intval & 0x8000 ) {
191
- val -> intval = (0x7fff & ~val -> intval ) + 1 ;
192
- val -> intval *= -1 ;
193
- }
194
- /* The value is converted into deci-centigrade scale */
195
- /* Units of LSB = 1 / 256 degree Celsius */
196
- val -> intval = val -> intval * 10 / 256 ;
197
298
break ;
198
299
case POWER_SUPPLY_PROP_CURRENT_NOW :
199
300
if (chip -> pdata -> enable_current_sense ) {
@@ -237,6 +338,69 @@ static int max17042_get_property(struct power_supply *psy,
237
338
return 0 ;
238
339
}
239
340
341
+ static int max17042_set_property (struct power_supply * psy ,
342
+ enum power_supply_property psp ,
343
+ const union power_supply_propval * val )
344
+ {
345
+ struct max17042_chip * chip = power_supply_get_drvdata (psy );
346
+ struct regmap * map = chip -> regmap ;
347
+ int ret = 0 ;
348
+ u32 data ;
349
+ int8_t temp ;
350
+
351
+ switch (psp ) {
352
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN :
353
+ ret = regmap_read (map , MAX17042_TALRT_Th , & data );
354
+ if (ret < 0 )
355
+ return ret ;
356
+
357
+ /* Input in deci-centigrade, convert to centigrade */
358
+ temp = val -> intval / 10 ;
359
+ /* force min < max */
360
+ if (temp >= (int8_t )(data >> 8 ))
361
+ temp = (int8_t )(data >> 8 ) - 1 ;
362
+ /* Write both MAX and MIN ALERT */
363
+ data = (data & 0xff00 ) + temp ;
364
+ ret = regmap_write (map , MAX17042_TALRT_Th , data );
365
+ break ;
366
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX :
367
+ ret = regmap_read (map , MAX17042_TALRT_Th , & data );
368
+ if (ret < 0 )
369
+ return ret ;
370
+
371
+ /* Input in Deci-Centigrade, convert to centigrade */
372
+ temp = val -> intval / 10 ;
373
+ /* force max > min */
374
+ if (temp <= (int8_t )(data & 0xff ))
375
+ temp = (int8_t )(data & 0xff ) + 1 ;
376
+ /* Write both MAX and MIN ALERT */
377
+ data = (data & 0xff ) + (temp << 8 );
378
+ ret = regmap_write (map , MAX17042_TALRT_Th , data );
379
+ break ;
380
+ default :
381
+ ret = - EINVAL ;
382
+ }
383
+
384
+ return ret ;
385
+ }
386
+
387
+ static int max17042_property_is_writeable (struct power_supply * psy ,
388
+ enum power_supply_property psp )
389
+ {
390
+ int ret ;
391
+
392
+ switch (psp ) {
393
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MIN :
394
+ case POWER_SUPPLY_PROP_TEMP_ALERT_MAX :
395
+ ret = 1 ;
396
+ break ;
397
+ default :
398
+ ret = 0 ;
399
+ }
400
+
401
+ return ret ;
402
+ }
403
+
240
404
static int max17042_write_verify_reg (struct regmap * map , u8 reg , u32 value )
241
405
{
242
406
int retries = 8 ;
@@ -665,6 +829,8 @@ static const struct power_supply_desc max17042_psy_desc = {
665
829
.name = "max170xx_battery" ,
666
830
.type = POWER_SUPPLY_TYPE_BATTERY ,
667
831
.get_property = max17042_get_property ,
832
+ .set_property = max17042_set_property ,
833
+ .property_is_writeable = max17042_property_is_writeable ,
668
834
.properties = max17042_battery_props ,
669
835
.num_properties = ARRAY_SIZE (max17042_battery_props ),
670
836
};
@@ -673,6 +839,8 @@ static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
673
839
.name = "max170xx_battery" ,
674
840
.type = POWER_SUPPLY_TYPE_BATTERY ,
675
841
.get_property = max17042_get_property ,
842
+ .set_property = max17042_set_property ,
843
+ .property_is_writeable = max17042_property_is_writeable ,
676
844
.properties = max17042_battery_props ,
677
845
.num_properties = ARRAY_SIZE (max17042_battery_props ) - 2 ,
678
846
};
0 commit comments