xref: /openbmc/linux/drivers/acpi/battery.c (revision 87c2ce3b)
1 /*
2  *  acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or (at
12  *  your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  */
25 
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
31 #include <linux/seq_file.h>
32 #include <asm/uaccess.h>
33 
34 #include <acpi/acpi_bus.h>
35 #include <acpi/acpi_drivers.h>
36 
37 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
38 
39 #define ACPI_BATTERY_FORMAT_BIF	"NNNNNNNNNSSSS"
40 #define ACPI_BATTERY_FORMAT_BST	"NNNN"
41 
42 #define ACPI_BATTERY_COMPONENT		0x00040000
43 #define ACPI_BATTERY_CLASS		"battery"
44 #define ACPI_BATTERY_HID		"PNP0C0A"
45 #define ACPI_BATTERY_DRIVER_NAME	"ACPI Battery Driver"
46 #define ACPI_BATTERY_DEVICE_NAME	"Battery"
47 #define ACPI_BATTERY_FILE_INFO		"info"
48 #define ACPI_BATTERY_FILE_STATUS	"state"
49 #define ACPI_BATTERY_FILE_ALARM		"alarm"
50 #define ACPI_BATTERY_NOTIFY_STATUS	0x80
51 #define ACPI_BATTERY_NOTIFY_INFO	0x81
52 #define ACPI_BATTERY_UNITS_WATTS	"mW"
53 #define ACPI_BATTERY_UNITS_AMPS		"mA"
54 
55 #define _COMPONENT		ACPI_BATTERY_COMPONENT
56 ACPI_MODULE_NAME("acpi_battery")
57 
58     MODULE_AUTHOR("Paul Diefenbaugh");
59 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
60 MODULE_LICENSE("GPL");
61 
62 static int acpi_battery_add(struct acpi_device *device);
63 static int acpi_battery_remove(struct acpi_device *device, int type);
64 
65 static struct acpi_driver acpi_battery_driver = {
66 	.name = ACPI_BATTERY_DRIVER_NAME,
67 	.class = ACPI_BATTERY_CLASS,
68 	.ids = ACPI_BATTERY_HID,
69 	.ops = {
70 		.add = acpi_battery_add,
71 		.remove = acpi_battery_remove,
72 		},
73 };
74 
75 struct acpi_battery_status {
76 	acpi_integer state;
77 	acpi_integer present_rate;
78 	acpi_integer remaining_capacity;
79 	acpi_integer present_voltage;
80 };
81 
82 struct acpi_battery_info {
83 	acpi_integer power_unit;
84 	acpi_integer design_capacity;
85 	acpi_integer last_full_capacity;
86 	acpi_integer battery_technology;
87 	acpi_integer design_voltage;
88 	acpi_integer design_capacity_warning;
89 	acpi_integer design_capacity_low;
90 	acpi_integer battery_capacity_granularity_1;
91 	acpi_integer battery_capacity_granularity_2;
92 	acpi_string model_number;
93 	acpi_string serial_number;
94 	acpi_string battery_type;
95 	acpi_string oem_info;
96 };
97 
98 struct acpi_battery_flags {
99 	u8 present:1;		/* Bay occupied? */
100 	u8 power_unit:1;	/* 0=watts, 1=apms */
101 	u8 alarm:1;		/* _BTP present? */
102 	u8 reserved:5;
103 };
104 
105 struct acpi_battery_trips {
106 	unsigned long warning;
107 	unsigned long low;
108 };
109 
110 struct acpi_battery {
111 	acpi_handle handle;
112 	struct acpi_battery_flags flags;
113 	struct acpi_battery_trips trips;
114 	unsigned long alarm;
115 	struct acpi_battery_info *info;
116 };
117 
118 /* --------------------------------------------------------------------------
119                                Battery Management
120    -------------------------------------------------------------------------- */
121 
122 static int
123 acpi_battery_get_info(struct acpi_battery *battery,
124 		      struct acpi_battery_info **bif)
125 {
126 	int result = 0;
127 	acpi_status status = 0;
128 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
129 	struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
130 		ACPI_BATTERY_FORMAT_BIF
131 	};
132 	struct acpi_buffer data = { 0, NULL };
133 	union acpi_object *package = NULL;
134 
135 	ACPI_FUNCTION_TRACE("acpi_battery_get_info");
136 
137 	if (!battery || !bif)
138 		return_VALUE(-EINVAL);
139 
140 	/* Evalute _BIF */
141 
142 	status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
143 	if (ACPI_FAILURE(status)) {
144 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
145 		return_VALUE(-ENODEV);
146 	}
147 
148 	package = (union acpi_object *)buffer.pointer;
149 
150 	/* Extract Package Data */
151 
152 	status = acpi_extract_package(package, &format, &data);
153 	if (status != AE_BUFFER_OVERFLOW) {
154 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
155 		result = -ENODEV;
156 		goto end;
157 	}
158 
159 	data.pointer = kmalloc(data.length, GFP_KERNEL);
160 	if (!data.pointer) {
161 		result = -ENOMEM;
162 		goto end;
163 	}
164 	memset(data.pointer, 0, data.length);
165 
166 	status = acpi_extract_package(package, &format, &data);
167 	if (ACPI_FAILURE(status)) {
168 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
169 		kfree(data.pointer);
170 		result = -ENODEV;
171 		goto end;
172 	}
173 
174       end:
175 	acpi_os_free(buffer.pointer);
176 
177 	if (!result)
178 		(*bif) = (struct acpi_battery_info *)data.pointer;
179 
180 	return_VALUE(result);
181 }
182 
183 static int
184 acpi_battery_get_status(struct acpi_battery *battery,
185 			struct acpi_battery_status **bst)
186 {
187 	int result = 0;
188 	acpi_status status = 0;
189 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
190 	struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
191 		ACPI_BATTERY_FORMAT_BST
192 	};
193 	struct acpi_buffer data = { 0, NULL };
194 	union acpi_object *package = NULL;
195 
196 	ACPI_FUNCTION_TRACE("acpi_battery_get_status");
197 
198 	if (!battery || !bst)
199 		return_VALUE(-EINVAL);
200 
201 	/* Evalute _BST */
202 
203 	status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
204 	if (ACPI_FAILURE(status)) {
205 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
206 		return_VALUE(-ENODEV);
207 	}
208 
209 	package = (union acpi_object *)buffer.pointer;
210 
211 	/* Extract Package Data */
212 
213 	status = acpi_extract_package(package, &format, &data);
214 	if (status != AE_BUFFER_OVERFLOW) {
215 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
216 		result = -ENODEV;
217 		goto end;
218 	}
219 
220 	data.pointer = kmalloc(data.length, GFP_KERNEL);
221 	if (!data.pointer) {
222 		result = -ENOMEM;
223 		goto end;
224 	}
225 	memset(data.pointer, 0, data.length);
226 
227 	status = acpi_extract_package(package, &format, &data);
228 	if (ACPI_FAILURE(status)) {
229 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
230 		kfree(data.pointer);
231 		result = -ENODEV;
232 		goto end;
233 	}
234 
235       end:
236 	acpi_os_free(buffer.pointer);
237 
238 	if (!result)
239 		(*bst) = (struct acpi_battery_status *)data.pointer;
240 
241 	return_VALUE(result);
242 }
243 
244 static int
245 acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
246 {
247 	acpi_status status = 0;
248 	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
249 	struct acpi_object_list arg_list = { 1, &arg0 };
250 
251 	ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
252 
253 	if (!battery)
254 		return_VALUE(-EINVAL);
255 
256 	if (!battery->flags.alarm)
257 		return_VALUE(-ENODEV);
258 
259 	arg0.integer.value = alarm;
260 
261 	status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL);
262 	if (ACPI_FAILURE(status))
263 		return_VALUE(-ENODEV);
264 
265 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
266 
267 	battery->alarm = alarm;
268 
269 	return_VALUE(0);
270 }
271 
272 static int acpi_battery_check(struct acpi_battery *battery)
273 {
274 	int result = 0;
275 	acpi_status status = AE_OK;
276 	acpi_handle handle = NULL;
277 	struct acpi_device *device = NULL;
278 	struct acpi_battery_info *bif = NULL;
279 
280 	ACPI_FUNCTION_TRACE("acpi_battery_check");
281 
282 	if (!battery)
283 		return_VALUE(-EINVAL);
284 
285 	result = acpi_bus_get_device(battery->handle, &device);
286 	if (result)
287 		return_VALUE(result);
288 
289 	result = acpi_bus_get_status(device);
290 	if (result)
291 		return_VALUE(result);
292 
293 	/* Insertion? */
294 
295 	if (!battery->flags.present && device->status.battery_present) {
296 
297 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
298 
299 		/* Evalute _BIF to get certain static information */
300 
301 		result = acpi_battery_get_info(battery, &bif);
302 		if (result)
303 			return_VALUE(result);
304 
305 		battery->flags.power_unit = bif->power_unit;
306 		battery->trips.warning = bif->design_capacity_warning;
307 		battery->trips.low = bif->design_capacity_low;
308 		kfree(bif);
309 
310 		/* See if alarms are supported, and if so, set default */
311 
312 		status = acpi_get_handle(battery->handle, "_BTP", &handle);
313 		if (ACPI_SUCCESS(status)) {
314 			battery->flags.alarm = 1;
315 			acpi_battery_set_alarm(battery, battery->trips.warning);
316 		}
317 	}
318 
319 	/* Removal? */
320 
321 	else if (battery->flags.present && !device->status.battery_present) {
322 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
323 	}
324 
325 	battery->flags.present = device->status.battery_present;
326 
327 	return_VALUE(result);
328 }
329 
330 /* --------------------------------------------------------------------------
331                               FS Interface (/proc)
332    -------------------------------------------------------------------------- */
333 
334 static struct proc_dir_entry *acpi_battery_dir;
335 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
336 {
337 	int result = 0;
338 	struct acpi_battery *battery = (struct acpi_battery *)seq->private;
339 	struct acpi_battery_info *bif = NULL;
340 	char *units = "?";
341 
342 	ACPI_FUNCTION_TRACE("acpi_battery_read_info");
343 
344 	if (!battery)
345 		goto end;
346 
347 	if (battery->flags.present)
348 		seq_printf(seq, "present:                 yes\n");
349 	else {
350 		seq_printf(seq, "present:                 no\n");
351 		goto end;
352 	}
353 
354 	/* Battery Info (_BIF) */
355 
356 	result = acpi_battery_get_info(battery, &bif);
357 	if (result || !bif) {
358 		seq_printf(seq, "ERROR: Unable to read battery information\n");
359 		goto end;
360 	}
361 
362 	units =
363 	    bif->
364 	    power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
365 
366 	if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
367 		seq_printf(seq, "design capacity:         unknown\n");
368 	else
369 		seq_printf(seq, "design capacity:         %d %sh\n",
370 			   (u32) bif->design_capacity, units);
371 
372 	if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
373 		seq_printf(seq, "last full capacity:      unknown\n");
374 	else
375 		seq_printf(seq, "last full capacity:      %d %sh\n",
376 			   (u32) bif->last_full_capacity, units);
377 
378 	switch ((u32) bif->battery_technology) {
379 	case 0:
380 		seq_printf(seq, "battery technology:      non-rechargeable\n");
381 		break;
382 	case 1:
383 		seq_printf(seq, "battery technology:      rechargeable\n");
384 		break;
385 	default:
386 		seq_printf(seq, "battery technology:      unknown\n");
387 		break;
388 	}
389 
390 	if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
391 		seq_printf(seq, "design voltage:          unknown\n");
392 	else
393 		seq_printf(seq, "design voltage:          %d mV\n",
394 			   (u32) bif->design_voltage);
395 
396 	seq_printf(seq, "design capacity warning: %d %sh\n",
397 		   (u32) bif->design_capacity_warning, units);
398 	seq_printf(seq, "design capacity low:     %d %sh\n",
399 		   (u32) bif->design_capacity_low, units);
400 	seq_printf(seq, "capacity granularity 1:  %d %sh\n",
401 		   (u32) bif->battery_capacity_granularity_1, units);
402 	seq_printf(seq, "capacity granularity 2:  %d %sh\n",
403 		   (u32) bif->battery_capacity_granularity_2, units);
404 	seq_printf(seq, "model number:            %s\n", bif->model_number);
405 	seq_printf(seq, "serial number:           %s\n", bif->serial_number);
406 	seq_printf(seq, "battery type:            %s\n", bif->battery_type);
407 	seq_printf(seq, "OEM info:                %s\n", bif->oem_info);
408 
409       end:
410 	kfree(bif);
411 
412 	return_VALUE(0);
413 }
414 
415 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
416 {
417 	return single_open(file, acpi_battery_read_info, PDE(inode)->data);
418 }
419 
420 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
421 {
422 	int result = 0;
423 	struct acpi_battery *battery = (struct acpi_battery *)seq->private;
424 	struct acpi_battery_status *bst = NULL;
425 	char *units = "?";
426 
427 	ACPI_FUNCTION_TRACE("acpi_battery_read_state");
428 
429 	if (!battery)
430 		goto end;
431 
432 	if (battery->flags.present)
433 		seq_printf(seq, "present:                 yes\n");
434 	else {
435 		seq_printf(seq, "present:                 no\n");
436 		goto end;
437 	}
438 
439 	/* Battery Units */
440 
441 	units =
442 	    battery->flags.
443 	    power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
444 
445 	/* Battery Status (_BST) */
446 
447 	result = acpi_battery_get_status(battery, &bst);
448 	if (result || !bst) {
449 		seq_printf(seq, "ERROR: Unable to read battery status\n");
450 		goto end;
451 	}
452 
453 	if (!(bst->state & 0x04))
454 		seq_printf(seq, "capacity state:          ok\n");
455 	else
456 		seq_printf(seq, "capacity state:          critical\n");
457 
458 	if ((bst->state & 0x01) && (bst->state & 0x02)) {
459 		seq_printf(seq,
460 			   "charging state:          charging/discharging\n");
461 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
462 				  "Battery Charging and Discharging?\n"));
463 	} else if (bst->state & 0x01)
464 		seq_printf(seq, "charging state:          discharging\n");
465 	else if (bst->state & 0x02)
466 		seq_printf(seq, "charging state:          charging\n");
467 	else {
468 		seq_printf(seq, "charging state:          charged\n");
469 	}
470 
471 	if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
472 		seq_printf(seq, "present rate:            unknown\n");
473 	else
474 		seq_printf(seq, "present rate:            %d %s\n",
475 			   (u32) bst->present_rate, units);
476 
477 	if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
478 		seq_printf(seq, "remaining capacity:      unknown\n");
479 	else
480 		seq_printf(seq, "remaining capacity:      %d %sh\n",
481 			   (u32) bst->remaining_capacity, units);
482 
483 	if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
484 		seq_printf(seq, "present voltage:         unknown\n");
485 	else
486 		seq_printf(seq, "present voltage:         %d mV\n",
487 			   (u32) bst->present_voltage);
488 
489       end:
490 	kfree(bst);
491 
492 	return_VALUE(0);
493 }
494 
495 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
496 {
497 	return single_open(file, acpi_battery_read_state, PDE(inode)->data);
498 }
499 
500 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
501 {
502 	struct acpi_battery *battery = (struct acpi_battery *)seq->private;
503 	char *units = "?";
504 
505 	ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
506 
507 	if (!battery)
508 		goto end;
509 
510 	if (!battery->flags.present) {
511 		seq_printf(seq, "present:                 no\n");
512 		goto end;
513 	}
514 
515 	/* Battery Units */
516 
517 	units =
518 	    battery->flags.
519 	    power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
520 
521 	/* Battery Alarm */
522 
523 	seq_printf(seq, "alarm:                   ");
524 	if (!battery->alarm)
525 		seq_printf(seq, "unsupported\n");
526 	else
527 		seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
528 
529       end:
530 	return_VALUE(0);
531 }
532 
533 static ssize_t
534 acpi_battery_write_alarm(struct file *file,
535 			 const char __user * buffer,
536 			 size_t count, loff_t * ppos)
537 {
538 	int result = 0;
539 	char alarm_string[12] = { '\0' };
540 	struct seq_file *m = (struct seq_file *)file->private_data;
541 	struct acpi_battery *battery = (struct acpi_battery *)m->private;
542 
543 	ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
544 
545 	if (!battery || (count > sizeof(alarm_string) - 1))
546 		return_VALUE(-EINVAL);
547 
548 	if (!battery->flags.present)
549 		return_VALUE(-ENODEV);
550 
551 	if (copy_from_user(alarm_string, buffer, count))
552 		return_VALUE(-EFAULT);
553 
554 	alarm_string[count] = '\0';
555 
556 	result = acpi_battery_set_alarm(battery,
557 					simple_strtoul(alarm_string, NULL, 0));
558 	if (result)
559 		return_VALUE(result);
560 
561 	return_VALUE(count);
562 }
563 
564 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
565 {
566 	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
567 }
568 
569 static struct file_operations acpi_battery_info_ops = {
570 	.open = acpi_battery_info_open_fs,
571 	.read = seq_read,
572 	.llseek = seq_lseek,
573 	.release = single_release,
574 	.owner = THIS_MODULE,
575 };
576 
577 static struct file_operations acpi_battery_state_ops = {
578 	.open = acpi_battery_state_open_fs,
579 	.read = seq_read,
580 	.llseek = seq_lseek,
581 	.release = single_release,
582 	.owner = THIS_MODULE,
583 };
584 
585 static struct file_operations acpi_battery_alarm_ops = {
586 	.open = acpi_battery_alarm_open_fs,
587 	.read = seq_read,
588 	.write = acpi_battery_write_alarm,
589 	.llseek = seq_lseek,
590 	.release = single_release,
591 	.owner = THIS_MODULE,
592 };
593 
594 static int acpi_battery_add_fs(struct acpi_device *device)
595 {
596 	struct proc_dir_entry *entry = NULL;
597 
598 	ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
599 
600 	if (!acpi_device_dir(device)) {
601 		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
602 						     acpi_battery_dir);
603 		if (!acpi_device_dir(device))
604 			return_VALUE(-ENODEV);
605 		acpi_device_dir(device)->owner = THIS_MODULE;
606 	}
607 
608 	/* 'info' [R] */
609 	entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
610 				  S_IRUGO, acpi_device_dir(device));
611 	if (!entry)
612 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
613 				  "Unable to create '%s' fs entry\n",
614 				  ACPI_BATTERY_FILE_INFO));
615 	else {
616 		entry->proc_fops = &acpi_battery_info_ops;
617 		entry->data = acpi_driver_data(device);
618 		entry->owner = THIS_MODULE;
619 	}
620 
621 	/* 'status' [R] */
622 	entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
623 				  S_IRUGO, acpi_device_dir(device));
624 	if (!entry)
625 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
626 				  "Unable to create '%s' fs entry\n",
627 				  ACPI_BATTERY_FILE_STATUS));
628 	else {
629 		entry->proc_fops = &acpi_battery_state_ops;
630 		entry->data = acpi_driver_data(device);
631 		entry->owner = THIS_MODULE;
632 	}
633 
634 	/* 'alarm' [R/W] */
635 	entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
636 				  S_IFREG | S_IRUGO | S_IWUSR,
637 				  acpi_device_dir(device));
638 	if (!entry)
639 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
640 				  "Unable to create '%s' fs entry\n",
641 				  ACPI_BATTERY_FILE_ALARM));
642 	else {
643 		entry->proc_fops = &acpi_battery_alarm_ops;
644 		entry->data = acpi_driver_data(device);
645 		entry->owner = THIS_MODULE;
646 	}
647 
648 	return_VALUE(0);
649 }
650 
651 static int acpi_battery_remove_fs(struct acpi_device *device)
652 {
653 	ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
654 
655 	if (acpi_device_dir(device)) {
656 		remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
657 				  acpi_device_dir(device));
658 		remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
659 				  acpi_device_dir(device));
660 		remove_proc_entry(ACPI_BATTERY_FILE_INFO,
661 				  acpi_device_dir(device));
662 
663 		remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
664 		acpi_device_dir(device) = NULL;
665 	}
666 
667 	return_VALUE(0);
668 }
669 
670 /* --------------------------------------------------------------------------
671                                  Driver Interface
672    -------------------------------------------------------------------------- */
673 
674 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
675 {
676 	struct acpi_battery *battery = (struct acpi_battery *)data;
677 	struct acpi_device *device = NULL;
678 
679 	ACPI_FUNCTION_TRACE("acpi_battery_notify");
680 
681 	if (!battery)
682 		return_VOID;
683 
684 	if (acpi_bus_get_device(handle, &device))
685 		return_VOID;
686 
687 	switch (event) {
688 	case ACPI_BATTERY_NOTIFY_STATUS:
689 	case ACPI_BATTERY_NOTIFY_INFO:
690 		acpi_battery_check(battery);
691 		acpi_bus_generate_event(device, event, battery->flags.present);
692 		break;
693 	default:
694 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
695 				  "Unsupported event [0x%x]\n", event));
696 		break;
697 	}
698 
699 	return_VOID;
700 }
701 
702 static int acpi_battery_add(struct acpi_device *device)
703 {
704 	int result = 0;
705 	acpi_status status = 0;
706 	struct acpi_battery *battery = NULL;
707 
708 	ACPI_FUNCTION_TRACE("acpi_battery_add");
709 
710 	if (!device)
711 		return_VALUE(-EINVAL);
712 
713 	battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
714 	if (!battery)
715 		return_VALUE(-ENOMEM);
716 	memset(battery, 0, sizeof(struct acpi_battery));
717 
718 	battery->handle = device->handle;
719 	strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
720 	strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
721 	acpi_driver_data(device) = battery;
722 
723 	result = acpi_battery_check(battery);
724 	if (result)
725 		goto end;
726 
727 	result = acpi_battery_add_fs(device);
728 	if (result)
729 		goto end;
730 
731 	status = acpi_install_notify_handler(battery->handle,
732 					     ACPI_DEVICE_NOTIFY,
733 					     acpi_battery_notify, battery);
734 	if (ACPI_FAILURE(status)) {
735 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
736 				  "Error installing notify handler\n"));
737 		result = -ENODEV;
738 		goto end;
739 	}
740 
741 	printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
742 	       ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
743 	       device->status.battery_present ? "present" : "absent");
744 
745       end:
746 	if (result) {
747 		acpi_battery_remove_fs(device);
748 		kfree(battery);
749 	}
750 
751 	return_VALUE(result);
752 }
753 
754 static int acpi_battery_remove(struct acpi_device *device, int type)
755 {
756 	acpi_status status = 0;
757 	struct acpi_battery *battery = NULL;
758 
759 	ACPI_FUNCTION_TRACE("acpi_battery_remove");
760 
761 	if (!device || !acpi_driver_data(device))
762 		return_VALUE(-EINVAL);
763 
764 	battery = (struct acpi_battery *)acpi_driver_data(device);
765 
766 	status = acpi_remove_notify_handler(battery->handle,
767 					    ACPI_DEVICE_NOTIFY,
768 					    acpi_battery_notify);
769 	if (ACPI_FAILURE(status))
770 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
771 				  "Error removing notify handler\n"));
772 
773 	acpi_battery_remove_fs(device);
774 
775 	kfree(battery);
776 
777 	return_VALUE(0);
778 }
779 
780 static int __init acpi_battery_init(void)
781 {
782 	int result = 0;
783 
784 	ACPI_FUNCTION_TRACE("acpi_battery_init");
785 
786 	acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
787 	if (!acpi_battery_dir)
788 		return_VALUE(-ENODEV);
789 	acpi_battery_dir->owner = THIS_MODULE;
790 
791 	result = acpi_bus_register_driver(&acpi_battery_driver);
792 	if (result < 0) {
793 		remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
794 		return_VALUE(-ENODEV);
795 	}
796 
797 	return_VALUE(0);
798 }
799 
800 static void __exit acpi_battery_exit(void)
801 {
802 	ACPI_FUNCTION_TRACE("acpi_battery_exit");
803 
804 	acpi_bus_unregister_driver(&acpi_battery_driver);
805 
806 	remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
807 
808 	return_VOID;
809 }
810 
811 module_init(acpi_battery_init);
812 module_exit(acpi_battery_exit);
813