battery.c 27.9 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2
 *  battery.c - ACPI Battery Driver (Revision: 2.0)
L
Linus Torvalds 已提交
3
 *
4 5
 *  Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
 *  Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
L
Linus Torvalds 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or (at
 *  your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
32
#include <linux/jiffies.h>
33
#include <linux/async.h>
34
#include <linux/dmi.h>
35
#include <linux/slab.h>
36

37
#ifdef CONFIG_ACPI_PROCFS_POWER
L
Linus Torvalds 已提交
38 39 40
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
41
#endif
L
Linus Torvalds 已提交
42 43 44

#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
45 46
#include <linux/power_supply.h>

47 48
#define PREFIX "ACPI: "

L
Linus Torvalds 已提交
49 50 51 52 53 54
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF

#define ACPI_BATTERY_CLASS		"battery"
#define ACPI_BATTERY_DEVICE_NAME	"Battery"
#define ACPI_BATTERY_NOTIFY_STATUS	0x80
#define ACPI_BATTERY_NOTIFY_INFO	0x81
55
#define ACPI_BATTERY_NOTIFY_THRESHOLD   0x82
L
Linus Torvalds 已提交
56 57

#define _COMPONENT		ACPI_BATTERY_COMPONENT
58

59
ACPI_MODULE_NAME("battery");
L
Linus Torvalds 已提交
60

61
MODULE_AUTHOR("Paul Diefenbaugh");
62
MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
63
MODULE_DESCRIPTION("ACPI Battery Driver");
L
Linus Torvalds 已提交
64 65
MODULE_LICENSE("GPL");

66 67 68
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
69

70
#ifdef CONFIG_ACPI_PROCFS_POWER
71 72 73
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);

74 75 76 77 78 79 80 81 82
enum acpi_battery_files {
	info_tag = 0,
	state_tag,
	alarm_tag,
	ACPI_BATTERY_NUMFILES,
};

#endif

83 84 85 86 87
static const struct acpi_device_id battery_device_ids[] = {
	{"PNP0C0A", 0},
	{"", 0},
};

88
MODULE_DEVICE_TABLE(acpi, battery_device_ids);
L
Linus Torvalds 已提交
89

90 91
enum {
	ACPI_BATTERY_ALARM_PRESENT,
92 93 94 95 96
	ACPI_BATTERY_XINFO_PRESENT,
	/* For buggy DSDTs that report negative 16-bit values for either
	 * charging or discharging current and/or report 0 as 65536
	 * due to bad math.
	 */
97 98
	ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
};
99

L
Linus Torvalds 已提交
100
struct acpi_battery {
101
	struct mutex lock;
102
	struct power_supply bat;
103 104
	struct acpi_device *device;
	unsigned long update_time;
105
	int rate_now;
106 107
	int capacity_now;
	int voltage_now;
108
	int design_capacity;
109
	int full_charge_capacity;
110 111 112 113
	int technology;
	int design_voltage;
	int design_capacity_warning;
	int design_capacity_low;
114 115 116 117 118 119
	int cycle_count;
	int measurement_accuracy;
	int max_sampling_time;
	int min_sampling_time;
	int max_averaging_interval;
	int min_averaging_interval;
120 121
	int capacity_granularity_1;
	int capacity_granularity_2;
122
	int alarm;
123 124 125 126
	char model_number[32];
	char serial_number[32];
	char type[32];
	char oem_info[32];
127 128
	int state;
	int power_unit;
129
	unsigned long flags;
L
Linus Torvalds 已提交
130 131
};

132 133
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);

134
inline int acpi_battery_present(struct acpi_battery *battery)
135
{
136 137
	return battery->device->status.battery_present;
}
138

139 140 141 142 143 144 145 146
static int acpi_battery_technology(struct acpi_battery *battery)
{
	if (!strcasecmp("NiCd", battery->type))
		return POWER_SUPPLY_TECHNOLOGY_NiCd;
	if (!strcasecmp("NiMH", battery->type))
		return POWER_SUPPLY_TECHNOLOGY_NiMH;
	if (!strcasecmp("LION", battery->type))
		return POWER_SUPPLY_TECHNOLOGY_LION;
147
	if (!strncasecmp("LI-ION", battery->type, 6))
148
		return POWER_SUPPLY_TECHNOLOGY_LION;
149 150 151 152 153
	if (!strcasecmp("LiP", battery->type))
		return POWER_SUPPLY_TECHNOLOGY_LIPO;
	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}

