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/err.h>
19 #include <linux/power_supply.h>
20 #include <linux/thermal.h>
21 #include "power_supply.h"
23 /* exported for the APM Power driver, APM emulation */
24 struct class *power_supply_class
;
25 EXPORT_SYMBOL_GPL(power_supply_class
);
27 static struct device_type power_supply_dev_type
;
29 static bool __power_supply_is_supplied_by(struct power_supply
*supplier
,
30 struct power_supply
*supply
)
34 if (!supply
->supplied_from
&& !supplier
->supplied_to
)
37 /* Support both supplied_to and supplied_from modes */
38 if (supply
->supplied_from
) {
41 for (i
= 0; i
< supply
->num_supplies
; i
++)
42 if (!strcmp(supplier
->name
, supply
->supplied_from
[i
]))
47 for (i
= 0; i
< supplier
->num_supplicants
; i
++)
48 if (!strcmp(supplier
->supplied_to
[i
], supply
->name
))
55 static int __power_supply_changed_work(struct device
*dev
, void *data
)
57 struct power_supply
*psy
= (struct power_supply
*)data
;
58 struct power_supply
*pst
= dev_get_drvdata(dev
);
60 if (__power_supply_is_supplied_by(psy
, pst
)) {
61 if (pst
->external_power_changed
)
62 pst
->external_power_changed(pst
);
68 static void power_supply_changed_work(struct work_struct
*work
)
71 struct power_supply
*psy
= container_of(work
, struct power_supply
,
74 dev_dbg(psy
->dev
, "%s\n", __func__
);
76 spin_lock_irqsave(&psy
->changed_lock
, flags
);
79 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
80 class_for_each_device(power_supply_class
, NULL
, psy
,
81 __power_supply_changed_work
);
82 power_supply_update_leds(psy
);
83 kobject_uevent(&psy
->dev
->kobj
, KOBJ_CHANGE
);
84 spin_lock_irqsave(&psy
->changed_lock
, flags
);
87 * Dependent power supplies (e.g. battery) may have changed state
88 * as a result of this event, so poll again and hold the
89 * wakeup_source until all events are processed.
93 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
96 void power_supply_changed(struct power_supply
*psy
)
100 dev_dbg(psy
->dev
, "%s\n", __func__
);
102 spin_lock_irqsave(&psy
->changed_lock
, flags
);
104 pm_stay_awake(psy
->dev
);
105 spin_unlock_irqrestore(&psy
->changed_lock
, flags
);
106 schedule_work(&psy
->changed_work
);
108 EXPORT_SYMBOL_GPL(power_supply_changed
);
111 #include <linux/of.h>
113 static int __power_supply_populate_supplied_from(struct device
*dev
,
116 struct power_supply
*psy
= (struct power_supply
*)data
;
117 struct power_supply
*epsy
= dev_get_drvdata(dev
);
118 struct device_node
*np
;
122 np
= of_parse_phandle(psy
->of_node
, "power-supplies", i
++);
126 if (np
== epsy
->of_node
) {
127 dev_info(psy
->dev
, "%s: Found supply : %s\n",
128 psy
->name
, epsy
->name
);
129 psy
->supplied_from
[i
-1] = (char *)epsy
->name
;
140 static int power_supply_populate_supplied_from(struct power_supply
*psy
)
144 error
= class_for_each_device(power_supply_class
, NULL
, psy
,
145 __power_supply_populate_supplied_from
);
147 dev_dbg(psy
->dev
, "%s %d\n", __func__
, error
);
152 static int __power_supply_find_supply_from_node(struct device
*dev
,
155 struct device_node
*np
= (struct device_node
*)data
;
156 struct power_supply
*epsy
= dev_get_drvdata(dev
);
158 /* return error breaks out of class_for_each_device loop */
159 if (epsy
->of_node
== np
)
165 static int power_supply_find_supply_from_node(struct device_node
*supply_node
)
169 struct class_dev_iter iter
;
172 * Use iterator to see if any other device is registered.
173 * This is required since class_for_each_device returns 0
174 * if there are no devices registered.
176 class_dev_iter_init(&iter
, power_supply_class
, NULL
, NULL
);
177 dev
= class_dev_iter_next(&iter
);
180 return -EPROBE_DEFER
;
183 * We have to treat the return value as inverted, because if
184 * we return error on not found, then it won't continue looking.
185 * So we trick it by returning error on success to stop looking
186 * once the matching device is found.
188 error
= class_for_each_device(power_supply_class
, NULL
, supply_node
,
189 __power_supply_find_supply_from_node
);
191 return error
? 0 : -EPROBE_DEFER
;
194 static int power_supply_check_supplies(struct power_supply
*psy
)
196 struct device_node
*np
;
199 /* If there is already a list honor it */
200 if (psy
->supplied_from
&& psy
->num_supplies
> 0)
203 /* No device node found, nothing to do */
210 np
= of_parse_phandle(psy
->of_node
, "power-supplies", cnt
++);
214 ret
= power_supply_find_supply_from_node(np
);
216 dev_dbg(psy
->dev
, "Failed to find supply, defer!\n");
218 return -EPROBE_DEFER
;
223 /* All supplies found, allocate char ** array for filling */
224 psy
->supplied_from
= devm_kzalloc(psy
->dev
, sizeof(psy
->supplied_from
),
226 if (!psy
->supplied_from
) {
227 dev_err(psy
->dev
, "Couldn't allocate memory for supply list\n");
231 *psy
->supplied_from
= devm_kzalloc(psy
->dev
, sizeof(char *) * cnt
,
233 if (!*psy
->supplied_from
) {
234 dev_err(psy
->dev
, "Couldn't allocate memory for supply list\n");
238 return power_supply_populate_supplied_from(psy
);
241 static inline int power_supply_check_supplies(struct power_supply
*psy
)
247 static int __power_supply_am_i_supplied(struct device
*dev
, void *data
)
249 union power_supply_propval ret
= {0,};
250 struct power_supply
*psy
= (struct power_supply
*)data
;
251 struct power_supply
*epsy
= dev_get_drvdata(dev
);
253 if (__power_supply_is_supplied_by(epsy
, psy
))
254 if (!epsy
->get_property(epsy
, POWER_SUPPLY_PROP_ONLINE
, &ret
)) {
262 int power_supply_am_i_supplied(struct power_supply
*psy
)
266 error
= class_for_each_device(power_supply_class
, NULL
, psy
,
267 __power_supply_am_i_supplied
);
269 dev_dbg(psy
->dev
, "%s %d\n", __func__
, error
);
273 EXPORT_SYMBOL_GPL(power_supply_am_i_supplied
);
275 static int __power_supply_is_system_supplied(struct device
*dev
, void *data
)
277 union power_supply_propval ret
= {0,};
278 struct power_supply
*psy
= dev_get_drvdata(dev
);
279 unsigned int *count
= data
;
282 if (psy
->type
!= POWER_SUPPLY_TYPE_BATTERY
) {
283 if (psy
->get_property(psy
, POWER_SUPPLY_PROP_ONLINE
, &ret
))
291 int power_supply_is_system_supplied(void)
294 unsigned int count
= 0;
296 error
= class_for_each_device(power_supply_class
, NULL
, &count
,
297 __power_supply_is_system_supplied
);
300 * If no power class device was found at all, most probably we are
301 * running on a desktop system, so assume we are on mains power.
308 EXPORT_SYMBOL_GPL(power_supply_is_system_supplied
);
310 int power_supply_set_battery_charged(struct power_supply
*psy
)
312 if (psy
->type
== POWER_SUPPLY_TYPE_BATTERY
&& psy
->set_charged
) {
313 psy
->set_charged(psy
);
319 EXPORT_SYMBOL_GPL(power_supply_set_battery_charged
);
321 static int power_supply_match_device_by_name(struct device
*dev
, const void *data
)
323 const char *name
= data
;
324 struct power_supply
*psy
= dev_get_drvdata(dev
);
326 return strcmp(psy
->name
, name
) == 0;
329 struct power_supply
*power_supply_get_by_name(const char *name
)
331 struct device
*dev
= class_find_device(power_supply_class
, NULL
, name
,
332 power_supply_match_device_by_name
);
334 return dev
? dev_get_drvdata(dev
) : NULL
;
336 EXPORT_SYMBOL_GPL(power_supply_get_by_name
);
338 int power_supply_powers(struct power_supply
*psy
, struct device
*dev
)
340 return sysfs_create_link(&psy
->dev
->kobj
, &dev
->kobj
, "powers");
342 EXPORT_SYMBOL_GPL(power_supply_powers
);
344 static void power_supply_dev_release(struct device
*dev
)
346 pr_debug("device: '%s': %s\n", dev_name(dev
), __func__
);
350 #ifdef CONFIG_THERMAL
351 static int power_supply_read_temp(struct thermal_zone_device
*tzd
,
354 struct power_supply
*psy
;
355 union power_supply_propval val
;
358 WARN_ON(tzd
== NULL
);
360 ret
= psy
->get_property(psy
, POWER_SUPPLY_PROP_TEMP
, &val
);
362 /* Convert tenths of degree Celsius to milli degree Celsius. */
364 *temp
= val
.intval
* 100;
369 static struct thermal_zone_device_ops psy_tzd_ops
= {
370 .get_temp
= power_supply_read_temp
,
373 static int psy_register_thermal(struct power_supply
*psy
)
377 /* Register battery zone device psy reports temperature */
378 for (i
= 0; i
< psy
->num_properties
; i
++) {
379 if (psy
->properties
[i
] == POWER_SUPPLY_PROP_TEMP
) {
380 psy
->tzd
= thermal_zone_device_register(psy
->name
, 0, 0,
381 psy
, &psy_tzd_ops
, NULL
, 0, 0);
382 if (IS_ERR(psy
->tzd
))
383 return PTR_ERR(psy
->tzd
);
390 static void psy_unregister_thermal(struct power_supply
*psy
)
392 if (IS_ERR_OR_NULL(psy
->tzd
))
394 thermal_zone_device_unregister(psy
->tzd
);
397 /* thermal cooling device callbacks */
398 static int ps_get_max_charge_cntl_limit(struct thermal_cooling_device
*tcd
,
399 unsigned long *state
)
401 struct power_supply
*psy
;
402 union power_supply_propval val
;
406 ret
= psy
->get_property(psy
,
407 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX
, &val
);
414 static int ps_get_cur_chrage_cntl_limit(struct thermal_cooling_device
*tcd
,
415 unsigned long *state
)
417 struct power_supply
*psy
;
418 union power_supply_propval val
;
422 ret
= psy
->get_property(psy
,
423 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
, &val
);
430 static int ps_set_cur_charge_cntl_limit(struct thermal_cooling_device
*tcd
,
433 struct power_supply
*psy
;
434 union power_supply_propval val
;
439 ret
= psy
->set_property(psy
,
440 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
, &val
);
445 static struct thermal_cooling_device_ops psy_tcd_ops
= {
446 .get_max_state
= ps_get_max_charge_cntl_limit
,
447 .get_cur_state
= ps_get_cur_chrage_cntl_limit
,
448 .set_cur_state
= ps_set_cur_charge_cntl_limit
,
451 static int psy_register_cooler(struct power_supply
*psy
)
455 /* Register for cooling device if psy can control charging */
456 for (i
= 0; i
< psy
->num_properties
; i
++) {
457 if (psy
->properties
[i
] ==
458 POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT
) {
459 psy
->tcd
= thermal_cooling_device_register(
462 if (IS_ERR(psy
->tcd
))
463 return PTR_ERR(psy
->tcd
);
470 static void psy_unregister_cooler(struct power_supply
*psy
)
472 if (IS_ERR_OR_NULL(psy
->tcd
))
474 thermal_cooling_device_unregister(psy
->tcd
);
477 static int psy_register_thermal(struct power_supply
*psy
)
482 static void psy_unregister_thermal(struct power_supply
*psy
)
486 static int psy_register_cooler(struct power_supply
*psy
)
491 static void psy_unregister_cooler(struct power_supply
*psy
)
496 int power_supply_register(struct device
*parent
, struct power_supply
*psy
)
501 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
505 device_initialize(dev
);
507 dev
->class = power_supply_class
;
508 dev
->type
= &power_supply_dev_type
;
509 dev
->parent
= parent
;
510 dev
->release
= power_supply_dev_release
;
511 dev_set_drvdata(dev
, psy
);
514 rc
= dev_set_name(dev
, "%s", psy
->name
);
516 goto dev_set_name_failed
;
518 INIT_WORK(&psy
->changed_work
, power_supply_changed_work
);
520 rc
= power_supply_check_supplies(psy
);
522 dev_info(dev
, "Not all required supplies found, defer probe\n");
523 goto check_supplies_failed
;
526 spin_lock_init(&psy
->changed_lock
);
527 rc
= device_init_wakeup(dev
, true);
529 goto wakeup_init_failed
;
531 rc
= device_add(dev
);
533 goto device_add_failed
;
535 rc
= psy_register_thermal(psy
);
537 goto register_thermal_failed
;
539 rc
= psy_register_cooler(psy
);
541 goto register_cooler_failed
;
543 rc
= power_supply_create_triggers(psy
);
545 goto create_triggers_failed
;
547 power_supply_changed(psy
);
551 create_triggers_failed
:
552 psy_unregister_cooler(psy
);
553 register_cooler_failed
:
554 psy_unregister_thermal(psy
);
555 register_thermal_failed
:
559 check_supplies_failed
:
565 EXPORT_SYMBOL_GPL(power_supply_register
);
567 void power_supply_unregister(struct power_supply
*psy
)
569 cancel_work_sync(&psy
->changed_work
);
570 sysfs_remove_link(&psy
->dev
->kobj
, "powers");
571 power_supply_remove_triggers(psy
);
572 psy_unregister_cooler(psy
);
573 psy_unregister_thermal(psy
);
574 device_init_wakeup(psy
->dev
, false);
575 device_unregister(psy
->dev
);
577 EXPORT_SYMBOL_GPL(power_supply_unregister
);
579 static int __init
power_supply_class_init(void)
581 power_supply_class
= class_create(THIS_MODULE
, "power_supply");
583 if (IS_ERR(power_supply_class
))
584 return PTR_ERR(power_supply_class
);
586 power_supply_class
->dev_uevent
= power_supply_uevent
;
587 power_supply_init_attrs(&power_supply_dev_type
);
592 static void __exit
power_supply_class_exit(void)
594 class_destroy(power_supply_class
);
597 subsys_initcall(power_supply_class_init
);
598 module_exit(power_supply_class_exit
);
600 MODULE_DESCRIPTION("Universal power supply monitor class");
601 MODULE_AUTHOR("Ian Molton <spyro@f2s.com>, "
603 "Anton Vorontsov <cbou@mail.ru>");
604 MODULE_LICENSE("GPL");