Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
da9052-battery.c
Go to the documentation of this file.
1 /*
2  * Batttery Driver for Dialog DA9052 PMICs
3  *
4  * Copyright(c) 2011 Dialog Semiconductor Ltd.
5  *
6  * Author: David Dajun Chen <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation; either version 2 of the License, or (at your
11  * option) any later version.
12  */
13 
14 #include <linux/delay.h>
15 #include <linux/freezer.h>
16 #include <linux/fs.h>
17 #include <linux/jiffies.h>
18 #include <linux/module.h>
19 #include <linux/timer.h>
20 #include <linux/uaccess.h>
21 #include <linux/platform_device.h>
22 #include <linux/power_supply.h>
23 
25 #include <linux/mfd/da9052/pdata.h>
26 #include <linux/mfd/da9052/reg.h>
27 
28 /* STATIC CONFIGURATION */
29 #define DA9052_BAT_CUTOFF_VOLT 2800
30 #define DA9052_BAT_TSH 62000
31 #define DA9052_BAT_LOW_CAP 4
32 #define DA9052_AVG_SZ 4
33 #define DA9052_VC_TBL_SZ 68
34 #define DA9052_VC_TBL_REF_SZ 3
35 
36 #define DA9052_ISET_USB_MASK 0x0F
37 #define DA9052_CHG_USB_ILIM_MASK 0x40
38 #define DA9052_CHG_LIM_COLS 16
39 
40 #define DA9052_MEAN(x, y) ((x + y) / 2)
41 
45 };
46 
47 static const u16 da9052_chg_current_lim[2][DA9052_CHG_LIM_COLS] = {
48  {70, 80, 90, 100, 110, 120, 400, 450,
49  500, 550, 600, 650, 700, 900, 1100, 1300},
50  {80, 90, 100, 110, 120, 400, 450, 500,
51  550, 600, 800, 1000, 1200, 1400, 1600, 1800},
52 };
53 
54 static const u16 vc_tbl_ref[3] = {10, 25, 40};
55 /* Lookup table for voltage vs capacity */
56 static u32 const vc_tbl[3][68][2] = {
57  /* For temperature 10 degree Celsius */
58  {
59  {4082, 100}, {4036, 98},
60  {4020, 96}, {4008, 95},
61  {3997, 93}, {3983, 91},
62  {3964, 90}, {3943, 88},
63  {3926, 87}, {3912, 85},
64  {3900, 84}, {3890, 82},
65  {3881, 80}, {3873, 79},
66  {3865, 77}, {3857, 76},
67  {3848, 74}, {3839, 73},
68  {3829, 71}, {3820, 70},
69  {3811, 68}, {3802, 67},
70  {3794, 65}, {3785, 64},
71  {3778, 62}, {3770, 61},
72  {3763, 59}, {3756, 58},
73  {3750, 56}, {3744, 55},
74  {3738, 53}, {3732, 52},
75  {3727, 50}, {3722, 49},
76  {3717, 47}, {3712, 46},
77  {3708, 44}, {3703, 43},
78  {3700, 41}, {3696, 40},
79  {3693, 38}, {3691, 37},
80  {3688, 35}, {3686, 34},
81  {3683, 32}, {3681, 31},
82  {3678, 29}, {3675, 28},
83  {3672, 26}, {3669, 25},
84  {3665, 23}, {3661, 22},
85  {3656, 21}, {3651, 19},
86  {3645, 18}, {3639, 16},
87  {3631, 15}, {3622, 13},
88  {3611, 12}, {3600, 10},
89  {3587, 9}, {3572, 7},
90  {3548, 6}, {3503, 5},
91  {3420, 3}, {3268, 2},
92  {2992, 1}, {2746, 0}
93  },
94  /* For temperature 25 degree Celsius */
95  {
96  {4102, 100}, {4065, 98},
97  {4048, 96}, {4034, 95},
98  {4021, 93}, {4011, 92},
99  {4001, 90}, {3986, 88},
100  {3968, 87}, {3952, 85},
101  {3938, 84}, {3926, 82},
102  {3916, 81}, {3908, 79},
103  {3900, 77}, {3892, 76},
104  {3883, 74}, {3874, 73},
105  {3864, 71}, {3855, 70},
106  {3846, 68}, {3836, 67},
107  {3827, 65}, {3819, 64},
108  {3810, 62}, {3801, 61},
109  {3793, 59}, {3786, 58},
110  {3778, 56}, {3772, 55},
111  {3765, 53}, {3759, 52},
112  {3754, 50}, {3748, 49},
113  {3743, 47}, {3738, 46},
114  {3733, 44}, {3728, 43},
115  {3724, 41}, {3720, 40},
116  {3716, 38}, {3712, 37},
117  {3709, 35}, {3706, 34},
118  {3703, 33}, {3701, 31},
119  {3698, 30}, {3696, 28},
120  {3693, 27}, {3690, 25},
121  {3687, 24}, {3683, 22},
122  {3680, 21}, {3675, 19},
123  {3671, 18}, {3666, 17},
124  {3660, 15}, {3654, 14},
125  {3647, 12}, {3639, 11},
126  {3630, 9}, {3621, 8},
127  {3613, 6}, {3606, 5},
128  {3597, 4}, {3582, 2},
129  {3546, 1}, {2747, 0}
130  },
131  /* For temperature 40 degree Celsius */
132  {
133  {4114, 100}, {4081, 98},
134  {4065, 96}, {4050, 95},
135  {4036, 93}, {4024, 92},
136  {4013, 90}, {4002, 88},
137  {3990, 87}, {3976, 85},
138  {3962, 84}, {3950, 82},
139  {3939, 81}, {3930, 79},
140  {3921, 77}, {3912, 76},
141  {3902, 74}, {3893, 73},
142  {3883, 71}, {3874, 70},
143  {3865, 68}, {3856, 67},
144  {3847, 65}, {3838, 64},
145  {3829, 62}, {3820, 61},
146  {3812, 59}, {3803, 58},
147  {3795, 56}, {3787, 55},
148  {3780, 53}, {3773, 52},
149  {3767, 50}, {3761, 49},
150  {3756, 47}, {3751, 46},
151  {3746, 44}, {3741, 43},
152  {3736, 41}, {3732, 40},
153  {3728, 38}, {3724, 37},
154  {3720, 35}, {3716, 34},
155  {3713, 33}, {3710, 31},
156  {3707, 30}, {3704, 28},
157  {3701, 27}, {3698, 25},
158  {3695, 24}, {3691, 22},
159  {3686, 21}, {3681, 19},
160  {3676, 18}, {3671, 17},
161  {3666, 15}, {3661, 14},
162  {3655, 12}, {3648, 11},
163  {3640, 9}, {3632, 8},
164  {3622, 6}, {3616, 5},
165  {3611, 4}, {3604, 2},
166  {3594, 1}, {2747, 0}
167  }
168 };
169 
171  struct da9052 *da9052;
175  int status;
176  int health;
177 };
178 
179 static inline int volt_reg_to_mV(int value)
180 {
181  return ((value * 1000) / 512) + 2500;
182 }
183 
184 static inline int ichg_reg_to_mA(int value)
185 {
186  return (value * 3900) / 1000;
187 }
188 
189 static int da9052_read_chgend_current(struct da9052_battery *bat,
190  int *current_mA)
191 {
192  int ret;
193 
195  return -EINVAL;
196 
197  ret = da9052_reg_read(bat->da9052, DA9052_ICHG_END_REG);
198  if (ret < 0)
199  return ret;
200 
201  *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGEND_ICHGEND);
202 
203  return 0;
204 }
205 
206 static int da9052_read_chg_current(struct da9052_battery *bat, int *current_mA)
207 {
208  int ret;
209 
211  return -EINVAL;
212 
213  ret = da9052_reg_read(bat->da9052, DA9052_ICHG_AV_REG);
214  if (ret < 0)
215  return ret;
216 
217  *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGAV_ICHGAV);
218 
219  return 0;
220 }
221 
222 static int da9052_bat_check_status(struct da9052_battery *bat, int *status)
223 {
224  u8 v[2] = {0, 0};
225  u8 bat_status;
226  u8 chg_end;
227  int ret;
228  int chg_current;
229  int chg_end_current;
230  bool dcinsel;
231  bool dcindet;
232  bool vbussel;
233  bool vbusdet;
234  bool dc;
235  bool vbus;
236 
237  ret = da9052_group_read(bat->da9052, DA9052_STATUS_A_REG, 2, v);
238  if (ret < 0)
239  return ret;
240 
241  bat_status = v[0];
242  chg_end = v[1];
243 
244  dcinsel = bat_status & DA9052_STATUSA_DCINSEL;
245  dcindet = bat_status & DA9052_STATUSA_DCINDET;
246  vbussel = bat_status & DA9052_STATUSA_VBUSSEL;
247  vbusdet = bat_status & DA9052_STATUSA_VBUSDET;
248  dc = dcinsel && dcindet;
249  vbus = vbussel && vbusdet;
250 
251  /* Preference to WALL(DCIN) charger unit */
252  if (dc || vbus) {
254 
255  /* If charging end flag is set and Charging current is greater
256  * than charging end limit then battery is charging
257  */
258  if ((chg_end & DA9052_STATUSB_CHGEND) != 0) {
259  ret = da9052_read_chg_current(bat, &chg_current);
260  if (ret < 0)
261  return ret;
262  ret = da9052_read_chgend_current(bat, &chg_end_current);
263  if (ret < 0)
264  return ret;
265 
266  if (chg_current >= chg_end_current)
268  else
270  } else {
271  /* If Charging end flag is cleared then battery is
272  * charging
273  */
275  }
276  } else if (dcindet || vbusdet) {
279  } else {
282  }
283 
284  if (status != NULL)
285  *status = bat->status;
286  return 0;
287 }
288 
289 static int da9052_bat_read_volt(struct da9052_battery *bat, int *volt_mV)
290 {
291  int volt;
292 
294  if (volt < 0)
295  return volt;
296 
297  *volt_mV = volt_reg_to_mV(volt);
298 
299  return 0;
300 }
301 
302 static int da9052_bat_check_presence(struct da9052_battery *bat, int *illegal)
303 {
304  int bat_temp;
305 
306  bat_temp = da9052_adc_read_temp(bat->da9052);
307  if (bat_temp < 0)
308  return bat_temp;
309 
310  if (bat_temp > DA9052_BAT_TSH)
311  *illegal = 1;
312  else
313  *illegal = 0;
314 
315  return 0;
316 }
317 
318 static int da9052_bat_interpolate(int vbat_lower, int vbat_upper,
319  int level_lower, int level_upper,
320  int bat_voltage)
321 {
322  int tmp;
323 
324  tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower);
325  tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000);
326 
327  return tmp;
328 }
329 
330 static unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
331 {
332  int i;
333 
334  if (adc_temp <= vc_tbl_ref[0])
335  return 0;
336 
337  if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1])
338  return DA9052_VC_TBL_REF_SZ - 1;
339 
340  for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) {
341  if ((adc_temp > vc_tbl_ref[i]) &&
342  (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
343  return i;
344  if ((adc_temp > DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))
345  && (adc_temp <= vc_tbl_ref[i]))
346  return i + 1;
347  }
348  /*
349  * For some reason authors of the driver didn't presume that we can
350  * end up here. It might be OK, but might be not, no one knows for
351  * sure. Go check your battery, is it on fire?
352  */
353  WARN_ON(1);
354  return 0;
355 }
356 
357 static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity)
358 {
359  int adc_temp;
360  int bat_voltage;
361  int vbat_lower;
362  int vbat_upper;
363  int level_upper;
364  int level_lower;
365  int ret;
366  int flag;
367  int i = 0;
368  int j;
369 
370  ret = da9052_bat_read_volt(bat, &bat_voltage);
371  if (ret < 0)
372  return ret;
373 
374  adc_temp = da9052_adc_read_temp(bat->da9052);
375  if (adc_temp < 0)
376  return adc_temp;
377 
378  i = da9052_determine_vc_tbl_index(adc_temp);
379 
380  if (bat_voltage >= vc_tbl[i][0][0]) {
381  *capacity = 100;
382  return 0;
383  }
384  if (bat_voltage <= vc_tbl[i][DA9052_VC_TBL_SZ - 1][0]) {
385  *capacity = 0;
386  return 0;
387  }
388  flag = 0;
389 
390  for (j = 0; j < (DA9052_VC_TBL_SZ-1); j++) {
391  if ((bat_voltage <= vc_tbl[i][j][0]) &&
392  (bat_voltage >= vc_tbl[i][j + 1][0])) {
393  vbat_upper = vc_tbl[i][j][0];
394  vbat_lower = vc_tbl[i][j + 1][0];
395  level_upper = vc_tbl[i][j][1];
396  level_lower = vc_tbl[i][j + 1][1];
397  flag = 1;
398  break;
399  }
400  }
401  if (!flag)
402  return -EIO;
403 
404  *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower,
405  level_upper, bat_voltage);
406 
407  return 0;
408 }
409 
410 static int da9052_bat_check_health(struct da9052_battery *bat, int *health)
411 {
412  int ret;
413  int bat_illegal;
414  int capacity;
415 
416  ret = da9052_bat_check_presence(bat, &bat_illegal);
417  if (ret < 0)
418  return ret;
419 
420  if (bat_illegal) {
422  return 0;
423  }
424 
425  if (bat->health != POWER_SUPPLY_HEALTH_OVERHEAT) {
426  ret = da9052_bat_read_capacity(bat, &capacity);
427  if (ret < 0)
428  return ret;
429  if (capacity < DA9052_BAT_LOW_CAP)
431  else
433  }
434 
435  *health = bat->health;
436 
437  return 0;
438 }
439 
440 static irqreturn_t da9052_bat_irq(int irq, void *data)
441 {
442  struct da9052_battery *bat = data;
443 
444  irq -= bat->da9052->irq_base;
445 
446  if (irq == DA9052_IRQ_CHGEND)
448  else
449  da9052_bat_check_status(bat, NULL);
450 
451  if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN ||
452  irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) {
453  power_supply_changed(&bat->psy);
454  }
455 
456  return IRQ_HANDLED;
457 }
458 
459 static int da9052_USB_current_notifier(struct notifier_block *nb,
460  unsigned long events, void *data)
461 {
462  u8 row;
463  u8 col;
464  int *current_mA = data;
465  int ret;
466  struct da9052_battery *bat = container_of(nb, struct da9052_battery,
467  nb);
468 
470  return -EPERM;
471 
472  ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG);
473  if (ret & DA9052_CHG_USB_ILIM_MASK)
474  return -EPERM;
475 
476  if (bat->da9052->chip_id == DA9052)
477  row = 0;
478  else
479  row = 1;
480 
481  if (*current_mA < da9052_chg_current_lim[row][0] ||
482  *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1])
483  return -EINVAL;
484 
485  for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) {
486  if (*current_mA <= da9052_chg_current_lim[row][col])
487  break;
488  }
489 
490  return da9052_reg_update(bat->da9052, DA9052_ISET_REG,
491  DA9052_ISET_USB_MASK, col);
492 }
493 
494 static int da9052_bat_get_property(struct power_supply *psy,
495  enum power_supply_property psp,
496  union power_supply_propval *val)
497 {
498  int ret;
499  int illegal;
500  struct da9052_battery *bat = container_of(psy, struct da9052_battery,
501  psy);
502 
503  ret = da9052_bat_check_presence(bat, &illegal);
504  if (ret < 0)
505  return ret;
506 
507  if (illegal && psp != POWER_SUPPLY_PROP_PRESENT)
508  return -ENODEV;
509 
510  switch (psp) {
512  ret = da9052_bat_check_status(bat, &val->intval);
513  break;
515  val->intval =
516  (bat->charger_type == DA9052_NOCHARGER) ? 0 : 1;
517  break;
519  ret = da9052_bat_check_presence(bat, &val->intval);
520  break;
522  ret = da9052_bat_check_health(bat, &val->intval);
523  break;
525  val->intval = DA9052_BAT_CUTOFF_VOLT * 1000;
526  break;
528  ret = da9052_bat_read_volt(bat, &val->intval);
529  break;
531  ret = da9052_read_chg_current(bat, &val->intval);
532  break;
534  ret = da9052_bat_read_capacity(bat, &val->intval);
535  break;
537  val->intval = da9052_adc_read_temp(bat->da9052);
538  ret = val->intval;
539  break;
542  break;
543  default:
544  return -EINVAL;
545  }
546  return ret;
547 }
548 
549 static enum power_supply_property da9052_bat_props[] = {
560 };
561 
562 static struct power_supply template_battery = {
563  .name = "da9052-bat",
565  .properties = da9052_bat_props,
566  .num_properties = ARRAY_SIZE(da9052_bat_props),
567  .get_property = da9052_bat_get_property,
568 };
569 
570 static const char *const da9052_bat_irqs[] = {
571  "BATT TEMP",
572  "DCIN DET",
573  "DCIN REM",
574  "VBUS DET",
575  "VBUS REM",
576  "CHG END",
577 };
578 
579 static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
580 {
581  struct da9052_pdata *pdata;
582  struct da9052_battery *bat;
583  int ret;
584  int irq;
585  int i;
586 
587  bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
588  if (!bat)
589  return -ENOMEM;
590 
591  bat->da9052 = dev_get_drvdata(pdev->dev.parent);
592  bat->psy = template_battery;
596  bat->nb.notifier_call = da9052_USB_current_notifier;
597 
598  pdata = bat->da9052->dev->platform_data;
599  if (pdata != NULL && pdata->use_for_apm)
600  bat->psy.use_for_apm = pdata->use_for_apm;
601  else
602  bat->psy.use_for_apm = 1;
603 
604  for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
605  irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
606  ret = request_threaded_irq(bat->da9052->irq_base + irq,
607  NULL, da9052_bat_irq,
609  da9052_bat_irqs[i], bat);
610  if (ret != 0) {
611  dev_err(bat->da9052->dev,
612  "DA9052 failed to request %s IRQ %d: %d\n",
613  da9052_bat_irqs[i], irq, ret);
614  goto err;
615  }
616  }
617 
618  ret = power_supply_register(&pdev->dev, &bat->psy);
619  if (ret)
620  goto err;
621 
622  platform_set_drvdata(pdev, bat);
623  return 0;
624 
625 err:
626  while (--i >= 0) {
627  irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
628  free_irq(bat->da9052->irq_base + irq, bat);
629  }
630  kfree(bat);
631  return ret;
632 }
633 static int __devexit da9052_bat_remove(struct platform_device *pdev)
634 {
635  int i;
636  int irq;
637  struct da9052_battery *bat = platform_get_drvdata(pdev);
638 
639  for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
640  irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
641  free_irq(bat->da9052->irq_base + irq, bat);
642  }
644  kfree(bat);
645 
646  return 0;
647 }
648 
649 static struct platform_driver da9052_bat_driver = {
650  .probe = da9052_bat_probe,
651  .remove = __devexit_p(da9052_bat_remove),
652  .driver = {
653  .name = "da9052-bat",
654  .owner = THIS_MODULE,
655  },
656 };
657 module_platform_driver(da9052_bat_driver);
658 
659 MODULE_DESCRIPTION("DA9052 BAT Device Driver");
660 MODULE_AUTHOR("David Dajun Chen <[email protected]>");
661 MODULE_LICENSE("GPL");
662 MODULE_ALIAS("platform:da9052-bat");