154
static int acpi_battery_get_state(struct acpi_battery *battery);
155

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
static int acpi_battery_is_charged(struct acpi_battery *battery)
{
	/* either charging or discharging */
	if (battery->state != 0)
		return 0;

	/* battery not reporting charge */
	if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
	    battery->capacity_now == 0)
		return 0;

	/* good batteries update full_charge as the batteries degrade */
	if (battery->full_charge_capacity == battery->capacity_now)
		return 1;

	/* fallback to using design values for broken batteries */
	if (battery->design_capacity == battery->capacity_now)
		return 1;

	/* we don't do any sort of metric based on percentages */
	return 0;
}

179 180 181 182 183 184
static int acpi_battery_get_property(struct power_supply *psy,
				     enum power_supply_property psp,
				     union power_supply_propval *val)
{
	struct acpi_battery *battery = to_acpi_battery(psy);

185 186 187 188
	if (acpi_battery_present(battery)) {
		/* run battery update only if it is present */
		acpi_battery_get_state(battery);
	} else if (psp != POWER_SUPPLY_PROP_PRESENT)
189 190 191 192 193 194 195
		return -ENODEV;
	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		if (battery->state & 0x01)
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
		else if (battery->state & 0x02)
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
196
		else if (acpi_battery_is_charged(battery))
197
			val->intval = POWER_SUPPLY_STATUS_FULL;
198 199
		else
			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
200 201 202 203 204 205 206
		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = acpi_battery_present(battery);
		break;
	case POWER_SUPPLY_PROP_TECHNOLOGY:
		val->intval = acpi_battery_technology(battery);
		break;
207 208 209
	case POWER_SUPPLY_PROP_CYCLE_COUNT:
		val->intval = battery->cycle_count;
		break;
210 211 212 213 214 215 216
	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
		val->intval = battery->design_voltage * 1000;
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
		val->intval = battery->voltage_now * 1000;
		break;
	case POWER_SUPPLY_PROP_CURRENT_NOW:
217 218
	case POWER_SUPPLY_PROP_POWER_NOW:
		val->intval = battery->rate_now * 1000;
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
		val->intval = battery->design_capacity * 1000;
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL:
	case POWER_SUPPLY_PROP_ENERGY_FULL:
		val->intval = battery->full_charge_capacity * 1000;
		break;
	case POWER_SUPPLY_PROP_CHARGE_NOW:
	case POWER_SUPPLY_PROP_ENERGY_NOW:
		val->intval = battery->capacity_now * 1000;
		break;
	case POWER_SUPPLY_PROP_MODEL_NAME:
		val->strval = battery->model_number;
		break;
	case POWER_SUPPLY_PROP_MANUFACTURER:
		val->strval = battery->oem_info;
		break;
238 239 240
	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
		val->strval = battery->serial_number;
		break;
241 242 243 244 245 246 247 248 249 250
	default:
		return -EINVAL;
	}
	return 0;
}

static enum power_supply_property charge_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_TECHNOLOGY,
251
	POWER_SUPPLY_PROP_CYCLE_COUNT,
252 253 254 255 256 257 258 259
	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_CHARGE_NOW,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MANUFACTURER,
260
	POWER_SUPPLY_PROP_SERIAL_NUMBER,
261 262 263 264 265 266
};

static enum power_supply_property energy_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_TECHNOLOGY,
267
	POWER_SUPPLY_PROP_CYCLE_COUNT,
268 269
	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
270
	POWER_SUPPLY_PROP_POWER_NOW,
271 272 273 274 275
	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
	POWER_SUPPLY_PROP_ENERGY_FULL,
	POWER_SUPPLY_PROP_ENERGY_NOW,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MANUFACTURER,
276
	POWER_SUPPLY_PROP_SERIAL_NUMBER,
277 278
};

279
#ifdef CONFIG_ACPI_PROCFS_POWER
280
inline char *acpi_battery_units(struct acpi_battery *battery)
281
{
282
	return (battery->power_unit)?"mA":"mW";
283
}
284
#endif
285

286 287 288
/* --------------------------------------------------------------------------
                               Battery Management
   -------------------------------------------------------------------------- */
289 290 291 292
struct acpi_offsets {
	size_t offset;		/* offset inside struct acpi_sbs_battery */
	u8 mode;		/* int or string? */
};
293

294 295
static struct acpi_offsets state_offsets[] = {
	{offsetof(struct acpi_battery, state), 0},
296
	{offsetof(struct acpi_battery, rate_now), 0},
297 298
	{offsetof(struct acpi_battery, capacity_now), 0},
	{offsetof(struct acpi_battery, voltage_now), 0},
299
};
300

