]> nv-tegra.nvidia Code Review - linux-2.6.git/blob - drivers/power/intel_mid_battery.c
Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux-2.6.git] / drivers / power / intel_mid_battery.c
1 /*
2  * intel_mid_battery.c - Intel MID PMIC Battery Driver
3  *
4  * Copyright (C) 2009 Intel Corporation
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22  * Author: Nithish Mahalingam <nithish.mahalingam@intel.com>
23  */
24
25 #include <linux/module.h>
26 #include <linux/init.h>
27 #include <linux/err.h>
28 #include <linux/interrupt.h>
29 #include <linux/workqueue.h>
30 #include <linux/jiffies.h>
31 #include <linux/param.h>
32 #include <linux/device.h>
33 #include <linux/spi/spi.h>
34 #include <linux/platform_device.h>
35 #include <linux/power_supply.h>
36
37 #include <asm/intel_scu_ipc.h>
38
39 #define DRIVER_NAME "pmic_battery"
40
41 /*********************************************************************
42  *              Generic defines
43  *********************************************************************/
44
45 static int debug;
46 module_param(debug, int, 0444);
47 MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages.");
48
49 #define PMIC_BATT_DRV_INFO_UPDATED      1
50 #define PMIC_BATT_PRESENT               1
51 #define PMIC_BATT_NOT_PRESENT           0
52 #define PMIC_USB_PRESENT                PMIC_BATT_PRESENT
53 #define PMIC_USB_NOT_PRESENT            PMIC_BATT_NOT_PRESENT
54
55 /* pmic battery register related */
56 #define PMIC_BATT_CHR_SCHRGINT_ADDR     0xD2
57 #define PMIC_BATT_CHR_SBATOVP_MASK      (1 << 1)
58 #define PMIC_BATT_CHR_STEMP_MASK        (1 << 2)
59 #define PMIC_BATT_CHR_SCOMP_MASK        (1 << 3)
60 #define PMIC_BATT_CHR_SUSBDET_MASK      (1 << 4)
61 #define PMIC_BATT_CHR_SBATDET_MASK      (1 << 5)
62 #define PMIC_BATT_CHR_SDCLMT_MASK       (1 << 6)
63 #define PMIC_BATT_CHR_SUSBOVP_MASK      (1 << 7)
64 #define PMIC_BATT_CHR_EXCPT_MASK        0xC6
65 #define PMIC_BATT_ADC_ACCCHRG_MASK      (1 << 31)
66 #define PMIC_BATT_ADC_ACCCHRGVAL_MASK   0x7FFFFFFF
67
68 /* pmic ipc related */
69 #define PMIC_BATT_CHR_IPC_FCHRG_SUBID   0x4
70 #define PMIC_BATT_CHR_IPC_TCHRG_SUBID   0x6
71
72 /* types of battery charging */
73 enum batt_charge_type {
74         BATT_USBOTG_500MA_CHARGE,
75         BATT_USBOTG_TRICKLE_CHARGE,
76 };
77
78 /* valid battery events */
79 enum batt_event {
80         BATT_EVENT_BATOVP_EXCPT,
81         BATT_EVENT_USBOVP_EXCPT,
82         BATT_EVENT_TEMP_EXCPT,
83         BATT_EVENT_DCLMT_EXCPT,
84         BATT_EVENT_EXCPT
85 };
86
87
88 /*********************************************************************
89  *              Battery properties
90  *********************************************************************/
91
92 /*
93  * pmic battery info
94  */
95 struct pmic_power_module_info {
96         bool is_dev_info_updated;
97         struct device *dev;
98         /* pmic battery data */
99         unsigned long update_time;              /* jiffies when data read */
100         unsigned int usb_is_present;
101         unsigned int batt_is_present;
102         unsigned int batt_health;
103         unsigned int usb_health;
104         unsigned int batt_status;
105         unsigned int batt_charge_now;           /* in mAS */
106         unsigned int batt_prev_charge_full;     /* in mAS */
107         unsigned int batt_charge_rate;          /* in units per second */
108
109         struct power_supply usb;
110         struct power_supply batt;
111         int irq;                                /* GPE_ID or IRQ# */
112         struct workqueue_struct *monitor_wqueue;
113         struct delayed_work monitor_battery;
114         struct work_struct handler;
115 };
116
117 static unsigned int delay_time = 2000;  /* in ms */
118
119 /*
120  * pmic ac properties
121  */
122 static enum power_supply_property pmic_usb_props[] = {
123         POWER_SUPPLY_PROP_PRESENT,
124         POWER_SUPPLY_PROP_HEALTH,
125 };
126
127 /*
128  * pmic battery properties
129  */
130 static enum power_supply_property pmic_battery_props[] = {
131         POWER_SUPPLY_PROP_STATUS,
132         POWER_SUPPLY_PROP_HEALTH,
133         POWER_SUPPLY_PROP_PRESENT,
134         POWER_SUPPLY_PROP_CHARGE_NOW,
135         POWER_SUPPLY_PROP_CHARGE_FULL,
136 };
137
138
139 /*
140  * Glue functions for talking to the IPC
141  */
142
143 struct battery_property {
144         u32 capacity;   /* Charger capacity */
145         u8  crnt;       /* Quick charge current value*/
146         u8  volt;       /* Fine adjustment of constant charge voltage */
147         u8  prot;       /* CHRGPROT register value */
148         u8  prot2;      /* CHRGPROT1 register value */
149         u8  timer;      /* Charging timer */
150 };
151
152 #define IPCMSG_BATTERY          0xEF
153
154 /* Battery coulomb counter accumulator commands */
155 #define IPC_CMD_CC_WR             0 /* Update coulomb counter value */
156 #define IPC_CMD_CC_RD             1 /* Read coulomb counter value */
157 #define IPC_CMD_BATTERY_PROPERTY  2 /* Read Battery property */
158
159 /**
160  *      pmic_scu_ipc_battery_cc_read    -       read battery cc
161  *      @value: battery coulomb counter read
162  *
163  *      Reads the battery couloumb counter value, returns 0 on success, or
164  *      an error code
165  *
166  *      This function may sleep. Locking for SCU accesses is handled for
167  *      the caller.
168  */
169 static int pmic_scu_ipc_battery_cc_read(u32 *value)
170 {
171         return intel_scu_ipc_command(IPCMSG_BATTERY, IPC_CMD_CC_RD,
172                                         NULL, 0, value, 1);
173 }
174
175 /**
176  *      pmic_scu_ipc_battery_property_get       -       fetch properties
177  *      @prop: battery properties
178  *
179  *      Retrieve the battery properties from the power management
180  *
181  *      This function may sleep. Locking for SCU accesses is handled for
182  *      the caller.
183  */
184 static int pmic_scu_ipc_battery_property_get(struct battery_property *prop)
185 {
186         u32 data[3];
187         u8 *p = (u8 *)&data[1];
188         int err = intel_scu_ipc_command(IPCMSG_BATTERY,
189                                 IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3);
190
191         prop->capacity = data[0];
192         prop->crnt = *p++;
193         prop->volt = *p++;
194         prop->prot = *p++;
195         prop->prot2 = *p++;
196         prop->timer = *p++;
197
198         return err;
199 }
200
201 /**
202  *      pmic_scu_ipc_set_charger        -       set charger
203  *      @charger: charger to select
204  *
205  *      Switch the charging mode for the SCU
206  */
207
208 static int pmic_scu_ipc_set_charger(int charger)
209 {
210         return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger);
211 }
212
213 /**
214  * pmic_battery_log_event - log battery events
215  * @event: battery event to be logged
216  * Context: can sleep
217  *
218  * There are multiple battery events which may be of interest to users;
219  * this battery function logs the different battery events onto the
220  * kernel log messages.
221  */
222 static void pmic_battery_log_event(enum batt_event event)
223 {
224         printk(KERN_WARNING "pmic-battery: ");
225         switch (event) {
226         case BATT_EVENT_BATOVP_EXCPT:
227                 printk(KERN_CONT "battery overvoltage condition\n");
228                 break;
229         case BATT_EVENT_USBOVP_EXCPT:
230                 printk(KERN_CONT "usb charger overvoltage condition\n");
231                 break;
232         case BATT_EVENT_TEMP_EXCPT:
233                 printk(KERN_CONT "high battery temperature condition\n");
234                 break;
235         case BATT_EVENT_DCLMT_EXCPT:
236                 printk(KERN_CONT "over battery charge current condition\n");
237                 break;
238         default:
239                 printk(KERN_CONT "charger/battery exception %d\n", event);
240                 break;
241         }
242 }
243
244 /**
245  * pmic_battery_read_status - read battery status information
246  * @pbi: device info structure to update the read information
247  * Context: can sleep
248  *
249  * PMIC power source information need to be updated based on the data read
250  * from the PMIC battery registers.
251  *
252  */
253 static void pmic_battery_read_status(struct pmic_power_module_info *pbi)
254 {
255         unsigned int update_time_intrvl;
256         unsigned int chrg_val;
257         u32 ccval;
258         u8 r8;
259         struct battery_property batt_prop;
260         int batt_present = 0;
261         int usb_present = 0;
262         int batt_exception = 0;
263
264         /* make sure the last batt_status read happened delay_time before */
265         if (pbi->update_time && time_before(jiffies, pbi->update_time +
266                                                 msecs_to_jiffies(delay_time)))
267                 return;
268
269         update_time_intrvl = jiffies_to_msecs(jiffies - pbi->update_time);
270         pbi->update_time = jiffies;
271
272         /* read coulomb counter registers and schrgint register */
273         if (pmic_scu_ipc_battery_cc_read(&ccval)) {
274                 dev_warn(pbi->dev, "%s(): ipc config cmd failed\n",
275                                                                 __func__);
276                 return;
277         }
278
279         if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) {
280                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
281                                                                 __func__);
282                 return;
283         }
284
285         /*
286          * set pmic_power_module_info members based on pmic register values
287          * read.
288          */
289
290         /* set batt_is_present */
291         if (r8 & PMIC_BATT_CHR_SBATDET_MASK) {
292                 pbi->batt_is_present = PMIC_BATT_PRESENT;
293                 batt_present = 1;
294         } else {
295                 pbi->batt_is_present = PMIC_BATT_NOT_PRESENT;
296                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
297                 pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN;
298         }
299
300         /* set batt_health */
301         if (batt_present) {
302                 if (r8 & PMIC_BATT_CHR_SBATOVP_MASK) {
303                         pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
304                         pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
305                         pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT);
306                         batt_exception = 1;
307                 } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) {
308                         pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
309                         pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
310                         pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT);
311                         batt_exception = 1;
312                 } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) {
313                         pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT;
314                         pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
315                         pmic_battery_log_event(BATT_EVENT_TEMP_EXCPT);
316                         batt_exception = 1;
317                 } else {
318                         pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD;
319                 }
320         }
321
322         /* set usb_is_present */
323         if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) {
324                 pbi->usb_is_present = PMIC_USB_PRESENT;
325                 usb_present = 1;
326         } else {
327                 pbi->usb_is_present = PMIC_USB_NOT_PRESENT;
328                 pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
329         }
330
331         if (usb_present) {
332                 if (r8 & PMIC_BATT_CHR_SUSBOVP_MASK) {
333                         pbi->usb_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
334                         pmic_battery_log_event(BATT_EVENT_USBOVP_EXCPT);
335                 } else {
336                         pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD;
337                 }
338         }
339
340         chrg_val = ccval & PMIC_BATT_ADC_ACCCHRGVAL_MASK;
341
342         /* set batt_prev_charge_full to battery capacity the first time */
343         if (!pbi->is_dev_info_updated) {
344                 if (pmic_scu_ipc_battery_property_get(&batt_prop)) {
345                         dev_warn(pbi->dev, "%s(): ipc config cmd failed\n",
346                                                                 __func__);
347                         return;
348                 }
349                 pbi->batt_prev_charge_full = batt_prop.capacity;
350         }
351
352         /* set batt_status */
353         if (batt_present && !batt_exception) {
354                 if (r8 & PMIC_BATT_CHR_SCOMP_MASK) {
355                         pbi->batt_status = POWER_SUPPLY_STATUS_FULL;
356                         pbi->batt_prev_charge_full = chrg_val;
357                 } else if (ccval & PMIC_BATT_ADC_ACCCHRG_MASK) {
358                         pbi->batt_status = POWER_SUPPLY_STATUS_DISCHARGING;
359                 } else {
360                         pbi->batt_status = POWER_SUPPLY_STATUS_CHARGING;
361                 }
362         }
363
364         /* set batt_charge_rate */
365         if (pbi->is_dev_info_updated && batt_present && !batt_exception) {
366                 if (pbi->batt_status == POWER_SUPPLY_STATUS_DISCHARGING) {
367                         if (pbi->batt_charge_now - chrg_val) {
368                                 pbi->batt_charge_rate = ((pbi->batt_charge_now -
369                                         chrg_val) * 1000 * 60) /
370                                         update_time_intrvl;
371                         }
372                 } else if (pbi->batt_status == POWER_SUPPLY_STATUS_CHARGING) {
373                         if (chrg_val - pbi->batt_charge_now) {
374                                 pbi->batt_charge_rate = ((chrg_val -
375                                         pbi->batt_charge_now) * 1000 * 60) /
376                                         update_time_intrvl;
377                         }
378                 } else
379                         pbi->batt_charge_rate = 0;
380         } else {
381                 pbi->batt_charge_rate = -1;
382         }
383
384         /* batt_charge_now */
385         if (batt_present && !batt_exception)
386                 pbi->batt_charge_now = chrg_val;
387         else
388                 pbi->batt_charge_now = -1;
389
390         pbi->is_dev_info_updated = PMIC_BATT_DRV_INFO_UPDATED;
391 }
392
393 /**
394  * pmic_usb_get_property - usb power source get property
395  * @psy: usb power supply context
396  * @psp: usb power source property
397  * @val: usb power source property value
398  * Context: can sleep
399  *
400  * PMIC usb power source property needs to be provided to power_supply
401  * subsytem for it to provide the information to users.
402  */
403 static int pmic_usb_get_property(struct power_supply *psy,
404                                 enum power_supply_property psp,
405                                 union power_supply_propval *val)
406 {
407         struct pmic_power_module_info *pbi = container_of(psy,
408                                 struct pmic_power_module_info, usb);
409
410         /* update pmic_power_module_info members */
411         pmic_battery_read_status(pbi);
412
413         switch (psp) {
414         case POWER_SUPPLY_PROP_PRESENT:
415                 val->intval = pbi->usb_is_present;
416                 break;
417         case POWER_SUPPLY_PROP_HEALTH:
418                 val->intval = pbi->usb_health;
419                 break;
420         default:
421                 return -EINVAL;
422         }
423
424         return 0;
425 }
426
427 static inline unsigned long mAStouAh(unsigned long v)
428 {
429         /* seconds to hours, mA to ÂµA */
430         return (v * 1000) / 3600;
431 }
432
433 /**
434  * pmic_battery_get_property - battery power source get property
435  * @psy: battery power supply context
436  * @psp: battery power source property
437  * @val: battery power source property value
438  * Context: can sleep
439  *
440  * PMIC battery power source property needs to be provided to power_supply
441  * subsytem for it to provide the information to users.
442  */
443 static int pmic_battery_get_property(struct power_supply *psy,
444                                 enum power_supply_property psp,
445                                 union power_supply_propval *val)
446 {
447         struct pmic_power_module_info *pbi = container_of(psy,
448                                 struct pmic_power_module_info, batt);
449
450         /* update pmic_power_module_info members */
451         pmic_battery_read_status(pbi);
452
453         switch (psp) {
454         case POWER_SUPPLY_PROP_STATUS:
455                 val->intval = pbi->batt_status;
456                 break;
457         case POWER_SUPPLY_PROP_HEALTH:
458                 val->intval = pbi->batt_health;
459                 break;
460         case POWER_SUPPLY_PROP_PRESENT:
461                 val->intval = pbi->batt_is_present;
462                 break;
463         case POWER_SUPPLY_PROP_CHARGE_NOW:
464                 val->intval = mAStouAh(pbi->batt_charge_now);
465                 break;
466         case POWER_SUPPLY_PROP_CHARGE_FULL:
467                 val->intval = mAStouAh(pbi->batt_prev_charge_full);
468                 break;
469         default:
470                 return -EINVAL;
471         }
472
473         return 0;
474 }
475
476 /**
477  * pmic_battery_monitor - monitor battery status
478  * @work: work structure
479  * Context: can sleep
480  *
481  * PMIC battery status needs to be monitored for any change
482  * and information needs to be frequently updated.
483  */
484 static void pmic_battery_monitor(struct work_struct *work)
485 {
486         struct pmic_power_module_info *pbi = container_of(work,
487                         struct pmic_power_module_info, monitor_battery.work);
488
489         /* update pmic_power_module_info members */
490         pmic_battery_read_status(pbi);
491         queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 10);
492 }
493
494 /**
495  * pmic_battery_set_charger - set battery charger
496  * @pbi: device info structure
497  * @chrg: charge mode to set battery charger in
498  * Context: can sleep
499  *
500  * PMIC battery charger needs to be enabled based on the usb charge
501  * capabilities connected to the platform.
502  */
503 static int pmic_battery_set_charger(struct pmic_power_module_info *pbi,
504                                                 enum batt_charge_type chrg)
505 {
506         int retval;
507
508         /* set usblmt bits and chrgcntl register bits appropriately */
509         switch (chrg) {
510         case BATT_USBOTG_500MA_CHARGE:
511                 retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_FCHRG_SUBID);
512                 break;
513         case BATT_USBOTG_TRICKLE_CHARGE:
514                 retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_TCHRG_SUBID);
515                 break;
516         default:
517                 dev_warn(pbi->dev, "%s(): out of range usb charger "
518                                                 "charge detected\n", __func__);
519                 return -EINVAL;
520         }
521
522         if (retval) {
523                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
524                                                                 __func__);
525                 return retval;;
526         }
527
528         return 0;
529 }
530
531 /**
532  * pmic_battery_interrupt_handler - pmic battery interrupt handler
533  * Context: interrupt context
534  *
535  * PMIC battery interrupt handler which will be called with either
536  * battery full condition occurs or usb otg & battery connect
537  * condition occurs.
538  */
539 static irqreturn_t pmic_battery_interrupt_handler(int id, void *dev)
540 {
541         struct pmic_power_module_info *pbi = dev;
542
543         schedule_work(&pbi->handler);
544
545         return IRQ_HANDLED;
546 }
547
548 /**
549  * pmic_battery_handle_intrpt - pmic battery service interrupt
550  * @work: work structure
551  * Context: can sleep
552  *
553  * PMIC battery needs to either update the battery status as full
554  * if it detects battery full condition caused the interrupt or needs
555  * to enable battery charger if it detects usb and battery detect
556  * caused the source of interrupt.
557  */
558 static void pmic_battery_handle_intrpt(struct work_struct *work)
559 {
560         struct pmic_power_module_info *pbi = container_of(work,
561                                 struct pmic_power_module_info, handler);
562         enum batt_charge_type chrg;
563         u8 r8;
564
565         if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) {
566                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
567                                                                 __func__);
568                 return;
569         }
570         /* find the cause of the interrupt */
571         if (r8 & PMIC_BATT_CHR_SBATDET_MASK) {
572                 pbi->batt_is_present = PMIC_BATT_PRESENT;
573         } else {
574                 pbi->batt_is_present = PMIC_BATT_NOT_PRESENT;
575                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
576                 pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN;
577                 return;
578         }
579
580         if (r8 & PMIC_BATT_CHR_EXCPT_MASK) {
581                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
582                 pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
583                 pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
584                 pmic_battery_log_event(BATT_EVENT_EXCPT);
585                 return;
586         } else {
587                 pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD;
588                 pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD;
589         }
590
591         if (r8 & PMIC_BATT_CHR_SCOMP_MASK) {
592                 u32 ccval;
593                 pbi->batt_status = POWER_SUPPLY_STATUS_FULL;
594
595                 if (pmic_scu_ipc_battery_cc_read(&ccval)) {
596                         dev_warn(pbi->dev, "%s(): ipc config cmd "
597                                                         "failed\n", __func__);
598                         return;
599                 }
600                 pbi->batt_prev_charge_full = ccval &
601                                                 PMIC_BATT_ADC_ACCCHRGVAL_MASK;
602                 return;
603         }
604
605         if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) {
606                 pbi->usb_is_present = PMIC_USB_PRESENT;
607         } else {
608                 pbi->usb_is_present = PMIC_USB_NOT_PRESENT;
609                 pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
610                 return;
611         }
612
613         /* setup battery charging */
614
615 #if 0
616         /* check usb otg power capability and set charger accordingly */
617         retval = langwell_udc_maxpower(&power);
618         if (retval) {
619                 dev_warn(pbi->dev,
620                     "%s(): usb otg power query failed with error code %d\n",
621                         __func__, retval);
622                 return;
623         }
624
625         if (power >= 500)
626                 chrg = BATT_USBOTG_500MA_CHARGE;
627         else
628 #endif
629                 chrg = BATT_USBOTG_TRICKLE_CHARGE;
630
631         /* enable battery charging */
632         if (pmic_battery_set_charger(pbi, chrg)) {
633                 dev_warn(pbi->dev,
634                         "%s(): failed to set up battery charging\n", __func__);
635                 return;
636         }
637
638         dev_dbg(pbi->dev,
639                 "pmic-battery: %s() - setting up battery charger successful\n",
640                         __func__);
641 }
642
643 /**
644  * pmic_battery_probe - pmic battery initialize
645  * @irq: pmic battery device irq
646  * @dev: pmic battery device structure
647  * Context: can sleep
648  *
649  * PMIC battery initializes its internal data structue and other
650  * infrastructure components for it to work as expected.
651  */
652 static __devinit int probe(int irq, struct device *dev)
653 {
654         int retval = 0;
655         struct pmic_power_module_info *pbi;
656
657         dev_dbg(dev, "pmic-battery: found pmic battery device\n");
658
659         pbi = kzalloc(sizeof(*pbi), GFP_KERNEL);
660         if (!pbi) {
661                 dev_err(dev, "%s(): memory allocation failed\n",
662                                                                 __func__);
663                 return -ENOMEM;
664         }
665
666         pbi->dev = dev;
667         pbi->irq = irq;
668         dev_set_drvdata(dev, pbi);
669
670         /* initialize all required framework before enabling interrupts */
671         INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt);
672         INIT_DELAYED_WORK(&pbi->monitor_battery, pmic_battery_monitor);
673         pbi->monitor_wqueue =
674                         create_singlethread_workqueue(dev_name(dev));
675         if (!pbi->monitor_wqueue) {
676                 dev_err(dev, "%s(): wqueue init failed\n", __func__);
677                 retval = -ESRCH;
678                 goto wqueue_failed;
679         }
680
681         /* register interrupt */
682         retval = request_irq(pbi->irq, pmic_battery_interrupt_handler,
683                                                         0, DRIVER_NAME, pbi);
684         if (retval) {
685                 dev_err(dev, "%s(): cannot get IRQ\n", __func__);
686                 goto requestirq_failed;
687         }
688
689         /* register pmic-batt with power supply subsystem */
690         pbi->batt.name = "pmic-batt";
691         pbi->batt.type = POWER_SUPPLY_TYPE_BATTERY;
692         pbi->batt.properties = pmic_battery_props;
693         pbi->batt.num_properties = ARRAY_SIZE(pmic_battery_props);
694         pbi->batt.get_property = pmic_battery_get_property;
695         retval = power_supply_register(dev, &pbi->batt);
696         if (retval) {
697                 dev_err(dev,
698                         "%s(): failed to register pmic battery device with power supply subsystem\n",
699                                 __func__);
700                 goto power_reg_failed;
701         }
702
703         dev_dbg(dev, "pmic-battery: %s() - pmic battery device "
704                 "registration with power supply subsystem successful\n",
705                 __func__);
706
707         queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 1);
708
709         /* register pmic-usb with power supply subsystem */
710         pbi->usb.name = "pmic-usb";
711         pbi->usb.type = POWER_SUPPLY_TYPE_USB;
712         pbi->usb.properties = pmic_usb_props;
713         pbi->usb.num_properties = ARRAY_SIZE(pmic_usb_props);
714         pbi->usb.get_property = pmic_usb_get_property;
715         retval = power_supply_register(dev, &pbi->usb);
716         if (retval) {
717                 dev_err(dev,
718                         "%s(): failed to register pmic usb device with power supply subsystem\n",
719                                 __func__);
720                 goto power_reg_failed_1;
721         }
722
723         if (debug)
724                 printk(KERN_INFO "pmic-battery: %s() - pmic usb device "
725                         "registration with power supply subsystem successful\n",
726                         __func__);
727
728         return retval;
729
730 power_reg_failed_1:
731         power_supply_unregister(&pbi->batt);
732 power_reg_failed:
733         cancel_rearming_delayed_workqueue(pbi->monitor_wqueue,
734                                                 &pbi->monitor_battery);
735 requestirq_failed:
736         destroy_workqueue(pbi->monitor_wqueue);
737 wqueue_failed:
738         kfree(pbi);
739
740         return retval;
741 }
742
743 static int __devinit platform_pmic_battery_probe(struct platform_device *pdev)
744 {
745         return probe(pdev->id, &pdev->dev);
746 }
747
748 /**
749  * pmic_battery_remove - pmic battery finalize
750  * @dev: pmic battery device structure
751  * Context: can sleep
752  *
753  * PMIC battery finalizes its internal data structue and other
754  * infrastructure components that it initialized in
755  * pmic_battery_probe.
756  */
757
758 static int __devexit platform_pmic_battery_remove(struct platform_device *pdev)
759 {
760         struct pmic_power_module_info *pbi = dev_get_drvdata(&pdev->dev);
761
762         free_irq(pbi->irq, pbi);
763         cancel_rearming_delayed_workqueue(pbi->monitor_wqueue,
764                                         &pbi->monitor_battery);
765         destroy_workqueue(pbi->monitor_wqueue);
766
767         power_supply_unregister(&pbi->usb);
768         power_supply_unregister(&pbi->batt);
769
770         flush_scheduled_work();
771         kfree(pbi);
772         return 0;
773 }
774
775 static struct platform_driver platform_pmic_battery_driver = {
776         .driver = {
777                 .name = DRIVER_NAME,
778                 .owner = THIS_MODULE,
779         },
780         .probe = platform_pmic_battery_probe,
781         .remove = __devexit_p(platform_pmic_battery_remove),
782 };
783
784 static int __init platform_pmic_battery_module_init(void)
785 {
786         return platform_driver_register(&platform_pmic_battery_driver);
787 }
788
789 static void __exit platform_pmic_battery_module_exit(void)
790 {
791         platform_driver_unregister(&platform_pmic_battery_driver);
792 }
793
794 module_init(platform_pmic_battery_module_init);
795 module_exit(platform_pmic_battery_module_exit);
796
797 MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
798 MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
799 MODULE_LICENSE("GPL");