Version:  2.0.40 2.2.26 2.4.37 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 3.19 4.0 4.1

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 = power_supply_get_drvdata(psy);
408 
409         /* update pmic_power_module_info members */
410         pmic_battery_read_status(pbi);
411 
412         switch (psp) {
413         case POWER_SUPPLY_PROP_PRESENT:
414                 val->intval = pbi->usb_is_present;
415                 break;
416         case POWER_SUPPLY_PROP_HEALTH:
417                 val->intval = pbi->usb_health;
418                 break;
419         default:
420                 return -EINVAL;
421         }
422 
423         return 0;
424 }
425 
426 static inline unsigned long mAStouAh(unsigned long v)
427 {
428         /* seconds to hours, mA to µA */
429         return (v * 1000) / 3600;
430 }
431 
432 /**
433  * pmic_battery_get_property - battery power source get property
434  * @psy: battery power supply context
435  * @psp: battery power source property
436  * @val: battery power source property value
437  * Context: can sleep
438  *
439  * PMIC battery power source property needs to be provided to power_supply
440  * subsytem for it to provide the information to users.
441  */
442 static int pmic_battery_get_property(struct power_supply *psy,
443                                 enum power_supply_property psp,
444                                 union power_supply_propval *val)
445 {
446         struct pmic_power_module_info *pbi = power_supply_get_drvdata(psy);
447 
448         /* update pmic_power_module_info members */
449         pmic_battery_read_status(pbi);
450 
451         switch (psp) {
452         case POWER_SUPPLY_PROP_STATUS:
453                 val->intval = pbi->batt_status;
454                 break;
455         case POWER_SUPPLY_PROP_HEALTH:
456                 val->intval = pbi->batt_health;
457                 break;
458         case POWER_SUPPLY_PROP_PRESENT:
459                 val->intval = pbi->batt_is_present;
460                 break;
461         case POWER_SUPPLY_PROP_CHARGE_NOW:
462                 val->intval = mAStouAh(pbi->batt_charge_now);
463                 break;
464         case POWER_SUPPLY_PROP_CHARGE_FULL:
465                 val->intval = mAStouAh(pbi->batt_prev_charge_full);
466                 break;
467         default:
468                 return -EINVAL;
469         }
470 
471         return 0;
472 }
473 
474 /**
475  * pmic_battery_monitor - monitor battery status
476  * @work: work structure
477  * Context: can sleep
478  *
479  * PMIC battery status needs to be monitored for any change
480  * and information needs to be frequently updated.
481  */
482 static void pmic_battery_monitor(struct work_struct *work)
483 {
484         struct pmic_power_module_info *pbi = container_of(work,
485                         struct pmic_power_module_info, monitor_battery.work);
486 
487         /* update pmic_power_module_info members */
488         pmic_battery_read_status(pbi);
489         queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 10);
490 }
491 
492 /**
493  * pmic_battery_set_charger - set battery charger
494  * @pbi: device info structure
495  * @chrg: charge mode to set battery charger in
496  * Context: can sleep
497  *
498  * PMIC battery charger needs to be enabled based on the usb charge
499  * capabilities connected to the platform.
500  */
501 static int pmic_battery_set_charger(struct pmic_power_module_info *pbi,
502                                                 enum batt_charge_type chrg)
503 {
504         int retval;
505 
506         /* set usblmt bits and chrgcntl register bits appropriately */
507         switch (chrg) {
508         case BATT_USBOTG_500MA_CHARGE:
509                 retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_FCHRG_SUBID);
510                 break;
511         case BATT_USBOTG_TRICKLE_CHARGE:
512                 retval = pmic_scu_ipc_set_charger(PMIC_BATT_CHR_IPC_TCHRG_SUBID);
513                 break;
514         default:
515                 dev_warn(pbi->dev, "%s(): out of range usb charger "
516                                                 "charge detected\n", __func__);
517                 return -EINVAL;
518         }
519 
520         if (retval) {
521                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
522                                                                 __func__);
523                 return retval;
524         }
525 
526         return 0;
527 }
528 
529 /**
530  * pmic_battery_interrupt_handler - pmic battery interrupt handler
531  * Context: interrupt context
532  *
533  * PMIC battery interrupt handler which will be called with either
534  * battery full condition occurs or usb otg & battery connect
535  * condition occurs.
536  */
537 static irqreturn_t pmic_battery_interrupt_handler(int id, void *dev)
538 {
539         struct pmic_power_module_info *pbi = dev;
540 
541         schedule_work(&pbi->handler);
542 
543         return IRQ_HANDLED;
544 }
545 
546 /**
547  * pmic_battery_handle_intrpt - pmic battery service interrupt
548  * @work: work structure
549  * Context: can sleep
550  *
551  * PMIC battery needs to either update the battery status as full
552  * if it detects battery full condition caused the interrupt or needs
553  * to enable battery charger if it detects usb and battery detect
554  * caused the source of interrupt.
555  */
556 static void pmic_battery_handle_intrpt(struct work_struct *work)
557 {
558         struct pmic_power_module_info *pbi = container_of(work,
559                                 struct pmic_power_module_info, handler);
560         enum batt_charge_type chrg;
561         u8 r8;
562 
563         if (intel_scu_ipc_ioread8(PMIC_BATT_CHR_SCHRGINT_ADDR, &r8)) {
564                 dev_warn(pbi->dev, "%s(): ipc pmic read failed\n",
565                                                                 __func__);
566                 return;
567         }
568         /* find the cause of the interrupt */
569         if (r8 & PMIC_BATT_CHR_SBATDET_MASK) {
570                 pbi->batt_is_present = PMIC_BATT_PRESENT;
571         } else {
572                 pbi->batt_is_present = PMIC_BATT_NOT_PRESENT;
573                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
574                 pbi->batt_status = POWER_SUPPLY_STATUS_UNKNOWN;
575                 return;
576         }
577 
578         if (r8 & PMIC_BATT_CHR_EXCPT_MASK) {
579                 pbi->batt_health = POWER_SUPPLY_HEALTH_UNKNOWN;
580                 pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
581                 pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
582                 pmic_battery_log_event(BATT_EVENT_EXCPT);
583                 return;
584         } else {
585                 pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD;
586                 pbi->usb_health = POWER_SUPPLY_HEALTH_GOOD;
587         }
588 
589         if (r8 & PMIC_BATT_CHR_SCOMP_MASK) {
590                 u32 ccval;
591                 pbi->batt_status = POWER_SUPPLY_STATUS_FULL;
592 
593                 if (pmic_scu_ipc_battery_cc_read(&ccval)) {
594                         dev_warn(pbi->dev, "%s(): ipc config cmd "
595                                                         "failed\n", __func__);
596                         return;
597                 }
598                 pbi->batt_prev_charge_full = ccval &
599                                                 PMIC_BATT_ADC_ACCCHRGVAL_MASK;
600                 return;
601         }
602 
603         if (r8 & PMIC_BATT_CHR_SUSBDET_MASK) {
604                 pbi->usb_is_present = PMIC_USB_PRESENT;
605         } else {
606                 pbi->usb_is_present = PMIC_USB_NOT_PRESENT;
607                 pbi->usb_health = POWER_SUPPLY_HEALTH_UNKNOWN;
608                 return;
609         }
610 
611         /* setup battery charging */
612 
613 #if 0
614         /* check usb otg power capability and set charger accordingly */
615         retval = langwell_udc_maxpower(&power);
616         if (retval) {
617                 dev_warn(pbi->dev,
618                     "%s(): usb otg power query failed with error code %d\n",
619                         __func__, retval);
620                 return;
621         }
622 
623         if (power >= 500)
624                 chrg = BATT_USBOTG_500MA_CHARGE;
625         else
626 #endif
627                 chrg = BATT_USBOTG_TRICKLE_CHARGE;
628 
629         /* enable battery charging */
630         if (pmic_battery_set_charger(pbi, chrg)) {
631                 dev_warn(pbi->dev,
632                         "%s(): failed to set up battery charging\n", __func__);
633                 return;
634         }
635 
636         dev_dbg(pbi->dev,
637                 "pmic-battery: %s() - setting up battery charger successful\n",
638                         __func__);
639 }
640 
641 /*
642  * Description of power supplies
643  */
644 static const struct power_supply_desc pmic_usb_desc = {
645         .name           = "pmic-usb",
646         .type           = POWER_SUPPLY_TYPE_USB,
647         .properties     = pmic_usb_props,
648         .num_properties = ARRAY_SIZE(pmic_usb_props),
649         .get_property   = pmic_usb_get_property,
650 };
651 
652 static const struct power_supply_desc pmic_batt_desc = {
653         .name           = "pmic-batt",
654         .type           = POWER_SUPPLY_TYPE_BATTERY,
655         .properties     = pmic_battery_props,
656         .num_properties = ARRAY_SIZE(pmic_battery_props),
657         .get_property   = pmic_battery_get_property,
658 };
659 
660 /**
661  * pmic_battery_probe - pmic battery initialize
662  * @irq: pmic battery device irq
663  * @dev: pmic battery device structure
664  * Context: can sleep
665  *
666  * PMIC battery initializes its internal data structue and other
667  * infrastructure components for it to work as expected.
668  */
669 static int probe(int irq, struct device *dev)
670 {
671         int retval = 0;
672         struct pmic_power_module_info *pbi;
673         struct power_supply_config psy_cfg = {};
674 
675         dev_dbg(dev, "pmic-battery: found pmic battery device\n");
676 
677         pbi = kzalloc(sizeof(*pbi), GFP_KERNEL);
678         if (!pbi) {
679                 dev_err(dev, "%s(): memory allocation failed\n",
680                                                                 __func__);
681                 return -ENOMEM;
682         }
683 
684         pbi->dev = dev;
685         pbi->irq = irq;
686         dev_set_drvdata(dev, pbi);
687         psy_cfg.drv_data = pbi;
688 
689         /* initialize all required framework before enabling interrupts */
690         INIT_WORK(&pbi->handler, pmic_battery_handle_intrpt);
691         INIT_DELAYED_WORK(&pbi->monitor_battery, pmic_battery_monitor);
692         pbi->monitor_wqueue =
693                         create_singlethread_workqueue(dev_name(dev));
694         if (!pbi->monitor_wqueue) {
695                 dev_err(dev, "%s(): wqueue init failed\n", __func__);
696                 retval = -ESRCH;
697                 goto wqueue_failed;
698         }
699 
700         /* register interrupt */
701         retval = request_irq(pbi->irq, pmic_battery_interrupt_handler,
702                                                         0, DRIVER_NAME, pbi);
703         if (retval) {
704                 dev_err(dev, "%s(): cannot get IRQ\n", __func__);
705                 goto requestirq_failed;
706         }
707 
708         /* register pmic-batt with power supply subsystem */
709         pbi->batt = power_supply_register(dev, &pmic_usb_desc, &psy_cfg);
710         if (IS_ERR(pbi->batt)) {
711                 dev_err(dev,
712                         "%s(): failed to register pmic battery device with power supply subsystem\n",
713                                 __func__);
714                 retval = PTR_ERR(pbi->batt);
715                 goto power_reg_failed;
716         }
717 
718         dev_dbg(dev, "pmic-battery: %s() - pmic battery device "
719                 "registration with power supply subsystem successful\n",
720                 __func__);
721 
722         queue_delayed_work(pbi->monitor_wqueue, &pbi->monitor_battery, HZ * 1);
723 
724         /* register pmic-usb with power supply subsystem */
725         pbi->usb = power_supply_register(dev, &pmic_batt_desc, &psy_cfg);
726         if (IS_ERR(pbi->usb)) {
727                 dev_err(dev,
728                         "%s(): failed to register pmic usb device with power supply subsystem\n",
729                                 __func__);
730                 retval = PTR_ERR(pbi->usb);
731                 goto power_reg_failed_1;
732         }
733 
734         if (debug)
735                 printk(KERN_INFO "pmic-battery: %s() - pmic usb device "
736                         "registration with power supply subsystem successful\n",
737                         __func__);
738 
739         return retval;
740 
741 power_reg_failed_1:
742         power_supply_unregister(pbi->batt);
743 power_reg_failed:
744         cancel_delayed_work_sync(&pbi->monitor_battery);
745 requestirq_failed:
746         destroy_workqueue(pbi->monitor_wqueue);
747 wqueue_failed:
748         kfree(pbi);
749 
750         return retval;
751 }
752 
753 static int platform_pmic_battery_probe(struct platform_device *pdev)
754 {
755         return probe(pdev->id, &pdev->dev);
756 }
757 
758 /**
759  * pmic_battery_remove - pmic battery finalize
760  * @dev: pmic battery device structure
761  * Context: can sleep
762  *
763  * PMIC battery finalizes its internal data structue and other
764  * infrastructure components that it initialized in
765  * pmic_battery_probe.
766  */
767 
768 static int platform_pmic_battery_remove(struct platform_device *pdev)
769 {
770         struct pmic_power_module_info *pbi = platform_get_drvdata(pdev);
771 
772         free_irq(pbi->irq, pbi);
773         cancel_delayed_work_sync(&pbi->monitor_battery);
774         destroy_workqueue(pbi->monitor_wqueue);
775 
776         power_supply_unregister(pbi->usb);
777         power_supply_unregister(pbi->batt);
778 
779         cancel_work_sync(&pbi->handler);
780         kfree(pbi);
781         return 0;
782 }
783 
784 static struct platform_driver platform_pmic_battery_driver = {
785         .driver = {
786                 .name = DRIVER_NAME,
787         },
788         .probe = platform_pmic_battery_probe,
789         .remove = platform_pmic_battery_remove,
790 };
791 
792 module_platform_driver(platform_pmic_battery_driver);
793 
794 MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
795 MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
796 MODULE_LICENSE("GPL");
797 

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