1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) ST-Ericsson SA 2012 4 * 5 * Battery temperature driver for AB8500 6 * 7 * Author: 8 * Johan Palsson <johan.palsson@stericsson.com> 9 * Karl Komierowski <karl.komierowski@stericsson.com> 10 * Arun R Murthy <arun.murthy@stericsson.com> 11 */ 12 13 #include <linux/init.h> 14 #include <linux/module.h> 15 #include <linux/device.h> 16 #include <linux/component.h> 17 #include <linux/interrupt.h> 18 #include <linux/delay.h> 19 #include <linux/slab.h> 20 #include <linux/platform_device.h> 21 #include <linux/power_supply.h> 22 #include <linux/completion.h> 23 #include <linux/workqueue.h> 24 #include <linux/jiffies.h> 25 #include <linux/of.h> 26 #include <linux/mfd/core.h> 27 #include <linux/mfd/abx500.h> 28 #include <linux/mfd/abx500/ab8500.h> 29 #include <linux/thermal.h> 30 #include <linux/iio/consumer.h> 31 #include <linux/fixp-arith.h> 32 33 #include "ab8500-bm.h" 34 35 #define BTEMP_THERMAL_LOW_LIMIT -10 36 #define BTEMP_THERMAL_MED_LIMIT 0 37 #define BTEMP_THERMAL_HIGH_LIMIT_52 52 38 #define BTEMP_THERMAL_HIGH_LIMIT_57 57 39 #define BTEMP_THERMAL_HIGH_LIMIT_62 62 40 41 #define BTEMP_BATCTRL_CURR_SRC_7UA 7 42 #define BTEMP_BATCTRL_CURR_SRC_20UA 20 43 44 #define BTEMP_BATCTRL_CURR_SRC_16UA 16 45 #define BTEMP_BATCTRL_CURR_SRC_18UA 18 46 47 #define BTEMP_BATCTRL_CURR_SRC_60UA 60 48 #define BTEMP_BATCTRL_CURR_SRC_120UA 120 49 50 /** 51 * struct ab8500_btemp_interrupts - ab8500 interrupts 52 * @name: name of the interrupt 53 * @isr function pointer to the isr 54 */ 55 struct ab8500_btemp_interrupts { 56 char *name; 57 irqreturn_t (*isr)(int irq, void *data); 58 }; 59 60 struct ab8500_btemp_events { 61 bool batt_rem; 62 bool btemp_high; 63 bool btemp_medhigh; 64 bool btemp_lowmed; 65 bool btemp_low; 66 bool ac_conn; 67 bool usb_conn; 68 }; 69 70 struct ab8500_btemp_ranges { 71 int btemp_high_limit; 72 int btemp_med_limit; 73 int btemp_low_limit; 74 }; 75 76 /** 77 * struct ab8500_btemp - ab8500 BTEMP device information 78 * @dev: Pointer to the structure device 79 * @node: List of AB8500 BTEMPs, hence prepared for reentrance 80 * @curr_source: What current source we use, in uA 81 * @bat_temp: Dispatched battery temperature in degree Celsius 82 * @prev_bat_temp Last measured battery temperature in degree Celsius 83 * @parent: Pointer to the struct ab8500 84 * @tz: Thermal zone for the battery 85 * @adc_bat_ctrl: ADC channel for the battery control 86 * @fg: Pointer to the struct fg 87 * @bm: Platform specific battery management information 88 * @btemp_psy: Structure for BTEMP specific battery properties 89 * @events: Structure for information about events triggered 90 * @btemp_ranges: Battery temperature range structure 91 * @btemp_wq: Work queue for measuring the temperature periodically 92 * @btemp_periodic_work: Work for measuring the temperature periodically 93 * @initialized: True if battery id read. 94 */ 95 struct ab8500_btemp { 96 struct device *dev; 97 struct list_head node; 98 int curr_source; 99 int bat_temp; 100 int prev_bat_temp; 101 struct ab8500 *parent; 102 struct thermal_zone_device *tz; 103 struct iio_channel *bat_ctrl; 104 struct ab8500_fg *fg; 105 struct ab8500_bm_data *bm; 106 struct power_supply *btemp_psy; 107 struct ab8500_btemp_events events; 108 struct ab8500_btemp_ranges btemp_ranges; 109 struct workqueue_struct *btemp_wq; 110 struct delayed_work btemp_periodic_work; 111 bool initialized; 112 }; 113 114 /* BTEMP power supply properties */ 115 static enum power_supply_property ab8500_btemp_props[] = { 116 POWER_SUPPLY_PROP_PRESENT, 117 POWER_SUPPLY_PROP_ONLINE, 118 POWER_SUPPLY_PROP_TECHNOLOGY, 119 POWER_SUPPLY_PROP_TEMP, 120 }; 121 122 static LIST_HEAD(ab8500_btemp_list); 123 124 /** 125 * ab8500_btemp_batctrl_volt_to_res() - convert batctrl voltage to resistance 126 * @di: pointer to the ab8500_btemp structure 127 * @v_batctrl: measured batctrl voltage 128 * @inst_curr: measured instant current 129 * 130 * This function returns the battery resistance that is 131 * derived from the BATCTRL voltage. 132 * Returns value in Ohms. 133 */ 134 static int ab8500_btemp_batctrl_volt_to_res(struct ab8500_btemp *di, 135 int v_batctrl, int inst_curr) 136 { 137 if (is_ab8500_1p1_or_earlier(di->parent)) { 138 /* 139 * For ABB cut1.0 and 1.1 BAT_CTRL is internally 140 * connected to 1.8V through a 450k resistor 141 */ 142 return (450000 * (v_batctrl)) / (1800 - v_batctrl); 143 } 144 145 /* 146 * BAT_CTRL is internally 147 * connected to 1.8V through a 80k resistor 148 */ 149 return (80000 * (v_batctrl)) / (1800 - v_batctrl); 150 } 151 152 /** 153 * ab8500_btemp_read_batctrl_voltage() - measure batctrl voltage 154 * @di: pointer to the ab8500_btemp structure 155 * 156 * This function returns the voltage on BATCTRL. Returns value in mV. 157 */ 158 static int ab8500_btemp_read_batctrl_voltage(struct ab8500_btemp *di) 159 { 160 int vbtemp, ret; 161 static int prev; 162 163 ret = iio_read_channel_processed(di->bat_ctrl, &vbtemp); 164 if (ret < 0) { 165 dev_err(di->dev, 166 "%s ADC conversion failed, using previous value", 167 __func__); 168 return prev; 169 } 170 prev = vbtemp; 171 return vbtemp; 172 } 173 174 /** 175 * ab8500_btemp_get_batctrl_res() - get battery resistance 176 * @di: pointer to the ab8500_btemp structure 177 * 178 * This function returns the battery pack identification resistance. 179 * Returns value in Ohms. 180 */ 181 static int ab8500_btemp_get_batctrl_res(struct ab8500_btemp *di) 182 { 183 int ret; 184 int batctrl = 0; 185 int res; 186 int inst_curr; 187 int i; 188 189 if (!di->fg) 190 di->fg = ab8500_fg_get(); 191 if (!di->fg) { 192 dev_err(di->dev, "No fg found\n"); 193 return -EINVAL; 194 } 195 196 ret = ab8500_fg_inst_curr_start(di->fg); 197 198 if (ret) { 199 dev_err(di->dev, "Failed to start current measurement\n"); 200 return ret; 201 } 202 203 do { 204 msleep(20); 205 } while (!ab8500_fg_inst_curr_started(di->fg)); 206 207 i = 0; 208 209 do { 210 batctrl += ab8500_btemp_read_batctrl_voltage(di); 211 i++; 212 msleep(20); 213 } while (!ab8500_fg_inst_curr_done(di->fg)); 214 batctrl /= i; 215 216 ret = ab8500_fg_inst_curr_finalize(di->fg, &inst_curr); 217 if (ret) { 218 dev_err(di->dev, "Failed to finalize current measurement\n"); 219 return ret; 220 } 221 222 res = ab8500_btemp_batctrl_volt_to_res(di, batctrl, inst_curr); 223 224 dev_dbg(di->dev, "%s batctrl: %d res: %d inst_curr: %d samples: %d\n", 225 __func__, batctrl, res, inst_curr, i); 226 227 return res; 228 } 229 230 /** 231 * ab8500_btemp_id() - Identify the connected battery 232 * @di: pointer to the ab8500_btemp structure 233 * 234 * This function will try to identify the battery by reading the ID 235 * resistor. Some brands use a combined ID resistor with a NTC resistor to 236 * both be able to identify and to read the temperature of it. 237 */ 238 static int ab8500_btemp_id(struct ab8500_btemp *di) 239 { 240 struct power_supply_battery_info *bi = di->bm->bi; 241 int res; 242 243 di->curr_source = BTEMP_BATCTRL_CURR_SRC_7UA; 244 245 res = ab8500_btemp_get_batctrl_res(di); 246 if (res < 0) { 247 dev_err(di->dev, "%s get batctrl res failed\n", __func__); 248 return -ENXIO; 249 } 250 251 if (power_supply_battery_bti_in_range(bi, res)) { 252 dev_info(di->dev, "Battery detected on BATCTRL (pin C3)" 253 " resistance %d Ohm = %d Ohm +/- %d%%\n", 254 res, bi->bti_resistance_ohm, 255 bi->bti_resistance_tolerance); 256 } else { 257 dev_warn(di->dev, "Battery identified as unknown" 258 ", resistance %d Ohm\n", res); 259 return -ENXIO; 260 } 261 262 return 0; 263 } 264 265 /** 266 * ab8500_btemp_periodic_work() - Measuring the temperature periodically 267 * @work: pointer to the work_struct structure 268 * 269 * Work function for measuring the temperature periodically 270 */ 271 static void ab8500_btemp_periodic_work(struct work_struct *work) 272 { 273 int interval; 274 int bat_temp; 275 struct ab8500_btemp *di = container_of(work, 276 struct ab8500_btemp, btemp_periodic_work.work); 277 /* Assume 25 degrees celsius as start temperature */ 278 static int prev = 25; 279 int ret; 280 281 if (!di->initialized) { 282 /* Identify the battery */ 283 if (ab8500_btemp_id(di) < 0) 284 dev_warn(di->dev, "failed to identify the battery\n"); 285 } 286 287 /* Failover if a reading is erroneous, use last meausurement */ 288 ret = thermal_zone_get_temp(di->tz, &bat_temp); 289 if (ret) { 290 dev_err(di->dev, "error reading temperature\n"); 291 bat_temp = prev; 292 } else { 293 /* Convert from millicentigrades to centigrades */ 294 bat_temp /= 1000; 295 prev = bat_temp; 296 } 297 298 /* 299 * Filter battery temperature. 300 * Allow direct updates on temperature only if two samples result in 301 * same temperature. Else only allow 1 degree change from previous 302 * reported value in the direction of the new measurement. 303 */ 304 if ((bat_temp == di->prev_bat_temp) || !di->initialized) { 305 if ((di->bat_temp != di->prev_bat_temp) || !di->initialized) { 306 di->initialized = true; 307 di->bat_temp = bat_temp; 308 power_supply_changed(di->btemp_psy); 309 } 310 } else if (bat_temp < di->prev_bat_temp) { 311 di->bat_temp--; 312 power_supply_changed(di->btemp_psy); 313 } else if (bat_temp > di->prev_bat_temp) { 314 di->bat_temp++; 315 power_supply_changed(di->btemp_psy); 316 } 317 di->prev_bat_temp = bat_temp; 318 319 if (di->events.ac_conn || di->events.usb_conn) 320 interval = di->bm->temp_interval_chg; 321 else 322 interval = di->bm->temp_interval_nochg; 323 324 /* Schedule a new measurement */ 325 queue_delayed_work(di->btemp_wq, 326 &di->btemp_periodic_work, 327 round_jiffies(interval * HZ)); 328 } 329 330 /** 331 * ab8500_btemp_batctrlindb_handler() - battery removal detected 332 * @irq: interrupt number 333 * @_di: void pointer that has to address of ab8500_btemp 334 * 335 * Returns IRQ status(IRQ_HANDLED) 336 */ 337 static irqreturn_t ab8500_btemp_batctrlindb_handler(int irq, void *_di) 338 { 339 struct ab8500_btemp *di = _di; 340 dev_err(di->dev, "Battery removal detected!\n"); 341 342 di->events.batt_rem = true; 343 power_supply_changed(di->btemp_psy); 344 345 return IRQ_HANDLED; 346 } 347 348 /** 349 * ab8500_btemp_templow_handler() - battery temp lower than 10 degrees 350 * @irq: interrupt number 351 * @_di: void pointer that has to address of ab8500_btemp 352 * 353 * Returns IRQ status(IRQ_HANDLED) 354 */ 355 static irqreturn_t ab8500_btemp_templow_handler(int irq, void *_di) 356 { 357 struct ab8500_btemp *di = _di; 358 359 if (is_ab8500_3p3_or_earlier(di->parent)) { 360 dev_dbg(di->dev, "Ignore false btemp low irq" 361 " for ABB cut 1.0, 1.1, 2.0 and 3.3\n"); 362 } else { 363 dev_crit(di->dev, "Battery temperature lower than -10deg c\n"); 364 365 di->events.btemp_low = true; 366 di->events.btemp_high = false; 367 di->events.btemp_medhigh = false; 368 di->events.btemp_lowmed = false; 369 power_supply_changed(di->btemp_psy); 370 } 371 372 return IRQ_HANDLED; 373 } 374 375 /** 376 * ab8500_btemp_temphigh_handler() - battery temp higher than max temp 377 * @irq: interrupt number 378 * @_di: void pointer that has to address of ab8500_btemp 379 * 380 * Returns IRQ status(IRQ_HANDLED) 381 */ 382 static irqreturn_t ab8500_btemp_temphigh_handler(int irq, void *_di) 383 { 384 struct ab8500_btemp *di = _di; 385 386 dev_crit(di->dev, "Battery temperature is higher than MAX temp\n"); 387 388 di->events.btemp_high = true; 389 di->events.btemp_medhigh = false; 390 di->events.btemp_lowmed = false; 391 di->events.btemp_low = false; 392 power_supply_changed(di->btemp_psy); 393 394 return IRQ_HANDLED; 395 } 396 397 /** 398 * ab8500_btemp_lowmed_handler() - battery temp between low and medium 399 * @irq: interrupt number 400 * @_di: void pointer that has to address of ab8500_btemp 401 * 402 * Returns IRQ status(IRQ_HANDLED) 403 */ 404 static irqreturn_t ab8500_btemp_lowmed_handler(int irq, void *_di) 405 { 406 struct ab8500_btemp *di = _di; 407 408 dev_dbg(di->dev, "Battery temperature is between low and medium\n"); 409 410 di->events.btemp_lowmed = true; 411 di->events.btemp_medhigh = false; 412 di->events.btemp_high = false; 413 di->events.btemp_low = false; 414 power_supply_changed(di->btemp_psy); 415 416 return IRQ_HANDLED; 417 } 418 419 /** 420 * ab8500_btemp_medhigh_handler() - battery temp between medium and high 421 * @irq: interrupt number 422 * @_di: void pointer that has to address of ab8500_btemp 423 * 424 * Returns IRQ status(IRQ_HANDLED) 425 */ 426 static irqreturn_t ab8500_btemp_medhigh_handler(int irq, void *_di) 427 { 428 struct ab8500_btemp *di = _di; 429 430 dev_dbg(di->dev, "Battery temperature is between medium and high\n"); 431 432 di->events.btemp_medhigh = true; 433 di->events.btemp_lowmed = false; 434 di->events.btemp_high = false; 435 di->events.btemp_low = false; 436 power_supply_changed(di->btemp_psy); 437 438 return IRQ_HANDLED; 439 } 440 441 /** 442 * ab8500_btemp_periodic() - Periodic temperature measurements 443 * @di: pointer to the ab8500_btemp structure 444 * @enable: enable or disable periodic temperature measurements 445 * 446 * Starts of stops periodic temperature measurements. Periodic measurements 447 * should only be done when a charger is connected. 448 */ 449 static void ab8500_btemp_periodic(struct ab8500_btemp *di, 450 bool enable) 451 { 452 dev_dbg(di->dev, "Enable periodic temperature measurements: %d\n", 453 enable); 454 /* 455 * Make sure a new measurement is done directly by cancelling 456 * any pending work 457 */ 458 cancel_delayed_work_sync(&di->btemp_periodic_work); 459 460 if (enable) 461 queue_delayed_work(di->btemp_wq, &di->btemp_periodic_work, 0); 462 } 463 464 /** 465 * ab8500_btemp_get_temp() - get battery temperature 466 * @di: pointer to the ab8500_btemp structure 467 * 468 * Returns battery temperature 469 */ 470 static int ab8500_btemp_get_temp(struct ab8500_btemp *di) 471 { 472 int temp = 0; 473 474 /* 475 * The BTEMP events are not reliabe on AB8500 cut3.3 476 * and prior versions 477 */ 478 if (is_ab8500_3p3_or_earlier(di->parent)) { 479 temp = di->bat_temp * 10; 480 } else { 481 if (di->events.btemp_low) { 482 if (temp > di->btemp_ranges.btemp_low_limit) 483 temp = di->btemp_ranges.btemp_low_limit * 10; 484 else 485 temp = di->bat_temp * 10; 486 } else if (di->events.btemp_high) { 487 if (temp < di->btemp_ranges.btemp_high_limit) 488 temp = di->btemp_ranges.btemp_high_limit * 10; 489 else 490 temp = di->bat_temp * 10; 491 } else if (di->events.btemp_lowmed) { 492 if (temp > di->btemp_ranges.btemp_med_limit) 493 temp = di->btemp_ranges.btemp_med_limit * 10; 494 else 495 temp = di->bat_temp * 10; 496 } else if (di->events.btemp_medhigh) { 497 if (temp < di->btemp_ranges.btemp_med_limit) 498 temp = di->btemp_ranges.btemp_med_limit * 10; 499 else 500 temp = di->bat_temp * 10; 501 } else 502 temp = di->bat_temp * 10; 503 } 504 return temp; 505 } 506 507 /** 508 * ab8500_btemp_get_property() - get the btemp properties 509 * @psy: pointer to the power_supply structure 510 * @psp: pointer to the power_supply_property structure 511 * @val: pointer to the power_supply_propval union 512 * 513 * This function gets called when an application tries to get the btemp 514 * properties by reading the sysfs files. 515 * online: presence of the battery 516 * present: presence of the battery 517 * technology: battery technology 518 * temp: battery temperature 519 * Returns error code in case of failure else 0(on success) 520 */ 521 static int ab8500_btemp_get_property(struct power_supply *psy, 522 enum power_supply_property psp, 523 union power_supply_propval *val) 524 { 525 struct ab8500_btemp *di = power_supply_get_drvdata(psy); 526 527 switch (psp) { 528 case POWER_SUPPLY_PROP_PRESENT: 529 case POWER_SUPPLY_PROP_ONLINE: 530 if (di->events.batt_rem) 531 val->intval = 0; 532 else 533 val->intval = 1; 534 break; 535 case POWER_SUPPLY_PROP_TECHNOLOGY: 536 if (di->bm->bi) 537 val->intval = di->bm->bi->technology; 538 else 539 val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 540 break; 541 case POWER_SUPPLY_PROP_TEMP: 542 val->intval = ab8500_btemp_get_temp(di); 543 break; 544 default: 545 return -EINVAL; 546 } 547 return 0; 548 } 549 550 static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data) 551 { 552 struct power_supply *psy; 553 struct power_supply *ext = dev_get_drvdata(dev); 554 const char **supplicants = (const char **)ext->supplied_to; 555 struct ab8500_btemp *di; 556 union power_supply_propval ret; 557 int j; 558 559 psy = (struct power_supply *)data; 560 di = power_supply_get_drvdata(psy); 561 562 /* 563 * For all psy where the name of your driver 564 * appears in any supplied_to 565 */ 566 j = match_string(supplicants, ext->num_supplicants, psy->desc->name); 567 if (j < 0) 568 return 0; 569 570 /* Go through all properties for the psy */ 571 for (j = 0; j < ext->desc->num_properties; j++) { 572 enum power_supply_property prop; 573 prop = ext->desc->properties[j]; 574 575 if (power_supply_get_property(ext, prop, &ret)) 576 continue; 577 578 switch (prop) { 579 case POWER_SUPPLY_PROP_PRESENT: 580 switch (ext->desc->type) { 581 case POWER_SUPPLY_TYPE_MAINS: 582 /* AC disconnected */ 583 if (!ret.intval && di->events.ac_conn) { 584 di->events.ac_conn = false; 585 } 586 /* AC connected */ 587 else if (ret.intval && !di->events.ac_conn) { 588 di->events.ac_conn = true; 589 if (!di->events.usb_conn) 590 ab8500_btemp_periodic(di, true); 591 } 592 break; 593 case POWER_SUPPLY_TYPE_USB: 594 /* USB disconnected */ 595 if (!ret.intval && di->events.usb_conn) { 596 di->events.usb_conn = false; 597 } 598 /* USB connected */ 599 else if (ret.intval && !di->events.usb_conn) { 600 di->events.usb_conn = true; 601 if (!di->events.ac_conn) 602 ab8500_btemp_periodic(di, true); 603 } 604 break; 605 default: 606 break; 607 } 608 break; 609 default: 610 break; 611 } 612 } 613 return 0; 614 } 615 616 /** 617 * ab8500_btemp_external_power_changed() - callback for power supply changes 618 * @psy: pointer to the structure power_supply 619 * 620 * This function is pointing to the function pointer external_power_changed 621 * of the structure power_supply. 622 * This function gets executed when there is a change in the external power 623 * supply to the btemp. 624 */ 625 static void ab8500_btemp_external_power_changed(struct power_supply *psy) 626 { 627 struct ab8500_btemp *di = power_supply_get_drvdata(psy); 628 629 class_for_each_device(power_supply_class, NULL, 630 di->btemp_psy, ab8500_btemp_get_ext_psy_data); 631 } 632 633 /* ab8500 btemp driver interrupts and their respective isr */ 634 static struct ab8500_btemp_interrupts ab8500_btemp_irq[] = { 635 {"BAT_CTRL_INDB", ab8500_btemp_batctrlindb_handler}, 636 {"BTEMP_LOW", ab8500_btemp_templow_handler}, 637 {"BTEMP_HIGH", ab8500_btemp_temphigh_handler}, 638 {"BTEMP_LOW_MEDIUM", ab8500_btemp_lowmed_handler}, 639 {"BTEMP_MEDIUM_HIGH", ab8500_btemp_medhigh_handler}, 640 }; 641 642 static int __maybe_unused ab8500_btemp_resume(struct device *dev) 643 { 644 struct ab8500_btemp *di = dev_get_drvdata(dev); 645 646 ab8500_btemp_periodic(di, true); 647 648 return 0; 649 } 650 651 static int __maybe_unused ab8500_btemp_suspend(struct device *dev) 652 { 653 struct ab8500_btemp *di = dev_get_drvdata(dev); 654 655 ab8500_btemp_periodic(di, false); 656 657 return 0; 658 } 659 660 static char *supply_interface[] = { 661 "ab8500_chargalg", 662 "ab8500_fg", 663 }; 664 665 static const struct power_supply_desc ab8500_btemp_desc = { 666 .name = "ab8500_btemp", 667 .type = POWER_SUPPLY_TYPE_BATTERY, 668 .properties = ab8500_btemp_props, 669 .num_properties = ARRAY_SIZE(ab8500_btemp_props), 670 .get_property = ab8500_btemp_get_property, 671 .external_power_changed = ab8500_btemp_external_power_changed, 672 }; 673 674 static int ab8500_btemp_bind(struct device *dev, struct device *master, 675 void *data) 676 { 677 struct ab8500_btemp *di = dev_get_drvdata(dev); 678 679 /* Create a work queue for the btemp */ 680 di->btemp_wq = 681 alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0); 682 if (di->btemp_wq == NULL) { 683 dev_err(dev, "failed to create work queue\n"); 684 return -ENOMEM; 685 } 686 687 /* Kick off periodic temperature measurements */ 688 ab8500_btemp_periodic(di, true); 689 690 return 0; 691 } 692 693 static void ab8500_btemp_unbind(struct device *dev, struct device *master, 694 void *data) 695 { 696 struct ab8500_btemp *di = dev_get_drvdata(dev); 697 698 /* Delete the work queue */ 699 destroy_workqueue(di->btemp_wq); 700 } 701 702 static const struct component_ops ab8500_btemp_component_ops = { 703 .bind = ab8500_btemp_bind, 704 .unbind = ab8500_btemp_unbind, 705 }; 706 707 static int ab8500_btemp_probe(struct platform_device *pdev) 708 { 709 struct power_supply_config psy_cfg = {}; 710 struct device *dev = &pdev->dev; 711 struct ab8500_btemp *di; 712 int irq, i, ret = 0; 713 u8 val; 714 715 di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL); 716 if (!di) 717 return -ENOMEM; 718 719 di->bm = &ab8500_bm_data; 720 721 /* get parent data */ 722 di->dev = dev; 723 di->parent = dev_get_drvdata(pdev->dev.parent); 724 725 /* Get thermal zone and ADC */ 726 di->tz = thermal_zone_get_zone_by_name("battery-thermal"); 727 if (IS_ERR(di->tz)) { 728 ret = PTR_ERR(di->tz); 729 /* 730 * This usually just means we are probing before the thermal 731 * zone, so just defer. 732 */ 733 if (ret == -ENODEV) 734 ret = -EPROBE_DEFER; 735 return dev_err_probe(dev, ret, 736 "failed to get battery thermal zone\n"); 737 } 738 di->bat_ctrl = devm_iio_channel_get(dev, "bat_ctrl"); 739 if (IS_ERR(di->bat_ctrl)) { 740 ret = dev_err_probe(dev, PTR_ERR(di->bat_ctrl), 741 "failed to get BAT CTRL ADC channel\n"); 742 return ret; 743 } 744 745 di->initialized = false; 746 747 psy_cfg.supplied_to = supply_interface; 748 psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface); 749 psy_cfg.drv_data = di; 750 751 /* Init work for measuring temperature periodically */ 752 INIT_DEFERRABLE_WORK(&di->btemp_periodic_work, 753 ab8500_btemp_periodic_work); 754 755 /* Set BTEMP thermal limits. Low and Med are fixed */ 756 di->btemp_ranges.btemp_low_limit = BTEMP_THERMAL_LOW_LIMIT; 757 di->btemp_ranges.btemp_med_limit = BTEMP_THERMAL_MED_LIMIT; 758 759 ret = abx500_get_register_interruptible(dev, AB8500_CHARGER, 760 AB8500_BTEMP_HIGH_TH, &val); 761 if (ret < 0) { 762 dev_err(dev, "%s ab8500 read failed\n", __func__); 763 return ret; 764 } 765 switch (val) { 766 case BTEMP_HIGH_TH_57_0: 767 case BTEMP_HIGH_TH_57_1: 768 di->btemp_ranges.btemp_high_limit = 769 BTEMP_THERMAL_HIGH_LIMIT_57; 770 break; 771 case BTEMP_HIGH_TH_52: 772 di->btemp_ranges.btemp_high_limit = 773 BTEMP_THERMAL_HIGH_LIMIT_52; 774 break; 775 case BTEMP_HIGH_TH_62: 776 di->btemp_ranges.btemp_high_limit = 777 BTEMP_THERMAL_HIGH_LIMIT_62; 778 break; 779 } 780 781 /* Register BTEMP power supply class */ 782 di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc, 783 &psy_cfg); 784 if (IS_ERR(di->btemp_psy)) { 785 dev_err(dev, "failed to register BTEMP psy\n"); 786 return PTR_ERR(di->btemp_psy); 787 } 788 789 /* Register interrupts */ 790 for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) { 791 irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name); 792 if (irq < 0) 793 return irq; 794 795 ret = devm_request_threaded_irq(dev, irq, NULL, 796 ab8500_btemp_irq[i].isr, 797 IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT, 798 ab8500_btemp_irq[i].name, di); 799 800 if (ret) { 801 dev_err(dev, "failed to request %s IRQ %d: %d\n" 802 , ab8500_btemp_irq[i].name, irq, ret); 803 return ret; 804 } 805 dev_dbg(dev, "Requested %s IRQ %d: %d\n", 806 ab8500_btemp_irq[i].name, irq, ret); 807 } 808 809 platform_set_drvdata(pdev, di); 810 811 list_add_tail(&di->node, &ab8500_btemp_list); 812 813 return component_add(dev, &ab8500_btemp_component_ops); 814 } 815 816 static int ab8500_btemp_remove(struct platform_device *pdev) 817 { 818 component_del(&pdev->dev, &ab8500_btemp_component_ops); 819 820 return 0; 821 } 822 823 static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, ab8500_btemp_resume); 824 825 static const struct of_device_id ab8500_btemp_match[] = { 826 { .compatible = "stericsson,ab8500-btemp", }, 827 { }, 828 }; 829 MODULE_DEVICE_TABLE(of, ab8500_btemp_match); 830 831 struct platform_driver ab8500_btemp_driver = { 832 .probe = ab8500_btemp_probe, 833 .remove = ab8500_btemp_remove, 834 .driver = { 835 .name = "ab8500-btemp", 836 .of_match_table = ab8500_btemp_match, 837 .pm = &ab8500_btemp_pm_ops, 838 }, 839 }; 840 MODULE_LICENSE("GPL v2"); 841 MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy"); 842 MODULE_ALIAS("platform:ab8500-btemp"); 843 MODULE_DESCRIPTION("AB8500 battery temperature driver"); 844