2 * Universal power supply monitor class
4 * Copyright © 2007 Anton Vorontsov <cbou@mail.ru>
5 * Copyright © 2004 Szabolcs Gyurko
6 * Copyright © 2003 Ian Molton <spyro@f2s.com>
8 * Modified: 2004, Oct Szabolcs Gyurko
10 * You may use this code as per GPL version 2
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"
24 /* exported for the APM Power driver, APM emulation */
25 struct class *power_supply_class
;
26 EXPORT_SYMBOL_GPL(power_supply_class
);
28 ATOMIC_NOTIFIER_HEAD(power_supply_notifier
);
29 EXPORT_SYMBOL_GPL(power_supply_notifier
);
31 static struct device_type power_supply_dev_type
;
33 static bool __power_supply_is_supplied_by(struct power_supply
*supplier
,
34 struct power_supply
*supply
)
38 if (!supply
->supplied_from
&& !supplier
->supplied_to
)
41 /* Support both supplied_to and supplied_from modes */
42 if (supply
->supplied_from
) {
45 for (i
= 0; i
< supply
->num_supplies
; i
++)
46 if (!strcmp(supplier
->name
, supply
->supplied_from
[i
]))
51 for (i
= 0; i
< supplier
->num_supplicants
; i
++)
52 if (!strcmp(supplier
->supplied_to
[i
], supply
->name
))
59 static int __power_supply_changed_work(struct device
*dev
, void *data
)
61 struct power_supply
*psy
= (struct power_supply
*)data
;
62 struct power_supply
*pst
= dev_get_drvdata(dev
);
64 if (__power_supply_is_supplied_by(psy
, pst
)) {
65 if (pst
->external_power_changed
)
66 pst
->external_power_changed(pst
);
72 static void power_supply_changed_work(struct work_struct
*work
)
75 struct power_supply
*psy
= container_of(work
, struct power_supply
,
78 dev_dbg(psy
->dev
, "%s\n", __func__
);
80 spin_lock_irqsave(&psy
->changed_lock
, flags
);
83 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
84 class_for_each_device(power_supply_class
, NULL
, psy
,
85 __power_supply_changed_work
);
86 power_supply_update_leds(psy
);
87 atomic_notifier_call_chain(&power_supply_notifier
,
88 PSY_EVENT_PROP_CHANGED
, psy
);
89 kobject_uevent(&psy
->dev
->kobj
, KOBJ_CHANGE
);
90 spin_lock_irqsave(&psy
->changed_lock
, flags
);
93 * Dependent power supplies (e.g. battery) may have changed state
94 * as a result of this event, so poll again and hold the
95 * wakeup_source until all events are processed.
99 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
102 void power_supply_changed(struct power_supply
*psy
)
106 dev_dbg(psy
->dev
, "%s\n", __func__
);
108 spin_lock_irqsave(&psy
->changed_lock
, flags
);
110 pm_stay_awake(psy
->dev
);
111 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
112 schedule_work(&psy
->changed_work
);
114 EXPORT_SYMBOL_GPL(power_supply_changed
);
117 #include <linux/of.h>
119 static int __power_supply_populate_supplied_from(struct device
*dev
,
122 struct power_supply
*psy
= (struct power_supply
*)data
;
123 struct power_supply
*epsy
= dev_get_drvdata(dev
);
124 struct device_node
*np
;
128 np
= of_parse_phandle(psy
->of_node
, "power-supplies", i
++);
132 if (np
== epsy
->of_node
) {
133 dev_info(psy
->dev
, "%s: Found supply : %s\n",
134 psy
->name
, epsy
->name
);
135 psy
->supplied_from
[i
-1] = (char *)epsy
->name
;
146 static int power_supply_populate_supplied_from(struct power_supply
*psy
)
150 error
= class_for_each_device(power_supply_class
, NULL
, psy
,
151 __power_supply_populate_supplied_from
);
153 dev_dbg(psy
->dev
, "%s %d\n", __func__
, error
);
158 static int __power_supply_find_supply_from_node(struct device
*dev
,
161 struct device_node
*np
= (struct device_node
*)data
;
162 struct power_supply
*epsy
= dev_get_drvdata(dev
);
164 /* return error breaks out of class_for_each_device loop */
165 if (epsy
->of_node
== np
)
171 static int power_supply_find_supply_from_node(struct device_node
*supply_node
)
175 struct class_dev_iter iter
;
178 * Use iterator to see if any other device is registered.
179 * This is required since class_for_each_device returns 0
180 * if there are no devices registered.
182 class_dev_iter_init(&iter
, power_supply_class
, NULL
, NULL
);
183 dev
= class_dev_iter_next(&iter
);
186 return -EPROBE_DEFER
;
189 * We have to treat the return value as inverted, because if
190 * we return error on not found, then it won't continue looking.
191 * So we trick it by returning error on success to stop looking
192 * once the matching device is found.
194 error
= class_for_each_device(power_supply_class
, NULL
, supply_node
,
195 __power_supply_find_supply_from_node
);
197 return error
? 0 : -EPROBE_DEFER
;
200 static int power_supply_check_supplies(struct power_supply
*psy
)
202 struct device_node
*np
;
205 /* If there is already a list honor it */
206 if (psy
->supplied_from
&& psy
->num_supplies
> 0)
209 /* No device node found, nothing to do */
216 np
= of_parse_phandle(psy
->of_node
, "power-supplies", cnt
++);
220 ret
= power_supply_find_supply_from_node(np
);
222 dev_dbg(psy
->dev
, "Failed to find supply, defer!\n");
224 return -EPROBE_DEFER
;
229 /* All supplies found, allocate char ** array for filling */
230 psy
->supplied_from
= devm_kzalloc(psy
->dev
, sizeof(psy
->supplied_from
),
232 if (!psy
->supplied_from
) {
233 dev_err(psy
->dev
, "Couldn't allocate memory for supply list\n");
237 *psy
->supplied_from
= devm_kzalloc(psy
->dev
, sizeof(char *) * cnt
,
239 if (!*psy
->supplied_from
) {
240 dev_err(psy
->dev
, "Couldn't allocate memory for supply list\n");
244 return power_supply_populate_supplied_from(psy
);
247 static inline int power_supply_check_supplies(struct power_supply
*psy
)
253 static int __power_supply_am_i_supplied(struct device
*dev
, void *data
)
255 union power_supply_propval ret
= {0,};
256 struct power_supply
*psy
= (struct power_supply
*)data
;
257 struct power_supply
*epsy
= dev_get_drvdata(dev
);
259 if (__power_supply_is_supplied_by(epsy
, psy
))
260 if (!epsy
->get_property(epsy
, POWER_SUPPLY_PROP_ONLINE
, &ret
)) {
268 int power_supply_am_i_supplied(struct power_supply
*psy
)
272 error
= class_for_each_device(power_supply_class
, NULL
, psy
,
273 __power_supply_am_i_supplied
);
275 dev_dbg(psy
->dev
, "%s %d\n", __func__
, error
);
279 EXPORT_SYMBOL_GPL(power_supply_am_i_supplied
);
281 static int __power_supply_is_system_supplied(struct device
*dev
, void *data
)
283 union power_supply_propval ret
= {0,};
284 struct power_supply
*psy
= dev_get_drvdata(dev
);
285 unsigned int *count
= data
;
288 if (psy
->type
!= POWER_SUPPLY_TYPE_BATTERY
) {
289 if (psy
->get_property(psy
, POWER_SUPPLY_PROP_ONLINE
, &ret
))
297 int power_supply_is_system_supplied(void)
300 unsigned int count
= 0;
302 error
= class_for_each_device(power_supply_class
, NULL
, &count
,
303 __power_supply_is_system_supplied
);
306 * If no power class device was found at all, most probably we are
307 * running on a desktop system, so assume we are on mains power.
314 EXPORT_SYMBOL_GPL(power_supply_is_system_supplied
);
316 int power_supply_set_battery_charged(struct power_supply
*psy
)
318 if (psy
->type
== POWER_SUPPLY_TYPE_BATTERY
&& psy
->set_charged
) {
319 psy
->set_charged(psy
);
325 EXPORT_SYMBOL_GPL(power_supply_set_battery_charged
);
327 static int power_supply_match_device_by_name(struct device
*dev
, const void *data
)
329 const char *name
= data
;
330 struct power_supply
*psy
= dev_get_drvdata(dev
);
332 return strcmp(psy
->name
, name
) == 0;
335 struct power_supply
*power_supply_get_by_name(const char *name
)
337 struct device
*dev
= class_find_device(power_supply_class
, NULL
, name
,
338 power_supply_match_device_by_name
);
340 return dev
? dev_get_drvdata(dev
) : NULL
;
342 EXPORT_SYMBOL_GPL(power_supply_get_by_name
);
345 static int power_supply_match_device_node(struct device
*dev
, const void *data
)
347 return dev
->parent
&& dev
->parent
->of_node
== data
;
350 struct power_supply
*power_supply_get_by_phandle(struct device_node
*np
,
351 const char *property
)
353 struct device_node
*power_supply_np
;
356 power_supply_np
= of_parse_phandle(np
, property
, 0);
357 if (!power_supply_np
)
358 return ERR_PTR(-ENODEV
);
360 dev
= class_find_device(power_supply_class
, NULL
, power_supply_np
,
361 power_supply_match_device_node
);
363 of_node_put(power_supply_np
);
365 return dev
? dev_get_drvdata(dev
) : NULL
;
367 EXPORT_SYMBOL_GPL(power_supply_get_by_phandle
);
368 #endif /* CONFIG_OF */
370 int power_supply_powers(struct power_supply
*psy
, struct device
*dev
)
372 return sysfs_create_link(&psy
->dev
->kobj
, &dev
->kobj
, "powers");
374 EXPORT_SYMBOL_GPL(power_supply_powers
);
376 static void power_supply_dev_release(struct device
*dev
)
378 pr_debug("device: '%s': %s\n", dev_name(dev
), __func__
);
382 int power_supply_reg_notifier(struct notifier_block
*nb
)
384 return atomic_notifier_chain_register(&power_supply_notifier
, nb
);
386 EXPORT_SYMBOL_GPL(power_supply_reg_notifier
);
388 void power_supply_unreg_notifier(struct notifier_block
*nb
)
390 atomic_notifier_chain_unregister(&power_supply_notifier
, nb
);
392 EXPORT_SYMBOL_GPL(power_supply_unreg_notifier
);
394 #ifdef CONFIG_THERMAL
395 static int power_supply_read_temp(struct thermal_zone_device
*tzd
,
398 struct power_supply
*psy
;
399 union power_supply_propval val
;
402 WARN_ON(tzd
== NULL
);
404 ret
= psy
->get_property(psy
, POWER_SUPPLY_PROP_TEMP
, &val
);
406 /* Convert tenths of degree Celsius to milli degree Celsius. */
408 *temp
= val
.intval
* 100;
413 static struct thermal_zone_device_ops psy_tzd_ops
= {
414 .get_temp
= power_supply_read_temp
,
417 static int psy_register_thermal(struct power_supply
*psy
)
421 /* Register battery zone device psy reports temperature */
422 for (i
= 0; i
< psy
->num_properties
; i
++) {
423 if (psy
->properties
[i
] == POWER_SUPPLY_PROP_TEMP
) {
424 psy
->tzd
= thermal_zone_device_register(psy
->name
, 0, 0,
425 psy
, &psy_tzd_ops
, NULL
, 0, 0);
426 if (IS_ERR(psy
->tzd
))
427 return PTR_ERR(psy
->tzd
);
434 static void psy_unregister_thermal(struct power_supply
*psy
)
436 if (IS_ERR_OR_NULL(psy
->tzd
))
438 thermal_zone_device_unregister(psy
->tzd
);
441 /* thermal cooling device callbacks */
442 static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device
*tcd
,
443 unsigned long *state
)
445 struct power_supply
*psy
;
446 union power_supply_propval val
;
450 ret
= psy
->get_property(psy
,
451 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX
, &val
);
458 static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device
*tcd
,
459 unsigned long *state
)
461 struct power_supply
*psy
;
462 union power_supply_propval val
;
466 ret
= psy
->get_property(psy
,
467 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
, &val
);
474 static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device
*tcd
,
477 struct power_supply
*psy
;
478 union power_supply_propval val
;
483 ret
= psy
->set_property(psy
,
484 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
, &val
);
489 static struct thermal_cooling_device_ops psy_tcd_ops
= {
490 .get_max_state
= ps_get_max_charge_cntl_limit
,
491 .get_cur_state
= ps_get_cur_chrage_cntl_limit
,
492 .set_cur_state
= ps_set_cur_charge_cntl_limit
,
495 static int psy_register_cooler(struct power_supply
*psy
)
499 /* Register for cooling device if psy can control charging */
500 for (i
= 0; i
< psy
->num_properties
; i
++) {
501 if (psy
->properties
[i
] ==
502 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
) {
503 psy
->tcd
= thermal_cooling_device_register(
506 if (IS_ERR(psy
->tcd
))
507 return PTR_ERR(psy
->tcd
);
514 static void psy_unregister_cooler(struct power_supply
*psy
)
516 if (IS_ERR_OR_NULL(psy
->tcd
))
518 thermal_cooling_device_unregister(psy
->tcd
);
521 static int psy_register_thermal(struct power_supply
*psy
)
526 static void psy_unregister_thermal(struct power_supply
*psy
)
530 static int psy_register_cooler(struct power_supply
*psy
)
535 static void psy_unregister_cooler(struct power_supply
*psy
)
540 int power_supply_register(struct device
*parent
, struct power_supply
*psy
)
545 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
549 device_initialize(dev
);
551 dev
->class = power_supply_class
;
552 dev
->type
= &power_supply_dev_type
;
553 dev
->parent
= parent
;
554 dev
->release
= power_supply_dev_release
;
555 dev_set_drvdata(dev
, psy
);
558 rc
= dev_set_name(dev
, "%s", psy
->name
);
560 goto dev_set_name_failed
;
562 INIT_WORK(&psy
->changed_work
, power_supply_changed_work
);
564 rc
= power_supply_check_supplies(psy
);
566 dev_info(dev
, "Not all required supplies found, defer probe\n");
567 goto check_supplies_failed
;
570 spin_lock_init(&psy
->changed_lock
);
571 rc
= device_init_wakeup(dev
, true);
573 goto wakeup_init_failed
;
575 rc
= device_add(dev
);
577 goto device_add_failed
;
579 rc
= psy_register_thermal(psy
);
581 goto register_thermal_failed
;
583 rc
= psy_register_cooler(psy
);
585 goto register_cooler_failed
;
587 rc
= power_supply_create_triggers(psy
);
589 goto create_triggers_failed
;
591 power_supply_changed(psy
);
595 create_triggers_failed
:
596 psy_unregister_cooler(psy
);
597 register_cooler_failed
:
598 psy_unregister_thermal(psy
);
599 register_thermal_failed
:
603 check_supplies_failed
:
609 EXPORT_SYMBOL_GPL(power_supply_register
);
611 void power_supply_unregister(struct power_supply
*psy
)
613 cancel_work_sync(&psy
->changed_work
);
614 sysfs_remove_link(&psy
->dev
->kobj
, "powers");
615 power_supply_remove_triggers(psy
);
616 psy_unregister_cooler(psy
);
617 psy_unregister_thermal(psy
);
618 device_init_wakeup(psy
->dev
, false);
619 device_unregister(psy
->dev
);
621 EXPORT_SYMBOL_GPL(power_supply_unregister
);
623 static int __init
power_supply_class_init(void)
625 power_supply_class
= class_create(THIS_MODULE
, "power_supply");
627 if (IS_ERR(power_supply_class
))
628 return PTR_ERR(power_supply_class
);
630 power_supply_class
->dev_uevent
= power_supply_uevent
;
631 power_supply_init_attrs(&power_supply_dev_type
);
636 static void __exit
power_supply_class_exit(void)
638 class_destroy(power_supply_class
);
641 subsys_initcall(power_supply_class_init
);
642 module_exit(power_supply_class_exit
);
644 MODULE_DESCRIPTION("Universal power supply monitor class");
645 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
647 "Anton Vorontsov <cbou@mail.ru>");
648 MODULE_LICENSE("GPL");