301 302 303
static struct acpi_offsets info_offsets[] = {
	{offsetof(struct acpi_battery, power_unit), 0},
	{offsetof(struct acpi_battery, design_capacity), 0},
304
	{offsetof(struct acpi_battery, full_charge_capacity), 0},
305 306 307 308 309 310 311 312 313 314 315
	{offsetof(struct acpi_battery, technology), 0},
	{offsetof(struct acpi_battery, design_voltage), 0},
	{offsetof(struct acpi_battery, design_capacity_warning), 0},
	{offsetof(struct acpi_battery, design_capacity_low), 0},
	{offsetof(struct acpi_battery, capacity_granularity_1), 0},
	{offsetof(struct acpi_battery, capacity_granularity_2), 0},
	{offsetof(struct acpi_battery, model_number), 1},
	{offsetof(struct acpi_battery, serial_number), 1},
	{offsetof(struct acpi_battery, type), 1},
	{offsetof(struct acpi_battery, oem_info), 1},
};
316

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
static struct acpi_offsets extended_info_offsets[] = {
	{offsetof(struct acpi_battery, power_unit), 0},
	{offsetof(struct acpi_battery, design_capacity), 0},
	{offsetof(struct acpi_battery, full_charge_capacity), 0},
	{offsetof(struct acpi_battery, technology), 0},
	{offsetof(struct acpi_battery, design_voltage), 0},
	{offsetof(struct acpi_battery, design_capacity_warning), 0},
	{offsetof(struct acpi_battery, design_capacity_low), 0},
	{offsetof(struct acpi_battery, cycle_count), 0},
	{offsetof(struct acpi_battery, measurement_accuracy), 0},
	{offsetof(struct acpi_battery, max_sampling_time), 0},
	{offsetof(struct acpi_battery, min_sampling_time), 0},
	{offsetof(struct acpi_battery, max_averaging_interval), 0},
	{offsetof(struct acpi_battery, min_averaging_interval), 0},
	{offsetof(struct acpi_battery, capacity_granularity_1), 0},
	{offsetof(struct acpi_battery, capacity_granularity_2), 0},
	{offsetof(struct acpi_battery, model_number), 1},
	{offsetof(struct acpi_battery, serial_number), 1},
	{offsetof(struct acpi_battery, type), 1},
	{offsetof(struct acpi_battery, oem_info), 1},
};

339 340 341 342
static int extract_package(struct acpi_battery *battery,
			   union acpi_object *package,
			   struct acpi_offsets *offsets, int num)
{
343
	int i;
344 345 346 347 348 349 350 351
	union acpi_object *element;
	if (package->type != ACPI_TYPE_PACKAGE)
		return -EFAULT;
	for (i = 0; i < num; ++i) {
		if (package->package.count <= i)
			return -EFAULT;
		element = &package->package.elements[i];
		if (offsets[i].mode) {
352 353 354 355 356 357
			u8 *ptr = (u8 *)battery + offsets[i].offset;
			if (element->type == ACPI_TYPE_STRING ||
			    element->type == ACPI_TYPE_BUFFER)
				strncpy(ptr, element->string.pointer, 32);
			else if (element->type == ACPI_TYPE_INTEGER) {
				strncpy(ptr, (u8 *)&element->integer.value,
L
Lin Ming 已提交
358 359
					sizeof(u64));
				ptr[sizeof(u64)] = 0;
360 361
			} else
				*ptr = 0; /* don't have value */
362
		} else {
363 364 365
			int *x = (int *)((u8 *)battery + offsets[i].offset);
			*x = (element->type == ACPI_TYPE_INTEGER) ?
				element->integer.value : -1;
366
		}
367 368 369 370 371 372
	}
	return 0;
}

static int acpi_battery_get_status(struct acpi_battery *battery)
{
373
	if (acpi_bus_get_status(battery->device)) {
374 375 376
		ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
		return -ENODEV;
	}
377
	return 0;
378 379 380
}

static int acpi_battery_get_info(struct acpi_battery *battery)
L
Linus Torvalds 已提交
381
{
382
	int result = -EFAULT;
L
Len Brown 已提交
383
	acpi_status status = 0;
384 385 386
	char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags)?
			"_BIX" : "_BIF";

L
Len Brown 已提交
387
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
L
Linus Torvalds 已提交
388

389 390
	if (!acpi_battery_present(battery))
		return 0;
391
	mutex_lock(&battery->lock);
392 393
	status = acpi_evaluate_object(battery->device->handle, name,
						NULL, &buffer);
394
	mutex_unlock(&battery->lock);
395

L
Linus Torvalds 已提交
396
	if (ACPI_FAILURE(status)) {
397
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
398
		return -ENODEV;
L
Linus Torvalds 已提交
399
	}
