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