ACPI: SBS: Simplify data structures in SBS
[linux-2.6-block.git] / drivers / acpi / sbs.c
CommitLineData
3f86b832
RT
1/*
2 * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $)
3 *
4 * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/kernel.h>
29#include <linux/proc_fs.h>
30#include <linux/seq_file.h>
31#include <asm/uaccess.h>
32#include <linux/acpi.h>
6d15702c 33#include <linux/timer.h>
72206233 34#include <linux/jiffies.h>
3f86b832
RT
35#include <linux/delay.h>
36
91087dfa
AS
37#include "sbshc.h"
38
3f86b832
RT
39#define ACPI_SBS_COMPONENT 0x00080000
40#define ACPI_SBS_CLASS "sbs"
41#define ACPI_AC_CLASS "ac_adapter"
42#define ACPI_BATTERY_CLASS "battery"
3f86b832
RT
43#define ACPI_SBS_DEVICE_NAME "Smart Battery System"
44#define ACPI_SBS_FILE_INFO "info"
45#define ACPI_SBS_FILE_STATE "state"
46#define ACPI_SBS_FILE_ALARM "alarm"
47#define ACPI_BATTERY_DIR_NAME "BAT%i"
48#define ACPI_AC_DIR_NAME "AC0"
49#define ACPI_SBC_SMBUS_ADDR 0x9
50#define ACPI_SBSM_SMBUS_ADDR 0xa
51#define ACPI_SB_SMBUS_ADDR 0xb
52#define ACPI_SBS_AC_NOTIFY_STATUS 0x80
53#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
54#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
55
56#define _COMPONENT ACPI_SBS_COMPONENT
57
f52fd66d 58ACPI_MODULE_NAME("sbs");
3f86b832
RT
59
60MODULE_AUTHOR("Rich Townsend");
61MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
62MODULE_LICENSE("GPL");
63
6d15702c
VL
64#define DEF_CAPACITY_UNIT 3
65#define MAH_CAPACITY_UNIT 1
66#define MWH_CAPACITY_UNIT 2
67#define CAPACITY_UNIT DEF_CAPACITY_UNIT
68
69#define REQUEST_UPDATE_MODE 1
70#define QUEUE_UPDATE_MODE 2
71
72#define DATA_TYPE_COMMON 0
73#define DATA_TYPE_INFO 1
74#define DATA_TYPE_STATE 2
75#define DATA_TYPE_ALARM 3
76#define DATA_TYPE_AC_STATE 4
77
78extern struct proc_dir_entry *acpi_lock_ac_dir(void);
79extern struct proc_dir_entry *acpi_lock_battery_dir(void);
80extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
81extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
82
83#define MAX_SBS_BAT 4
84#define ACPI_SBS_BLOCK_MAX 32
85
72206233 86#define UPDATE_DELAY 10
3f86b832 87
72206233
VL
88/* 0 - every time, > 0 - by update_time */
89static unsigned int update_time = 120;
3f86b832 90
89862e3b 91static unsigned int mode = CAPACITY_UNIT;
3f86b832 92
72206233 93module_param(update_time, uint, 0644);
89862e3b 94module_param(mode, uint, 0444);
3f86b832
RT
95
96static int acpi_sbs_add(struct acpi_device *device);
97static int acpi_sbs_remove(struct acpi_device *device, int type);
72206233 98static int acpi_sbs_resume(struct acpi_device *device);
3f86b832 99
1ba90e3a 100static const struct acpi_device_id sbs_device_ids[] = {
91087dfa 101 {"ACPI0002", 0},
1ba90e3a
TR
102 {"", 0},
103};
104MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
105
3f86b832 106static struct acpi_driver acpi_sbs_driver = {
c2b6705b 107 .name = "sbs",
3f86b832 108 .class = ACPI_SBS_CLASS,
1ba90e3a 109 .ids = sbs_device_ids,
3f86b832
RT
110 .ops = {
111 .add = acpi_sbs_add,
112 .remove = acpi_sbs_remove,
72206233 113 .resume = acpi_sbs_resume,
3f86b832
RT
114 },
115};
116
3f86b832 117struct acpi_battery {
3f86b832 118 struct acpi_sbs *sbs;
89862e3b
AS
119 struct proc_dir_entry *proc_entry;
120 int vscale;
121 int ipscale;
122 char manufacturer_name[ACPI_SBS_BLOCK_MAX];
123 char device_name[ACPI_SBS_BLOCK_MAX];
124 char device_chemistry[ACPI_SBS_BLOCK_MAX];
125 u16 full_charge_capacity;
126 u16 design_capacity;
127 u16 design_voltage;
128 u16 serial_number;
129 u16 voltage_now;
130 s16 current_now;
131 u16 capacity_now;
132 u16 state;
133 u16 alarm_capacity;
134 u16 mode;
135 u8 id;
136 u8 alive:1;
137 u8 init_state:1;
138 u8 present:1;
3f86b832
RT
139};
140
141struct acpi_sbs {
3f86b832 142 struct acpi_device *device;
91087dfa 143 struct acpi_smb_hc *hc;
72206233 144 struct mutex mutex;
3f86b832
RT
145 struct proc_dir_entry *ac_entry;
146 struct acpi_battery battery[MAX_SBS_BAT];
3f86b832 147 int zombie;
3f86b832 148 struct timer_list update_timer;
72206233
VL
149 int run_cnt;
150 int update_proc_flg;
89862e3b
AS
151 u8 batteries_supported;
152 u8 manager_present:1;
153 u8 charger_present:1;
3f86b832
RT
154};
155
72206233
VL
156static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type);
157static void acpi_sbs_update_time(void *data);
158
72206233
VL
159static int sbs_zombie(struct acpi_sbs *sbs)
160{
161 return (sbs->zombie);
162}
163
164static int sbs_mutex_lock(struct acpi_sbs *sbs)
165{
166 if (sbs_zombie(sbs)) {
167 return -ENODEV;
168 }
169 mutex_lock(&sbs->mutex);
170 return 0;
171}
172
173static void sbs_mutex_unlock(struct acpi_sbs *sbs)
174{
175 mutex_unlock(&sbs->mutex);
176}
177
3f86b832
RT
178/* --------------------------------------------------------------------------
179 Smart Battery System Management
180 -------------------------------------------------------------------------- */
181
72206233
VL
182static int acpi_check_update_proc(struct acpi_sbs *sbs)
183{
184 acpi_status status = AE_OK;
185
186 if (update_time == 0) {
187 sbs->update_proc_flg = 0;
188 return 0;
189 }
190 if (sbs->update_proc_flg == 0) {
191 status = acpi_os_execute(OSL_GPE_HANDLER,
192 acpi_sbs_update_time, sbs);
193 if (status != AE_OK) {
194 ACPI_EXCEPTION((AE_INFO, status,
195 "acpi_os_execute() failed"));
196 return 1;
197 }
198 sbs->update_proc_flg = 1;
199 }
200 return 0;
201}
3f86b832 202
3f86b832
RT
203static int acpi_battery_get_present(struct acpi_battery *battery)
204{
205 s16 state;
206 int result = 0;
207 int is_present = 0;
208
91087dfa
AS
209 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
210 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state);
3f86b832 211 if (result) {
6845118b 212 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 213 "acpi_smbus_read() failed"));
3f86b832
RT
214 }
215 if (!result) {
216 is_present = (state & 0x000f) & (1 << battery->id);
217 }
89862e3b 218 battery->present = is_present;
3f86b832 219
635227ee 220 return result;
3f86b832
RT
221}
222
3f86b832
RT
223static int acpi_battery_select(struct acpi_battery *battery)
224{
6d15702c 225 struct acpi_sbs *sbs = battery->sbs;
3f86b832
RT
226 int result = 0;
227 s16 state;
228 int foo;
229
89862e3b 230 if (sbs->manager_present) {
3f86b832
RT
231
232 /* Take special care not to knobble other nibbles of
233 * state (aka selector_state), since
234 * it causes charging to halt on SBSELs */
235
89862e3b
AS
236 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
237 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state);
3f86b832 238 if (result) {
6845118b 239 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 240 "acpi_smbus_read() failed"));
3f86b832
RT
241 goto end;
242 }
243
244 foo = (state & 0x0fff) | (1 << (battery->id + 12));
89862e3b
AS
245 result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
246 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2);
3f86b832 247 if (result) {
6845118b 248 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 249 "acpi_smbus_write() failed"));
3f86b832
RT
250 goto end;
251 }
252 }
253
254 end:
635227ee 255 return result;
3f86b832
RT
256}
257
258static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
259{
3f86b832
RT
260 int result = 0;
261 s16 battery_system_info;
262
91087dfa
AS
263 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x04,
264 (u8 *)&battery_system_info);
3f86b832 265 if (result) {
6845118b 266 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 267 "acpi_smbus_read() failed"));
3f86b832
RT
268 goto end;
269 }
89862e3b 270 sbs->manager_present = 1;
3f86b832
RT
271
272 end:
273
635227ee 274 return result;
3f86b832
RT
275}
276
277static int acpi_battery_get_info(struct acpi_battery *battery)
278{
3f86b832
RT
279 int result = 0;
280 s16 battery_mode;
281 s16 specification_info;
282
91087dfa
AS
283 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03,
284 (u8 *)&battery_mode);
3f86b832 285 if (result) {
6845118b 286 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 287 "acpi_smbus_read() failed"));
3f86b832
RT
288 goto end;
289 }
89862e3b 290 battery->mode = (battery_mode & 0x8000) >> 15;
3f86b832 291
91087dfa 292 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x10,
89862e3b 293 (u8 *)&battery->full_charge_capacity);
3f86b832 294 if (result) {
6845118b 295 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 296 "acpi_smbus_read() failed"));
3f86b832
RT
297 goto end;
298 }
299
91087dfa 300 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x18,
89862e3b 301 (u8 *)&battery->design_capacity);
3f86b832
RT
302
303 if (result) {
72206233 304 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 305 "acpi_smbus_read() failed"));
3f86b832
RT
306 goto end;
307 }
308
91087dfa 309 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x19,
89862e3b 310 (u8 *)&battery->design_voltage);
3f86b832 311 if (result) {
6845118b 312 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 313 "acpi_smbus_read() failed"));
3f86b832
RT
314 goto end;
315 }
316
91087dfa
AS
317 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1a,
318 (u8 *)&specification_info);
3f86b832 319 if (result) {
6845118b 320 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 321 "acpi_smbus_read() failed"));
3f86b832
RT
322 goto end;
323 }
324
325 switch ((specification_info & 0x0f00) >> 8) {
326 case 1:
89862e3b 327 battery->vscale = 10;
3f86b832
RT
328 break;
329 case 2:
89862e3b 330 battery->vscale = 100;
3f86b832
RT
331 break;
332 case 3:
89862e3b 333 battery->vscale = 1000;
3f86b832
RT
334 break;
335 default:
89862e3b 336 battery->vscale = 1;
3f86b832
RT
337 }
338
339 switch ((specification_info & 0xf000) >> 12) {
340 case 1:
89862e3b 341 battery->ipscale = 10;
3f86b832
RT
342 break;
343 case 2:
89862e3b 344 battery->ipscale = 100;
3f86b832
RT
345 break;
346 case 3:
89862e3b 347 battery->ipscale = 1000;
3f86b832
RT
348 break;
349 default:
89862e3b 350 battery->ipscale = 1;
3f86b832
RT
351 }
352
91087dfa 353 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1c,
89862e3b 354 (u8 *)&battery->serial_number);
3f86b832 355 if (result) {
72206233 356 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 357 "acpi_smbus_read() failed"));
3f86b832
RT
358 goto end;
359 }
360
91087dfa 361 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x20,
89862e3b 362 (u8 *)battery->manufacturer_name);
3f86b832 363 if (result) {
6845118b
VL
364 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
365 "acpi_sbs_read_str() failed"));
3f86b832
RT
366 goto end;
367 }
368
91087dfa 369 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x21,
89862e3b 370 (u8 *)battery->device_name);
3f86b832 371 if (result) {
6845118b
VL
372 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
373 "acpi_sbs_read_str() failed"));
3f86b832
RT
374 goto end;
375 }
376
91087dfa 377 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x22,
89862e3b 378 (u8 *)battery->device_chemistry);
3f86b832 379 if (result) {
6845118b
VL
380 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
381 "acpi_sbs_read_str() failed"));
3f86b832
RT
382 goto end;
383 }
384
385 end:
635227ee 386 return result;
3f86b832
RT
387}
388
3f86b832
RT
389static int acpi_battery_get_state(struct acpi_battery *battery)
390{
3f86b832
RT
391 int result = 0;
392
91087dfa 393 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x09,
89862e3b 394 (u8 *)&battery->voltage_now);
3f86b832 395 if (result) {
6845118b 396 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 397 "acpi_smbus_read() failed"));
3f86b832
RT
398 goto end;
399 }
400
91087dfa 401 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0a,
89862e3b 402 (u8 *)&battery->current_now);
3f86b832 403 if (result) {
6845118b 404 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 405 "acpi_smbus_read() failed"));
3f86b832
RT
406 goto end;
407 }
408
91087dfa 409 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0f,
89862e3b 410 (u8 *)&battery->capacity_now);
3f86b832 411 if (result) {
6845118b 412 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 413 "acpi_smbus_read() failed"));
3f86b832
RT
414 goto end;
415 }
416
91087dfa 417 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x16,
89862e3b 418 (u8 *)&battery->state);
3f86b832 419 if (result) {
6845118b 420 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 421 "acpi_smbus_read() failed"));
3f86b832
RT
422 goto end;
423 }
424
3f86b832 425 end:
635227ee 426 return result;
3f86b832
RT
427}
428
429static int acpi_battery_get_alarm(struct acpi_battery *battery)
430{
3f86b832
RT
431 int result = 0;
432
91087dfa 433 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
89862e3b 434 (u8 *)&battery->alarm_capacity);
3f86b832 435 if (result) {
6845118b 436 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 437 "acpi_smbus_read() failed"));
3f86b832
RT
438 goto end;
439 }
440
3f86b832
RT
441 end:
442
635227ee 443 return result;
3f86b832
RT
444}
445
446static int acpi_battery_set_alarm(struct acpi_battery *battery,
447 unsigned long alarm)
448{
3f86b832
RT
449 int result = 0;
450 s16 battery_mode;
451 int foo;
452
3f86b832
RT
453 result = acpi_battery_select(battery);
454 if (result) {
6845118b
VL
455 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
456 "acpi_battery_select() failed"));
3f86b832
RT
457 goto end;
458 }
459
460 /* If necessary, enable the alarm */
461
462 if (alarm > 0) {
463 result =
91087dfa
AS
464 acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03,
465 (u8 *)&battery_mode);
3f86b832 466 if (result) {
6845118b 467 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 468 "acpi_smbus_read() failed"));
3f86b832
RT
469 goto end;
470 }
471
91087dfa 472 battery_mode &= 0xbfff;
3f86b832 473 result =
91087dfa
AS
474 acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
475 (u8 *)&battery_mode, 2);
3f86b832 476 if (result) {
6845118b 477 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 478 "acpi_smbus_write() failed"));
3f86b832
RT
479 goto end;
480 }
481 }
482
89862e3b
AS
483 foo = alarm / (battery->mode ? 10 : 1);
484 result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
485 (u8 *)&foo, 2);
3f86b832 486 if (result) {
6845118b 487 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 488 "acpi_smbus_write() failed"));
3f86b832
RT
489 goto end;
490 }
491
492 end:
493
635227ee 494 return result;
3f86b832
RT
495}
496
497static int acpi_battery_set_mode(struct acpi_battery *battery)
498{
499 int result = 0;
500 s16 battery_mode;
501
89862e3b 502 if (mode == DEF_CAPACITY_UNIT) {
3f86b832
RT
503 goto end;
504 }
505
91087dfa 506 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
89862e3b 507 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode);
3f86b832 508 if (result) {
6845118b 509 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 510 "acpi_smbus_read() failed"));
3f86b832
RT
511 goto end;
512 }
513
89862e3b 514 if (mode == MAH_CAPACITY_UNIT) {
3f86b832
RT
515 battery_mode &= 0x7fff;
516 } else {
517 battery_mode |= 0x8000;
518 }
91087dfa 519 result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD,
89862e3b 520 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2);
3f86b832 521 if (result) {
6845118b 522 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 523 "acpi_smbus_write() failed"));
3f86b832
RT
524 goto end;
525 }
526
91087dfa 527 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
89862e3b 528 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode);
3f86b832 529 if (result) {
6845118b 530 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 531 "acpi_smbus_read() failed"));
3f86b832
RT
532 goto end;
533 }
534
535 end:
635227ee 536 return result;
3f86b832
RT
537}
538
539static int acpi_battery_init(struct acpi_battery *battery)
540{
541 int result = 0;
542
3f86b832
RT
543 result = acpi_battery_select(battery);
544 if (result) {
6845118b 545 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
72206233 546 "acpi_battery_select() failed"));
3f86b832
RT
547 goto end;
548 }
549
550 result = acpi_battery_set_mode(battery);
551 if (result) {
6845118b
VL
552 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
553 "acpi_battery_set_mode() failed"));
3f86b832
RT
554 goto end;
555 }
556
557 result = acpi_battery_get_info(battery);
558 if (result) {
6845118b
VL
559 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
560 "acpi_battery_get_info() failed"));
3f86b832
RT
561 goto end;
562 }
563
564 result = acpi_battery_get_state(battery);
565 if (result) {
6845118b
VL
566 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
567 "acpi_battery_get_state() failed"));
3f86b832
RT
568 goto end;
569 }
570
571 result = acpi_battery_get_alarm(battery);
572 if (result) {
6845118b
VL
573 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
574 "acpi_battery_get_alarm() failed"));
3f86b832
RT
575 goto end;
576 }
577
578 end:
635227ee 579 return result;
3f86b832
RT
580}
581
582static int acpi_ac_get_present(struct acpi_sbs *sbs)
583{
3f86b832
RT
584 int result = 0;
585 s16 charger_status;
586
91087dfa 587 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBC_SMBUS_ADDR, 0x13,
89862e3b 588 (u8 *)&charger_status);
3f86b832
RT
589
590 if (result) {
6845118b 591 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
91087dfa 592 "acpi_smbus_read() failed"));
3f86b832
RT
593 goto end;
594 }
595
89862e3b 596 sbs->charger_present = (charger_status & 0x8000) >> 15;
3f86b832
RT
597
598 end:
599
635227ee 600 return result;
3f86b832
RT
601}
602
603/* --------------------------------------------------------------------------
604 FS Interface (/proc/acpi)
605 -------------------------------------------------------------------------- */
606
607/* Generic Routines */
608
609static int
610acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
611 struct proc_dir_entry *parent_dir,
612 char *dir_name,
613 struct file_operations *info_fops,
614 struct file_operations *state_fops,
615 struct file_operations *alarm_fops, void *data)
616{
617 struct proc_dir_entry *entry = NULL;
618
3f86b832
RT
619 if (!*dir) {
620 *dir = proc_mkdir(dir_name, parent_dir);
621 if (!*dir) {
6845118b
VL
622 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
623 "proc_mkdir() failed"));
635227ee 624 return -ENODEV;
3f86b832
RT
625 }
626 (*dir)->owner = THIS_MODULE;
627 }
628
629 /* 'info' [R] */
630 if (info_fops) {
631 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
632 if (!entry) {
6845118b
VL
633 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
634 "create_proc_entry() failed"));
3f86b832
RT
635 } else {
636 entry->proc_fops = info_fops;
637 entry->data = data;
638 entry->owner = THIS_MODULE;
639 }
640 }
641
642 /* 'state' [R] */
643 if (state_fops) {
644 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
645 if (!entry) {
6845118b
VL
646 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
647 "create_proc_entry() failed"));
3f86b832
RT
648 } else {
649 entry->proc_fops = state_fops;
650 entry->data = data;
651 entry->owner = THIS_MODULE;
652 }
653 }
654
655 /* 'alarm' [R/W] */
656 if (alarm_fops) {
657 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
658 if (!entry) {
6845118b
VL
659 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
660 "create_proc_entry() failed"));
3f86b832
RT
661 } else {
662 entry->proc_fops = alarm_fops;
663 entry->data = data;
664 entry->owner = THIS_MODULE;
665 }
666 }
667
635227ee 668 return 0;
3f86b832
RT
669}
670
671static void
672acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
673 struct proc_dir_entry *parent_dir)
674{
3f86b832
RT
675
676 if (*dir) {
677 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
678 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
679 remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
680 remove_proc_entry((*dir)->name, parent_dir);
681 *dir = NULL;
682 }
683
684}
685
686/* Smart Battery Interface */
687
688static struct proc_dir_entry *acpi_battery_dir = NULL;
689
690static int acpi_battery_read_info(struct seq_file *seq, void *offset)
691{
50dd0969 692 struct acpi_battery *battery = seq->private;
72206233 693 struct acpi_sbs *sbs = battery->sbs;
3f86b832
RT
694 int cscale;
695 int result = 0;
696
72206233 697 if (sbs_mutex_lock(sbs)) {
635227ee 698 return -ENODEV;
3f86b832
RT
699 }
700
72206233
VL
701 result = acpi_check_update_proc(sbs);
702 if (result)
703 goto end;
3f86b832 704
72206233
VL
705 if (update_time == 0) {
706 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
3f86b832 707 if (result) {
6845118b
VL
708 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
709 "acpi_sbs_update_run() failed"));
3f86b832
RT
710 }
711 }
712
89862e3b 713 if (battery->present) {
3f86b832
RT
714 seq_printf(seq, "present: yes\n");
715 } else {
716 seq_printf(seq, "present: no\n");
717 goto end;
718 }
719
89862e3b
AS
720 if (battery->mode) {
721 cscale = battery->vscale * battery->ipscale;
3f86b832 722 } else {
89862e3b 723 cscale = battery->ipscale;
3f86b832 724 }
72206233 725 seq_printf(seq, "design capacity: %i%s\n",
89862e3b
AS
726 battery->design_capacity * cscale,
727 battery->mode ? "0 mWh" : " mAh");
3f86b832 728
72206233 729 seq_printf(seq, "last full capacity: %i%s\n",
89862e3b
AS
730 battery->full_charge_capacity * cscale,
731 battery->mode ? "0 mWh" : " mAh");
3f86b832
RT
732
733 seq_printf(seq, "battery technology: rechargeable\n");
734
735 seq_printf(seq, "design voltage: %i mV\n",
89862e3b 736 battery->design_voltage * battery->vscale);
3f86b832
RT
737
738 seq_printf(seq, "design capacity warning: unknown\n");
739 seq_printf(seq, "design capacity low: unknown\n");
740 seq_printf(seq, "capacity granularity 1: unknown\n");
741 seq_printf(seq, "capacity granularity 2: unknown\n");
742
743 seq_printf(seq, "model number: %s\n",
89862e3b 744 battery->device_name);
3f86b832
RT
745
746 seq_printf(seq, "serial number: %i\n",
89862e3b 747 battery->serial_number);
3f86b832
RT
748
749 seq_printf(seq, "battery type: %s\n",
89862e3b 750 battery->device_chemistry);
3f86b832
RT
751
752 seq_printf(seq, "OEM info: %s\n",
89862e3b 753 battery->manufacturer_name);
3f86b832
RT
754
755 end:
756
72206233 757 sbs_mutex_unlock(sbs);
3f86b832 758
635227ee 759 return result;
3f86b832
RT
760}
761
762static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
763{
764 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
765}
766
767static int acpi_battery_read_state(struct seq_file *seq, void *offset)
768{
72206233
VL
769 struct acpi_battery *battery = seq->private;
770 struct acpi_sbs *sbs = battery->sbs;
3f86b832
RT
771 int result = 0;
772 int cscale;
773 int foo;
774
72206233 775 if (sbs_mutex_lock(sbs)) {
635227ee 776 return -ENODEV;
3f86b832
RT
777 }
778
72206233
VL
779 result = acpi_check_update_proc(sbs);
780 if (result)
781 goto end;
3f86b832 782
72206233
VL
783 if (update_time == 0) {
784 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE);
3f86b832 785 if (result) {
6845118b
VL
786 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
787 "acpi_sbs_update_run() failed"));
3f86b832
RT
788 }
789 }
790
89862e3b 791 if (battery->present) {
3f86b832
RT
792 seq_printf(seq, "present: yes\n");
793 } else {
794 seq_printf(seq, "present: no\n");
795 goto end;
796 }
797
89862e3b
AS
798 if (battery->mode) {
799 cscale = battery->vscale * battery->ipscale;
3f86b832 800 } else {
89862e3b 801 cscale = battery->ipscale;
3f86b832
RT
802 }
803
89862e3b 804 if (battery->state & 0x0010) {
3f86b832
RT
805 seq_printf(seq, "capacity state: critical\n");
806 } else {
807 seq_printf(seq, "capacity state: ok\n");
808 }
e6d0f562 809
89862e3b
AS
810 foo = (s16) battery->current_now * battery->ipscale;
811 if (battery->mode) {
812 foo = foo * battery->design_voltage / 1000;
e6d0f562 813 }
89862e3b 814 if (battery->current_now < 0) {
3f86b832 815 seq_printf(seq, "charging state: discharging\n");
e6d0f562 816 seq_printf(seq, "present rate: %d %s\n",
89862e3b
AS
817 -foo, battery->mode ? "mW" : "mA");
818 } else if (battery->current_now > 0) {
3f86b832 819 seq_printf(seq, "charging state: charging\n");
e6d0f562 820 seq_printf(seq, "present rate: %d %s\n",
89862e3b 821 foo, battery->mode ? "mW" : "mA");
3f86b832
RT
822 } else {
823 seq_printf(seq, "charging state: charged\n");
824 seq_printf(seq, "present rate: 0 %s\n",
89862e3b 825 battery->mode ? "mW" : "mA");
3f86b832
RT
826 }
827
72206233 828 seq_printf(seq, "remaining capacity: %i%s\n",
89862e3b
AS
829 battery->capacity_now * cscale,
830 battery->mode ? "0 mWh" : " mAh");
3f86b832
RT
831
832 seq_printf(seq, "present voltage: %i mV\n",
89862e3b 833 battery->voltage_now * battery->vscale);
3f86b832
RT
834
835 end:
836
72206233 837 sbs_mutex_unlock(sbs);
3f86b832 838
635227ee 839 return result;
3f86b832
RT
840}
841
842static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
843{
844 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
845}
846
847static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
848{
50dd0969 849 struct acpi_battery *battery = seq->private;
72206233 850 struct acpi_sbs *sbs = battery->sbs;
3f86b832
RT
851 int result = 0;
852 int cscale;
853
72206233 854 if (sbs_mutex_lock(sbs)) {
635227ee 855 return -ENODEV;
3f86b832
RT
856 }
857
72206233
VL
858 result = acpi_check_update_proc(sbs);
859 if (result)
860 goto end;
3f86b832 861
72206233
VL
862 if (update_time == 0) {
863 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM);
3f86b832 864 if (result) {
6845118b
VL
865 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
866 "acpi_sbs_update_run() failed"));
3f86b832
RT
867 }
868 }
869
89862e3b 870 if (!battery->present) {
3f86b832
RT
871 seq_printf(seq, "present: no\n");
872 goto end;
873 }
874
89862e3b
AS
875 if (battery->mode) {
876 cscale = battery->vscale * battery->ipscale;
3f86b832 877 } else {
89862e3b 878 cscale = battery->ipscale;
3f86b832
RT
879 }
880
881 seq_printf(seq, "alarm: ");
89862e3b 882 if (battery->alarm_capacity) {
72206233 883 seq_printf(seq, "%i%s\n",
89862e3b
AS
884 battery->alarm_capacity * cscale,
885 battery->mode ? "0 mWh" : " mAh");
3f86b832
RT
886 } else {
887 seq_printf(seq, "disabled\n");
888 }
889
890 end:
891
72206233 892 sbs_mutex_unlock(sbs);
3f86b832 893
635227ee 894 return result;
3f86b832
RT
895}
896
897static ssize_t
898acpi_battery_write_alarm(struct file *file, const char __user * buffer,
899 size_t count, loff_t * ppos)
900{
50dd0969
JE
901 struct seq_file *seq = file->private_data;
902 struct acpi_battery *battery = seq->private;
72206233 903 struct acpi_sbs *sbs = battery->sbs;
3f86b832
RT
904 char alarm_string[12] = { '\0' };
905 int result, old_alarm, new_alarm;
906
72206233 907 if (sbs_mutex_lock(sbs)) {
635227ee 908 return -ENODEV;
3f86b832
RT
909 }
910
72206233
VL
911 result = acpi_check_update_proc(sbs);
912 if (result)
913 goto end;
3f86b832 914
89862e3b 915 if (!battery->present) {
3f86b832
RT
916 result = -ENODEV;
917 goto end;
918 }
919
920 if (count > sizeof(alarm_string) - 1) {
921 result = -EINVAL;
922 goto end;
923 }
924
925 if (copy_from_user(alarm_string, buffer, count)) {
926 result = -EFAULT;
927 goto end;
928 }
929
930 alarm_string[count] = 0;
931
89862e3b 932 old_alarm = battery->alarm_capacity;
3f86b832
RT
933 new_alarm = simple_strtoul(alarm_string, NULL, 0);
934
935 result = acpi_battery_set_alarm(battery, new_alarm);
936 if (result) {
6845118b
VL
937 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
938 "acpi_battery_set_alarm() failed"));
50dd0969 939 acpi_battery_set_alarm(battery, old_alarm);
3f86b832
RT
940 goto end;
941 }
942 result = acpi_battery_get_alarm(battery);
943 if (result) {
6845118b
VL
944 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
945 "acpi_battery_get_alarm() failed"));
50dd0969 946 acpi_battery_set_alarm(battery, old_alarm);
3f86b832
RT
947 goto end;
948 }
949
950 end:
72206233 951 sbs_mutex_unlock(sbs);
3f86b832
RT
952
953 if (result) {
635227ee 954 return result;
3f86b832 955 } else {
635227ee 956 return count;
3f86b832
RT
957 }
958}
959
960static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
961{
962 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
963}
964
965static struct file_operations acpi_battery_info_fops = {
966 .open = acpi_battery_info_open_fs,
967 .read = seq_read,
968 .llseek = seq_lseek,
969 .release = single_release,
970 .owner = THIS_MODULE,
971};
972
973static struct file_operations acpi_battery_state_fops = {
974 .open = acpi_battery_state_open_fs,
975 .read = seq_read,
976 .llseek = seq_lseek,
977 .release = single_release,
978 .owner = THIS_MODULE,
979};
980
981static struct file_operations acpi_battery_alarm_fops = {
982 .open = acpi_battery_alarm_open_fs,
983 .read = seq_read,
984 .write = acpi_battery_write_alarm,
985 .llseek = seq_lseek,
986 .release = single_release,
987 .owner = THIS_MODULE,
988};
989
990/* Legacy AC Adapter Interface */
991
992static struct proc_dir_entry *acpi_ac_dir = NULL;
993
994static int acpi_ac_read_state(struct seq_file *seq, void *offset)
995{
50dd0969 996 struct acpi_sbs *sbs = seq->private;
3f86b832
RT
997 int result;
998
72206233 999 if (sbs_mutex_lock(sbs)) {
635227ee 1000 return -ENODEV;
3f86b832
RT
1001 }
1002
72206233
VL
1003 if (update_time == 0) {
1004 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE);
3f86b832 1005 if (result) {
6845118b
VL
1006 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1007 "acpi_sbs_update_run() failed"));
3f86b832
RT
1008 }
1009 }
1010
1011 seq_printf(seq, "state: %s\n",
89862e3b 1012 sbs->charger_present ? "on-line" : "off-line");
3f86b832 1013
72206233 1014 sbs_mutex_unlock(sbs);
3f86b832 1015
635227ee 1016 return 0;
3f86b832
RT
1017}
1018
1019static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
1020{
1021 return single_open(file, acpi_ac_read_state, PDE(inode)->data);
1022}
1023
1024static struct file_operations acpi_ac_state_fops = {
1025 .open = acpi_ac_state_open_fs,
1026 .read = seq_read,
1027 .llseek = seq_lseek,
1028 .release = single_release,
1029 .owner = THIS_MODULE,
1030};
1031
1032/* --------------------------------------------------------------------------
1033 Driver Interface
1034 -------------------------------------------------------------------------- */
1035
1036/* Smart Battery */
1037
1038static int acpi_battery_add(struct acpi_sbs *sbs, int id)
1039{
1040 int is_present;
1041 int result;
1042 char dir_name[32];
1043 struct acpi_battery *battery;
1044
3f86b832
RT
1045 battery = &sbs->battery[id];
1046
1047 battery->alive = 0;
1048
1049 battery->init_state = 0;
1050 battery->id = id;
1051 battery->sbs = sbs;
1052
1053 result = acpi_battery_select(battery);
1054 if (result) {
6845118b
VL
1055 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1056 "acpi_battery_select() failed"));
3f86b832
RT
1057 goto end;
1058 }
1059
1060 result = acpi_battery_get_present(battery);
1061 if (result) {
6845118b
VL
1062 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1063 "acpi_battery_get_present() failed"));
3f86b832
RT
1064 goto end;
1065 }
1066
89862e3b 1067 is_present = battery->present;
3f86b832
RT
1068
1069 if (is_present) {
1070 result = acpi_battery_init(battery);
1071 if (result) {
6845118b
VL
1072 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1073 "acpi_battery_init() failed"));
3f86b832
RT
1074 goto end;
1075 }
1076 battery->init_state = 1;
1077 }
1078
50dd0969 1079 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
3f86b832 1080
89862e3b 1081 result = acpi_sbs_generic_add_fs(&battery->proc_entry,
3f86b832
RT
1082 acpi_battery_dir,
1083 dir_name,
1084 &acpi_battery_info_fops,
1085 &acpi_battery_state_fops,
1086 &acpi_battery_alarm_fops, battery);
1087 if (result) {
6845118b
VL
1088 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1089 "acpi_sbs_generic_add_fs() failed"));
3f86b832
RT
1090 goto end;
1091 }
1092 battery->alive = 1;
1093
72206233
VL
1094 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
1095 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name,
89862e3b 1096 sbs->battery->present ? "present" : "absent");
72206233 1097
3f86b832 1098 end:
635227ee 1099 return result;
3f86b832
RT
1100}
1101
1102static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
1103{
3f86b832 1104
89862e3b
AS
1105 if (sbs->battery[id].proc_entry) {
1106 acpi_sbs_generic_remove_fs(&(sbs->battery[id].proc_entry),
3f86b832
RT
1107 acpi_battery_dir);
1108 }
1109}
1110
1111static int acpi_ac_add(struct acpi_sbs *sbs)
1112{
1113 int result;
1114
3f86b832
RT
1115 result = acpi_ac_get_present(sbs);
1116 if (result) {
6845118b
VL
1117 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1118 "acpi_ac_get_present() failed"));
3f86b832
RT
1119 goto end;
1120 }
1121
1122 result = acpi_sbs_generic_add_fs(&sbs->ac_entry,
1123 acpi_ac_dir,
1124 ACPI_AC_DIR_NAME,
1125 NULL, &acpi_ac_state_fops, NULL, sbs);
1126 if (result) {
6845118b
VL
1127 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1128 "acpi_sbs_generic_add_fs() failed"));
3f86b832
RT
1129 goto end;
1130 }
1131
72206233
VL
1132 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
1133 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
89862e3b 1134 ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
72206233 1135
3f86b832
RT
1136 end:
1137
635227ee 1138 return result;
3f86b832
RT
1139}
1140
1141static void acpi_ac_remove(struct acpi_sbs *sbs)
1142{
3f86b832
RT
1143
1144 if (sbs->ac_entry) {
1145 acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir);
1146 }
1147}
1148
72206233 1149static void acpi_sbs_update_time_run(unsigned long data)
3f86b832 1150{
72206233 1151 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data);
3f86b832
RT
1152}
1153
72206233 1154static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type)
3f86b832
RT
1155{
1156 struct acpi_battery *battery;
72206233
VL
1157 int result = 0, cnt;
1158 int old_ac_present = -1;
89862e3b 1159 int old_present = -1;
72206233 1160 int new_ac_present = -1;
89862e3b 1161 int new_present = -1;
72206233 1162 int id_min = 0, id_max = MAX_SBS_BAT - 1;
3f86b832 1163 char dir_name[32];
72206233
VL
1164 int do_battery_init = 0, do_ac_init = 0;
1165 int old_remaining_capacity = 0;
bc90a010 1166 int update_battery = 1;
72206233
VL
1167 int up_tm = update_time;
1168
1169 if (sbs_zombie(sbs)) {
1170 goto end;
1171 }
3f86b832 1172
72206233
VL
1173 if (id >= 0) {
1174 id_min = id_max = id;
1175 }
1176
1177 if (data_type == DATA_TYPE_COMMON && up_tm > 0) {
1178 cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1179 if (sbs->run_cnt % cnt != 0) {
1180 update_battery = 0;
1181 }
1182 }
1183
1184 sbs->run_cnt++;
1185
89862e3b
AS
1186 if (!update_battery) {
1187 goto end;
1188 }
1189
1190 old_ac_present = sbs->charger_present;
3f86b832
RT
1191
1192 result = acpi_ac_get_present(sbs);
1193 if (result) {
6845118b
VL
1194 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1195 "acpi_ac_get_present() failed"));
3f86b832
RT
1196 }
1197
89862e3b 1198 new_ac_present = sbs->charger_present;
3f86b832
RT
1199
1200 do_ac_init = (old_ac_present != new_ac_present);
72206233
VL
1201 if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) {
1202 do_ac_init = 1;
1203 }
3f86b832 1204
72206233 1205 if (do_ac_init) {
8db85d4c 1206 result = acpi_bus_generate_proc_event4(ACPI_AC_CLASS,
72206233 1207 ACPI_AC_DIR_NAME,
8db85d4c
AS
1208 ACPI_SBS_AC_NOTIFY_STATUS,
1209 new_ac_present);
72206233
VL
1210 if (result) {
1211 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
8db85d4c 1212 "acpi_bus_generate_event4() failed"));
72206233 1213 }
8db85d4c
AS
1214 acpi_bus_generate_netlink_event(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
1215 ACPI_SBS_AC_NOTIFY_STATUS,
1216 new_ac_present);
72206233
VL
1217 }
1218
1219 if (data_type == DATA_TYPE_COMMON) {
1220 if (!do_ac_init && !update_battery) {
1221 goto end;
1222 }
1223 }
1224
1225 if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) {
3f86b832
RT
1226 goto end;
1227 }
1228
72206233 1229 for (id = id_min; id <= id_max; id++) {
3f86b832
RT
1230 battery = &sbs->battery[id];
1231 if (battery->alive == 0) {
1232 continue;
1233 }
1234
89862e3b 1235 old_remaining_capacity = battery->capacity_now;
3f86b832 1236
89862e3b 1237 old_present = battery->present;
3f86b832
RT
1238
1239 result = acpi_battery_select(battery);
1240 if (result) {
6845118b
VL
1241 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1242 "acpi_battery_select() failed"));
3f86b832 1243 }
3f86b832
RT
1244
1245 result = acpi_battery_get_present(battery);
1246 if (result) {
6845118b
VL
1247 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1248 "acpi_battery_get_present() failed"));
3f86b832 1249 }
3f86b832 1250
89862e3b 1251 new_present = battery->present;
3f86b832 1252
89862e3b
AS
1253 do_battery_init = ((old_present != new_present)
1254 && new_present);
1255 if (!new_present)
72206233
VL
1256 goto event;
1257 if (do_ac_init || do_battery_init) {
3f86b832
RT
1258 result = acpi_battery_init(battery);
1259 if (result) {
6845118b
VL
1260 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1261 "acpi_battery_init() "
1262 "failed"));
3f86b832
RT
1263 }
1264 }
72206233 1265 if (sbs_zombie(sbs)) {
3f86b832
RT
1266 goto end;
1267 }
72206233
VL
1268
1269 if ((data_type == DATA_TYPE_COMMON
1270 || data_type == DATA_TYPE_INFO)
89862e3b 1271 && new_present) {
72206233 1272 result = acpi_battery_get_info(battery);
3f86b832 1273 if (result) {
6845118b 1274 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
72206233 1275 "acpi_battery_get_info() failed"));
3f86b832 1276 }
72206233
VL
1277 }
1278 if (data_type == DATA_TYPE_INFO) {
1279 continue;
1280 }
1281 if (sbs_zombie(sbs)) {
1282 goto end;
1283 }
3f86b832 1284
72206233
VL
1285 if ((data_type == DATA_TYPE_COMMON
1286 || data_type == DATA_TYPE_STATE)
89862e3b 1287 && new_present) {
3f86b832
RT
1288 result = acpi_battery_get_state(battery);
1289 if (result) {
6845118b 1290 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
72206233 1291 "acpi_battery_get_state() failed"));
3f86b832
RT
1292 }
1293 }
72206233
VL
1294 if (data_type == DATA_TYPE_STATE) {
1295 goto event;
3f86b832 1296 }
72206233
VL
1297 if (sbs_zombie(sbs)) {
1298 goto end;
3f86b832
RT
1299 }
1300
72206233
VL
1301 if ((data_type == DATA_TYPE_COMMON
1302 || data_type == DATA_TYPE_ALARM)
89862e3b 1303 && new_present) {
72206233 1304 result = acpi_battery_get_alarm(battery);
3f86b832 1305 if (result) {
6845118b 1306 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
72206233 1307 "acpi_battery_get_alarm() "
6845118b 1308 "failed"));
3f86b832
RT
1309 }
1310 }
72206233
VL
1311 if (data_type == DATA_TYPE_ALARM) {
1312 continue;
1313 }
1314 if (sbs_zombie(sbs)) {
1315 goto end;
1316 }
1317
1318 event:
1319
89862e3b 1320 if (old_present != new_present || do_ac_init ||
72206233 1321 old_remaining_capacity !=
89862e3b 1322 battery->capacity_now) {
50dd0969 1323 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
8db85d4c 1324 result = acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
3f86b832 1325 dir_name,
8db85d4c 1326 ACPI_SBS_BATTERY_NOTIFY_STATUS,
89862e3b 1327 new_present);
8db85d4c
AS
1328 acpi_bus_generate_netlink_event(ACPI_BATTERY_CLASS, dir_name,
1329 ACPI_SBS_BATTERY_NOTIFY_STATUS,
89862e3b 1330 new_present);
3f86b832 1331 if (result) {
6845118b 1332 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
8db85d4c 1333 "acpi_bus_generate_proc_event4() "
72206233 1334 "failed"));
3f86b832
RT
1335 }
1336 }
3f86b832
RT
1337 }
1338
1339 end:
72206233 1340
635227ee 1341 return result;
3f86b832
RT
1342}
1343
72206233 1344static void acpi_sbs_update_time(void *data)
3f86b832
RT
1345{
1346 struct acpi_sbs *sbs = data;
1347 unsigned long delay = -1;
1348 int result;
72206233 1349 unsigned int up_tm = update_time;
3f86b832 1350
72206233
VL
1351 if (sbs_mutex_lock(sbs))
1352 return;
3f86b832 1353
72206233 1354 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON);
3f86b832 1355 if (result) {
6845118b
VL
1356 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1357 "acpi_sbs_update_run() failed"));
3f86b832
RT
1358 }
1359
72206233 1360 if (sbs_zombie(sbs)) {
3f86b832
RT
1361 goto end;
1362 }
1363
72206233
VL
1364 if (!up_tm) {
1365 if (timer_pending(&sbs->update_timer))
1366 del_timer(&sbs->update_timer);
1367 } else {
1368 delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1369 delay = jiffies + HZ * delay;
1370 if (timer_pending(&sbs->update_timer)) {
1371 mod_timer(&sbs->update_timer, delay);
1372 } else {
1373 sbs->update_timer.data = (unsigned long)data;
1374 sbs->update_timer.function = acpi_sbs_update_time_run;
1375 sbs->update_timer.expires = delay;
1376 add_timer(&sbs->update_timer);
1377 }
3f86b832
RT
1378 }
1379
3f86b832 1380 end:
72206233
VL
1381
1382 sbs_mutex_unlock(sbs);
3f86b832
RT
1383}
1384
1385static int acpi_sbs_add(struct acpi_device *device)
1386{
1387 struct acpi_sbs *sbs = NULL;
72206233 1388 int result = 0, remove_result = 0;
6d15702c 1389 int id;
3f86b832 1390
36bcbec7 1391 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
3f86b832 1392 if (!sbs) {
72206233
VL
1393 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed"));
1394 result = -ENOMEM;
1395 goto end;
3f86b832 1396 }
3f86b832 1397
72206233
VL
1398 mutex_init(&sbs->mutex);
1399
1400 sbs_mutex_lock(sbs);
1401
3f86b832 1402 sbs->device = device;
91087dfa 1403 sbs->hc = acpi_driver_data(device->parent);
3f86b832
RT
1404
1405 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
1406 strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
1407 acpi_driver_data(device) = sbs;
1408
3f86b832
RT
1409 result = acpi_ac_add(sbs);
1410 if (result) {
6845118b 1411 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
3f86b832
RT
1412 goto end;
1413 }
72206233 1414
addad454
AS
1415 acpi_sbsm_get_info(sbs);
1416
89862e3b 1417 if (!sbs->manager_present) {
3f86b832
RT
1418 result = acpi_battery_add(sbs, 0);
1419 if (result) {
6845118b
VL
1420 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1421 "acpi_battery_add() failed"));
3f86b832
RT
1422 goto end;
1423 }
1424 } else {
1425 for (id = 0; id < MAX_SBS_BAT; id++) {
89862e3b 1426 if ((sbs->batteries_supported & (1 << id))) {
3f86b832
RT
1427 result = acpi_battery_add(sbs, id);
1428 if (result) {
6845118b 1429 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
72206233 1430 "acpi_battery_add() failed"));
3f86b832
RT
1431 goto end;
1432 }
1433 }
1434 }
1435 }
1436
3f86b832 1437 init_timer(&sbs->update_timer);
72206233
VL
1438 result = acpi_check_update_proc(sbs);
1439 if (result)
1440 goto end;
3f86b832
RT
1441
1442 end:
72206233
VL
1443
1444 sbs_mutex_unlock(sbs);
1445
3f86b832 1446 if (result) {
72206233
VL
1447 remove_result = acpi_sbs_remove(device, 0);
1448 if (remove_result) {
1449 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1450 "acpi_sbs_remove() failed"));
1451 }
3f86b832
RT
1452 }
1453
635227ee 1454 return result;
3f86b832
RT
1455}
1456
72206233 1457static int acpi_sbs_remove(struct acpi_device *device, int type)
3f86b832 1458{
cece9014 1459 struct acpi_sbs *sbs;
3f86b832
RT
1460 int id;
1461
963497c1
LV
1462 if (!device) {
1463 return -EINVAL;
1464 }
1465
72206233 1466 sbs = acpi_driver_data(device);
963497c1 1467 if (!sbs) {
635227ee 1468 return -EINVAL;
3f86b832
RT
1469 }
1470
72206233
VL
1471 sbs_mutex_lock(sbs);
1472
3f86b832 1473 sbs->zombie = 1;
3f86b832
RT
1474 del_timer_sync(&sbs->update_timer);
1475 acpi_os_wait_events_complete(NULL);
1476 del_timer_sync(&sbs->update_timer);
1477
1478 for (id = 0; id < MAX_SBS_BAT; id++) {
1479 acpi_battery_remove(sbs, id);
1480 }
1481
1482 acpi_ac_remove(sbs);
1483
72206233
VL
1484 sbs_mutex_unlock(sbs);
1485
1486 mutex_destroy(&sbs->mutex);
6d15702c 1487
3f86b832
RT
1488 kfree(sbs);
1489
635227ee 1490 return 0;
3f86b832
RT
1491}
1492
72206233
VL
1493static void acpi_sbs_rmdirs(void)
1494{
1495 if (acpi_ac_dir) {
1496 acpi_unlock_ac_dir(acpi_ac_dir);
1497 acpi_ac_dir = NULL;
1498 }
1499 if (acpi_battery_dir) {
1500 acpi_unlock_battery_dir(acpi_battery_dir);
1501 acpi_battery_dir = NULL;
1502 }
1503}
1504
1505static int acpi_sbs_resume(struct acpi_device *device)
1506{
1507 struct acpi_sbs *sbs;
1508
1509 if (!device)
1510 return -EINVAL;
1511
1512 sbs = device->driver_data;
1513
1514 sbs->run_cnt = 0;
1515
1516 return 0;
1517}
1518
3f86b832
RT
1519static int __init acpi_sbs_init(void)
1520{
1521 int result = 0;
1522
b20d2aeb
LB
1523 if (acpi_disabled)
1524 return -ENODEV;
1525
89862e3b
AS
1526 if (mode != DEF_CAPACITY_UNIT
1527 && mode != MAH_CAPACITY_UNIT
1528 && mode != MWH_CAPACITY_UNIT) {
72206233 1529 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
89862e3b 1530 "invalid mode = %d", mode));
635227ee 1531 return -EINVAL;
3f86b832
RT
1532 }
1533
1534 acpi_ac_dir = acpi_lock_ac_dir();
1535 if (!acpi_ac_dir) {
6845118b
VL
1536 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1537 "acpi_lock_ac_dir() failed"));
635227ee 1538 return -ENODEV;
3f86b832
RT
1539 }
1540
1541 acpi_battery_dir = acpi_lock_battery_dir();
1542 if (!acpi_battery_dir) {
6845118b
VL
1543 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1544 "acpi_lock_battery_dir() failed"));
72206233 1545 acpi_sbs_rmdirs();
635227ee 1546 return -ENODEV;
3f86b832
RT
1547 }
1548
1549 result = acpi_bus_register_driver(&acpi_sbs_driver);
1550 if (result < 0) {
6845118b
VL
1551 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1552 "acpi_bus_register_driver() failed"));
72206233 1553 acpi_sbs_rmdirs();
635227ee 1554 return -ENODEV;
3f86b832
RT
1555 }
1556
635227ee 1557 return 0;
3f86b832
RT
1558}
1559
1560static void __exit acpi_sbs_exit(void)
1561{
3f86b832
RT
1562 acpi_bus_unregister_driver(&acpi_sbs_driver);
1563
72206233 1564 acpi_sbs_rmdirs();
3f86b832 1565
635227ee 1566 return;
3f86b832
RT
1567}
1568
1569module_init(acpi_sbs_init);
1570module_exit(acpi_sbs_exit);