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 45static int debug; 46module_param(debug, int, 0444); 47MODULE_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 */ 74enum batt_charge_type { 75 BATT_USBOTG_500MA_CHARGE, 76 BATT_USBOTG_TRICKLE_CHARGE, 77}; 78 79/* valid battery events */ 80enum 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 */ 96struct 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 118static unsigned int delay_time = 2000; /* in ms */ 119 120/* 121 * pmic ac properties 122 */ 123static 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 */ 131static 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 144struct 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 */ 170static 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 */ 185static 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 209static 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 */ 223static 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 */ 254static 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 */ 403static 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 427static 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 */ 443static 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 */ 484static 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 */ 503static 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 */ 539static 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 */ 558static 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 */ 652static 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 730power_reg_failed_1: 731 power_supply_unregister(&pbi->batt); 732power_reg_failed: 733 cancel_delayed_work_sync(&pbi->monitor_battery); 734requestirq_failed: 735 destroy_workqueue(pbi->monitor_wqueue); 736wqueue_failed: 737 kfree(pbi); 738 739 return retval; 740} 741 742static 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 757static 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 773static 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 782module_platform_driver(platform_pmic_battery_driver); 783 784MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>"); 785MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver"); 786MODULE_LICENSE("GPL"); 787