sbs.c 26.8 KB
Newer Older
1
/*
2
 *  sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3
 *
4 5
 *  Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
 *  Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
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
 *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  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/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
31

32
#ifdef CONFIG_ACPI_PROCFS
33 34 35
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
36
#endif
37

38
#include <linux/acpi.h>
39
#include <linux/timer.h>
40
#include <linux/jiffies.h>
41 42
#include <linux/delay.h>

43 44
#include <linux/power_supply.h>

45 46
#include "sbshc.h"

47 48 49 50 51 52 53 54 55 56
#define ACPI_SBS_CLASS			"sbs"
#define ACPI_AC_CLASS			"ac_adapter"
#define ACPI_BATTERY_CLASS		"battery"
#define ACPI_SBS_DEVICE_NAME		"Smart Battery System"
#define ACPI_SBS_FILE_INFO		"info"
#define ACPI_SBS_FILE_STATE		"state"
#define ACPI_SBS_FILE_ALARM		"alarm"
#define ACPI_BATTERY_DIR_NAME		"BAT%i"
#define ACPI_AC_DIR_NAME		"AC0"

57 58 59 60 61 62 63 64
enum acpi_sbs_device_addr {
	ACPI_SBS_CHARGER = 0x9,
	ACPI_SBS_MANAGER = 0xa,
	ACPI_SBS_BATTERY = 0xb,
};

#define ACPI_SBS_NOTIFY_STATUS		0x80
#define ACPI_SBS_NOTIFY_INFO		0x81
65

66
MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
67 68 69
MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
MODULE_LICENSE("GPL");

70 71 72
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
73 74 75 76 77 78

extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);

79
#define MAX_SBS_BAT			4
80 81
#define ACPI_SBS_BLOCK_MAX		32

82
static const struct acpi_device_id sbs_device_ids[] = {
83
	{"ACPI0002", 0},
84 85 86 87
	{"", 0},
};
MODULE_DEVICE_TABLE(acpi, sbs_device_ids);

88
struct acpi_battery {
89
	struct power_supply bat;
90
	struct acpi_sbs *sbs;
91
#ifdef CONFIG_ACPI_PROCFS
92
	struct proc_dir_entry *proc_entry;
93
#endif
94 95
	unsigned long update_time;
	char name[8];
96 97 98
	char manufacturer_name[ACPI_SBS_BLOCK_MAX];
	char device_name[ACPI_SBS_BLOCK_MAX];
	char device_chemistry[ACPI_SBS_BLOCK_MAX];
99
	u16 alarm_capacity;
100 101 102 103
	u16 full_charge_capacity;
	u16 design_capacity;
	u16 design_voltage;
	u16 serial_number;
104 105
	u16 cycle_count;
	u16 temp_now;
106 107
	u16 voltage_now;
	s16 current_now;
108
	s16 current_avg;
109
	u16 capacity_now;
110
	u16 state_of_charge;
111 112
	u16 state;
	u16 mode;
113
	u16 spec;
114 115
	u8 id;
	u8 present:1;
116 117
};

118 119
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);

120
struct acpi_sbs {
121
	struct power_supply charger;
122
	struct acpi_device *device;
123
	struct acpi_smb_hc *hc;
124
	struct mutex lock;
125
#ifdef CONFIG_ACPI_PROCFS
126
	struct proc_dir_entry *charger_entry;
127
#endif
128
	struct acpi_battery battery[MAX_SBS_BAT];
129
	u8 batteries_supported:4;
130 131
	u8 manager_present:1;
	u8 charger_present:1;
132 133
};

134 135
#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)

136
static inline int battery_scale(int log)
137
{
138 139 140 141
	int scale = 1;
	while (log--)
		scale *= 10;
	return scale;
142 143
}

144
static inline int acpi_battery_vscale(struct acpi_battery *battery)
145
{
146
	return battery_scale((battery->spec & 0x0f00) >> 8);
147 148
}

149
static inline int acpi_battery_ipscale(struct acpi_battery *battery)
150
{
151
	return battery_scale((battery->spec & 0xf000) >> 12);
152 153
}

154
static inline int acpi_battery_mode(struct acpi_battery *battery)
155
{
156
	return (battery->mode & 0x8000);
157
}
158

159
static inline int acpi_battery_scale(struct acpi_battery *battery)
160
{
161 162
	return (acpi_battery_mode(battery) ? 10 : 1) *
	    acpi_battery_ipscale(battery);
163 164
}

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static int sbs_get_ac_property(struct power_supply *psy,
			       enum power_supply_property psp,
			       union power_supply_propval *val)
{
	struct acpi_sbs *sbs = to_acpi_sbs(psy);
	switch (psp) {
	case POWER_SUPPLY_PROP_ONLINE:
		val->intval = sbs->charger_present;
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static int acpi_battery_technology(struct acpi_battery *battery)
{
	if (!strcasecmp("NiCd", battery->device_chemistry))
		return POWER_SUPPLY_TECHNOLOGY_NiCd;
	if (!strcasecmp("NiMH", battery->device_chemistry))
		return POWER_SUPPLY_TECHNOLOGY_NiMH;
	if (!strcasecmp("LION", battery->device_chemistry))
		return POWER_SUPPLY_TECHNOLOGY_LION;
	if (!strcasecmp("LiP", battery->device_chemistry))
		return POWER_SUPPLY_TECHNOLOGY_LIPO;
	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
}

static int acpi_sbs_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);

	if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
		return -ENODEV;
	switch (psp) {
	case POWER_SUPPLY_PROP_STATUS:
		if (battery->current_now < 0)
			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
		else if (battery->current_now > 0)
			val->intval = POWER_SUPPLY_STATUS_CHARGING;
		else
			val->intval = POWER_SUPPLY_STATUS_FULL;
		break;
	case POWER_SUPPLY_PROP_PRESENT:
		val->intval = battery->present;
		break;
	case POWER_SUPPLY_PROP_TECHNOLOGY:
		val->intval = acpi_battery_technology(battery);
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
		val->intval = battery->design_voltage *
			acpi_battery_vscale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
		val->intval = battery->voltage_now *
				acpi_battery_vscale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_CURRENT_NOW:
		val->intval = abs(battery->current_now) *
				acpi_battery_ipscale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_CURRENT_AVG:
		val->intval = abs(battery->current_avg) *
				acpi_battery_ipscale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_CAPACITY:
		val->intval = battery->state_of_charge;
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
		val->intval = battery->design_capacity *
			acpi_battery_scale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_CHARGE_FULL:
	case POWER_SUPPLY_PROP_ENERGY_FULL:
		val->intval = battery->full_charge_capacity *
			acpi_battery_scale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_CHARGE_NOW:
	case POWER_SUPPLY_PROP_ENERGY_NOW:
		val->intval = battery->capacity_now *
				acpi_battery_scale(battery) * 1000;
		break;
	case POWER_SUPPLY_PROP_TEMP:
		val->intval = battery->temp_now - 2730;	// dK -> dC
		break;
	case POWER_SUPPLY_PROP_MODEL_NAME:
		val->strval = battery->device_name;
		break;
	case POWER_SUPPLY_PROP_MANUFACTURER:
		val->strval = battery->manufacturer_name;
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static enum power_supply_property sbs_ac_props[] = {
	POWER_SUPPLY_PROP_ONLINE,
};

static enum power_supply_property sbs_charge_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CURRENT_AVG,
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
	POWER_SUPPLY_PROP_CHARGE_FULL,
	POWER_SUPPLY_PROP_CHARGE_NOW,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MANUFACTURER,
};

static enum power_supply_property sbs_energy_battery_props[] = {
	POWER_SUPPLY_PROP_STATUS,
	POWER_SUPPLY_PROP_PRESENT,
	POWER_SUPPLY_PROP_TECHNOLOGY,
	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
	POWER_SUPPLY_PROP_VOLTAGE_NOW,
	POWER_SUPPLY_PROP_CURRENT_NOW,
	POWER_SUPPLY_PROP_CURRENT_AVG,
	POWER_SUPPLY_PROP_CAPACITY,
	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
	POWER_SUPPLY_PROP_ENERGY_FULL,
	POWER_SUPPLY_PROP_ENERGY_NOW,
	POWER_SUPPLY_PROP_TEMP,
	POWER_SUPPLY_PROP_MODEL_NAME,
	POWER_SUPPLY_PROP_MANUFACTURER,
};

303 304 305
/* --------------------------------------------------------------------------
                            Smart Battery System Management
   -------------------------------------------------------------------------- */
