aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-09-26 11:43:04 -0400
committerLen Brown <len.brown@intel.com>2007-09-27 15:50:22 -0400
commitd7380965752505951668e85de59c128d1d6fd21f (patch)
treeaeb4bf05e111047c17619e01abe6dbfce67364a4
parentaa650bbdcb94bde4292eabc44490970825c98669 (diff)
ACPI: Battery: Add sysfs support
Refer to Documentation/power_supply_class.txt for interface description. Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/battery.c186
2 files changed, 165 insertions, 23 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 4875f0149eb4..8560bc3b157b 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -97,7 +97,7 @@ config ACPI_AC
97 97
98config ACPI_BATTERY 98config ACPI_BATTERY
99 tristate "Battery" 99 tristate "Battery"
100 depends on X86 100 depends on X86 && POWER_SUPPLY
101 default y 101 default y
102 help 102 help
103 This driver adds support for battery information through 103 This driver adds support for battery information through
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index db725bfe5840..057a5eb67ccc 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -30,13 +30,18 @@
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/types.h> 31#include <linux/types.h>
32#include <linux/jiffies.h> 32#include <linux/jiffies.h>
33
34#ifdef CONFIG_ACPI_PROCFS
33#include <linux/proc_fs.h> 35#include <linux/proc_fs.h>
34#include <linux/seq_file.h> 36#include <linux/seq_file.h>
35#include <asm/uaccess.h> 37#include <asm/uaccess.h>
38#endif
36 39
37#include <acpi/acpi_bus.h> 40#include <acpi/acpi_bus.h>
38#include <acpi/acpi_drivers.h> 41#include <acpi/acpi_drivers.h>
39 42
43#include <linux/power_supply.h>
44
40#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF 45#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
41 46
42#define ACPI_BATTERY_COMPONENT 0x00040000 47#define ACPI_BATTERY_COMPONENT 0x00040000
@@ -58,9 +63,19 @@ static unsigned int cache_time = 1000;
58module_param(cache_time, uint, 0644); 63module_param(cache_time, uint, 0644);
59MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); 64MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
60 65
66#ifdef CONFIG_ACPI_PROCFS
61extern struct proc_dir_entry *acpi_lock_battery_dir(void); 67extern struct proc_dir_entry *acpi_lock_battery_dir(void);
62extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 68extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
63 69
70enum acpi_battery_files {
71 info_tag = 0,
72 state_tag,
73 alarm_tag,
74 ACPI_BATTERY_NUMFILES,
75};
76
77#endif
78
64static const struct acpi_device_id battery_device_ids[] = { 79static const struct acpi_device_id battery_device_ids[] = {
65 {"PNP0C0A", 0}, 80 {"PNP0C0A", 0},
66 {"", 0}, 81 {"", 0},
@@ -68,22 +83,17 @@ static const struct acpi_device_id battery_device_ids[] = {
68 83
69MODULE_DEVICE_TABLE(acpi, battery_device_ids); 84MODULE_DEVICE_TABLE(acpi, battery_device_ids);
70 85
71enum acpi_battery_files {
72 info_tag = 0,
73 state_tag,
74 alarm_tag,
75 ACPI_BATTERY_NUMFILES,
76};
77 86
78struct acpi_battery { 87struct acpi_battery {
79 struct mutex lock; 88 struct mutex lock;
89 struct power_supply bat;
80 struct acpi_device *device; 90 struct acpi_device *device;
81 unsigned long update_time; 91 unsigned long update_time;
82 int present_rate; 92 int current_now;
83 int remaining_capacity; 93 int capacity_now;
84 int present_voltage; 94 int voltage_now;
85 int design_capacity; 95 int design_capacity;
86 int last_full_capacity; 96 int full_charge_capacity;
87 int technology; 97 int technology;
88 int design_voltage; 98 int design_voltage;
89 int design_capacity_warning; 99 int design_capacity_warning;
@@ -100,15 +110,117 @@ struct acpi_battery {
100 u8 alarm_present; 110 u8 alarm_present;
101}; 111};
102 112
113#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
114
103inline int acpi_battery_present(struct acpi_battery *battery) 115inline int acpi_battery_present(struct acpi_battery *battery)
104{ 116{
105 return battery->device->status.battery_present; 117 return battery->device->status.battery_present;
106} 118}
107 119
120static int acpi_battery_technology(struct acpi_battery *battery)
121{
122 if (!strcasecmp("NiCd", battery->type))
123 return POWER_SUPPLY_TECHNOLOGY_NiCd;
124 if (!strcasecmp("NiMH", battery->type))
125 return POWER_SUPPLY_TECHNOLOGY_NiMH;
126 if (!strcasecmp("LION", battery->type))
127 return POWER_SUPPLY_TECHNOLOGY_LION;
128 if (!strcasecmp("LiP", battery->type))
129 return POWER_SUPPLY_TECHNOLOGY_LIPO;
130 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
131}
132
133static int acpi_battery_get_property(struct power_supply *psy,
134 enum power_supply_property psp,
135 union power_supply_propval *val)
136{
137 struct acpi_battery *battery = to_acpi_battery(psy);
138
139 if ((!acpi_battery_present(battery)) &&
140 psp != POWER_SUPPLY_PROP_PRESENT)
141 return -ENODEV;
142 switch (psp) {
143 case POWER_SUPPLY_PROP_STATUS:
144 if (battery->state & 0x01)
145 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
146 else if (battery->state & 0x02)
147 val->intval = POWER_SUPPLY_STATUS_CHARGING;
148 else if (battery->state == 0)
149 val->intval = POWER_SUPPLY_STATUS_FULL;
150 break;
151 case POWER_SUPPLY_PROP_PRESENT:
152 val->intval = acpi_battery_present(battery);
153 break;
154 case POWER_SUPPLY_PROP_TECHNOLOGY:
155 val->intval = acpi_battery_technology(battery);
156 break;
157 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
158 val->intval = battery->design_voltage * 1000;
159 break;
160 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
161 val->intval = battery->voltage_now * 1000;
162 break;
163 case POWER_SUPPLY_PROP_CURRENT_NOW:
164 val->intval = battery->current_now * 1000;
165 break;
166 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
167 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
168 val->intval = battery->design_capacity * 1000;
169 break;
170 case POWER_SUPPLY_PROP_CHARGE_FULL:
171 case POWER_SUPPLY_PROP_ENERGY_FULL:
172 val->intval = battery->full_charge_capacity * 1000;
173 break;
174 case POWER_SUPPLY_PROP_CHARGE_NOW:
175 case POWER_SUPPLY_PROP_ENERGY_NOW:
176 val->intval = battery->capacity_now * 1000;
177 break;
178 case POWER_SUPPLY_PROP_MODEL_NAME:
179 val->strval = battery->model_number;
180 break;
181 case POWER_SUPPLY_PROP_MANUFACTURER:
182 val->strval = battery->oem_info;
183 break;
184 default:
185 return -EINVAL;
186 }
187 return 0;
188}
189
190static enum power_supply_property charge_battery_props[] = {
191 POWER_SUPPLY_PROP_STATUS,
192 POWER_SUPPLY_PROP_PRESENT,
193 POWER_SUPPLY_PROP_TECHNOLOGY,
194 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
195 POWER_SUPPLY_PROP_VOLTAGE_NOW,
196 POWER_SUPPLY_PROP_CURRENT_NOW,
197 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
198 POWER_SUPPLY_PROP_CHARGE_FULL,
199 POWER_SUPPLY_PROP_CHARGE_NOW,
200 POWER_SUPPLY_PROP_MODEL_NAME,
201 POWER_SUPPLY_PROP_MANUFACTURER,
202};
203
204static enum power_supply_property energy_battery_props[] = {
205 POWER_SUPPLY_PROP_STATUS,
206 POWER_SUPPLY_PROP_PRESENT,
207 POWER_SUPPLY_PROP_TECHNOLOGY,
208 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
209 POWER_SUPPLY_PROP_VOLTAGE_NOW,
210 POWER_SUPPLY_PROP_CURRENT_NOW,
211 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
212 POWER_SUPPLY_PROP_ENERGY_FULL,
213 POWER_SUPPLY_PROP_ENERGY_NOW,
214 POWER_SUPPLY_PROP_MODEL_NAME,
215 POWER_SUPPLY_PROP_MANUFACTURER,
216};
217
218#ifdef CONFIG_ACPI_PROCFS
108inline char *acpi_battery_units(struct acpi_battery *battery) 219inline char *acpi_battery_units(struct acpi_battery *battery)
109{ 220{
110 return (battery->power_unit)?"mA":"mW"; 221 return (battery->power_unit)?"mA":"mW";
111} 222}
223#endif
112 224
113/* -------------------------------------------------------------------------- 225/* --------------------------------------------------------------------------
114 Battery Management 226 Battery Management
@@ -120,15 +232,15 @@ struct acpi_offsets {
120 232
121static struct acpi_offsets state_offsets[] = { 233static struct acpi_offsets state_offsets[] = {
122 {offsetof(struct acpi_battery, state), 0}, 234 {offsetof(struct acpi_battery, state), 0},
123 {offsetof(struct acpi_battery, present_rate), 0}, 235 {offsetof(struct acpi_battery, current_now), 0},
124 {offsetof(struct acpi_battery, remaining_capacity), 0}, 236 {offsetof(struct acpi_battery, capacity_now), 0},
125 {offsetof(struct acpi_battery, present_voltage), 0}, 237 {offsetof(struct acpi_battery, voltage_now), 0},
126}; 238};
127 239
128static struct acpi_offsets info_offsets[] = { 240static struct acpi_offsets info_offsets[] = {
129 {offsetof(struct acpi_battery, power_unit), 0}, 241 {offsetof(struct acpi_battery, power_unit), 0},
130 {offsetof(struct acpi_battery, design_capacity), 0}, 242 {offsetof(struct acpi_battery, design_capacity), 0},
131 {offsetof(struct acpi_battery, last_full_capacity), 0}, 243 {offsetof(struct acpi_battery, full_charge_capacity), 0},
132 {offsetof(struct acpi_battery, technology), 0}, 244 {offsetof(struct acpi_battery, technology), 0},
133 {offsetof(struct acpi_battery, design_voltage), 0}, 245 {offsetof(struct acpi_battery, design_voltage), 0},
134 {offsetof(struct acpi_battery, design_capacity_warning), 0}, 246 {offsetof(struct acpi_battery, design_capacity_warning), 0},
@@ -285,6 +397,15 @@ static int acpi_battery_update(struct acpi_battery *battery)
285 result = acpi_battery_get_info(battery); 397 result = acpi_battery_get_info(battery);
286 if (result) 398 if (result)
287 return result; 399 return result;
400 if (battery->power_unit) {
401 battery->bat.properties = charge_battery_props;
402 battery->bat.num_properties =
403 ARRAY_SIZE(charge_battery_props);
404 } else {
405 battery->bat.properties = energy_battery_props;
406 battery->bat.num_properties =
407 ARRAY_SIZE(energy_battery_props);
408 }
288 acpi_battery_init_alarm(battery); 409 acpi_battery_init_alarm(battery);
289 } 410 }
290 return acpi_battery_get_state(battery); 411 return acpi_battery_get_state(battery);
@@ -294,6 +415,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
294 FS Interface (/proc) 415 FS Interface (/proc)
295 -------------------------------------------------------------------------- */ 416 -------------------------------------------------------------------------- */
296 417
418#ifdef CONFIG_ACPI_PROCFS
297static struct proc_dir_entry *acpi_battery_dir; 419static struct proc_dir_entry *acpi_battery_dir;
298 420
299static int acpi_battery_print_info(struct seq_file *seq, int result) 421static int acpi_battery_print_info(struct seq_file *seq, int result)
@@ -314,11 +436,11 @@ static int acpi_battery_print_info(struct seq_file *seq, int result)
314 battery->design_capacity, 436 battery->design_capacity,
315 acpi_battery_units(battery)); 437 acpi_battery_units(battery));
316 438
317 if (battery->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 439 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
318 seq_printf(seq, "last full capacity: unknown\n"); 440 seq_printf(seq, "last full capacity: unknown\n");
319 else 441 else
320 seq_printf(seq, "last full capacity: %d %sh\n", 442 seq_printf(seq, "last full capacity: %d %sh\n",
321 battery->last_full_capacity, 443 battery->full_charge_capacity,
322 acpi_battery_units(battery)); 444 acpi_battery_units(battery));
323 445
324 seq_printf(seq, "battery technology: %srechargeable\n", 446 seq_printf(seq, "battery technology: %srechargeable\n",
@@ -375,22 +497,22 @@ static int acpi_battery_print_state(struct seq_file *seq, int result)
375 else 497 else
376 seq_printf(seq, "charging state: charged\n"); 498 seq_printf(seq, "charging state: charged\n");
377 499
378 if (battery->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) 500 if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN)
379 seq_printf(seq, "present rate: unknown\n"); 501 seq_printf(seq, "present rate: unknown\n");
380 else 502 else
381 seq_printf(seq, "present rate: %d %s\n", 503 seq_printf(seq, "present rate: %d %s\n",
382 battery->present_rate, acpi_battery_units(battery)); 504 battery->current_now, acpi_battery_units(battery));
383 505
384 if (battery->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 506 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
385 seq_printf(seq, "remaining capacity: unknown\n"); 507 seq_printf(seq, "remaining capacity: unknown\n");
386 else 508 else
387 seq_printf(seq, "remaining capacity: %d %sh\n", 509 seq_printf(seq, "remaining capacity: %d %sh\n",
388 battery->remaining_capacity, acpi_battery_units(battery)); 510 battery->capacity_now, acpi_battery_units(battery));
389 if (battery->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) 511 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
390 seq_printf(seq, "present voltage: unknown\n"); 512 seq_printf(seq, "present voltage: unknown\n");
391 else 513 else
392 seq_printf(seq, "present voltage: %d mV\n", 514 seq_printf(seq, "present voltage: %d mV\n",
393 battery->present_voltage); 515 battery->voltage_now);
394 end: 516 end:
395 if (result) 517 if (result)
396 seq_printf(seq, "ERROR: Unable to read battery state\n"); 518 seq_printf(seq, "ERROR: Unable to read battery state\n");
@@ -564,6 +686,7 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
564 acpi_device_dir(device) = NULL; 686 acpi_device_dir(device) = NULL;
565} 687}
566 688
689#endif
567/* -------------------------------------------------------------------------- 690/* --------------------------------------------------------------------------
568 Driver Interface 691 Driver Interface
569 -------------------------------------------------------------------------- */ 692 -------------------------------------------------------------------------- */
@@ -581,6 +704,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
581 acpi_bus_generate_netlink_event(device->pnp.device_class, 704 acpi_bus_generate_netlink_event(device->pnp.device_class,
582 device->dev.bus_id, event, 705 device->dev.bus_id, event,
583 acpi_battery_present(battery)); 706 acpi_battery_present(battery));
707 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
584} 708}
585 709
586static int acpi_battery_add(struct acpi_device *device) 710static int acpi_battery_add(struct acpi_device *device)
@@ -599,9 +723,15 @@ static int acpi_battery_add(struct acpi_device *device)
599 acpi_driver_data(device) = battery; 723 acpi_driver_data(device) = battery;
600 mutex_init(&battery->lock); 724 mutex_init(&battery->lock);
601 acpi_battery_update(battery); 725 acpi_battery_update(battery);
726#ifdef CONFIG_ACPI_PROCFS
602 result = acpi_battery_add_fs(device); 727 result = acpi_battery_add_fs(device);
603 if (result) 728 if (result)
604 goto end; 729 goto end;
730#endif
731 battery->bat.name = acpi_device_bid(device);
732 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
733 battery->bat.get_property = acpi_battery_get_property;
734 result = power_supply_register(&battery->device->dev, &battery->bat);
605 status = acpi_install_notify_handler(device->handle, 735 status = acpi_install_notify_handler(device->handle,
606 ACPI_ALL_NOTIFY, 736 ACPI_ALL_NOTIFY,
607 acpi_battery_notify, battery); 737 acpi_battery_notify, battery);
@@ -615,7 +745,9 @@ static int acpi_battery_add(struct acpi_device *device)
615 device->status.battery_present ? "present" : "absent"); 745 device->status.battery_present ? "present" : "absent");
616 end: 746 end:
617 if (result) { 747 if (result) {
748#ifdef CONFIG_ACPI_PROCFS
618 acpi_battery_remove_fs(device); 749 acpi_battery_remove_fs(device);
750#endif
619 kfree(battery); 751 kfree(battery);
620 } 752 }
621 return result; 753 return result;
@@ -632,7 +764,11 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
632 status = acpi_remove_notify_handler(device->handle, 764 status = acpi_remove_notify_handler(device->handle,
633 ACPI_ALL_NOTIFY, 765 ACPI_ALL_NOTIFY,
634 acpi_battery_notify); 766 acpi_battery_notify);
767#ifdef CONFIG_ACPI_PROCFS
635 acpi_battery_remove_fs(device); 768 acpi_battery_remove_fs(device);
769#endif
770 if (battery->bat.dev)
771 power_supply_unregister(&battery->bat);
636 mutex_destroy(&battery->lock); 772 mutex_destroy(&battery->lock);
637 kfree(battery); 773 kfree(battery);
638 return 0; 774 return 0;
@@ -664,11 +800,15 @@ static int __init acpi_battery_init(void)
664{ 800{
665 if (acpi_disabled) 801 if (acpi_disabled)
666 return -ENODEV; 802 return -ENODEV;
803#ifdef CONFIG_ACPI_PROCFS
667 acpi_battery_dir = acpi_lock_battery_dir(); 804 acpi_battery_dir = acpi_lock_battery_dir();
668 if (!acpi_battery_dir) 805 if (!acpi_battery_dir)
669 return -ENODEV; 806 return -ENODEV;
807#endif
670 if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { 808 if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
809#ifdef CONFIG_ACPI_PROCFS
671 acpi_unlock_battery_dir(acpi_battery_dir); 810 acpi_unlock_battery_dir(acpi_battery_dir);
811#endif
672 return -ENODEV; 812 return -ENODEV;
673 } 813 }
674 return 0; 814 return 0;
@@ -677,7 +817,9 @@ static int __init acpi_battery_init(void)
677static void __exit acpi_battery_exit(void) 817static void __exit acpi_battery_exit(void)
678{ 818{
679 acpi_bus_unregister_driver(&acpi_battery_driver); 819 acpi_bus_unregister_driver(&acpi_battery_driver);
820#ifdef CONFIG_ACPI_PROCFS
680 acpi_unlock_battery_dir(acpi_battery_dir); 821 acpi_unlock_battery_dir(acpi_battery_dir);
822#endif
681} 823}
682 824
683module_init(acpi_battery_init); 825module_init(acpi_battery_init);