6363#define dP_ACC_100 0x1900
6464#define dP_ACC_200 0x3200
6565
66+ #define MAX17042_VMAX_TOLERANCE 50 /* 50 mV */
67+
6668struct max17042_chip {
6769 struct i2c_client * client ;
6870 struct regmap * regmap ;
@@ -85,10 +87,94 @@ static enum power_supply_property max17042_battery_props[] = {
8587 POWER_SUPPLY_PROP_CHARGE_FULL ,
8688 POWER_SUPPLY_PROP_CHARGE_COUNTER ,
8789 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 ,
8895 POWER_SUPPLY_PROP_CURRENT_NOW ,
8996 POWER_SUPPLY_PROP_CURRENT_AVG ,
9097};
9198
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+
92178static int max17042_get_property (struct power_supply * psy ,
93179 enum power_supply_property psp ,
94180 union power_supply_propval * val )
@@ -181,19 +267,34 @@ static int max17042_get_property(struct power_supply *psy,
181267 val -> intval = data * 1000 / 2 ;
182268 break ;
183269 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 );
185296 if (ret < 0 )
186297 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 ;
197298 break ;
198299 case POWER_SUPPLY_PROP_CURRENT_NOW :
199300 if (chip -> pdata -> enable_current_sense ) {
@@ -237,6 +338,69 @@ static int max17042_get_property(struct power_supply *psy,
237338 return 0 ;
238339}
239340
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+
240404static int max17042_write_verify_reg (struct regmap * map , u8 reg , u32 value )
241405{
242406 int retries = 8 ;
@@ -665,6 +829,8 @@ static const struct power_supply_desc max17042_psy_desc = {
665829 .name = "max170xx_battery" ,
666830 .type = POWER_SUPPLY_TYPE_BATTERY ,
667831 .get_property = max17042_get_property ,
832+ .set_property = max17042_set_property ,
833+ .property_is_writeable = max17042_property_is_writeable ,
668834 .properties = max17042_battery_props ,
669835 .num_properties = ARRAY_SIZE (max17042_battery_props ),
670836};
@@ -673,6 +839,8 @@ static const struct power_supply_desc max17042_no_current_sense_psy_desc = {
673839 .name = "max170xx_battery" ,
674840 .type = POWER_SUPPLY_TYPE_BATTERY ,
675841 .get_property = max17042_get_property ,
842+ .set_property = max17042_set_property ,
843+ .property_is_writeable = max17042_property_is_writeable ,
676844 .properties = max17042_battery_props ,
677845 .num_properties = ARRAY_SIZE (max17042_battery_props ) - 2 ,
678846};
0 commit comments