400 401 402 403 404 405 406
	if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
		result = extract_package(battery, buffer.pointer,
				extended_info_offsets,
				ARRAY_SIZE(extended_info_offsets));
	else
		result = extract_package(battery, buffer.pointer,
				info_offsets, ARRAY_SIZE(info_offsets));
407
	kfree(buffer.pointer);
408
	return result;
L
Linus Torvalds 已提交
409 410
}

411
static int acpi_battery_get_state(struct acpi_battery *battery)
L
Linus Torvalds 已提交
412
{
L
Len Brown 已提交
413 414 415
	int result = 0;
	acpi_status status = 0;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
L
Linus Torvalds 已提交
416

417 418
	if (!acpi_battery_present(battery))
		return 0;
L
Linus Torvalds 已提交
419

420 421 422 423 424
	if (battery->update_time &&
	    time_before(jiffies, battery->update_time +
			msecs_to_jiffies(cache_time)))
		return 0;

425
	mutex_lock(&battery->lock);
426
	status = acpi_evaluate_object(battery->device->handle, "_BST",
427 428
				      NULL, &buffer);
	mutex_unlock(&battery->lock);
429

L
Linus Torvalds 已提交
430
	if (ACPI_FAILURE(status)) {
431
		ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
432
		return -ENODEV;
L
Linus Torvalds 已提交
433
	}
434

435 436
	result = extract_package(battery, buffer.pointer,
				 state_offsets, ARRAY_SIZE(state_offsets));
437
	battery->update_time = jiffies;
438
	kfree(buffer.pointer);
439

440
	if (test_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags) &&
441 442 443
	    battery->rate_now != -1)
		battery->rate_now = abs((s16)battery->rate_now);

444 445
	return result;
}
L
Linus Torvalds 已提交
446

447
static int acpi_battery_set_alarm(struct acpi_battery *battery)
L
Linus Torvalds 已提交
448
{
L
Len Brown 已提交
449
	acpi_status status = 0;
450
	union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER };
L
Len Brown 已提交
451
	struct acpi_object_list arg_list = { 1, &arg0 };
L
Linus Torvalds 已提交
452

453
	if (!acpi_battery_present(battery) ||
454
	    !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
455
		return -ENODEV;
L
Linus Torvalds 已提交
456

457
	arg0.integer.value = battery->alarm;
L
Linus Torvalds 已提交
458

459
	mutex_lock(&battery->lock);
460 461
	status = acpi_evaluate_object(battery->device->handle, "_BTP",
				 &arg_list, NULL);
462
	mutex_unlock(&battery->lock);
463

L
Linus Torvalds 已提交
464
	if (ACPI_FAILURE(status))
465
		return -ENODEV;
L
Linus Torvalds 已提交
466

467
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
468
	return 0;
L
Linus Torvalds 已提交
469 470
}

471
static int acpi_battery_init_alarm(struct acpi_battery *battery)
L
Linus Torvalds 已提交
472
{
L
Len Brown 已提交
473 474 475
	acpi_status status = AE_OK;
	acpi_handle handle = NULL;

476
	/* See if alarms are supported, and if so, set default */
477 478
	status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
	if (ACPI_FAILURE(status)) {
479
		clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
480
		return 0;
481
	}
482
	set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
483 484
	if (!battery->alarm)
		battery->alarm = battery->design_capacity_warning;
485
	return acpi_battery_set_alarm(battery);
486
}
L
Linus Torvalds 已提交
487

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
static ssize_t acpi_battery_alarm_show(struct device *dev,
					struct device_attribute *attr,
					char *buf)
{
	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
	return sprintf(buf, "%d\n", battery->alarm * 1000);
}

static ssize_t acpi_battery_alarm_store(struct device *dev,
					struct device_attribute *attr,
					const char *buf, size_t count)
{
	unsigned long x;
	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
	if (sscanf(buf, "%ld\n", &x) == 1)
		battery->alarm = x/1000;
	if (acpi_battery_present(battery))
		acpi_battery_set_alarm(battery);
	return count;
}

static struct device_attribute alarm_attr = {
510
	.attr = {.name = "alarm", .mode = 0644},
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
	.show = acpi_battery_alarm_show,
	.store = acpi_battery_alarm_store,
};

