Version:  2.0.40 2.2.26 2.4.37 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2

Linux/drivers/power/ab8500_btemp.c

  1 /*
  2  * Copyright (C) ST-Ericsson SA 2012
  3  *
  4  * Battery temperature driver for AB8500
  5  *
  6  * License Terms: GNU General Public License v2
  7  * Author:
  8  *      Johan Palsson <johan.palsson@stericsson.com>
  9  *      Karl Komierowski <karl.komierowski@stericsson.com>
 10  *      Arun R Murthy <arun.murthy@stericsson.com>
 11  */
 12 
 13 #include <linux/init.h>
 14 #include <linux/module.h>
 15 #include <linux/device.h>
 16 #include <linux/interrupt.h>
 17 #include <linux/delay.h>
 18 #include <linux/slab.h>
 19 #include <linux/platform_device.h>
 20 #include <linux/power_supply.h>
 21 #include <linux/completion.h>
 22 #include <linux/workqueue.h>
 23 #include <linux/jiffies.h>
 24 #include <linux/of.h>
 25 #include <linux/mfd/core.h>
 26 #include <linux/mfd/abx500.h>
 27 #include <linux/mfd/abx500/ab8500.h>
 28 #include <linux/mfd/abx500/ab8500-bm.h>
 29 #include <linux/mfd/abx500/ab8500-gpadc.h>
 30 
 31 #define VTVOUT_V                        1800
 32 
 33 #define BTEMP_THERMAL_LOW_LIMIT         -10
 34 #define BTEMP_THERMAL_MED_LIMIT         0
 35 #define BTEMP_THERMAL_HIGH_LIMIT_52     52
 36 #define BTEMP_THERMAL_HIGH_LIMIT_57     57
 37 #define BTEMP_THERMAL_HIGH_LIMIT_62     62
 38 
 39 #define BTEMP_BATCTRL_CURR_SRC_7UA      7
 40 #define BTEMP_BATCTRL_CURR_SRC_20UA     20
 41 
 42 #define BTEMP_BATCTRL_CURR_SRC_16UA     16
 43 #define BTEMP_BATCTRL_CURR_SRC_18UA     18
 44 
 45 #define BTEMP_BATCTRL_CURR_SRC_60UA     60
 46 #define BTEMP_BATCTRL_CURR_SRC_120UA    120
 47 
 48 /**
 49  * struct ab8500_btemp_interrupts - ab8500 interrupts
 50  * @name:       name of the interrupt
 51  * @isr         function pointer to the isr
 52  */
 53 struct ab8500_btemp_interrupts {
 54         char *name;
 55         irqreturn_t (*isr)(int irq, void *data);
 56 };
 57 
 58 struct ab8500_btemp_events {
 59         bool batt_rem;
 60         bool btemp_high;
 61         bool btemp_medhigh;
 62         bool btemp_lowmed;
 63         bool btemp_low;
 64         bool ac_conn;
 65         bool usb_conn;
 66 };
 67 
 68 struct ab8500_btemp_ranges {
 69         int btemp_high_limit;
 70         int btemp_med_limit;
 71         int btemp_low_limit;
 72 };
 73 
 74 /**
 75  * struct ab8500_btemp - ab8500 BTEMP device information
 76  * @dev:                Pointer to the structure device
 77  * @node:               List of AB8500 BTEMPs, hence prepared for reentrance
 78  * @curr_source:        What current source we use, in uA
 79  * @bat_temp:           Dispatched battery temperature in degree Celcius
 80  * @prev_bat_temp       Last measured battery temperature in degree Celcius
 81  * @parent:             Pointer to the struct ab8500
 82  * @gpadc:              Pointer to the struct gpadc
 83  * @fg:                 Pointer to the struct fg
 84  * @bm:                 Platform specific battery management information
 85  * @btemp_psy:          Structure for BTEMP specific battery properties
 86  * @events:             Structure for information about events triggered
 87  * @btemp_ranges:       Battery temperature range structure
 88  * @btemp_wq:           Work queue for measuring the temperature periodically
 89  * @btemp_periodic_work:        Work for measuring the temperature periodically
 90  * @initialized:        True if battery id read.
 91  */
 92 struct ab8500_btemp {
 93         struct device *dev;
 94         struct list_head node;
 95         int curr_source;
 96         int bat_temp;
 97         int prev_bat_temp;
 98         struct ab8500 *parent;
 99         struct ab8500_gpadc *gpadc;
100         struct ab8500_fg *fg;
101         struct abx500_bm_data *bm;
102         struct power_supply *btemp_psy;
103         struct ab8500_btemp_events events;
104         struct ab8500_btemp_ranges btemp_ranges;
105         struct workqueue_struct *btemp_wq;
106         struct delayed_work btemp_periodic_work;
107         bool initialized;
108 };
109 
110 /* BTEMP power supply properties */
111 static enum power_supply_property ab8500_btemp_props[] = {
112         POWER_SUPPLY_PROP_PRESENT,
113         POWER_SUPPLY_PROP_ONLINE,
114         POWER_SUPPLY_PROP_TECHNOLOGY,
115         POWER_SUPPLY_PROP_TEMP,
116 };
117 
118 static LIST_HEAD(ab8500_btemp_list);
119 
120 /**
121  * ab8500_btemp_get() - returns a reference to the primary AB8500 BTEMP
122  * (i.e. the first BTEMP in the instance list)
123  */
124 struct ab8500_btemp *ab8500_btemp_get(void)
125 {
126         struct ab8500_btemp *btemp;
127         btemp = list_first_entry(&ab8500_btemp_list, struct ab8500_btemp, node);
128 
129         return btemp;
130 }
131 EXPORT_SYMBOL(ab8500_btemp_get);
132 
133 /**
134  * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance
135  * @di:         pointer to the ab8500_btemp structure
136  * @v_batctrl:  measured batctrl voltage
137  * @inst_curr:  measured instant current
138  *
139  * This function returns the battery resistance that is
140  * derived from the BATCTRL voltage.
141  * Returns value in Ohms.
142  */
143 static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di,
144         int v_batctrl, int inst_curr)
145 {
146         int rbs;
147 
148         if (is_ab8500_1p1_or_earlier(di->parent)) {
149                 /*
150                  * For ABB cut1.0 and 1.1 BAT_CTRL is internally
151                  * connected to 1.8V through a 450k resistor
152                  */
153                 return (450000 * (v_batctrl)) / (1800 - v_batctrl);
154         }
155 
156         if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL) {
157                 /*
158                  * If the battery has internal NTC, we use the current
159                  * source to calculate the resistance.
160                  */
161                 rbs = (v_batctrl * 1000
162                        - di->bm->gnd_lift_resistance * inst_curr)
163                       / di->curr_source;
164         } else {
165                 /*
166                  * BAT_CTRL is internally
167                  * connected to 1.8V through a 80k resistor
168                  */
169                 rbs = (80000 * (v_batctrl)) / (1800 - v_batctrl);
170         }
171 
172         return rbs;
173 }
174 
175 /**
176  * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage
177  * @di:         pointer to the ab8500_btemp structure
178  *
179  * This function returns the voltage on BATCTRL. Returns value in mV.
180  */
181 static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di)
182 {
183         int vbtemp;
184         static int prev;
185 
186         vbtemp = ab8500_gpadc_convert(di->gpadc, BAT_CTRL);
187         if (vbtemp < 0) {
188                 dev_err(di->dev,
189                         "%s gpadc conversion failed, using previous value",
190                         __func__);
191                 return prev;
192         }
193         prev = vbtemp;
194         return vbtemp;
195 }
196 
197 /**
198  * ab8500_btemp_curr_source_enable() - enable/disable batctrl current source
199  * @di:         pointer to the ab8500_btemp structure
200  * @enable:     enable or disable the current source
201  *
202  * Enable or disable the current sources for the BatCtrl AD channel
203  */
204 static int ab8500_btemp_curr_source_enable(struct ab8500_btemp *di,
205         bool enable)
206 {
207         int curr;
208         int ret = 0;
209 
210         /*
211          * BATCTRL current sources are included on AB8500 cut2.0
212          * and future versions
213          */
214         if (is_ab8500_1p1_or_earlier(di->parent))
215                 return 0;
216 
217         /* Only do this for batteries with internal NTC */
218         if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && enable) {
219 
220                 if (is_ab8540(di->parent)) {
221                         if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_60UA)
222                                 curr = BAT_CTRL_60U_ENA;
223                         else
224                                 curr = BAT_CTRL_120U_ENA;
225                 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
226                         if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_16UA)
227                                 curr = BAT_CTRL_16U_ENA;
228                         else
229                                 curr = BAT_CTRL_18U_ENA;
230                 } else {
231                         if (di->curr_source == BTEMP_BATCTRL_CURR_SRC_7UA)
232                                 curr = BAT_CTRL_7U_ENA;
233                         else
234                                 curr = BAT_CTRL_20U_ENA;
235                 }
236 
237                 dev_dbg(di->dev, "Set BATCTRL %duA\n", di->curr_source);
238 
239                 ret = abx500_mask_and_set_register_interruptible(di->dev,
240                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
241                         FORCE_BAT_CTRL_CMP_HIGH, FORCE_BAT_CTRL_CMP_HIGH);
242                 if (ret) {
243                         dev_err(di->dev, "%s failed setting cmp_force\n",
244                                 __func__);
245                         return ret;
246                 }
247 
248                 /*
249                  * We have to wait one 32kHz cycle before enabling
250                  * the current source, since ForceBatCtrlCmpHigh needs
251                  * to be written in a separate cycle
252                  */
253                 udelay(32);
254 
255                 ret = abx500_set_register_interruptible(di->dev,
256                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
257                         FORCE_BAT_CTRL_CMP_HIGH | curr);
258                 if (ret) {
259                         dev_err(di->dev, "%s failed enabling current source\n",
260                                 __func__);
261                         goto disable_curr_source;
262                 }
263         } else if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL && !enable) {
264                 dev_dbg(di->dev, "Disable BATCTRL curr source\n");
265 
266                 if (is_ab8540(di->parent)) {
267                         /* Write 0 to the curr bits */
268                         ret = abx500_mask_and_set_register_interruptible(
269                                 di->dev,
270                                 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
271                                 BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
272                                 ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
273                 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
274                         /* Write 0 to the curr bits */
275                         ret = abx500_mask_and_set_register_interruptible(
276                                 di->dev,
277                                 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
278                                 BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
279                                 ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
280                 } else {
281                         /* Write 0 to the curr bits */
282                         ret = abx500_mask_and_set_register_interruptible(
283                                 di->dev,
284                                 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
285                                 BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
286                                 ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
287                 }
288 
289                 if (ret) {
290                         dev_err(di->dev, "%s failed disabling current source\n",
291                                 __func__);
292                         goto disable_curr_source;
293                 }
294 
295                 /* Enable Pull-Up and comparator */
296                 ret = abx500_mask_and_set_register_interruptible(di->dev,
297                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
298                         BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
299                         BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
300                 if (ret) {
301                         dev_err(di->dev, "%s failed enabling PU and comp\n",
302                                 __func__);
303                         goto enable_pu_comp;
304                 }
305 
306                 /*
307                  * We have to wait one 32kHz cycle before disabling
308                  * ForceBatCtrlCmpHigh since this needs to be written
309                  * in a separate cycle
310                  */
311                 udelay(32);
312 
313                 /* Disable 'force comparator' */
314                 ret = abx500_mask_and_set_register_interruptible(di->dev,
315                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
316                         FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
317                 if (ret) {
318                         dev_err(di->dev, "%s failed disabling force comp\n",
319                                 __func__);
320                         goto disable_force_comp;
321                 }
322         }
323         return ret;
324 
325         /*
326          * We have to try unsetting FORCE_BAT_CTRL_CMP_HIGH one more time
327          * if we got an error above
328          */
329 disable_curr_source:
330         if (is_ab8540(di->parent)) {
331                 /* Write 0 to the curr bits */
332                 ret = abx500_mask_and_set_register_interruptible(di->dev,
333                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
334                         BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA,
335                         ~(BAT_CTRL_60U_ENA | BAT_CTRL_120U_ENA));
336         } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
337                 /* Write 0 to the curr bits */
338                 ret = abx500_mask_and_set_register_interruptible(di->dev,
339                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
340                         BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA,
341                         ~(BAT_CTRL_16U_ENA | BAT_CTRL_18U_ENA));
342         } else {
343                 /* Write 0 to the curr bits */
344                 ret = abx500_mask_and_set_register_interruptible(di->dev,
345                         AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
346                         BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA,
347                         ~(BAT_CTRL_7U_ENA | BAT_CTRL_20U_ENA));
348         }
349 
350         if (ret) {
351                 dev_err(di->dev, "%s failed disabling current source\n",
352                         __func__);
353                 return ret;
354         }
355 enable_pu_comp:
356         /* Enable Pull-Up and comparator */
357         ret = abx500_mask_and_set_register_interruptible(di->dev,
358                 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
359                 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA,
360                 BAT_CTRL_PULL_UP_ENA | BAT_CTRL_CMP_ENA);
361         if (ret) {
362                 dev_err(di->dev, "%s failed enabling PU and comp\n",
363                         __func__);
364                 return ret;
365         }
366 
367 disable_force_comp:
368         /*
369          * We have to wait one 32kHz cycle before disabling
370          * ForceBatCtrlCmpHigh since this needs to be written
371          * in a separate cycle
372          */
373         udelay(32);
374 
375         /* Disable 'force comparator' */
376         ret = abx500_mask_and_set_register_interruptible(di->dev,
377                 AB8500_CHARGER, AB8500_BAT_CTRL_CURRENT_SOURCE,
378                 FORCE_BAT_CTRL_CMP_HIGH, ~FORCE_BAT_CTRL_CMP_HIGH);
379         if (ret) {
380                 dev_err(di->dev, "%s failed disabling force comp\n",
381                         __func__);
382                 return ret;
383         }
384 
385         return ret;
386 }
387 
388 /**
389  * ab8500_btemp_get_batctrl_res() - get battery resistance
390  * @di:         pointer to the ab8500_btemp structure
391  *
392  * This function returns the battery pack identification resistance.
393  * Returns value in Ohms.
394  */
395 static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di)
396 {
397         int ret;
398         int batctrl = 0;
399         int res;
400         int inst_curr;
401         int i;
402 
403         /*
404          * BATCTRL current sources are included on AB8500 cut2.0
405          * and future versions
406          */
407         ret = ab8500_btemp_curr_source_enable(di, true);
408         if (ret) {
409                 dev_err(di->dev, "%s curr source enabled failed\n", __func__);
410                 return ret;
411         }
412 
413         if (!di->fg)
414                 di->fg = ab8500_fg_get();
415         if (!di->fg) {
416                 dev_err(di->dev, "No fg found\n");
417                 return -EINVAL;
418         }
419 
420         ret = ab8500_fg_inst_curr_start(di->fg);
421 
422         if (ret) {
423                 dev_err(di->dev, "Failed to start current measurement\n");
424                 return ret;
425         }
426 
427         do {
428                 msleep(20);
429         } while (!ab8500_fg_inst_curr_started(di->fg));
430 
431         i = 0;
432 
433         do {
434                 batctrl += ab8500_btemp_read_batctrl_voltage(di);
435                 i++;
436                 msleep(20);
437         } while (!ab8500_fg_inst_curr_done(di->fg));
438         batctrl /= i;
439 
440         ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr);
441         if (ret) {
442                 dev_err(di->dev, "Failed to finalize current measurement\n");
443                 return ret;
444         }
445 
446         res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr);
447 
448         ret = ab8500_btemp_curr_source_enable(di, false);
449         if (ret) {
450                 dev_err(di->dev, "%s curr source disable failed\n", __func__);
451                 return ret;
452         }
453 
454         dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n",
455                 __func__, batctrl, res, inst_curr, i);
456 
457         return res;
458 }
459 
460 /**
461  * ab8500_btemp_res_to_temp() - resistance to temperature
462  * @di:         pointer to the ab8500_btemp structure
463  * @tbl:        pointer to the resiatance to temperature table
464  * @tbl_size:   size of the resistance to temperature table
465  * @res:        resistance to calculate the temperature from
466  *
467  * This function returns the battery temperature in degrees Celcius
468  * based on the NTC resistance.
469  */
470 static int ab8500_btemp_res_to_temp(struct ab8500_btemp *di,
471         const struct abx500_res_to_temp *tbl, int tbl_size, int res)
472 {
473         int i, temp;
474         /*
475          * Calculate the formula for the straight line
476          * Simple interpolation if we are within
477          * the resistance table limits, extrapolate
478          * if resistance is outside the limits.
479          */
480         if (res > tbl[0].resist)
481                 i = 0;
482         else if (res <= tbl[tbl_size - 1].resist)
483                 i = tbl_size - 2;
484         else {
485                 i = 0;
486                 while (!(res <= tbl[i].resist &&
487                         res > tbl[i + 1].resist))
488                         i++;
489         }
490 
491         temp = tbl[i].temp + ((tbl[i + 1].temp - tbl[i].temp) *
492                 (res - tbl[i].resist)) / (tbl[i + 1].resist - tbl[i].resist);
493         return temp;
494 }
495 
496 /**
497  * ab8500_btemp_measure_temp() - measure battery temperature
498  * @di:         pointer to the ab8500_btemp structure
499  *
500  * Returns battery temperature (on success) else the previous temperature
501  */
502 static int ab8500_btemp_measure_temp(struct ab8500_btemp *di)
503 {
504         int temp;
505         static int prev;
506         int rbat, rntc, vntc;
507         u8 id;
508 
509         id = di->bm->batt_id;
510 
511         if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
512                         id != BATTERY_UNKNOWN) {
513 
514                 rbat = ab8500_btemp_get_batctrl_res(di);
515                 if (rbat < 0) {
516                         dev_err(di->dev, "%s get batctrl res failed\n",
517                                 __func__);
518                         /*
519                          * Return out-of-range temperature so that
520                          * charging is stopped
521                          */
522                         return BTEMP_THERMAL_LOW_LIMIT;
523                 }
524 
525                 temp = ab8500_btemp_res_to_temp(di,
526                         di->bm->bat_type[id].r_to_t_tbl,
527                         di->bm->bat_type[id].n_temp_tbl_elements, rbat);
528         } else {
529                 vntc = ab8500_gpadc_convert(di->gpadc, BTEMP_BALL);
530                 if (vntc < 0) {
531                         dev_err(di->dev,
532                                 "%s gpadc conversion failed,"
533                                 " using previous value\n", __func__);
534                         return prev;
535                 }
536                 /*
537                  * The PCB NTC is sourced from VTVOUT via a 230kOhm
538                  * resistor.
539                  */
540                 rntc = 230000 * vntc / (VTVOUT_V - vntc);
541 
542                 temp = ab8500_btemp_res_to_temp(di,
543                         di->bm->bat_type[id].r_to_t_tbl,
544                         di->bm->bat_type[id].n_temp_tbl_elements, rntc);
545                 prev = temp;
546         }
547         dev_dbg(di->dev, "Battery temperature is %d\n", temp);
548         return temp;
549 }
550 
551 /**
552  * ab8500_btemp_id() - Identify the connected battery
553  * @di:         pointer to the ab8500_btemp structure
554  *
555  * This function will try to identify the battery by reading the ID
556  * resistor. Some brands use a combined ID resistor with a NTC resistor to
557  * both be able to identify and to read the temperature of it.
558  */
559 static int ab8500_btemp_id(struct ab8500_btemp *di)
560 {
561         int res;
562         u8 i;
563         if (is_ab8540(di->parent))
564                 di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
565         else if (is_ab9540(di->parent) || is_ab8505(di->parent))
566                 di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
567         else
568                 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA;
569 
570         di->bm->batt_id = BATTERY_UNKNOWN;
571 
572         res =  ab8500_btemp_get_batctrl_res(di);
573         if (res < 0) {
574                 dev_err(di->dev, "%s get batctrl res failed\n", __func__);
575                 return -ENXIO;
576         }
577 
578         /* BATTERY_UNKNOWN is defined on position 0, skip it! */
579         for (i = BATTERY_UNKNOWN + 1; i < di->bm->n_btypes; i++) {
580                 if ((res <= di->bm->bat_type[i].resis_high) &&
581                         (res >= di->bm->bat_type[i].resis_low)) {
582                         dev_dbg(di->dev, "Battery detected on %s"
583                                 " low %d < res %d < high: %d"
584                                 " index: %d\n",
585                                 di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL ?
586                                 "BATCTRL" : "BATTEMP",
587                                 di->bm->bat_type[i].resis_low, res,
588                                 di->bm->bat_type[i].resis_high, i);
589 
590                         di->bm->batt_id = i;
591                         break;
592                 }
593         }
594 
595         if (di->bm->batt_id == BATTERY_UNKNOWN) {
596                 dev_warn(di->dev, "Battery identified as unknown"
597                         ", resistance %d Ohm\n", res);
598                 return -ENXIO;
599         }
600 
601         /*
602          * We only have to change current source if the
603          * detected type is Type 1.
604          */
605         if (di->bm->adc_therm == ABx500_ADC_THERM_BATCTRL &&
606             di->bm->batt_id == 1) {
607                 if (is_ab8540(di->parent)) {
608                         dev_dbg(di->dev,
609                                 "Set BATCTRL current source to 60uA\n");
610                         di->curr_source = BTEMP_BATCTRL_CURR_SRC_60UA;
611                 } else if (is_ab9540(di->parent) || is_ab8505(di->parent)) {
612                         dev_dbg(di->dev,
613                                 "Set BATCTRL current source to 16uA\n");
614                         di->curr_source = BTEMP_BATCTRL_CURR_SRC_16UA;
615                 } else {
616                         dev_dbg(di->dev, "Set BATCTRL current source to 20uA\n");
617                         di->curr_source = BTEMP_BATCTRL_CURR_SRC_20UA;
618                 }
619         }
620 
621         return di->bm->batt_id;
622 }
623 
624 /**
625  * ab8500_btemp_periodic_work() - Measuring the temperature periodically
626  * @work:       pointer to the work_struct structure
627  *
628  * Work function for measuring the temperature periodically
629  */
630 static void ab8500_btemp_periodic_work(struct work_struct *work)
631 {
632         int interval;
633         int bat_temp;
634         struct ab8500_btemp *di = container_of(work,
635                 struct ab8500_btemp, btemp_periodic_work.work);
636 
637         if (!di->initialized) {
638                 /* Identify the battery */
639                 if (ab8500_btemp_id(di) < 0)
640                         dev_warn(di->dev, "failed to identify the battery\n");
641         }
642 
643         bat_temp = ab8500_btemp_measure_temp(di);
644         /*
645          * Filter battery temperature.
646          * Allow direct updates on temperature only if two samples result in
647          * same temperature. Else only allow 1 degree change from previous
648          * reported value in the direction of the new measurement.
649          */
650         if ((bat_temp == di->prev_bat_temp) || !di->initialized) {
651                 if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) {
652                         di->initialized = true;
653                         di->bat_temp = bat_temp;
654                         power_supply_changed(di->btemp_psy);
655                 }
656         } else if (bat_temp < di->prev_bat_temp) {
657                 di->bat_temp--;
658                 power_supply_changed(di->btemp_psy);
659         } else if (bat_temp > di->prev_bat_temp) {
660                 di->bat_temp++;
661                 power_supply_changed(di->btemp_psy);
662         }
663         di->prev_bat_temp = bat_temp;
664 
665         if (di->events.ac_conn || di->events.usb_conn)
666                 interval = di->bm->temp_interval_chg;
667         else
668                 interval = di->bm->temp_interval_nochg;
669 
670         /* Schedule a new measurement */
671         queue_delayed_work(di->btemp_wq,
672                 &di->btemp_periodic_work,
673                 round_jiffies(interval * HZ));
674 }
675 
676 /**
677  * ab8500_btemp_batctrlindb_handler() - battery removal detected
678  * @irq:       interrupt number
679  * @_di:       void pointer that has to address of ab8500_btemp
680  *
681  * Returns IRQ status(IRQ_HANDLED)
682  */
683 static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di)
684 {
685         struct ab8500_btemp *di = _di;
686         dev_err(di->dev, "Battery removal detected!\n");
687 
688         di->events.batt_rem = true;
689         power_supply_changed(di->btemp_psy);
690 
691         return IRQ_HANDLED;
692 }
693 
694 /**
695  * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees
696  * @irq:       interrupt number
697  * @_di:       void pointer that has to address of ab8500_btemp
698  *
699  * Returns IRQ status(IRQ_HANDLED)
700  */
701 static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di)
702 {
703         struct ab8500_btemp *di = _di;
704 
705         if (is_ab8500_3p3_or_earlier(di->parent)) {
706                 dev_dbg(di->dev, "Ignore false btemp low irq"
707                         " for ABB cut 1.0, 1.1, 2.0 and 3.3\n");
708         } else {
709                 dev_crit(di->dev, "Battery temperature lower than -10deg c\n");
710 
711                 di->events.btemp_low = true;
712                 di->events.btemp_high = false;
713                 di->events.btemp_medhigh = false;
714                 di->events.btemp_lowmed = false;
715                 power_supply_changed(di->btemp_psy);
716         }
717 
718         return IRQ_HANDLED;
719 }
720 
721 /**
722  * ab8500_btemp_temphigh_handler() - battery temp higher than max temp
723  * @irq:       interrupt number
724  * @_di:       void pointer that has to address of ab8500_btemp
725  *
726  * Returns IRQ status(IRQ_HANDLED)
727  */
728 static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di)
729 {
730         struct ab8500_btemp *di = _di;
731 
732         dev_crit(di->dev, "Battery temperature is higher than MAX temp\n");
733 
734         di->events.btemp_high = true;
735         di->events.btemp_medhigh = false;
736         di->events.btemp_lowmed = false;
737         di->events.btemp_low = false;
738         power_supply_changed(di->btemp_psy);
739 
740         return IRQ_HANDLED;
741 }
742 
743 /**
744  * ab8500_btemp_lowmed_handler() - battery temp between low and medium
745  * @irq:       interrupt number
746  * @_di:       void pointer that has to address of ab8500_btemp
747  *
748  * Returns IRQ status(IRQ_HANDLED)
749  */
750 static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di)
751 {
752         struct ab8500_btemp *di = _di;
753 
754         dev_dbg(di->dev, "Battery temperature is between low and medium\n");
755 
756         di->events.btemp_lowmed = true;
757         di->events.btemp_medhigh = false;
758         di->events.btemp_high = false;
759         di->events.btemp_low = false;
760         power_supply_changed(di->btemp_psy);
761 
762         return IRQ_HANDLED;
763 }
764 
765 /**
766  * ab8500_btemp_medhigh_handler() - battery temp between medium and high
767  * @irq:       interrupt number
768  * @_di:       void pointer that has to address of ab8500_btemp
769  *
770  * Returns IRQ status(IRQ_HANDLED)
771  */
772 static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di)
773 {
774         struct ab8500_btemp *di = _di;
775 
776         dev_dbg(di->dev, "Battery temperature is between medium and high\n");
777 
778         di->events.btemp_medhigh = true;
779         di->events.btemp_lowmed = false;
780         di->events.btemp_high = false;
781         di->events.btemp_low = false;
782         power_supply_changed(di->btemp_psy);
783 
784         return IRQ_HANDLED;
785 }
786 
787 /**
788  * ab8500_btemp_periodic() - Periodic temperature measurements
789  * @di:         pointer to the ab8500_btemp structure
790  * @enable:     enable or disable periodic temperature measurements
791  *
792  * Starts of stops periodic temperature measurements. Periodic measurements
793  * should only be done when a charger is connected.
794  */
795 static void ab8500_btemp_periodic(struct ab8500_btemp *di,
796         bool enable)
797 {
798         dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n",
799                 enable);
800         /*
801          * Make sure a new measurement is done directly by cancelling
802          * any pending work
803          */
804         cancel_delayed_work_sync(&di->btemp_periodic_work);
805 
806         if (enable)
807                 queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0);
808 }
809 
810 /**
811  * ab8500_btemp_get_temp() - get battery temperature
812  * @di:         pointer to the ab8500_btemp structure
813  *
814  * Returns battery temperature
815  */
816 int ab8500_btemp_get_temp(struct ab8500_btemp *di)
817 {
818         int temp = 0;
819 
820         /*
821          * The BTEMP events are not reliabe on AB8500 cut3.3
822          * and prior versions
823          */
824         if (is_ab8500_3p3_or_earlier(di->parent)) {
825                 temp = di->bat_temp * 10;
826         } else {
827                 if (di->events.btemp_low) {
828                         if (temp > di->btemp_ranges.btemp_low_limit)
829                                 temp = di->btemp_ranges.btemp_low_limit * 10;
830                         else
831                                 temp = di->bat_temp * 10;
832                 } else if (di->events.btemp_high) {
833                         if (temp < di->btemp_ranges.btemp_high_limit)
834                                 temp = di->btemp_ranges.btemp_high_limit * 10;
835                         else
836                                 temp = di->bat_temp * 10;
837                 } else if (di->events.btemp_lowmed) {
838                         if (temp > di->btemp_ranges.btemp_med_limit)
839                                 temp = di->btemp_ranges.btemp_med_limit * 10;
840                         else
841                                 temp = di->bat_temp * 10;
842                 } else if (di->events.btemp_medhigh) {
843                         if (temp < di->btemp_ranges.btemp_med_limit)
844                                 temp = di->btemp_ranges.btemp_med_limit * 10;
845                         else
846                                 temp = di->bat_temp * 10;
847                 } else
848                         temp = di->bat_temp * 10;
849         }
850         return temp;
851 }
852 EXPORT_SYMBOL(ab8500_btemp_get_temp);
853 
854 /**
855  * ab8500_btemp_get_batctrl_temp() - get the temperature
856  * @btemp:      pointer to the btemp structure
857  *
858  * Returns the batctrl temperature in millidegrees
859  */
860 int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
861 {
862         return btemp->bat_temp * 1000;
863 }
864 EXPORT_SYMBOL(ab8500_btemp_get_batctrl_temp);
865 
866 /**
867  * ab8500_btemp_get_property() - get the btemp properties
868  * @psy:        pointer to the power_supply structure
869  * @psp:        pointer to the power_supply_property structure
870  * @val:        pointer to the power_supply_propval union
871  *
872  * This function gets called when an application tries to get the btemp
873  * properties by reading the sysfs files.
874  * online:      presence of the battery
875  * present:     presence of the battery
876  * technology:  battery technology
877  * temp:        battery temperature
878  * Returns error code in case of failure else 0(on success)
879  */
880 static int ab8500_btemp_get_property(struct power_supply *psy,
881         enum power_supply_property psp,
882         union power_supply_propval *val)
883 {
884         struct ab8500_btemp *di = power_supply_get_drvdata(psy);
885 
886         switch (psp) {
887         case POWER_SUPPLY_PROP_PRESENT:
888         case POWER_SUPPLY_PROP_ONLINE:
889                 if (di->events.batt_rem)
890                         val->intval = 0;
891                 else
892                         val->intval = 1;
893                 break;
894         case POWER_SUPPLY_PROP_TECHNOLOGY:
895                 val->intval = di->bm->bat_type[di->bm->batt_id].name;
896                 break;
897         case POWER_SUPPLY_PROP_TEMP:
898                 val->intval = ab8500_btemp_get_temp(di);
899                 break;
900         default:
901                 return -EINVAL;
902         }
903         return 0;
904 }
905 
906 static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data)
907 {
908         struct power_supply *psy;
909         struct power_supply *ext;
910         struct ab8500_btemp *di;
911         union power_supply_propval ret;
912         int i, j;
913         bool psy_found = false;
914 
915         psy = (struct power_supply *)data;
916         ext = dev_get_drvdata(dev);
917         di = power_supply_get_drvdata(psy);
918 
919         /*
920          * For all psy where the name of your driver
921          * appears in any supplied_to
922          */
923         for (i = 0; i < ext->num_supplicants; i++) {
924                 if (!strcmp(ext->supplied_to[i], psy->desc->name))
925                         psy_found = true;
926         }
927 
928         if (!psy_found)
929                 return 0;
930 
931         /* Go through all properties for the psy */
932         for (j = 0; j < ext->desc->num_properties; j++) {
933                 enum power_supply_property prop;
934                 prop = ext->desc->properties[j];
935 
936                 if (power_supply_get_property(ext, prop, &ret))
937                         continue;
938 
939                 switch (prop) {
940                 case POWER_SUPPLY_PROP_PRESENT:
941                         switch (ext->desc->type) {
942                         case POWER_SUPPLY_TYPE_MAINS:
943                                 /* AC disconnected */
944                                 if (!ret.intval && di->events.ac_conn) {
945                                         di->events.ac_conn = false;
946                                 }
947                                 /* AC connected */
948                                 else if (ret.intval && !di->events.ac_conn) {
949                                         di->events.ac_conn = true;
950                                         if (!di->events.usb_conn)
951                                                 ab8500_btemp_periodic(di, true);
952                                 }
953                                 break;
954                         case POWER_SUPPLY_TYPE_USB:
955                                 /* USB disconnected */
956                                 if (!ret.intval && di->events.usb_conn) {
957                                         di->events.usb_conn = false;
958                                 }
959                                 /* USB connected */
960                                 else if (ret.intval && !di->events.usb_conn) {
961                                         di->events.usb_conn = true;
962                                         if (!di->events.ac_conn)
963                                                 ab8500_btemp_periodic(di, true);
964                                 }
965                                 break;
966                         default:
967                                 break;
968                         }
969                         break;
970                 default:
971                         break;
972                 }
973         }
974         return 0;
975 }
976 
977 /**
978  * ab8500_btemp_external_power_changed() - callback for power supply changes
979  * @psy:       pointer to the structure power_supply
980  *
981  * This function is pointing to the function pointer external_power_changed
982  * of the structure power_supply.
983  * This function gets executed when there is a change in the external power
984  * supply to the btemp.
985  */
986 static void ab8500_btemp_external_power_changed(struct power_supply *psy)
987 {
988         struct ab8500_btemp *di = power_supply_get_drvdata(psy);
989 
990         class_for_each_device(power_supply_class, NULL,
991                 di->btemp_psy, ab8500_btemp_get_ext_psy_data);
992 }
993 
994 /* ab8500 btemp driver interrupts and their respective isr */
995 static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = {
996         {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler},
997         {"BTEMP_LOW", ab8500_btemp_templow_handler},
998         {"BTEMP_HIGH", ab8500_btemp_temphigh_handler},
999         {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler},
1000         {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler},
1001 };
1002 
1003 #if defined(CONFIG_PM)
1004 static int ab8500_btemp_resume(struct platform_device *pdev)
1005 {
1006         struct ab8500_btemp *di = platform_get_drvdata(pdev);
1007 
1008         ab8500_btemp_periodic(di, true);
1009 
1010         return 0;
1011 }
1012 
1013 static int ab8500_btemp_suspend(struct platform_device *pdev,
1014         pm_message_t state)
1015 {
1016         struct ab8500_btemp *di = platform_get_drvdata(pdev);
1017 
1018         ab8500_btemp_periodic(di, false);
1019 
1020         return 0;
1021 }
1022 #else
1023 #define ab8500_btemp_suspend      NULL
1024 #define ab8500_btemp_resume       NULL
1025 #endif
1026 
1027 static int ab8500_btemp_remove(struct platform_device *pdev)
1028 {
1029         struct ab8500_btemp *di = platform_get_drvdata(pdev);
1030         int i, irq;
1031 
1032         /* Disable interrupts */
1033         for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1034                 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1035                 free_irq(irq, di);
1036         }
1037 
1038         /* Delete the work queue */
1039         destroy_workqueue(di->btemp_wq);
1040 
1041         flush_scheduled_work();
1042         power_supply_unregister(di->btemp_psy);
1043 
1044         return 0;
1045 }
1046 
1047 static char *supply_interface[] = {
1048         "ab8500_chargalg",
1049         "ab8500_fg",
1050 };
1051 
1052 static const struct power_supply_desc ab8500_btemp_desc = {
1053         .name                   = "ab8500_btemp",
1054         .type                   = POWER_SUPPLY_TYPE_BATTERY,
1055         .properties             = ab8500_btemp_props,
1056         .num_properties         = ARRAY_SIZE(ab8500_btemp_props),
1057         .get_property           = ab8500_btemp_get_property,
1058         .external_power_changed = ab8500_btemp_external_power_changed,
1059 };
1060 
1061 static int ab8500_btemp_probe(struct platform_device *pdev)
1062 {
1063         struct device_node *np = pdev->dev.of_node;
1064         struct abx500_bm_data *plat = pdev->dev.platform_data;
1065         struct power_supply_config psy_cfg = {};
1066         struct ab8500_btemp *di;
1067         int irq, i, ret = 0;
1068         u8 val;
1069 
1070         di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
1071         if (!di) {
1072                 dev_err(&pdev->dev, "%s no mem for ab8500_btemp\n", __func__);
1073                 return -ENOMEM;
1074         }
1075 
1076         if (!plat) {
1077                 dev_err(&pdev->dev, "no battery management data supplied\n");
1078                 return -EINVAL;
1079         }
1080         di->bm = plat;
1081 
1082         if (np) {
1083                 ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
1084                 if (ret) {
1085                         dev_err(&pdev->dev, "failed to get battery information\n");
1086                         return ret;
1087                 }
1088         }
1089 
1090         /* get parent data */
1091         di->dev = &pdev->dev;
1092         di->parent = dev_get_drvdata(pdev->dev.parent);
1093         di->gpadc = ab8500_gpadc_get("ab8500-gpadc.0");
1094 
1095         di->initialized = false;
1096 
1097         psy_cfg.supplied_to = supply_interface;
1098         psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
1099         psy_cfg.drv_data = di;
1100 
1101         /* Create a work queue for the btemp */
1102         di->btemp_wq =
1103                 create_singlethread_workqueue("ab8500_btemp_wq");
1104         if (di->btemp_wq == NULL) {
1105                 dev_err(di->dev, "failed to create work queue\n");
1106                 return -ENOMEM;
1107         }
1108 
1109         /* Init work for measuring temperature periodically */
1110         INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
1111                 ab8500_btemp_periodic_work);
1112 
1113         /* Set BTEMP thermal limits. Low and Med are fixed */
1114         di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT;
1115         di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT;
1116 
1117         ret = abx500_get_register_interruptible(di->dev, AB8500_CHARGER,
1118                 AB8500_BTEMP_HIGH_TH, &val);
1119         if (ret < 0) {
1120                 dev_err(di->dev, "%s ab8500 read failed\n", __func__);
1121                 goto free_btemp_wq;
1122         }
1123         switch (val) {
1124         case BTEMP_HIGH_TH_57_0:
1125         case BTEMP_HIGH_TH_57_1:
1126                 di->btemp_ranges.btemp_high_limit =
1127                         BTEMP_THERMAL_HIGH_LIMIT_57;
1128                 break;
1129         case BTEMP_HIGH_TH_52:
1130                 di->btemp_ranges.btemp_high_limit =
1131                         BTEMP_THERMAL_HIGH_LIMIT_52;
1132                 break;
1133         case BTEMP_HIGH_TH_62:
1134                 di->btemp_ranges.btemp_high_limit =
1135                         BTEMP_THERMAL_HIGH_LIMIT_62;
1136                 break;
1137         }
1138 
1139         /* Register BTEMP power supply class */
1140         di->btemp_psy = power_supply_register(di->dev, &ab8500_btemp_desc,
1141                                               &psy_cfg);
1142         if (IS_ERR(di->btemp_psy)) {
1143                 dev_err(di->dev, "failed to register BTEMP psy\n");
1144                 ret = PTR_ERR(di->btemp_psy);
1145                 goto free_btemp_wq;
1146         }
1147 
1148         /* Register interrupts */
1149         for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
1150                 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1151                 ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
1152                         IRQF_SHARED | IRQF_NO_SUSPEND,
1153                         ab8500_btemp_irq[i].name, di);
1154 
1155                 if (ret) {
1156                         dev_err(di->dev, "failed to request %s IRQ %d: %d\n"
1157                                 , ab8500_btemp_irq[i].name, irq, ret);
1158                         goto free_irq;
1159                 }
1160                 dev_dbg(di->dev, "Requested %s IRQ %d: %d\n",
1161                         ab8500_btemp_irq[i].name, irq, ret);
1162         }
1163 
1164         platform_set_drvdata(pdev, di);
1165 
1166         /* Kick off periodic temperature measurements */
1167         ab8500_btemp_periodic(di, true);
1168         list_add_tail(&di->node, &ab8500_btemp_list);
1169 
1170         return ret;
1171 
1172 free_irq:
1173         power_supply_unregister(di->btemp_psy);
1174 
1175         /* We also have to free all successfully registered irqs */
1176         for (i = i - 1; i >= 0; i--) {
1177                 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
1178                 free_irq(irq, di);
1179         }
1180 free_btemp_wq:
1181         destroy_workqueue(di->btemp_wq);
1182         return ret;
1183 }
1184 
1185 static const struct of_device_id ab8500_btemp_match[] = {
1186         { .compatible = "stericsson,ab8500-btemp", },
1187         { },
1188 };
1189 
1190 static struct platform_driver ab8500_btemp_driver = {
1191         .probe = ab8500_btemp_probe,
1192         .remove = ab8500_btemp_remove,
1193         .suspend = ab8500_btemp_suspend,
1194         .resume = ab8500_btemp_resume,
1195         .driver = {
1196                 .name = "ab8500-btemp",
1197                 .of_match_table = ab8500_btemp_match,
1198         },
1199 };
1200 
1201 static int __init ab8500_btemp_init(void)
1202 {
1203         return platform_driver_register(&ab8500_btemp_driver);
1204 }
1205 
1206 static void __exit ab8500_btemp_exit(void)
1207 {
1208         platform_driver_unregister(&ab8500_btemp_driver);
1209 }
1210 
1211 device_initcall(ab8500_btemp_init);
1212 module_exit(ab8500_btemp_exit);
1213 
1214 MODULE_LICENSE("GPL v2");
1215 MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
1216 MODULE_ALIAS("platform:ab8500-btemp");
1217 MODULE_DESCRIPTION("AB8500 battery temperature driver");
1218 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us