1 /* 2 * TI LP8788 MFD - battery charger driver 3 * 4 * Copyright 2012 Texas Instruments 5 * 6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com> 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 version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14 #include <linux/err.h> 15 #include <linux/iio/consumer.h> 16 #include <linux/interrupt.h> 17 #include <linux/irqdomain.h> 18 #include <linux/mfd/lp8788.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/power_supply.h> 22 #include <linux/slab.h> 23 #include <linux/workqueue.h> 24 25 /* register address */ 26 #define LP8788_CHG_STATUS 0x07 27 #define LP8788_CHG_IDCIN 0x13 28 #define LP8788_CHG_IBATT 0x14 29 #define LP8788_CHG_VTERM 0x15 30 #define LP8788_CHG_EOC 0x16 31 32 /* mask/shift bits */ 33 #define LP8788_CHG_INPUT_STATE_M 0x03 /* Addr 07h */ 34 #define LP8788_CHG_STATE_M 0x3C 35 #define LP8788_CHG_STATE_S 2 36 #define LP8788_NO_BATT_M BIT(6) 37 #define LP8788_BAD_BATT_M BIT(7) 38 #define LP8788_CHG_IBATT_M 0x1F /* Addr 14h */ 39 #define LP8788_CHG_VTERM_M 0x0F /* Addr 15h */ 40 #define LP8788_CHG_EOC_LEVEL_M 0x30 /* Addr 16h */ 41 #define LP8788_CHG_EOC_LEVEL_S 4 42 #define LP8788_CHG_EOC_TIME_M 0x0E 43 #define LP8788_CHG_EOC_TIME_S 1 44 #define LP8788_CHG_EOC_MODE_M BIT(0) 45 46 #define LP8788_CHARGER_NAME "charger" 47 #define LP8788_BATTERY_NAME "main_batt" 48 49 #define LP8788_CHG_START 0x11 50 #define LP8788_CHG_END 0x1C 51 52 #define LP8788_ISEL_MAX 23 53 #define LP8788_ISEL_STEP 50 54 #define LP8788_VTERM_MIN 4100 55 #define LP8788_VTERM_STEP 25 56 #define LP8788_MAX_BATT_CAPACITY 100 57 #define LP8788_MAX_CHG_IRQS 11 58 59 enum lp8788_charging_state { 60 LP8788_OFF, 61 LP8788_WARM_UP, 62 LP8788_LOW_INPUT = 0x3, 63 LP8788_PRECHARGE, 64 LP8788_CC, 65 LP8788_CV, 66 LP8788_MAINTENANCE, 67 LP8788_BATTERY_FAULT, 68 LP8788_SYSTEM_SUPPORT = 0xC, 69 LP8788_HIGH_CURRENT = 0xF, 70 LP8788_MAX_CHG_STATE, 71 }; 72 73 enum lp8788_charger_adc_sel { 74 LP8788_VBATT, 75 LP8788_BATT_TEMP, 76 LP8788_NUM_CHG_ADC, 77 }; 78 79 enum lp8788_charger_input_state { 80 LP8788_SYSTEM_SUPPLY = 1, 81 LP8788_FULL_FUNCTION, 82 }; 83 84 /* 85 * struct lp8788_chg_irq 86 * @which : lp8788 interrupt id 87 * @virq : Linux IRQ number from irq_domain 88 */ 89 struct lp8788_chg_irq { 90 enum lp8788_int_id which; 91 int virq; 92 }; 93 94 /* 95 * struct lp8788_charger 96 * @lp : used for accessing the registers of mfd lp8788 device 97 * @charger : power supply driver for the battery charger 98 * @battery : power supply driver for the battery 99 * @charger_work : work queue for charger input interrupts 100 * @chan : iio channels for getting adc values 101 * eg) battery voltage, capacity and temperature 102 * @irqs : charger dedicated interrupts 103 * @num_irqs : total numbers of charger interrupts 104 * @pdata : charger platform specific data 105 */ 106 struct lp8788_charger { 107 struct lp8788 *lp; 108 struct power_supply *charger; 109 struct power_supply *battery; 110 struct work_struct charger_work; 111 struct iio_channel *chan[LP8788_NUM_CHG_ADC]; 112 struct lp8788_chg_irq irqs[LP8788_MAX_CHG_IRQS]; 113 int num_irqs; 114 struct lp8788_charger_platform_data *pdata; 115 }; 116 117 static char *battery_supplied_to[] = { 118 LP8788_BATTERY_NAME, 119 }; 120 121 static enum power_supply_property lp8788_charger_prop[] = { 122 POWER_SUPPLY_PROP_ONLINE, 123 POWER_SUPPLY_PROP_CURRENT_MAX, 124 }; 125 126 static enum power_supply_property lp8788_battery_prop[] = { 127 POWER_SUPPLY_PROP_STATUS, 128 POWER_SUPPLY_PROP_HEALTH, 129 POWER_SUPPLY_PROP_PRESENT, 130 POWER_SUPPLY_PROP_VOLTAGE_NOW, 131 POWER_SUPPLY_PROP_CAPACITY, 132 POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT, 133 POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX, 134 POWER_SUPPLY_PROP_TEMP, 135 }; 136 137 static bool lp8788_is_charger_detected(struct lp8788_charger *pchg) 138 { 139 u8 data; 140 141 lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); 142 data &= LP8788_CHG_INPUT_STATE_M; 143 144 return data == LP8788_SYSTEM_SUPPLY || data == LP8788_FULL_FUNCTION; 145 } 146 147 static int lp8788_charger_get_property(struct power_supply *psy, 148 enum power_supply_property psp, 149 union power_supply_propval *val) 150 { 151 struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent); 152 u8 read; 153 154 switch (psp) { 155 case POWER_SUPPLY_PROP_ONLINE: 156 val->intval = lp8788_is_charger_detected(pchg); 157 break; 158 case POWER_SUPPLY_PROP_CURRENT_MAX: 159 lp8788_read_byte(pchg->lp, LP8788_CHG_IDCIN, &read); 160 val->intval = LP8788_ISEL_STEP * 161 (min_t(int, read, LP8788_ISEL_MAX) + 1); 162 break; 163 default: 164 return -EINVAL; 165 } 166 167 return 0; 168 } 169 170 static int lp8788_get_battery_status(struct lp8788_charger *pchg, 171 union power_supply_propval *val) 172 { 173 enum lp8788_charging_state state; 174 u8 data; 175 int ret; 176 177 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); 178 if (ret) 179 return ret; 180 181 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; 182 switch (state) { 183 case LP8788_OFF: 184 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 185 break; 186 case LP8788_PRECHARGE: 187 case LP8788_CC: 188 case LP8788_CV: 189 case LP8788_HIGH_CURRENT: 190 val->intval = POWER_SUPPLY_STATUS_CHARGING; 191 break; 192 case LP8788_MAINTENANCE: 193 val->intval = POWER_SUPPLY_STATUS_FULL; 194 break; 195 default: 196 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 197 break; 198 } 199 200 return 0; 201 } 202 203 static int lp8788_get_battery_health(struct lp8788_charger *pchg, 204 union power_supply_propval *val) 205 { 206 u8 data; 207 int ret; 208 209 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); 210 if (ret) 211 return ret; 212 213 if (data & LP8788_NO_BATT_M) 214 val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; 215 else if (data & LP8788_BAD_BATT_M) 216 val->intval = POWER_SUPPLY_HEALTH_DEAD; 217 else 218 val->intval = POWER_SUPPLY_HEALTH_GOOD; 219 220 return 0; 221 } 222 223 static int lp8788_get_battery_present(struct lp8788_charger *pchg, 224 union power_supply_propval *val) 225 { 226 u8 data; 227 int ret; 228 229 ret = lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); 230 if (ret) 231 return ret; 232 233 val->intval = !(data & LP8788_NO_BATT_M); 234 return 0; 235 } 236 237 static int lp8788_get_vbatt_adc(struct lp8788_charger *pchg, int *result) 238 { 239 struct iio_channel *channel = pchg->chan[LP8788_VBATT]; 240 241 if (!channel) 242 return -EINVAL; 243 244 return iio_read_channel_processed(channel, result); 245 } 246 247 static int lp8788_get_battery_voltage(struct lp8788_charger *pchg, 248 union power_supply_propval *val) 249 { 250 return lp8788_get_vbatt_adc(pchg, &val->intval); 251 } 252 253 static int lp8788_get_battery_capacity(struct lp8788_charger *pchg, 254 union power_supply_propval *val) 255 { 256 struct lp8788 *lp = pchg->lp; 257 struct lp8788_charger_platform_data *pdata = pchg->pdata; 258 unsigned int max_vbatt; 259 int vbatt; 260 enum lp8788_charging_state state; 261 u8 data; 262 int ret; 263 264 if (!pdata) 265 return -EINVAL; 266 267 max_vbatt = pdata->max_vbatt_mv; 268 if (max_vbatt == 0) 269 return -EINVAL; 270 271 ret = lp8788_read_byte(lp, LP8788_CHG_STATUS, &data); 272 if (ret) 273 return ret; 274 275 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; 276 277 if (state == LP8788_MAINTENANCE) { 278 val->intval = LP8788_MAX_BATT_CAPACITY; 279 } else { 280 ret = lp8788_get_vbatt_adc(pchg, &vbatt); 281 if (ret) 282 return ret; 283 284 val->intval = (vbatt * LP8788_MAX_BATT_CAPACITY) / max_vbatt; 285 val->intval = min(val->intval, LP8788_MAX_BATT_CAPACITY); 286 } 287 288 return 0; 289 } 290 291 static int lp8788_get_battery_temperature(struct lp8788_charger *pchg, 292 union power_supply_propval *val) 293 { 294 struct iio_channel *channel = pchg->chan[LP8788_BATT_TEMP]; 295 int result; 296 int ret; 297 298 if (!channel) 299 return -EINVAL; 300 301 ret = iio_read_channel_processed(channel, &result); 302 if (ret < 0) 303 return -EINVAL; 304 305 /* unit: 0.1 'C */ 306 val->intval = result * 10; 307 308 return 0; 309 } 310 311 static int lp8788_get_battery_charging_current(struct lp8788_charger *pchg, 312 union power_supply_propval *val) 313 { 314 u8 read; 315 316 lp8788_read_byte(pchg->lp, LP8788_CHG_IBATT, &read); 317 read &= LP8788_CHG_IBATT_M; 318 val->intval = LP8788_ISEL_STEP * 319 (min_t(int, read, LP8788_ISEL_MAX) + 1); 320 321 return 0; 322 } 323 324 static int lp8788_get_charging_termination_voltage(struct lp8788_charger *pchg, 325 union power_supply_propval *val) 326 { 327 u8 read; 328 329 lp8788_read_byte(pchg->lp, LP8788_CHG_VTERM, &read); 330 read &= LP8788_CHG_VTERM_M; 331 val->intval = LP8788_VTERM_MIN + LP8788_VTERM_STEP * read; 332 333 return 0; 334 } 335 336 static int lp8788_battery_get_property(struct power_supply *psy, 337 enum power_supply_property psp, 338 union power_supply_propval *val) 339 { 340 struct lp8788_charger *pchg = dev_get_drvdata(psy->dev.parent); 341 342 switch (psp) { 343 case POWER_SUPPLY_PROP_STATUS: 344 return lp8788_get_battery_status(pchg, val); 345 case POWER_SUPPLY_PROP_HEALTH: 346 return lp8788_get_battery_health(pchg, val); 347 case POWER_SUPPLY_PROP_PRESENT: 348 return lp8788_get_battery_present(pchg, val); 349 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 350 return lp8788_get_battery_voltage(pchg, val); 351 case POWER_SUPPLY_PROP_CAPACITY: 352 return lp8788_get_battery_capacity(pchg, val); 353 case POWER_SUPPLY_PROP_TEMP: 354 return lp8788_get_battery_temperature(pchg, val); 355 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT: 356 return lp8788_get_battery_charging_current(pchg, val); 357 case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX: 358 return lp8788_get_charging_termination_voltage(pchg, val); 359 default: 360 return -EINVAL; 361 } 362 } 363 364 static inline bool lp8788_is_valid_charger_register(u8 addr) 365 { 366 return addr >= LP8788_CHG_START && addr <= LP8788_CHG_END; 367 } 368 369 static int lp8788_update_charger_params(struct platform_device *pdev, 370 struct lp8788_charger *pchg) 371 { 372 struct lp8788 *lp = pchg->lp; 373 struct lp8788_charger_platform_data *pdata = pchg->pdata; 374 struct lp8788_chg_param *param; 375 int i; 376 int ret; 377 378 if (!pdata || !pdata->chg_params) { 379 dev_info(&pdev->dev, "skip updating charger parameters\n"); 380 return 0; 381 } 382 383 /* settting charging parameters */ 384 for (i = 0; i < pdata->num_chg_params; i++) { 385 param = pdata->chg_params + i; 386 387 if (lp8788_is_valid_charger_register(param->addr)) { 388 ret = lp8788_write_byte(lp, param->addr, param->val); 389 if (ret) 390 return ret; 391 } 392 } 393 394 return 0; 395 } 396 397 static const struct power_supply_desc lp8788_psy_charger_desc = { 398 .name = LP8788_CHARGER_NAME, 399 .type = POWER_SUPPLY_TYPE_MAINS, 400 .properties = lp8788_charger_prop, 401 .num_properties = ARRAY_SIZE(lp8788_charger_prop), 402 .get_property = lp8788_charger_get_property, 403 }; 404 405 static const struct power_supply_desc lp8788_psy_battery_desc = { 406 .name = LP8788_BATTERY_NAME, 407 .type = POWER_SUPPLY_TYPE_BATTERY, 408 .properties = lp8788_battery_prop, 409 .num_properties = ARRAY_SIZE(lp8788_battery_prop), 410 .get_property = lp8788_battery_get_property, 411 }; 412 413 static int lp8788_psy_register(struct platform_device *pdev, 414 struct lp8788_charger *pchg) 415 { 416 struct power_supply_config charger_cfg = {}; 417 418 charger_cfg.supplied_to = battery_supplied_to; 419 charger_cfg.num_supplicants = ARRAY_SIZE(battery_supplied_to); 420 421 pchg->charger = power_supply_register(&pdev->dev, 422 &lp8788_psy_charger_desc, 423 &charger_cfg); 424 if (IS_ERR(pchg->charger)) 425 return -EPERM; 426 427 pchg->battery = power_supply_register(&pdev->dev, 428 &lp8788_psy_battery_desc, NULL); 429 if (IS_ERR(pchg->battery)) { 430 power_supply_unregister(pchg->charger); 431 return -EPERM; 432 } 433 434 return 0; 435 } 436 437 static void lp8788_psy_unregister(struct lp8788_charger *pchg) 438 { 439 power_supply_unregister(pchg->battery); 440 power_supply_unregister(pchg->charger); 441 } 442 443 static void lp8788_charger_event(struct work_struct *work) 444 { 445 struct lp8788_charger *pchg = 446 container_of(work, struct lp8788_charger, charger_work); 447 struct lp8788_charger_platform_data *pdata = pchg->pdata; 448 enum lp8788_charger_event event = lp8788_is_charger_detected(pchg); 449 450 pdata->charger_event(pchg->lp, event); 451 } 452 453 static bool lp8788_find_irq_id(struct lp8788_charger *pchg, int virq, int *id) 454 { 455 bool found = false; 456 int i; 457 458 for (i = 0; i < pchg->num_irqs; i++) { 459 if (pchg->irqs[i].virq == virq) { 460 *id = pchg->irqs[i].which; 461 found = true; 462 break; 463 } 464 } 465 466 return found; 467 } 468 469 static irqreturn_t lp8788_charger_irq_thread(int virq, void *ptr) 470 { 471 struct lp8788_charger *pchg = ptr; 472 struct lp8788_charger_platform_data *pdata = pchg->pdata; 473 int id = -1; 474 475 if (!lp8788_find_irq_id(pchg, virq, &id)) 476 return IRQ_NONE; 477 478 switch (id) { 479 case LP8788_INT_CHG_INPUT_STATE: 480 case LP8788_INT_CHG_STATE: 481 case LP8788_INT_EOC: 482 case LP8788_INT_BATT_LOW: 483 case LP8788_INT_NO_BATT: 484 power_supply_changed(pchg->charger); 485 power_supply_changed(pchg->battery); 486 break; 487 default: 488 break; 489 } 490 491 /* report charger dectection event if used */ 492 if (!pdata) 493 goto irq_handled; 494 495 if (pdata->charger_event && id == LP8788_INT_CHG_INPUT_STATE) 496 schedule_work(&pchg->charger_work); 497 498 irq_handled: 499 return IRQ_HANDLED; 500 } 501 502 static int lp8788_set_irqs(struct platform_device *pdev, 503 struct lp8788_charger *pchg, const char *name) 504 { 505 struct resource *r; 506 struct irq_domain *irqdm = pchg->lp->irqdm; 507 int irq_start; 508 int irq_end; 509 int virq; 510 int nr_irq; 511 int i; 512 int ret; 513 514 /* no error even if no irq resource */ 515 r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, name); 516 if (!r) 517 return 0; 518 519 irq_start = r->start; 520 irq_end = r->end; 521 522 for (i = irq_start; i <= irq_end; i++) { 523 nr_irq = pchg->num_irqs; 524 525 virq = irq_create_mapping(irqdm, i); 526 pchg->irqs[nr_irq].virq = virq; 527 pchg->irqs[nr_irq].which = i; 528 pchg->num_irqs++; 529 530 ret = request_threaded_irq(virq, NULL, 531 lp8788_charger_irq_thread, 532 0, name, pchg); 533 if (ret) 534 break; 535 } 536 537 if (i <= irq_end) 538 goto err_free_irq; 539 540 return 0; 541 542 err_free_irq: 543 for (i = 0; i < pchg->num_irqs; i++) 544 free_irq(pchg->irqs[i].virq, pchg); 545 return ret; 546 } 547 548 static int lp8788_irq_register(struct platform_device *pdev, 549 struct lp8788_charger *pchg) 550 { 551 const char *name[] = { 552 LP8788_CHG_IRQ, LP8788_PRSW_IRQ, LP8788_BATT_IRQ 553 }; 554 int i; 555 int ret; 556 557 INIT_WORK(&pchg->charger_work, lp8788_charger_event); 558 pchg->num_irqs = 0; 559 560 for (i = 0; i < ARRAY_SIZE(name); i++) { 561 ret = lp8788_set_irqs(pdev, pchg, name[i]); 562 if (ret) { 563 dev_warn(&pdev->dev, "irq setup failed: %s\n", name[i]); 564 return ret; 565 } 566 } 567 568 if (pchg->num_irqs > LP8788_MAX_CHG_IRQS) { 569 dev_err(&pdev->dev, "invalid total number of irqs: %d\n", 570 pchg->num_irqs); 571 return -EINVAL; 572 } 573 574 575 return 0; 576 } 577 578 static void lp8788_irq_unregister(struct platform_device *pdev, 579 struct lp8788_charger *pchg) 580 { 581 int i; 582 int irq; 583 584 for (i = 0; i < pchg->num_irqs; i++) { 585 irq = pchg->irqs[i].virq; 586 if (!irq) 587 continue; 588 589 free_irq(irq, pchg); 590 } 591 } 592 593 static void lp8788_setup_adc_channel(struct device *dev, 594 struct lp8788_charger *pchg) 595 { 596 struct lp8788_charger_platform_data *pdata = pchg->pdata; 597 struct iio_channel *chan; 598 599 if (!pdata) 600 return; 601 602 /* ADC channel for battery voltage */ 603 chan = iio_channel_get(dev, pdata->adc_vbatt); 604 pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan; 605 606 /* ADC channel for battery temperature */ 607 chan = iio_channel_get(dev, pdata->adc_batt_temp); 608 pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan; 609 } 610 611 static void lp8788_release_adc_channel(struct lp8788_charger *pchg) 612 { 613 int i; 614 615 for (i = 0; i < LP8788_NUM_CHG_ADC; i++) { 616 if (!pchg->chan[i]) 617 continue; 618 619 iio_channel_release(pchg->chan[i]); 620 pchg->chan[i] = NULL; 621 } 622 } 623 624 static ssize_t lp8788_show_charger_status(struct device *dev, 625 struct device_attribute *attr, char *buf) 626 { 627 struct lp8788_charger *pchg = dev_get_drvdata(dev); 628 enum lp8788_charging_state state; 629 static const char * const desc[LP8788_MAX_CHG_STATE] = { 630 [LP8788_OFF] = "CHARGER OFF", 631 [LP8788_WARM_UP] = "WARM UP", 632 [LP8788_LOW_INPUT] = "LOW INPUT STATE", 633 [LP8788_PRECHARGE] = "CHARGING - PRECHARGE", 634 [LP8788_CC] = "CHARGING - CC", 635 [LP8788_CV] = "CHARGING - CV", 636 [LP8788_MAINTENANCE] = "NO CHARGING - MAINTENANCE", 637 [LP8788_BATTERY_FAULT] = "BATTERY FAULT", 638 [LP8788_SYSTEM_SUPPORT] = "SYSTEM SUPPORT", 639 [LP8788_HIGH_CURRENT] = "HIGH CURRENT", 640 }; 641 u8 data; 642 643 lp8788_read_byte(pchg->lp, LP8788_CHG_STATUS, &data); 644 state = (data & LP8788_CHG_STATE_M) >> LP8788_CHG_STATE_S; 645 646 return scnprintf(buf, PAGE_SIZE, "%s\n", desc[state]); 647 } 648 649 static ssize_t lp8788_show_eoc_time(struct device *dev, 650 struct device_attribute *attr, char *buf) 651 { 652 struct lp8788_charger *pchg = dev_get_drvdata(dev); 653 static const char * const stime[] = { 654 "400ms", "5min", "10min", "15min", 655 "20min", "25min", "30min", "No timeout" 656 }; 657 u8 val; 658 659 lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); 660 val = (val & LP8788_CHG_EOC_TIME_M) >> LP8788_CHG_EOC_TIME_S; 661 662 return scnprintf(buf, PAGE_SIZE, "End Of Charge Time: %s\n", 663 stime[val]); 664 } 665 666 static ssize_t lp8788_show_eoc_level(struct device *dev, 667 struct device_attribute *attr, char *buf) 668 { 669 struct lp8788_charger *pchg = dev_get_drvdata(dev); 670 static const char * const abs_level[] = { 671 "25mA", "49mA", "75mA", "98mA" 672 }; 673 static const char * const relative_level[] = { 674 "5%", "10%", "15%", "20%" 675 }; 676 const char *level; 677 u8 val; 678 u8 mode; 679 680 lp8788_read_byte(pchg->lp, LP8788_CHG_EOC, &val); 681 682 mode = val & LP8788_CHG_EOC_MODE_M; 683 val = (val & LP8788_CHG_EOC_LEVEL_M) >> LP8788_CHG_EOC_LEVEL_S; 684 level = mode ? abs_level[val] : relative_level[val]; 685 686 return scnprintf(buf, PAGE_SIZE, "End Of Charge Level: %s\n", level); 687 } 688 689 static DEVICE_ATTR(charger_status, S_IRUSR, lp8788_show_charger_status, NULL); 690 static DEVICE_ATTR(eoc_time, S_IRUSR, lp8788_show_eoc_time, NULL); 691 static DEVICE_ATTR(eoc_level, S_IRUSR, lp8788_show_eoc_level, NULL); 692 693 static struct attribute *lp8788_charger_attr[] = { 694 &dev_attr_charger_status.attr, 695 &dev_attr_eoc_time.attr, 696 &dev_attr_eoc_level.attr, 697 NULL, 698 }; 699 700 static const struct attribute_group lp8788_attr_group = { 701 .attrs = lp8788_charger_attr, 702 }; 703 704 static int lp8788_charger_probe(struct platform_device *pdev) 705 { 706 struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent); 707 struct lp8788_charger *pchg; 708 struct device *dev = &pdev->dev; 709 int ret; 710 711 pchg = devm_kzalloc(dev, sizeof(struct lp8788_charger), GFP_KERNEL); 712 if (!pchg) 713 return -ENOMEM; 714 715 pchg->lp = lp; 716 pchg->pdata = lp->pdata ? lp->pdata->chg_pdata : NULL; 717 platform_set_drvdata(pdev, pchg); 718 719 ret = lp8788_update_charger_params(pdev, pchg); 720 if (ret) 721 return ret; 722 723 lp8788_setup_adc_channel(&pdev->dev, pchg); 724 725 ret = lp8788_psy_register(pdev, pchg); 726 if (ret) 727 return ret; 728 729 ret = sysfs_create_group(&pdev->dev.kobj, &lp8788_attr_group); 730 if (ret) { 731 lp8788_psy_unregister(pchg); 732 return ret; 733 } 734 735 ret = lp8788_irq_register(pdev, pchg); 736 if (ret) 737 dev_warn(dev, "failed to register charger irq: %d\n", ret); 738 739 return 0; 740 } 741 742 static int lp8788_charger_remove(struct platform_device *pdev) 743 { 744 struct lp8788_charger *pchg = platform_get_drvdata(pdev); 745 746 flush_work(&pchg->charger_work); 747 lp8788_irq_unregister(pdev, pchg); 748 sysfs_remove_group(&pdev->dev.kobj, &lp8788_attr_group); 749 lp8788_psy_unregister(pchg); 750 lp8788_release_adc_channel(pchg); 751 752 return 0; 753 } 754 755 static struct platform_driver lp8788_charger_driver = { 756 .probe = lp8788_charger_probe, 757 .remove = lp8788_charger_remove, 758 .driver = { 759 .name = LP8788_DEV_CHARGER, 760 }, 761 }; 762 module_platform_driver(lp8788_charger_driver); 763 764 MODULE_DESCRIPTION("TI LP8788 Charger Driver"); 765 MODULE_AUTHOR("Milo Kim"); 766 MODULE_LICENSE("GPL"); 767 MODULE_ALIAS("platform:lp8788-charger"); 768