static int sysfs_add_battery(struct acpi_battery *battery)
{
	int result;

	if (battery->power_unit) {
		battery->bat.properties = charge_battery_props;
		battery->bat.num_properties =
			ARRAY_SIZE(charge_battery_props);
	} else {
		battery->bat.properties = energy_battery_props;
		battery->bat.num_properties =
			ARRAY_SIZE(energy_battery_props);
	}

	battery->bat.name = acpi_device_bid(battery->device);
	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	battery->bat.get_property = acpi_battery_get_property;

	result = power_supply_register(&battery->device->dev, &battery->bat);
	if (result)
		return result;
	return device_create_file(battery->bat.dev, &alarm_attr);
}

static void sysfs_remove_battery(struct acpi_battery *battery)
{
	if (!battery->bat.dev)
		return;
	device_remove_file(battery->bat.dev, &alarm_attr);
	power_supply_unregister(&battery->bat);
545
	battery->bat.dev = NULL;
546 547
}

548 549 550
static void acpi_battery_quirks(struct acpi_battery *battery)
{
	if (dmi_name_in_vendors("Acer") && battery->power_unit) {
551
		set_bit(ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, &battery->flags);
552 553 554
	}
}

555
static int acpi_battery_update(struct acpi_battery *battery)
556
{
557
	int result, old_present = acpi_battery_present(battery);
558
	result = acpi_battery_get_status(battery);
559
	if (result)
560
		return result;
561 562
	if (!acpi_battery_present(battery)) {
		sysfs_remove_battery(battery);
563
		battery->update_time = 0;
564
		return 0;
565
	}
566 567
	if (!battery->update_time ||
	    old_present != acpi_battery_present(battery)) {
568 569 570
		result = acpi_battery_get_info(battery);
		if (result)
			return result;
571
		acpi_battery_quirks(battery);
572 573
		acpi_battery_init_alarm(battery);
	}
574 575
	if (!battery->bat.dev)
		sysfs_add_battery(battery);
576
	return acpi_battery_get_state(battery);
577 578
}

L
Linus Torvalds 已提交
579 580 581 582
/* --------------------------------------------------------------------------
                              FS Interface (/proc)
   -------------------------------------------------------------------------- */

583
#ifdef CONFIG_ACPI_PROCFS_POWER
L
Len Brown 已提交
584
static struct proc_dir_entry *acpi_battery_dir;
585

586
static int acpi_battery_print_info(struct seq_file *seq, int result)
L
Linus Torvalds 已提交
587
{
588
	struct acpi_battery *battery = seq->private;
L
Linus Torvalds 已提交
589

590
	if (result)
L
Linus Torvalds 已提交
591 592
		goto end;

593 594 595
	seq_printf(seq, "present:                 %s\n",
		   acpi_battery_present(battery)?"yes":"no");
	if (!acpi_battery_present(battery))
L
Linus Torvalds 已提交
596
		goto end;
597
	if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
598 599 600
		seq_printf(seq, "design capacity:         unknown\n");
	else
		seq_printf(seq, "design capacity:         %d %sh\n",
601 602
			   battery->design_capacity,
			   acpi_battery_units(battery));
L
Linus Torvalds 已提交
603

604
	if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
605 606 607
		seq_printf(seq, "last full capacity:      unknown\n");
	else
		seq_printf(seq, "last full capacity:      %d %sh\n",
608
			   battery->full_charge_capacity,
609 610 611 612
			   acpi_battery_units(battery));

	seq_printf(seq, "battery technology:      %srechargeable\n",
		   (!battery->technology)?"non-":"");
L
Linus Torvalds 已提交
613

614
	if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
615 616 617
		seq_printf(seq, "design voltage:          unknown\n");
	else
		seq_printf(seq, "design voltage:          %d mV\n",
618
			   battery->design_voltage);
L
Linus Torvalds 已提交
619
	seq_printf(seq, "design capacity warning: %d %sh\n",
620 621
		   battery->design_capacity_warning,
		   acpi_battery_units(battery));
L
Linus Torvalds 已提交
622
	seq_printf(seq, "design capacity low:     %d %sh\n",
623 624
		   battery->design_capacity_low,
		   acpi_battery_units(battery));
625
	seq_printf(seq, "cycle count:		  %i\n", battery->cycle_count);
L
Linus Torvalds 已提交
626
	seq_printf(seq, "capacity granularity 1:  %d %sh\n",
627 628
		   battery->capacity_granularity_1,
		   acpi_battery_units(battery));
L
Linus Torvalds 已提交
629
	seq_printf(seq, "capacity granularity 2:  %d %sh\n",
630 631
		   battery->capacity_granularity_2,
		   acpi_battery_units(battery));
632 633 634 635
	seq_printf(seq, "model number:            %s\n", battery->model_number);
	seq_printf(seq, "serial number:           %s\n", battery->serial_number);
	seq_printf(seq, "battery type:            %s\n", battery->type);
	seq_printf(seq, "OEM info:                %s\n", battery->oem_info);
L
Len Brown 已提交
636
      end:
637 638 639 640 641
	if (result)
		seq_printf(seq, "ERROR: Unable to read battery info\n");
	return result;
}