306

307 308 309 310 311
struct acpi_battery_reader {
	u8 command;		/* command for battery */
	u8 mode;		/* word or block? */
	size_t offset;		/* offset inside struct acpi_sbs_battery */
};
312

313 314 315 316 317 318 319 320 321 322 323 324 325
static struct acpi_battery_reader info_readers[] = {
	{0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
	{0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
	{0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
	{0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
	{0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
	{0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
	{0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
	{0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
	{0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
	{0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
	{0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
};
326

327 328 329 330 331 332 333 334 335
static struct acpi_battery_reader state_readers[] = {
	{0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
	{0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
	{0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
	{0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
	{0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
	{0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
	{0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
};
336

337
static int acpi_manager_get_info(struct acpi_sbs *sbs)
338 339
{
	int result = 0;
340
	u16 battery_system_info;
341

342
	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
343
				 0x04, (u8 *)&battery_system_info);
344 345
	if (!result)
		sbs->batteries_supported = battery_system_info & 0x000f;
346
	return result;
347 348 349 350
}

static int acpi_battery_get_info(struct acpi_battery *battery)
{
351
	int i, result = 0;
352

353
	for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
354 355 356 357 358 359
		result = acpi_smbus_read(battery->sbs->hc,
					 info_readers[i].mode,
					 ACPI_SBS_BATTERY,
					 info_readers[i].command,
					 (u8 *) battery +
						info_readers[i].offset);
360 361
		if (result)
			break;
362
	}
363
	return result;
364 365 366 367
}

static int acpi_battery_get_state(struct acpi_battery *battery)
{
368
	int i, result = 0;
369

370 371
	if (battery->update_time &&
	    time_before(jiffies, battery->update_time +
372 373 374 375 376 377 378 379 380 381
				msecs_to_jiffies(cache_time)))
		return 0;
	for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
		result = acpi_smbus_read(battery->sbs->hc,
					 state_readers[i].mode,
					 ACPI_SBS_BATTERY,
					 state_readers[i].command,
				         (u8 *)battery +
						state_readers[i].offset);
		if (result)
382 383 384
			goto end;
	}
      end:
385
	battery->update_time = jiffies;
386
	return result;
387 388
}

389 390
#ifdef CONFIG_ACPI_PROCFS

391
static int acpi_battery_get_alarm(struct acpi_battery *battery)
392
{
393 394
	return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
				 ACPI_SBS_BATTERY, 0x01,
395
				 (u8 *)&battery->alarm_capacity);
396 397
}

398
static int acpi_battery_set_alarm(struct acpi_battery *battery)
399
{
400
	struct acpi_sbs *sbs = battery->sbs;
401 402 403 404
	u16 value, sel = 1 << (battery->id + 12);

	int ret;

405

406
	if (sbs->manager_present) {
407
		ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
408
				0x01, (u8 *)&value);
409 410 411 412 413 414 415 416 417 418 419
		if (ret)
			goto end;
		if ((value & 0xf000) != sel) {
			value &= 0x0fff;
			value |= sel;
		ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
					 ACPI_SBS_MANAGER,
					 0x01, (u8 *)&value, 2);
		if (ret)
			goto end;
		}
420
	}
421 422 423 424
	ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
				0x01, (u8 *)&battery->alarm_capacity, 2);
      end:
	return ret;
425 426
}

427 428
#endif

429 430
static int acpi_ac_get_present(struct acpi_sbs *sbs)
{
431 432
	int result;
	u16 status;
433

434 435 436 437
	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
				 0x13, (u8 *) & status);
	if (!result)
		sbs->charger_present = (status >> 15) & 0x1;
438
	return result;
439 440 441 442 443 444
}

/* --------------------------------------------------------------------------
                              FS Interface (/proc/acpi)
   -------------------------------------------------------------------------- */

445
#ifdef CONFIG_ACPI_PROCFS
446 447
/* Generic Routines */
static int
448
acpi_sbs_add_fs(struct proc_dir_entry **dir,
449 450 451 452 453
		struct proc_dir_entry *parent_dir,
		char *dir_name,
		struct file_operations *info_fops,
		struct file_operations *state_fops,
		struct file_operations *alarm_fops, void *data)
454 455 456 457 458 459
{
	struct proc_dir_entry *entry = NULL;

	if (!*dir) {
		*dir = proc_mkdir(dir_name, parent_dir);
		if (!*dir) {
460
			return -ENODEV;
461 462 463 464 465 466 467
		}
		(*dir)->owner = THIS_MODULE;
	}

	/* 'info' [R] */
	if (info_fops) {
		entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
468
		if (entry) {
469 470 471 472 473 474 475 476 477
			entry->proc_fops = info_fops;
			entry->data = data;
			entry->owner = THIS_MODULE;
		}
	}

	/* 'state' [R] */
	if (state_fops) {
		entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
478
		if (entry) {
479 480 481 482 483 484 485 486 487
			entry->proc_fops = state_fops;
			entry->data = data;
			entry->owner = THIS_MODULE;
		}
	}

	/* 'alarm' [R/W] */
	if (alarm_fops) {
		entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
488
		if (entry) {
489 490 491 492 493
			entry->proc_fops = alarm_fops;
			entry->data = data;
			entry->owner = THIS_MODULE;
		}
	}
494
	return 0;
495 496 497
}

static void
498
acpi_sbs_remove_fs(struct proc_dir_entry **dir,
499 500 501 502 503 504 505 506 507 508 509 510 511 512
			   struct proc_dir_entry *parent_dir)
{
	if (*dir) {
		remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
		remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
		remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
		remove_proc_entry((*dir)->name, parent_dir);
		*dir = NULL;
	}
}

/* Smart Battery Interface */
static struct proc_dir_entry *acpi_battery_dir = NULL;

513 514 515 516 517 518
static inline char *acpi_battery_units(struct acpi_battery *battery)
{
	return acpi_battery_mode(battery) ? " mWh" : " mAh";
}


519 520
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
521
	struct acpi_battery *battery = seq->private;
522
	struct acpi_sbs *sbs = battery->sbs;
523 524
	int result = 0;

525
	mutex_lock(&sbs->lock);
526

527 528 529
	seq_printf(seq, "present:                 %s\n",
		   (battery->present) ? "yes" : "no");
	if (!battery->present)
530
		goto end;
531

532
	seq_printf(seq, "design capacity:         %i%s\n",
533 534
		   battery->design_capacity * acpi_battery_scale(battery),
		   acpi_battery_units(battery));
535
	seq_printf(seq, "last full capacity:      %i%s\n",
536 537
		   battery->full_charge_capacity * acpi_battery_scale(battery),
		   acpi_battery_units(battery));
538 539
	seq_printf(seq, "battery technology:      rechargeable\n");
	seq_printf(seq, "design voltage:          %i mV\n",
540
		   battery->design_voltage * acpi_battery_vscale(battery));
541 542 543 544
	seq_printf(seq, "design capacity warning: unknown\n");
	seq_printf(seq, "design capacity low:     unknown\n");
	seq_printf(seq, "capacity granularity 1:  unknown\n");
	seq_printf(seq, "capacity granularity 2:  unknown\n");
545
	seq_printf(seq, "model number:            %s\n", battery->device_name);
546
	seq_printf(seq, "serial number:           %i\n",
547
		   battery->serial_number);
548
	seq_printf(seq, "battery type:            %s\n",
549
		   battery->device_chemistry);
550
	seq_printf(seq, "OEM info:                %s\n",
551
		   battery->manufacturer_name);
552
      end:
553
	mutex_unlock(&sbs->lock);
554
	return result;
555 556 557 558 559 560 561 562 563
}

static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
{
	return single_open(file, acpi_battery_read_info, PDE(inode)->data);
}

static int acpi_battery_read_state(struct seq_file *seq, void *offset)
{
564 565
	struct acpi_battery *battery = seq->private;
	struct acpi_sbs *sbs = battery->sbs;
566 567
	int result = 0;

568 569 570 571
	mutex_lock(&sbs->lock);
	seq_printf(seq, "present:                 %s\n",
		   (battery->present) ? "yes" : "no");
	if (!battery->present)
572 573
		goto end;

574 575 576 577 578 579 580 581
	acpi_battery_get_state(battery);
	seq_printf(seq, "capacity state:          %s\n",
		   (battery->state & 0x0010) ? "critical" : "ok");
	seq_printf(seq, "charging state:          %s\n",
		   (battery->current_now < 0) ? "discharging" :
		   ((battery->current_now > 0) ? "charging" : "charged"));
	seq_printf(seq, "present rate:            %d mA\n",
		   abs(battery->current_now) * acpi_battery_ipscale(battery));
582
	seq_printf(seq, "remaining capacity:      %i%s\n",
583 584
		   battery->capacity_now * acpi_battery_scale(battery),
		   acpi_battery_units(battery));
585
	seq_printf(seq, "present voltage:         %i mV\n",
586
		   battery->voltage_now * acpi_battery_vscale(battery));
587 588

      end:
589
	mutex_unlock(&sbs->lock);
590
	return result;
591 592 593 594 595 596 597 598 599
}

static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
{
	return single_open(file, acpi_battery_read_state, PDE(inode)->data);
}

static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
{
600
	struct acpi_battery *battery = seq->private;
601
	struct acpi_sbs *sbs = battery->sbs;
602 603
	int result = 0;

604
	mutex_lock(&sbs->lock);
605

606
	if (!battery->present) {
607 608 609 610
		seq_printf(seq, "present:                 no\n");
		goto end;
	}

611
	acpi_battery_get_alarm(battery);
612
	seq_printf(seq, "alarm:                   ");
613
	if (battery->alarm_capacity)
614
		seq_printf(seq, "%i%s\n",
615 616 617 618
			   battery->alarm_capacity *
			   acpi_battery_scale(battery),
			   acpi_battery_units(battery));
	else
619 620
		seq_printf(seq, "disabled\n");
      end:
621
	mutex_unlock(&sbs->lock);
622
	return result;
623 624 625 626 627 628
}

static ssize_t
acpi_battery_write_alarm(struct file *file, const char __user * buffer,
			 size_t count, loff_t * ppos)
{
629 630
	struct seq_file *seq = file->private_data;
	struct acpi_battery *battery = seq->private;
631
	struct acpi_sbs *sbs = battery->sbs;
632
	char alarm_string[12] = { '\0' };
633 634
	int result = 0;
	mutex_lock(&sbs->lock);
635
	if (!battery->present) {
636 637 638 639 640 641 642 643 644 645 646 647
		result = -ENODEV;
		goto end;
	}
	if (count > sizeof(alarm_string) - 1) {
		result = -EINVAL;
		goto end;
	}
	if (copy_from_user(alarm_string, buffer, count)) {
		result = -EFAULT;
		goto end;
	}
	alarm_string[count] = 0;
648 649
	battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
					acpi_battery_scale(battery);
650
	acpi_battery_set_alarm(battery);
651
      end:
652 653
	mutex_unlock(&sbs->lock);
	if (result)
654
		return result;
655
	return count;
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
}

static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
{
	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
}

static struct file_operations acpi_battery_info_fops = {
	.open = acpi_battery_info_open_fs,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

static struct file_operations acpi_battery_state_fops = {
	.open = acpi_battery_state_open_fs,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

static struct file_operations acpi_battery_alarm_fops = {
	.open = acpi_battery_alarm_open_fs,
	.read = seq_read,
	.write = acpi_battery_write_alarm,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

/* Legacy AC Adapter Interface */

static struct proc_dir_entry *acpi_ac_dir = NULL;

static int acpi_ac_read_state(struct seq_file *seq, void *offset)
{

695
	struct acpi_sbs *sbs = seq->private;
696

697
	mutex_lock(&sbs->lock);
698 699

	seq_printf(seq, "state:                   %s\n",
700
		   sbs->charger_present ? "on-line" : "off-line");
701

702
	mutex_unlock(&sbs->lock);
703
	return 0;
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
}

static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
{
	return single_open(file, acpi_ac_read_state, PDE(inode)->data);
}

static struct file_operations acpi_ac_state_fops = {
	.open = acpi_ac_state_open_fs,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
	.owner = THIS_MODULE,
};

719 720
#endif

721 722 723
/* --------------------------------------------------------------------------
                                 Driver Interface
   -------------------------------------------------------------------------- */
724
static int acpi_battery_read(struct acpi_battery *battery)
725
{
726 727
	int result = 0, saved_present = battery->present;
	u16 state;
728

729 730 731 732 733 734 735 736 737 738 739 740 741
	if (battery->sbs->manager_present) {
		result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
				ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
		if (!result)
			battery->present = state & (1 << battery->id);
		state &= 0x0fff;
		state |= 1 << (battery->id + 12);
		acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
				  ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
	} else if (battery->id == 0)
		battery->present = 1;
	if (result || !battery->present)
		return result;
742

743 744 745 746 747 748 749 750 751
	if (saved_present != battery->present) {
		battery->update_time = 0;
		result = acpi_battery_get_info(battery);
		if (result)
			return result;
	}
	result = acpi_battery_get_state(battery);
	return result;
}
752

753
/* Smart Battery */
754 755 756
static int acpi_battery_add(struct acpi_sbs *sbs, int id)
{
	struct acpi_battery *battery = &sbs->battery[id];
757 758
	int result;

759 760
	battery->id = id;
	battery->sbs = sbs;
761 762 763
	result = acpi_battery_read(battery);
	if (result)
		return result;
764

765
	sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
766
#ifdef CONFIG_ACPI_PROCFS
767 768 769 770
	acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
			battery->name, &acpi_battery_info_fops,
			&acpi_battery_state_fops, &acpi_battery_alarm_fops,
			battery);
771
#endif
772 773 774 775 776 777 778 779 780 781 782 783 784
	battery->bat.name = battery->name;
	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	if (!acpi_battery_mode(battery)) {
		battery->bat.properties = sbs_charge_battery_props;
		battery->bat.num_properties =
		    ARRAY_SIZE(sbs_charge_battery_props);
	} else {
		battery->bat.properties = sbs_energy_battery_props;
		battery->bat.num_properties =
		    ARRAY_SIZE(sbs_energy_battery_props);
	}
	battery->bat.get_property = acpi_sbs_battery_get_property;
	result = power_supply_register(&sbs->device->dev, &battery->bat);
785
	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
786 787
	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
	       battery->name, sbs->battery->present ? "present" : "absent");
788
	return result;
789 790 791 792
}

static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
{
793 794
	if (sbs->battery[id].bat.dev)
		power_supply_unregister(&sbs->battery[id].bat);
795
#ifdef CONFIG_ACPI_PROCFS
796
	if (sbs->battery[id].proc_entry) {
797 798
		acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
				   acpi_battery_dir);
799
	}
800
#endif
801 802
}

803
static int acpi_charger_add(struct acpi_sbs *sbs)
804 805 806 807
{
	int result;

	result = acpi_ac_get_present(sbs);
808
	if (result)
809
		goto end;
810
#ifdef CONFIG_ACPI_PROCFS
811 812 813 814
	result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
				 ACPI_AC_DIR_NAME, NULL,
				 &acpi_ac_state_fops, NULL, sbs);
	if (result)
815
		goto end;
816
#endif
817 818 819 820 821 822
	sbs->charger.name = "sbs-charger";
	sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
	sbs->charger.properties = sbs_ac_props;
	sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
	sbs->charger.get_property = sbs_get_ac_property;
	power_supply_register(&sbs->device->dev, &sbs->charger);
823 824
	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
825
	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
826
      end:
827
	return result;
828 829
}

830
static void acpi_charger_remove(struct acpi_sbs *sbs)
831
{
832 833
	if (sbs->charger.dev)
		power_supply_unregister(&sbs->charger);
834
#ifdef CONFIG_ACPI_PROCFS
835 836
	if (sbs->charger_entry)
		acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
837
#endif
838 839
}

840
void acpi_sbs_callback(void *context)
841
{
842 843 844 845 846 847 848
	int id;
	struct acpi_sbs *sbs = context;
	struct acpi_battery *bat;
	u8 saved_charger_state = sbs->charger_present;
	u8 saved_battery_state;
	acpi_ac_get_present(sbs);
	if (sbs->charger_present != saved_charger_state) {
849
#ifdef CONFIG_ACPI_PROC_EVENT
850 851 852
		acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
					      ACPI_SBS_NOTIFY_STATUS,
					      sbs->charger_present);
853 854
#endif
		kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
855
	}
856 857 858 859 860 861 862 863 864
	if (sbs->manager_present) {
		for (id = 0; id < MAX_SBS_BAT; ++id) {
			if (!(sbs->batteries_supported & (1 << id)))
				continue;
			bat = &sbs->battery[id];
			saved_battery_state = bat->present;
			acpi_battery_read(bat);
			if (saved_battery_state == bat->present)
				continue;
865
#ifdef CONFIG_ACPI_PROC_EVENT
866 867 868 869
			acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
						      bat->name,
						      ACPI_SBS_NOTIFY_STATUS,
						      bat->present);
870 871
#endif
			kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
872 873 874 875
		}
	}
}

876
static int acpi_sbs_remove(struct acpi_device *device, int type);
877 878 879

static int acpi_sbs_add(struct acpi_device *device)
{
880 881
	struct acpi_sbs *sbs;
	int result = 0;
882
	int id;
883

884
	sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
885
	if (!sbs) {
886 887
		result = -ENOMEM;
		goto end;
888 889
	}

890
	mutex_init(&sbs->lock);
891

892
	sbs->hc = acpi_driver_data(device->parent);
893
	sbs->device = device;
894 895 896 897
	strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
	acpi_driver_data(device) = sbs;

898
	result = acpi_charger_add(sbs);
899 900
	if (result)
		goto end;
901

902 903 904 905 906 907 908 909 910
	result = acpi_manager_get_info(sbs);
	if (!result) {
		sbs->manager_present = 1;
		for (id = 0; id < MAX_SBS_BAT; ++id)
			if ((sbs->batteries_supported & (1 << id)))
				acpi_battery_add(sbs, id);
	} else
		acpi_battery_add(sbs, 0);
	acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
911
      end:
912 913
	if (result)
		acpi_sbs_remove(device, 0);
914
	return result;
915 916
}

917
static int acpi_sbs_remove(struct acpi_device *device, int type)
918
{
L
Len Brown 已提交
919
	struct acpi_sbs *sbs;
920 921
	int id;

922
	if (!device)
923
		return -EINVAL;
924
	sbs = acpi_driver_data(device);
925
	if (!sbs)
926
		return -EINVAL;
927 928 929
	mutex_lock(&sbs->lock);
	acpi_smbus_unregister_callback(sbs->hc);
	for (id = 0; id < MAX_SBS_BAT; ++id)
930
		acpi_battery_remove(sbs, id);
931 932 933
	acpi_charger_remove(sbs);
	mutex_unlock(&sbs->lock);
	mutex_destroy(&sbs->lock);
934
	kfree(sbs);
935
	return 0;
936 937
}

938 939
static void acpi_sbs_rmdirs(void)
{
940
#ifdef CONFIG_ACPI_PROCFS
941 942 943 944 945 946 947 948
	if (acpi_ac_dir) {
		acpi_unlock_ac_dir(acpi_ac_dir);
		acpi_ac_dir = NULL;
	}
	if (acpi_battery_dir) {
		acpi_unlock_battery_dir(acpi_battery_dir);
		acpi_battery_dir = NULL;
	}
949
#endif
950 951 952 953 954 955 956 957
}

static int acpi_sbs_resume(struct acpi_device *device)
{
	struct acpi_sbs *sbs;
	if (!device)
		return -EINVAL;
	sbs = device->driver_data;
958
	acpi_sbs_callback(sbs);
959 960 961
	return 0;
}

962 963 964 965 966 967 968 969 970 971 972
static struct acpi_driver acpi_sbs_driver = {
	.name = "sbs",
	.class = ACPI_SBS_CLASS,
	.ids = sbs_device_ids,
	.ops = {
		.add = acpi_sbs_add,
		.remove = acpi_sbs_remove,
		.resume = acpi_sbs_resume,
		},
};

973 974 975 976
static int __init acpi_sbs_init(void)
{
	int result = 0;

977 978
	if (acpi_disabled)
		return -ENODEV;
979
#ifdef CONFIG_ACPI_PROCFS
980
	acpi_ac_dir = acpi_lock_ac_dir();
981
	if (!acpi_ac_dir)
982
		return -ENODEV;
983 984
	acpi_battery_dir = acpi_lock_battery_dir();
	if (!acpi_battery_dir) {
985
		acpi_sbs_rmdirs();
986
		return -ENODEV;
987
	}
988
#endif
989 990
	result = acpi_bus_register_driver(&acpi_sbs_driver);
	if (result < 0) {
991
		acpi_sbs_rmdirs();
992
		return -ENODEV;
993
	}
994
	return 0;
995 996 997 998 999
}

static void __exit acpi_sbs_exit(void)
{
	acpi_bus_unregister_driver(&acpi_sbs_driver);
1000
	acpi_sbs_rmdirs();
1001
	return;
1002 1003 1004 1005
}

module_init(acpi_sbs_init);
module_exit(acpi_sbs_exit);