Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
max8925_power.c
Go to the documentation of this file.
1 /*
2  * Battery driver for Maxim MAX8925
3  *
4  * Copyright (c) 2009-2010 Marvell International Ltd.
5  * Haojian Zhuang <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 
12 #include <linux/module.h>
13 #include <linux/err.h>
14 #include <linux/slab.h>
15 #include <linux/i2c.h>
16 #include <linux/interrupt.h>
17 #include <linux/platform_device.h>
18 #include <linux/power_supply.h>
19 #include <linux/mfd/max8925.h>
20 
21 /* registers in GPM */
22 #define MAX8925_OUT5VEN 0x54
23 #define MAX8925_OUT3VEN 0x58
24 #define MAX8925_CHG_CNTL1 0x7c
25 
26 /* bits definition */
27 #define MAX8925_CHG_STAT_VSYSLOW (1 << 0)
28 #define MAX8925_CHG_STAT_MODE_MASK (3 << 2)
29 #define MAX8925_CHG_STAT_EN_MASK (1 << 4)
30 #define MAX8925_CHG_MBDET (1 << 1)
31 #define MAX8925_CHG_AC_RANGE_MASK (3 << 6)
32 
33 /* registers in ADC */
34 #define MAX8925_ADC_RES_CNFG1 0x06
35 #define MAX8925_ADC_AVG_CNFG1 0x07
36 #define MAX8925_ADC_ACQ_CNFG1 0x08
37 #define MAX8925_ADC_ACQ_CNFG2 0x09
38 /* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
39 #define MAX8925_ADC_AUX2 0x62
40 #define MAX8925_ADC_VCHG 0x64
41 #define MAX8925_ADC_VBBATT 0x66
42 #define MAX8925_ADC_VMBATT 0x68
43 #define MAX8925_ADC_ISNS 0x6a
44 #define MAX8925_ADC_THM 0x6c
45 #define MAX8925_ADC_TDIE 0x6e
46 #define MAX8925_CMD_AUX2 0xc8
47 #define MAX8925_CMD_VCHG 0xd0
48 #define MAX8925_CMD_VBBATT 0xd8
49 #define MAX8925_CMD_VMBATT 0xe0
50 #define MAX8925_CMD_ISNS 0xe8
51 #define MAX8925_CMD_THM 0xf0
52 #define MAX8925_CMD_TDIE 0xf8
53 
54 enum {
63 };
64 
66  struct max8925_chip *chip;
67  struct i2c_client *gpm;
68  struct i2c_client *adc;
69 
70  struct power_supply ac;
71  struct power_supply usb;
73  int irq_base;
74  unsigned ac_online:1;
75  unsigned usb_online:1;
76  unsigned bat_online:1;
77  unsigned chg_mode:2;
78  unsigned batt_detect:1; /* detecing MB by ID pin */
79  unsigned topoff_threshold:2;
80  unsigned fast_charge:3;
81  unsigned no_temp_support:1;
82  unsigned no_insert_detect:1;
83 
85 };
86 
87 static int __set_charger(struct max8925_power_info *info, int enable)
88 {
89  struct max8925_chip *chip = info->chip;
90  if (enable) {
91  /* enable charger in platform */
92  if (info->set_charger)
93  info->set_charger(1);
94  /* enable charger */
95  max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
96  } else {
97  /* disable charge */
98  max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
99  if (info->set_charger)
100  info->set_charger(0);
101  }
102  dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
103  : "Disable charger");
104  return 0;
105 }
106 
107 static irqreturn_t max8925_charger_handler(int irq, void *data)
108 {
109  struct max8925_power_info *info = (struct max8925_power_info *)data;
110  struct max8925_chip *chip = info->chip;
111 
112  switch (irq - chip->irq_base) {
114  info->ac_online = 1;
115  __set_charger(info, 1);
116  dev_dbg(chip->dev, "Adapter inserted\n");
117  break;
119  info->ac_online = 0;
120  __set_charger(info, 0);
121  dev_dbg(chip->dev, "Adapter removed\n");
122  break;
124  /* Battery is not ready yet */
125  dev_dbg(chip->dev, "Battery temperature is out of range\n");
127  dev_dbg(chip->dev, "Error detection\n");
128  __set_charger(info, 0);
129  break;
131  /* Battery is ready now */
132  dev_dbg(chip->dev, "Battery temperature is in range\n");
133  break;
135  /* VSYS is low */
136  dev_info(chip->dev, "Sys power is too low\n");
137  break;
139  dev_dbg(chip->dev, "Sys power is above low threshold\n");
140  break;
142  __set_charger(info, 0);
143  dev_dbg(chip->dev, "Charging is done\n");
144  break;
146  dev_dbg(chip->dev, "Charging in top-off mode\n");
147  break;
149  __set_charger(info, 0);
150  dev_dbg(chip->dev, "Safe timer is expired\n");
151  break;
153  __set_charger(info, 0);
154  dev_dbg(chip->dev, "Charger is reset\n");
155  break;
156  }
157  return IRQ_HANDLED;
158 }
159 
160 static int start_measure(struct max8925_power_info *info, int type)
161 {
162  unsigned char buf[2] = {0, 0};
163  int meas_cmd;
164  int meas_reg = 0, ret;
165 
166  switch (type) {
167  case MEASURE_VCHG:
168  meas_cmd = MAX8925_CMD_VCHG;
169  meas_reg = MAX8925_ADC_VCHG;
170  break;
171  case MEASURE_VBBATT:
172  meas_cmd = MAX8925_CMD_VBBATT;
173  meas_reg = MAX8925_ADC_VBBATT;
174  break;
175  case MEASURE_VMBATT:
176  meas_cmd = MAX8925_CMD_VMBATT;
177  meas_reg = MAX8925_ADC_VMBATT;
178  break;
179  case MEASURE_ISNS:
180  meas_cmd = MAX8925_CMD_ISNS;
181  meas_reg = MAX8925_ADC_ISNS;
182  break;
183  default:
184  return -EINVAL;
185  }
186 
187  max8925_reg_write(info->adc, meas_cmd, 0);
188  max8925_bulk_read(info->adc, meas_reg, 2, buf);
189  ret = ((buf[0]<<8) | buf[1]) >> 4;
190 
191  return ret;
192 }
193 
194 static int max8925_ac_get_prop(struct power_supply *psy,
195  enum power_supply_property psp,
196  union power_supply_propval *val)
197 {
198  struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
199  int ret = 0;
200 
201  switch (psp) {
203  val->intval = info->ac_online;
204  break;
206  if (info->ac_online) {
207  ret = start_measure(info, MEASURE_VCHG);
208  if (ret >= 0) {
209  val->intval = ret * 2000; /* unit is uV */
210  goto out;
211  }
212  }
213  ret = -ENODATA;
214  break;
215  default:
216  ret = -ENODEV;
217  break;
218  }
219 out:
220  return ret;
221 }
222 
223 static enum power_supply_property max8925_ac_props[] = {
226 };
227 
228 static int max8925_usb_get_prop(struct power_supply *psy,
229  enum power_supply_property psp,
230  union power_supply_propval *val)
231 {
232  struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
233  int ret = 0;
234 
235  switch (psp) {
237  val->intval = info->usb_online;
238  break;
240  if (info->usb_online) {
241  ret = start_measure(info, MEASURE_VCHG);
242  if (ret >= 0) {
243  val->intval = ret * 2000; /* unit is uV */
244  goto out;
245  }
246  }
247  ret = -ENODATA;
248  break;
249  default:
250  ret = -ENODEV;
251  break;
252  }
253 out:
254  return ret;
255 }
256 
257 static enum power_supply_property max8925_usb_props[] = {
260 };
261 
262 static int max8925_bat_get_prop(struct power_supply *psy,
263  enum power_supply_property psp,
264  union power_supply_propval *val)
265 {
266  struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
267  int ret = 0;
268 
269  switch (psp) {
271  val->intval = info->bat_online;
272  break;
274  if (info->bat_online) {
275  ret = start_measure(info, MEASURE_VMBATT);
276  if (ret >= 0) {
277  val->intval = ret * 2000; /* unit is uV */
278  ret = 0;
279  break;
280  }
281  }
282  ret = -ENODATA;
283  break;
285  if (info->bat_online) {
286  ret = start_measure(info, MEASURE_ISNS);
287  if (ret >= 0) {
288  /* assume r_sns is 0.02 */
289  ret = ((ret * 6250) - 3125) /* uA */;
290  val->intval = 0;
291  if (ret > 0)
292  val->intval = ret; /* unit is mA */
293  ret = 0;
294  break;
295  }
296  }
297  ret = -ENODATA;
298  break;
300  if (!info->bat_online) {
301  ret = -ENODATA;
302  break;
303  }
305  ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
306  switch (ret) {
307  case 1:
309  break;
310  case 0:
311  case 2:
313  break;
314  case 3:
316  break;
317  }
318  ret = 0;
319  break;
321  if (!info->bat_online) {
322  ret = -ENODATA;
323  break;
324  }
326  if (info->usb_online || info->ac_online) {
328  if (ret & MAX8925_CHG_STAT_EN_MASK)
330  } else
332  ret = 0;
333  break;
334  default:
335  ret = -ENODEV;
336  break;
337  }
338  return ret;
339 }
340 
341 static enum power_supply_property max8925_battery_props[] = {
347 };
348 
349 #define REQUEST_IRQ(_irq, _name) \
350 do { \
351  ret = request_threaded_irq(chip->irq_base + _irq, NULL, \
352  max8925_charger_handler, \
353  IRQF_ONESHOT, _name, info); \
354  if (ret) \
355  dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \
356  _irq, ret); \
357 } while (0)
358 
359 static __devinit int max8925_init_charger(struct max8925_chip *chip,
360  struct max8925_power_info *info)
361 {
362  int ret;
363 
365  if (!info->no_insert_detect) {
366  REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
367  REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
368  }
369  if (!info->no_temp_support) {
370  REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
371  REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
372  }
375  REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
376  REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
377  REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
378  REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
379 
380  info->usb_online = 0;
381  info->bat_online = 0;
382 
383  /* check for power - can miss interrupt at boot time */
384  if (start_measure(info, MEASURE_VCHG) * 2000 > 500000)
385  info->ac_online = 1;
386  else
387  info->ac_online = 0;
388 
390  if (ret >= 0) {
391  /*
392  * If battery detection is enabled, ID pin of battery is
393  * connected to MBDET pin of MAX8925. It could be used to
394  * detect battery presence.
395  * Otherwise, we have to assume that battery is always on.
396  */
397  if (info->batt_detect)
398  info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
399  else
400  info->bat_online = 1;
401  if (ret & MAX8925_CHG_AC_RANGE_MASK)
402  info->ac_online = 1;
403  else
404  info->ac_online = 0;
405  }
406  /* disable charge */
407  max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
408  /* set charging current in charge topoff mode */
409  max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
410  info->topoff_threshold << 5);
411  /* set charing current in fast charge mode */
413 
414  return 0;
415 }
416 
417 static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
418 {
419  struct max8925_chip *chip = info->chip;
420  int irq;
421 
422  irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
423  for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
424  free_irq(irq, info);
425 
426  return 0;
427 }
428 
429 static __devinit int max8925_power_probe(struct platform_device *pdev)
430 {
431  struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
432  struct max8925_power_pdata *pdata = NULL;
433  struct max8925_power_info *info;
434  int ret;
435 
436  pdata = pdev->dev.platform_data;
437  if (!pdata) {
438  dev_err(&pdev->dev, "platform data isn't assigned to "
439  "power supply\n");
440  return -EINVAL;
441  }
442 
443  info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
444  if (!info)
445  return -ENOMEM;
446  info->chip = chip;
447  info->gpm = chip->i2c;
448  info->adc = chip->adc;
449  platform_set_drvdata(pdev, info);
450 
451  info->ac.name = "max8925-ac";
452  info->ac.type = POWER_SUPPLY_TYPE_MAINS;
453  info->ac.properties = max8925_ac_props;
454  info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
455  info->ac.get_property = max8925_ac_get_prop;
456  info->ac.supplied_to = pdata->supplied_to;
457  info->ac.num_supplicants = pdata->num_supplicants;
458  ret = power_supply_register(&pdev->dev, &info->ac);
459  if (ret)
460  goto out;
461  info->ac.dev->parent = &pdev->dev;
462 
463  info->usb.name = "max8925-usb";
464  info->usb.type = POWER_SUPPLY_TYPE_USB;
465  info->usb.properties = max8925_usb_props;
466  info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
467  info->usb.get_property = max8925_usb_get_prop;
468  info->usb.supplied_to = pdata->supplied_to;
469  info->usb.num_supplicants = pdata->num_supplicants;
470 
471  ret = power_supply_register(&pdev->dev, &info->usb);
472  if (ret)
473  goto out_usb;
474  info->usb.dev->parent = &pdev->dev;
475 
476  info->battery.name = "max8925-battery";
477  info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
478  info->battery.properties = max8925_battery_props;
479  info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
480  info->battery.get_property = max8925_bat_get_prop;
481  ret = power_supply_register(&pdev->dev, &info->battery);
482  if (ret)
483  goto out_battery;
484  info->battery.dev->parent = &pdev->dev;
485 
486  info->batt_detect = pdata->batt_detect;
487  info->topoff_threshold = pdata->topoff_threshold;
488  info->fast_charge = pdata->fast_charge;
489  info->set_charger = pdata->set_charger;
490  info->no_temp_support = pdata->no_temp_support;
491  info->no_insert_detect = pdata->no_insert_detect;
492 
493  max8925_init_charger(chip, info);
494  return 0;
495 out_battery:
497 out_usb:
498  power_supply_unregister(&info->ac);
499 out:
500  kfree(info);
501  return ret;
502 }
503 
504 static __devexit int max8925_power_remove(struct platform_device *pdev)
505 {
506  struct max8925_power_info *info = platform_get_drvdata(pdev);
507 
508  if (info) {
509  power_supply_unregister(&info->ac);
512  max8925_deinit_charger(info);
513  kfree(info);
514  }
515  return 0;
516 }
517 
518 static struct platform_driver max8925_power_driver = {
519  .probe = max8925_power_probe,
520  .remove = __devexit_p(max8925_power_remove),
521  .driver = {
522  .name = "max8925-power",
523  },
524 };
525 
526 module_platform_driver(max8925_power_driver);
527 
528 MODULE_LICENSE("GPL");
529 MODULE_DESCRIPTION("Power supply driver for MAX8925");
530 MODULE_ALIAS("platform:max8925-power");