642
static int acpi_battery_print_state(struct seq_file *seq, int result)
L
Linus Torvalds 已提交
643
{
644
	struct acpi_battery *battery = seq->private;
L
Linus Torvalds 已提交
645

646
	if (result)
L
Linus Torvalds 已提交
647 648
		goto end;

649 650 651
	seq_printf(seq, "present:                 %s\n",
		   acpi_battery_present(battery)?"yes":"no");
	if (!acpi_battery_present(battery))
L
Linus Torvalds 已提交
652
		goto end;
653

654 655 656
	seq_printf(seq, "capacity state:          %s\n",
			(battery->state & 0x04)?"critical":"ok");
	if ((battery->state & 0x01) && (battery->state & 0x02))
L
Len Brown 已提交
657 658
		seq_printf(seq,
			   "charging state:          charging/discharging\n");
659
	else if (battery->state & 0x01)
L
Linus Torvalds 已提交
660
		seq_printf(seq, "charging state:          discharging\n");
661
	else if (battery->state & 0x02)
L
Linus Torvalds 已提交
662
		seq_printf(seq, "charging state:          charging\n");
663
	else
L
Linus Torvalds 已提交
664 665
		seq_printf(seq, "charging state:          charged\n");

666
	if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
667 668 669
		seq_printf(seq, "present rate:            unknown\n");
	else
		seq_printf(seq, "present rate:            %d %s\n",
670
			   battery->rate_now, acpi_battery_units(battery));
L
Linus Torvalds 已提交
671

672
	if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
673 674 675
		seq_printf(seq, "remaining capacity:      unknown\n");
	else
		seq_printf(seq, "remaining capacity:      %d %sh\n",
676 677
			   battery->capacity_now, acpi_battery_units(battery));
	if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
L
Linus Torvalds 已提交
678 679 680
		seq_printf(seq, "present voltage:         unknown\n");
	else
		seq_printf(seq, "present voltage:         %d mV\n",
681
			   battery->voltage_now);
L
Len Brown 已提交
682
      end:
683
	if (result)
684 685 686 687 688
		seq_printf(seq, "ERROR: Unable to read battery state\n");

	return result;
}

689
static int acpi_battery_print_alarm(struct seq_file *seq, int result)
L
Linus Torvalds 已提交
690
{
691
	struct acpi_battery *battery = seq->private;
L
Linus Torvalds 已提交
692

693
	if (result)
L
Linus Torvalds 已提交
694 695
		goto end;

696
	if (!acpi_battery_present(battery)) {
L
Linus Torvalds 已提交
697 698 699 700 701 702 703
		seq_printf(seq, "present:                 no\n");
		goto end;
	}
	seq_printf(seq, "alarm:                   ");
	if (!battery->alarm)
		seq_printf(seq, "unsupported\n");
	else
704 705
		seq_printf(seq, "%u %sh\n", battery->alarm,
				acpi_battery_units(battery));
L
Len Brown 已提交
706
      end:
707 708 709 710 711
	if (result)
		seq_printf(seq, "ERROR: Unable to read battery alarm\n");
	return result;
}

712 713 714
static ssize_t acpi_battery_write_alarm(struct file *file,
					const char __user * buffer,
					size_t count, loff_t * ppos)
L
Linus Torvalds 已提交
715
{
L
Len Brown 已提交
716 717
	int result = 0;
	char alarm_string[12] = { '\0' };
718 719
	struct seq_file *m = file->private_data;
	struct acpi_battery *battery = m->private;
L
Linus Torvalds 已提交
720 721

	if (!battery || (count > sizeof(alarm_string) - 1))
722
		return -EINVAL;
723 724 725 726 727 728 729 730
	if (!acpi_battery_present(battery)) {
		result = -ENODEV;
		goto end;
	}
	if (copy_from_user(alarm_string, buffer, count)) {
		result = -EFAULT;
		goto end;
	}
L
Linus Torvalds 已提交
731
	alarm_string[count] = '\0';
732
	battery->alarm = simple_strtol(alarm_string, NULL, 0);
733
	result = acpi_battery_set_alarm(battery);
734 735
      end:
	if (!result)
736
		return count;
737 738 739 740
	return result;
}

typedef int(*print_func)(struct seq_file *seq, int result);
741 742 743 744 745

static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
	acpi_battery_print_info,
	acpi_battery_print_state,
	acpi_battery_print_alarm,
