Version:  2.0.40 2.2.26 2.4.37 3.2 3.3 3.4 3.5 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

Linux/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        0x86
 65 
 66 #define PMIC_BATT_ADC_ACCCHRG_MASK      (1 << 31)
 67 #define PMIC_BATT_ADC_ACCCHRGVAL_MASK   0x7FFFFFFF
 68 
 69 /* pmic ipc related */
 70 #define PMIC_BATT_CHR_IPC_FCHRG_SUBID   0x4
 71 #define PMIC_BATT_CHR_IPC_TCHRG_SUBID   0x6
 72 
 73 /* types of battery charging */
 74 enum batt_charge_type {
 75         BATT_USBOTG_500MA_CHARGE,
 76         BATT_USBOTG_TRICKLE_CHARGE,
 77 };
 78 
 79 /* valid battery events */
 80 enum batt_event {
 81         BATT_EVENT_BATOVP_EXCPT,
 82         BATT_EVENT_USBOVP_EXCPT,
 83         BATT_EVENT_TEMP_EXCPT,
 84         BATT_EVENT_DCLMT_EXCPT,
 85         BATT_EVENT_EXCPT
 86 };
 87 
 88 
 89 /*********************************************************************
 90  *              Battery properties
 91  *********************************************************************/
 92 
 93 /*
 94  * pmic battery info
 95  */
 96 struct pmic_power_module_info {
 97         bool is_dev_info_updated;
 98         struct device *dev;
 99         /* pmic battery data */
100         unsigned long update_time;              /* jiffies when data read */
101         unsigned int usb_is_present;
102         unsigned int batt_is_present;
103         unsigned int batt_health;
104         unsigned int usb_health;
105         unsigned int batt_status;
106         unsigned int batt_charge_now;           /* in mAS */
107         unsigned int batt_prev_charge_full;     /* in mAS */
108         unsigned int batt_charge_rate;          /* in units per second */
109 
110         struct power_supply usb;
111         struct power_supply batt;
112         int irq;                                /* GPE_ID or IRQ# */
113         struct workqueue_struct *monitor_wqueue;
114         struct delayed_work monitor_battery;
115         struct work_struct handler;
116 };
117 
118 static unsigned int delay_time = 2000;  /* in ms */
119 
120 /*
121  * pmic ac properties
122  */
123 static enum power_supply_property pmic_usb_props[] = {
124         POWER_SUPPLY_PROP_PRESENT,
125         POWER_SUPPLY_PROP_HEALTH,
126 };
127 
128 /*
129  * pmic battery properties
130  */
131 static enum power_supply_property pmic_battery_props[] = {
132         POWER_SUPPLY_PROP_STATUS,
133         POWER_SUPPLY_PROP_HEALTH,
134         POWER_SUPPLY_PROP_PRESENT,
135         POWER_SUPPLY_PROP_CHARGE_NOW,
136         POWER_SUPPLY_PROP_CHARGE_FULL,
137 };
138 
139 
140 /*
141  * Glue functions for talking to the IPC
142  */
143 
144 struct battery_property {
145         u32 capacity;   /* Charger capacity */
146         u8  crnt;       /* Quick charge current value*/
147         u8  volt;       /* Fine adjustment of constant charge voltage */
148         u8  prot;       /* CHRGPROT register value */
149         u8  prot2;      /* CHRGPROT1 register value */
150         u8  timer;      /* Charging timer */
151 };
152 
153 #define IPCMSG_BATTERY          0xEF
154 
155 /* Battery coulomb counter accumulator commands */
156 #define IPC_CMD_CC_WR             0 /* Update coulomb counter value */
157 #define IPC_CMD_CC_RD             1 /* Read coulomb counter value */
158 #define IPC_CMD_BATTERY_PROPERTY  2 /* Read Battery property */
159 
160 /**
161  *      pmic_scu_ipc_battery_cc_read    -       read battery cc
162  *      @value: battery coulomb counter read
163  *
164  *      Reads the battery couloumb counter value, returns 0 on success, or
165  *      an error code
166  *
167  *      This function may sleep. Locking for SCU accesses is handled for
168  *      the caller.
169  */
170 static int pmic_scu_ipc_battery_cc_read(u32 *value)
171 {
172         return intel_scu_ipc_command(IPCMSG_BATTERY, IPC_CMD_CC_RD,
173                                         NULL, 0, value, 1);
174 }
175 
176 /**
177  *      pmic_scu_ipc_battery_property_get       -       fetch properties
178  *      @prop: battery properties
179  *
180  *      Retrieve the battery properties from the power management
181  *
182  *      This function may sleep. Locking for SCU accesses is handled for
183  *      the caller.
184  */
185 static int pmic_scu_ipc_battery_property_get(struct battery_property *prop)
186 {
187         u32 data[3];
188         u8 *p = (u8 *)&data[1];
189         int err = intel_scu_ipc_command(IPCMSG_BATTERY,
190                                 IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3);
191 
192         prop->capacity = data[0];
193         prop->crnt = *p++;
194         prop->volt = *p++;
195         prop->prot = *p++;
196         prop->prot2 = *p++;
197         prop->timer = *p++;
198 
199         return err;
200 }
201 
202 /**
203  *      pmic_scu_ipc_set_charger        -       set charger
204  *      @charger: charger to select
205  *
206  *      Switch the charging mode for the SCU
207  */
208 
209 static int pmic_scu_ipc_set_charger(int charger)
210 {
211         return intel_scu_ipc_simple_command(IPCMSG_BATTERY, charger);
212 }
213 
214 /**
215  * pmic_battery_log_event - log battery events
216  * @event: battery event to be logged
217  * Context: can sleep
218  *
219  * There are multiple battery events which may be of interest to users;
220  * this battery function logs the different battery events onto the
221  * kernel log messages.
222  */
223 static void pmic_battery_log_event(enum batt_event event)
224 {
225         printk(KERN_WARNING "pmic-battery: ");
226         switch (event) {
227         case BATT_EVENT_BATOVP_EXCPT:
228                 printk(KERN_CONT "battery overvoltage condition\n");
229                 break;
230         case BATT_EVENT_USBOVP_EXCPT:
231                 printk(KERN_CONT "usb charger overvoltage condition\n");
232                 break;
233         case BATT_EVENT_TEMP_EXCPT:
234                 printk(KERN_CONT "high battery temperature condition\n");
235                 break;
236         case BATT_EVENT_DCLMT_EXCPT:
237                 printk(KERN_CONT "over battery charge current condition\n");
238                 break;
239         default:
240                 printk(KERN_CONT "charger/battery exception %d\n", event);
241                 break;
242         }
243 }
244 
245 /**
246  * pmic_battery_read_status - read battery status information
247  * @pbi: device info structure to update the read information
248  * Context: can sleep
249  *
250  * PMIC power source information need to be updated based on the data read
251  * from the PMIC battery registers.
252  *
253  */
254 static void pmic_battery_read_status(struct pmic_power_module_info *pbi)
255 {
256         unsigned int update_time_intrvl;
257         unsigned int chrg_val;
258         u32 ccval;
259         u8 r8;
260         struct battery_property batt_prop;
261         int batt_present = 0;
262         int usb_present = 0;
263         int batt_exception = 0;
264 
265         /* make sure the last batt_status read happened delay_time before */
266         if (pbi->update_time && time_before(jiffies, pbi->update_time +
267                                                 msecs_to_jiffies(delay_time)))
268                 return;
269 
270         update_time_intrvl = jiffies_to_msecs(jiffies - pbi->update_time);
271         pbi->update_time = jiffies;
272 
273         /* read coulomb counter registers and schrgint register */
274         if (pmic_scu_ipc_battery_cc_read(&ccval)) {
275                 dev_warn(pbi->dev, "%s(): ipc config cmd failed\n",
276                                                                 __func__);
277                 return;
278         }
279 
280         if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) {
281                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
282                                                                 __func__);
283                 return;
284         }
285 
286         /*
287          * set pmic_power_module_info members based on pmic register values
288          * read.
289          */
290 
291         /* set batt_is_present */
292         if (r8 & PMIC_BATT_CHR_SBATDET_MASK) {
293                 pbi->batt_is_present = PMIC_BATT_PRESENT;
294                 batt_present = 1;
295         } else {
296                 pbi->batt_is_present = PMIC_BATT_NOT_PRESENT;
297                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
298                 pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN;
299         }
300 
301         /* set batt_health */
302         if (batt_present) {
303                 if (r8 & PMIC_BATT_CHR_SBATOVP_MASK) {
304                         pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
305                         pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
306                         pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT);
307                         batt_exception = 1;
308                 } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) {
309                         pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT;
310                         pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
311                         pmic_battery_log_event(BATT_EVENT_TEMP_EXCPT);
312                         batt_exception = 1;
313                 } else {
314                         pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD;
315                         if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) {
316                                 /* PMIC will change charging current automatically */
317                                 pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT);
318                         }
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 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_delayed_work_sync(&pbi->monitor_battery);
734 requestirq_failed:
735         destroy_workqueue(pbi->monitor_wqueue);
736 wqueue_failed:
737         kfree(pbi);
738 
739         return retval;
740 }
741 
742 static int platform_pmic_battery_probe(struct platform_device *pdev)
743 {
744         return probe(pdev->id, &pdev->dev);
745 }
746 
747 /**
748  * pmic_battery_remove - pmic battery finalize
749  * @dev: pmic battery device structure
750  * Context: can sleep
751  *
752  * PMIC battery finalizes its internal data structue and other
753  * infrastructure components that it initialized in
754  * pmic_battery_probe.
755  */
756 
757 static int platform_pmic_battery_remove(struct platform_device *pdev)
758 {
759         struct pmic_power_module_info *pbi = platform_get_drvdata(pdev);
760 
761         free_irq(pbi->irq, pbi);
762         cancel_delayed_work_sync(&pbi->monitor_battery);
763         destroy_workqueue(pbi->monitor_wqueue);
764 
765         power_supply_unregister(&pbi->usb);
766         power_supply_unregister(&pbi->batt);
767 
768         cancel_work_sync(&pbi->handler);
769         kfree(pbi);
770         return 0;
771 }
772 
773 static struct platform_driver platform_pmic_battery_driver = {
774         .driver = {
775                 .name = DRIVER_NAME,
776                 .owner = THIS_MODULE,
777         },
778         .probe = platform_pmic_battery_probe,
779         .remove = platform_pmic_battery_remove,
780 };
781 
782 module_platform_driver(platform_pmic_battery_driver);
783 
784 MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
785 MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
786 MODULE_LICENSE("GPL");
787 

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