power_supply_core.c revision 9d2410c79b5b2dd741648de26ad52ffd2ce3dc01
1/* 2 * Universal power supply monitor class 3 * 4 * Copyright © 2007 Anton Vorontsov <cbou@mail.ru> 5 * Copyright © 2004 Szabolcs Gyurko 6 * Copyright © 2003 Ian Molton <spyro@f2s.com> 7 * 8 * Modified: 2004, Oct Szabolcs Gyurko 9 * 10 * You may use this code as per GPL version 2 11 */ 12 13#include <linux/module.h> 14#include <linux/types.h> 15#include <linux/init.h> 16#include <linux/slab.h> 17#include <linux/device.h> 18#include <linux/notifier.h> 19#include <linux/err.h> 20#include <linux/power_supply.h> 21#include <linux/thermal.h> 22#include "power_supply.h" 23 24/* exported for the APM Power driver, APM emulation */ 25struct class *power_supply_class; 26EXPORT_SYMBOL_GPL(power_supply_class); 27 28ATOMIC_NOTIFIER_HEAD(power_supply_notifier); 29EXPORT_SYMBOL_GPL(power_supply_notifier); 30 31static struct device_type power_supply_dev_type; 32 33static bool __power_supply_is_supplied_by(struct power_supply *supplier, 34 struct power_supply *supply) 35{ 36 int i; 37 38 if (!supply->supplied_from && !supplier->supplied_to) 39 return false; 40 41 /* Support both supplied_to and supplied_from modes */ 42 if (supply->supplied_from) { 43 if (!supplier->name) 44 return false; 45 for (i = 0; i < supply->num_supplies; i++) 46 if (!strcmp(supplier->name, supply->supplied_from[i])) 47 return true; 48 } else { 49 if (!supply->name) 50 return false; 51 for (i = 0; i < supplier->num_supplicants; i++) 52 if (!strcmp(supplier->supplied_to[i], supply->name)) 53 return true; 54 } 55 56 return false; 57} 58 59static int __power_supply_changed_work(struct device *dev, void *data) 60{ 61 struct power_supply *psy = data; 62 struct power_supply *pst = dev_get_drvdata(dev); 63 64 if (__power_supply_is_supplied_by(psy, pst)) { 65 if (pst->external_power_changed) 66 pst->external_power_changed(pst); 67 } 68 69 return 0; 70} 71 72static void power_supply_changed_work(struct work_struct *work) 73{ 74 unsigned long flags; 75 struct power_supply *psy = container_of(work, struct power_supply, 76 changed_work); 77 78 dev_dbg(psy->dev, "%s\n", __func__); 79 80 spin_lock_irqsave(&psy->changed_lock, flags); 81 /* 82 * Check 'changed' here to avoid issues due to race between 83 * power_supply_changed() and this routine. In worst case 84 * power_supply_changed() can be called again just before we take above 85 * lock. During the first call of this routine we will mark 'changed' as 86 * false and it will stay false for the next call as well. 87 */ 88 if (likely(psy->changed)) { 89 psy->changed = false; 90 spin_unlock_irqrestore(&psy->changed_lock, flags); 91 class_for_each_device(power_supply_class, NULL, psy, 92 __power_supply_changed_work); 93 power_supply_update_leds(psy); 94 atomic_notifier_call_chain(&power_supply_notifier, 95 PSY_EVENT_PROP_CHANGED, psy); 96 kobject_uevent(&psy->dev->kobj, KOBJ_CHANGE); 97 spin_lock_irqsave(&psy->changed_lock, flags); 98 } 99 100 /* 101 * Hold the wakeup_source until all events are processed. 102 * power_supply_changed() might have called again and have set 'changed' 103 * to true. 104 */ 105 if (likely(!psy->changed)) 106 pm_relax(psy->dev); 107 spin_unlock_irqrestore(&psy->changed_lock, flags); 108} 109 110void power_supply_changed(struct power_supply *psy) 111{ 112 unsigned long flags; 113 114 dev_dbg(psy->dev, "%s\n", __func__); 115 116 spin_lock_irqsave(&psy->changed_lock, flags); 117 psy->changed = true; 118 pm_stay_awake(psy->dev); 119 spin_unlock_irqrestore(&psy->changed_lock, flags); 120 schedule_work(&psy->changed_work); 121} 122EXPORT_SYMBOL_GPL(power_supply_changed); 123 124#ifdef CONFIG_OF 125#include <linux/of.h> 126 127static int __power_supply_populate_supplied_from(struct device *dev, 128 void *data) 129{ 130 struct power_supply *psy = data; 131 struct power_supply *epsy = dev_get_drvdata(dev); 132 struct device_node *np; 133 int i = 0; 134 135 do { 136 np = of_parse_phandle(psy->of_node, "power-supplies", i++); 137 if (!np) 138 break; 139 140 if (np == epsy->of_node) { 141 dev_info(psy->dev, "%s: Found supply : %s\n", 142 psy->name, epsy->name); 143 psy->supplied_from[i-1] = (char *)epsy->name; 144 psy->num_supplies++; 145 of_node_put(np); 146 break; 147 } 148 of_node_put(np); 149 } while (np); 150 151 return 0; 152} 153 154static int power_supply_populate_supplied_from(struct power_supply *psy) 155{ 156 int error; 157 158 error = class_for_each_device(power_supply_class, NULL, psy, 159 __power_supply_populate_supplied_from); 160 161 dev_dbg(psy->dev, "%s %d\n", __func__, error); 162 163 return error; 164} 165 166static int __power_supply_find_supply_from_node(struct device *dev, 167 void *data) 168{ 169 struct device_node *np = data; 170 struct power_supply *epsy = dev_get_drvdata(dev); 171 172 /* returning non-zero breaks out of class_for_each_device loop */ 173 if (epsy->of_node == np) 174 return 1; 175 176 return 0; 177} 178 179static int power_supply_find_supply_from_node(struct device_node *supply_node) 180{ 181 int error; 182 struct device *dev; 183 struct class_dev_iter iter; 184 185 /* 186 * Use iterator to see if any other device is registered. 187 * This is required since class_for_each_device returns 0 188 * if there are no devices registered. 189 */ 190 class_dev_iter_init(&iter, power_supply_class, NULL, NULL); 191 dev = class_dev_iter_next(&iter); 192 193 if (!dev) 194 return -EPROBE_DEFER; 195 196 /* 197 * class_for_each_device() either returns its own errors or values 198 * returned by __power_supply_find_supply_from_node(). 199 * 200 * __power_supply_find_supply_from_node() will return 0 (no match) 201 * or 1 (match). 202 * 203 * We return 0 if class_for_each_device() returned 1, -EPROBE_DEFER if 204 * it returned 0, or error as returned by it. 205 */ 206 error = class_for_each_device(power_supply_class, NULL, supply_node, 207 __power_supply_find_supply_from_node); 208 209 return error ? (error == 1 ? 0 : error) : -EPROBE_DEFER; 210} 211 212static int power_supply_check_supplies(struct power_supply *psy) 213{ 214 struct device_node *np; 215 int cnt = 0; 216 217 /* If there is already a list honor it */ 218 if (psy->supplied_from && psy->num_supplies > 0) 219 return 0; 220 221 /* No device node found, nothing to do */ 222 if (!psy->of_node) 223 return 0; 224 225 do { 226 int ret; 227 228 np = of_parse_phandle(psy->of_node, "power-supplies", cnt++); 229 if (!np) 230 break; 231 232 ret = power_supply_find_supply_from_node(np); 233 of_node_put(np); 234 235 if (ret) { 236 dev_dbg(psy->dev, "Failed to find supply!\n"); 237 return ret; 238 } 239 } while (np); 240 241 /* Missing valid "power-supplies" entries */ 242 if (cnt == 1) 243 return 0; 244 245 /* All supplies found, allocate char ** array for filling */ 246 psy->supplied_from = devm_kzalloc(psy->dev, sizeof(psy->supplied_from), 247 GFP_KERNEL); 248 if (!psy->supplied_from) { 249 dev_err(psy->dev, "Couldn't allocate memory for supply list\n"); 250 return -ENOMEM; 251 } 252 253 *psy->supplied_from = devm_kzalloc(psy->dev, sizeof(char *) * (cnt - 1), 254 GFP_KERNEL); 255 if (!*psy->supplied_from) { 256 dev_err(psy->dev, "Couldn't allocate memory for supply list\n"); 257 return -ENOMEM; 258 } 259 260 return power_supply_populate_supplied_from(psy); 261} 262#else 263static inline int power_supply_check_supplies(struct power_supply *psy) 264{ 265 return 0; 266} 267#endif 268 269static int __power_supply_am_i_supplied(struct device *dev, void *data) 270{ 271 union power_supply_propval ret = {0,}; 272 struct power_supply *psy = data; 273 struct power_supply *epsy = dev_get_drvdata(dev); 274 275 if (__power_supply_is_supplied_by(epsy, psy)) 276 if (!epsy->get_property(epsy, POWER_SUPPLY_PROP_ONLINE, &ret)) 277 return ret.intval; 278 279 return 0; 280} 281 282int power_supply_am_i_supplied(struct power_supply *psy) 283{ 284 int error; 285 286 error = class_for_each_device(power_supply_class, NULL, psy, 287 __power_supply_am_i_supplied); 288 289 dev_dbg(psy->dev, "%s %d\n", __func__, error); 290 291 return error; 292} 293EXPORT_SYMBOL_GPL(power_supply_am_i_supplied); 294 295static int __power_supply_is_system_supplied(struct device *dev, void *data) 296{ 297 union power_supply_propval ret = {0,}; 298 struct power_supply *psy = dev_get_drvdata(dev); 299 unsigned int *count = data; 300 301 (*count)++; 302 if (psy->type != POWER_SUPPLY_TYPE_BATTERY) 303 if (!psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) 304 return ret.intval; 305 306 return 0; 307} 308 309int power_supply_is_system_supplied(void) 310{ 311 int error; 312 unsigned int count = 0; 313 314 error = class_for_each_device(power_supply_class, NULL, &count, 315 __power_supply_is_system_supplied); 316 317 /* 318 * If no power class device was found at all, most probably we are 319 * running on a desktop system, so assume we are on mains power. 320 */ 321 if (count == 0) 322 return 1; 323 324 return error; 325} 326EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); 327 328int power_supply_set_battery_charged(struct power_supply *psy) 329{ 330 if (psy->type == POWER_SUPPLY_TYPE_BATTERY && psy->set_charged) { 331 psy->set_charged(psy); 332 return 0; 333 } 334 335 return -EINVAL; 336} 337EXPORT_SYMBOL_GPL(power_supply_set_battery_charged); 338 339static int power_supply_match_device_by_name(struct device *dev, const void *data) 340{ 341 const char *name = data; 342 struct power_supply *psy = dev_get_drvdata(dev); 343 344 return strcmp(psy->name, name) == 0; 345} 346 347struct power_supply *power_supply_get_by_name(const char *name) 348{ 349 struct device *dev = class_find_device(power_supply_class, NULL, name, 350 power_supply_match_device_by_name); 351 352 return dev ? dev_get_drvdata(dev) : NULL; 353} 354EXPORT_SYMBOL_GPL(power_supply_get_by_name); 355 356#ifdef CONFIG_OF 357static int power_supply_match_device_node(struct device *dev, const void *data) 358{ 359 return dev->parent && dev->parent->of_node == data; 360} 361 362struct power_supply *power_supply_get_by_phandle(struct device_node *np, 363 const char *property) 364{ 365 struct device_node *power_supply_np; 366 struct device *dev; 367 368 power_supply_np = of_parse_phandle(np, property, 0); 369 if (!power_supply_np) 370 return ERR_PTR(-ENODEV); 371 372 dev = class_find_device(power_supply_class, NULL, power_supply_np, 373 power_supply_match_device_node); 374 375 of_node_put(power_supply_np); 376 377 return dev ? dev_get_drvdata(dev) : NULL; 378} 379EXPORT_SYMBOL_GPL(power_supply_get_by_phandle); 380#endif /* CONFIG_OF */ 381 382int power_supply_powers(struct power_supply *psy, struct device *dev) 383{ 384 return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers"); 385} 386EXPORT_SYMBOL_GPL(power_supply_powers); 387 388static void power_supply_dev_release(struct device *dev) 389{ 390 pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 391 kfree(dev); 392} 393 394int power_supply_reg_notifier(struct notifier_block *nb) 395{ 396 return atomic_notifier_chain_register(&power_supply_notifier, nb); 397} 398EXPORT_SYMBOL_GPL(power_supply_reg_notifier); 399 400void power_supply_unreg_notifier(struct notifier_block *nb) 401{ 402 atomic_notifier_chain_unregister(&power_supply_notifier, nb); 403} 404EXPORT_SYMBOL_GPL(power_supply_unreg_notifier); 405 406#ifdef CONFIG_THERMAL 407static int power_supply_read_temp(struct thermal_zone_device *tzd, 408 unsigned long *temp) 409{ 410 struct power_supply *psy; 411 union power_supply_propval val; 412 int ret; 413 414 WARN_ON(tzd == NULL); 415 psy = tzd->devdata; 416 ret = psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &val); 417 418 /* Convert tenths of degree Celsius to milli degree Celsius. */ 419 if (!ret) 420 *temp = val.intval * 100; 421 422 return ret; 423} 424 425static struct thermal_zone_device_ops psy_tzd_ops = { 426 .get_temp = power_supply_read_temp, 427}; 428 429static int psy_register_thermal(struct power_supply *psy) 430{ 431 int i; 432 433 /* Register battery zone device psy reports temperature */ 434 for (i = 0; i < psy->num_properties; i++) { 435 if (psy->properties[i] == POWER_SUPPLY_PROP_TEMP) { 436 psy->tzd = thermal_zone_device_register(psy->name, 0, 0, 437 psy, &psy_tzd_ops, NULL, 0, 0); 438 return PTR_ERR_OR_ZERO(psy->tzd); 439 } 440 } 441 return 0; 442} 443 444static void psy_unregister_thermal(struct power_supply *psy) 445{ 446 if (IS_ERR_OR_NULL(psy->tzd)) 447 return; 448 thermal_zone_device_unregister(psy->tzd); 449} 450 451/* thermal cooling device callbacks */ 452static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device *tcd, 453 unsigned long *state) 454{ 455 struct power_supply *psy; 456 union power_supply_propval val; 457 int ret; 458 459 psy = tcd->devdata; 460 ret = psy->get_property(psy, 461 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, &val); 462 if (!ret) 463 *state = val.intval; 464 465 return ret; 466} 467 468static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device *tcd, 469 unsigned long *state) 470{ 471 struct power_supply *psy; 472 union power_supply_propval val; 473 int ret; 474 475 psy = tcd->devdata; 476 ret = psy->get_property(psy, 477 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); 478 if (!ret) 479 *state = val.intval; 480 481 return ret; 482} 483 484static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device *tcd, 485 unsigned long state) 486{ 487 struct power_supply *psy; 488 union power_supply_propval val; 489 int ret; 490 491 psy = tcd->devdata; 492 val.intval = state; 493 ret = psy->set_property(psy, 494 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, &val); 495 496 return ret; 497} 498 499static struct thermal_cooling_device_ops psy_tcd_ops = { 500 .get_max_state = ps_get_max_charge_cntl_limit, 501 .get_cur_state = ps_get_cur_chrage_cntl_limit, 502 .set_cur_state = ps_set_cur_charge_cntl_limit, 503}; 504 505static int psy_register_cooler(struct power_supply *psy) 506{ 507 int i; 508 509 /* Register for cooling device if psy can control charging */ 510 for (i = 0; i < psy->num_properties; i++) { 511 if (psy->properties[i] == 512 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT) { 513 psy->tcd = thermal_cooling_device_register( 514 (char *)psy->name, 515 psy, &psy_tcd_ops); 516 return PTR_ERR_OR_ZERO(psy->tcd); 517 } 518 } 519 return 0; 520} 521 522static void psy_unregister_cooler(struct power_supply *psy) 523{ 524 if (IS_ERR_OR_NULL(psy->tcd)) 525 return; 526 thermal_cooling_device_unregister(psy->tcd); 527} 528#else 529static int psy_register_thermal(struct power_supply *psy) 530{ 531 return 0; 532} 533 534static void psy_unregister_thermal(struct power_supply *psy) 535{ 536} 537 538static int psy_register_cooler(struct power_supply *psy) 539{ 540 return 0; 541} 542 543static void psy_unregister_cooler(struct power_supply *psy) 544{ 545} 546#endif 547 548static int __power_supply_register(struct device *parent, 549 struct power_supply *psy, bool ws) 550{ 551 struct device *dev; 552 int rc; 553 554 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 555 if (!dev) 556 return -ENOMEM; 557 558 device_initialize(dev); 559 560 dev->class = power_supply_class; 561 dev->type = &power_supply_dev_type; 562 dev->parent = parent; 563 dev->release = power_supply_dev_release; 564 dev_set_drvdata(dev, psy); 565 psy->dev = dev; 566 567 rc = dev_set_name(dev, "%s", psy->name); 568 if (rc) 569 goto dev_set_name_failed; 570 571 INIT_WORK(&psy->changed_work, power_supply_changed_work); 572 573 rc = power_supply_check_supplies(psy); 574 if (rc) { 575 dev_info(dev, "Not all required supplies found, defer probe\n"); 576 goto check_supplies_failed; 577 } 578 579 spin_lock_init(&psy->changed_lock); 580 rc = device_init_wakeup(dev, ws); 581 if (rc) 582 goto wakeup_init_failed; 583 584 rc = device_add(dev); 585 if (rc) 586 goto device_add_failed; 587 588 rc = psy_register_thermal(psy); 589 if (rc) 590 goto register_thermal_failed; 591 592 rc = psy_register_cooler(psy); 593 if (rc) 594 goto register_cooler_failed; 595 596 rc = power_supply_create_triggers(psy); 597 if (rc) 598 goto create_triggers_failed; 599 600 power_supply_changed(psy); 601 602 goto success; 603 604create_triggers_failed: 605 psy_unregister_cooler(psy); 606register_cooler_failed: 607 psy_unregister_thermal(psy); 608register_thermal_failed: 609 device_del(dev); 610device_add_failed: 611wakeup_init_failed: 612check_supplies_failed: 613dev_set_name_failed: 614 put_device(dev); 615success: 616 return rc; 617} 618 619int power_supply_register(struct device *parent, struct power_supply *psy) 620{ 621 return __power_supply_register(parent, psy, true); 622} 623EXPORT_SYMBOL_GPL(power_supply_register); 624 625int power_supply_register_no_ws(struct device *parent, struct power_supply *psy) 626{ 627 return __power_supply_register(parent, psy, false); 628} 629EXPORT_SYMBOL_GPL(power_supply_register_no_ws); 630 631void power_supply_unregister(struct power_supply *psy) 632{ 633 cancel_work_sync(&psy->changed_work); 634 sysfs_remove_link(&psy->dev->kobj, "powers"); 635 power_supply_remove_triggers(psy); 636 psy_unregister_cooler(psy); 637 psy_unregister_thermal(psy); 638 device_init_wakeup(psy->dev, false); 639 device_unregister(psy->dev); 640} 641EXPORT_SYMBOL_GPL(power_supply_unregister); 642 643static int __init power_supply_class_init(void) 644{ 645 power_supply_class = class_create(THIS_MODULE, "power_supply"); 646 647 if (IS_ERR(power_supply_class)) 648 return PTR_ERR(power_supply_class); 649 650 power_supply_class->dev_uevent = power_supply_uevent; 651 power_supply_init_attrs(&power_supply_dev_type); 652 653 return 0; 654} 655 656static void __exit power_supply_class_exit(void) 657{ 658 class_destroy(power_supply_class); 659} 660 661subsys_initcall(power_supply_class_init); 662module_exit(power_supply_class_exit); 663 664MODULE_DESCRIPTION("Universal power supply monitor class"); 665MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, " 666 "Szabolcs Gyurko, " 667 "Anton Vorontsov <cbou@mail.ru>"); 668MODULE_LICENSE("GPL"); 669