746
};
747

748 749 750
static int acpi_battery_read(int fid, struct seq_file *seq)
{
	struct acpi_battery *battery = seq->private;
751
	int result = acpi_battery_update(battery);
752
	return acpi_print_funcs[fid](seq, result);
753 754
}

755 756 757 758 759 760 761 762
#define DECLARE_FILE_FUNCTIONS(_name) \
static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
{ \
	return acpi_battery_read(_name##_tag, seq); \
} \
static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
{ \
	return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \
763 764
}

765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
DECLARE_FILE_FUNCTIONS(info);
DECLARE_FILE_FUNCTIONS(state);
DECLARE_FILE_FUNCTIONS(alarm);

#undef DECLARE_FILE_FUNCTIONS

#define FILE_DESCRIPTION_RO(_name) \
	{ \
	.name = __stringify(_name), \
	.mode = S_IRUGO, \
	.ops = { \
		.open = acpi_battery_##_name##_open_fs, \
		.read = seq_read, \
		.llseek = seq_lseek, \
		.release = single_release, \
		.owner = THIS_MODULE, \
		}, \
	}
783

784 785 786 787 788 789 790 791 792 793 794 795 796
#define FILE_DESCRIPTION_RW(_name) \
	{ \
	.name = __stringify(_name), \
	.mode = S_IFREG | S_IRUGO | S_IWUSR, \
	.ops = { \
		.open = acpi_battery_##_name##_open_fs, \
		.read = seq_read, \
		.llseek = seq_lseek, \
		.write = acpi_battery_write_##_name, \
		.release = single_release, \
		.owner = THIS_MODULE, \
		}, \
	}
L
Linus Torvalds 已提交
797

798 799 800
static struct battery_file {
	struct file_operations ops;
	mode_t mode;
J
Jan Engelhardt 已提交
801
	const char *name;
802
} acpi_battery_file[] = {
803 804 805
	FILE_DESCRIPTION_RO(info),
	FILE_DESCRIPTION_RO(state),
	FILE_DESCRIPTION_RW(alarm),
L
Linus Torvalds 已提交
806 807
};

808 809 810
#undef FILE_DESCRIPTION_RO
#undef FILE_DESCRIPTION_RW

L
Len Brown 已提交
811
static int acpi_battery_add_fs(struct acpi_device *device)
L
Linus Torvalds 已提交
812
{
L
Len Brown 已提交
813
	struct proc_dir_entry *entry = NULL;
814
	int i;
L
Linus Torvalds 已提交
815 816 817

	if (!acpi_device_dir(device)) {
		acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
L
Len Brown 已提交
818
						     acpi_battery_dir);
L
Linus Torvalds 已提交
819
		if (!acpi_device_dir(device))
820
			return -ENODEV;
L
Linus Torvalds 已提交
821 822
	}

823
	for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
824 825 826 827 828
		entry = proc_create_data(acpi_battery_file[i].name,
					 acpi_battery_file[i].mode,
					 acpi_device_dir(device),
					 &acpi_battery_file[i].ops,
					 acpi_driver_data(device));
829 830
		if (!entry)
			return -ENODEV;
L
Linus Torvalds 已提交
831
	}
832
	return 0;
L
Linus Torvalds 已提交
833 834
}

835
static void acpi_battery_remove_fs(struct acpi_device *device)
L
Linus Torvalds 已提交
836
{
837
	int i;
838 839 840 841
	if (!acpi_device_dir(device))
		return;
	for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
		remove_proc_entry(acpi_battery_file[i].name,
L
Linus Torvalds 已提交
842 843
				  acpi_device_dir(device));

844 845
	remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
	acpi_device_dir(device) = NULL;
L
Linus Torvalds 已提交
846 847
}

848
#endif
849

L
Linus Torvalds 已提交
850 851 852 853
/* --------------------------------------------------------------------------
                                 Driver Interface
   -------------------------------------------------------------------------- */

854
static void acpi_battery_notify(struct acpi_device *device, u32 event)
L
Linus Torvalds 已提交
855
{
856
	struct acpi_battery *battery = acpi_driver_data(device);
857
	struct device *old;
858

L
Linus Torvalds 已提交
859
	if (!battery)
860
		return;
861
	old = battery->bat.dev;
862 863 864 865
	acpi_battery_update(battery);
	acpi_bus_generate_proc_event(device, event,
				     acpi_battery_present(battery));
	acpi_bus_generate_netlink_event(device->pnp.device_class,
866
					dev_name(&device->dev), event,
V
Vladimir Lebedev 已提交
867
					acpi_battery_present(battery));
J
Justin P. Mattock 已提交
868
	/* acpi_battery_update could remove power_supply object */
869
	if (old && battery->bat.dev)
870
		power_supply_changed(&battery->bat);
L
Linus Torvalds 已提交
871 872
}

L
Len Brown 已提交
873
static int acpi_battery_add(struct acpi_device *device)
L
Linus Torvalds 已提交
874
{
L
Len Brown 已提交
875 876
	int result = 0;
	struct acpi_battery *battery = NULL;
877
	acpi_handle handle;
L
Linus Torvalds 已提交
878
	if (!device)
879
		return -EINVAL;
880
	battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
L
Linus Torvalds 已提交
881
	if (!battery)
882
		return -ENOMEM;
883
	battery->device = device;
L
Linus Torvalds 已提交
884 885
	strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
886
	device->driver_data = battery;
887
	mutex_init(&battery->lock);
888 889 890
	if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
			"_BIX", &handle)))
		set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
891
	acpi_battery_update(battery);
892
#ifdef CONFIG_ACPI_PROCFS_POWER
L
Linus Torvalds 已提交
893
	result = acpi_battery_add_fs(device);
894
#endif
895 896 897 898 899
	if (!result) {
		printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
			ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
			device->status.battery_present ? "present" : "absent");
	} else {
900
#ifdef CONFIG_ACPI_PROCFS_POWER
L
Linus Torvalds 已提交
901
		acpi_battery_remove_fs(device);
902
#endif
L
Linus Torvalds 已提交
903 904
		kfree(battery);
	}
905
	return result;
L
Linus Torvalds 已提交
906 907
}

L
Len Brown 已提交
908
static int acpi_battery_remove(struct acpi_device *device, int type)
L
Linus Torvalds 已提交
909
{
L
Len Brown 已提交
910
	struct acpi_battery *battery = NULL;
L
Linus Torvalds 已提交
911 912

	if (!device || !acpi_driver_data(device))
913
		return -EINVAL;
914
	battery = acpi_driver_data(device);
915
#ifdef CONFIG_ACPI_PROCFS_POWER
L
Linus Torvalds 已提交
916
	acpi_battery_remove_fs(device);
917
#endif
918
	sysfs_remove_battery(battery);
919
	mutex_destroy(&battery->lock);
L
Linus Torvalds 已提交
920
	kfree(battery);
921
	return 0;
L
Linus Torvalds 已提交
922 923
}

924
/* this is needed to learn about changes made in suspended state */
925
static int acpi_battery_resume(struct acpi_device *device)
926 927 928 929
{
	struct acpi_battery *battery;
	if (!device)
		return -EINVAL;
930 931
	battery = acpi_driver_data(device);
	battery->update_time = 0;
932
	acpi_battery_update(battery);
933
	return 0;
934 935
}

936 937 938 939
static struct acpi_driver acpi_battery_driver = {
	.name = "battery",
	.class = ACPI_BATTERY_CLASS,
	.ids = battery_device_ids,
940
	.flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
941 942 943 944
	.ops = {
		.add = acpi_battery_add,
		.resume = acpi_battery_resume,
		.remove = acpi_battery_remove,
945
		.notify = acpi_battery_notify,
946 947 948
		},
};

949
static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
L
Linus Torvalds 已提交
950
{
P
Pavel Machek 已提交
951
	if (acpi_disabled)
952
		return;
953
#ifdef CONFIG_ACPI_PROCFS_POWER
954
	acpi_battery_dir = acpi_lock_battery_dir();
L
Linus Torvalds 已提交
955
	if (!acpi_battery_dir)
956
		return;
957
#endif
958
	if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
959
#ifdef CONFIG_ACPI_PROCFS_POWER
960
		acpi_unlock_battery_dir(acpi_battery_dir);
961
#endif
962
		return;
L
Linus Torvalds 已提交
963
	}
964 965 966 967 968 969
	return;
}

static int __init acpi_battery_init(void)
{
	async_schedule(acpi_battery_init_async, NULL);
970
	return 0;
L
Linus Torvalds 已提交
971 972
}

L
Len Brown 已提交
973
static void __exit acpi_battery_exit(void)
L
Linus Torvalds 已提交
974 975
{
	acpi_bus_unregister_driver(&acpi_battery_driver);
976
#ifdef CONFIG_ACPI_PROCFS_POWER
977
	acpi_unlock_battery_dir(acpi_battery_dir);
978
#endif
L
Linus Torvalds 已提交
979 980 981 982
}

module_init(acpi_battery_init);
module_exit(acpi_battery_exit);