aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sbs.c
diff options
context:
space:
mode:
authorRich Townsend <rhdt@bartol.udel.edu>2006-07-01 11:36:54 -0400
committerLen Brown <len.brown@intel.com>2006-07-01 16:36:14 -0400
commit3f86b83243d59bb50caf5938d284d22e10d082a4 (patch)
treeebc93aff4abae0b3f4aa96c19973782eede3411d /drivers/acpi/sbs.c
parent37672d4c5263d54ee4302f55242f6fd5317b0f9f (diff)
ACPI: add support for Smart Battery
Most batteries today are ACPI "Control Method" batteries, but some models ship with the older "Smart Battery" that requires this code. Rich Townsend and Bruno Ducrot were the original authors. Vladimir Lebedev updated to run on latest kernel. http://bugzilla.kernel.org/show_bug.cgi?id=3734 Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/sbs.c')
-rw-r--r--drivers/acpi/sbs.c1828
1 files changed, 1828 insertions, 0 deletions
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
new file mode 100644
index 000000000000..8bebcebff5f0
--- /dev/null
+++ b/drivers/acpi/sbs.c
@@ -0,0 +1,1828 @@
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>
33#include <linux/i2c.h>
34#include <linux/delay.h>
35
36#include "i2c_ec.h"
37
38#define DEF_CAPACITY_UNIT 3
39#define MAH_CAPACITY_UNIT 1
40#define MWH_CAPACITY_UNIT 2
41#define CAPACITY_UNIT DEF_CAPACITY_UNIT
42
43#define REQUEST_UPDATE_MODE 1
44#define QUEUE_UPDATE_MODE 2
45
46#define DATA_TYPE_COMMON 0
47#define DATA_TYPE_INFO 1
48#define DATA_TYPE_STATE 2
49#define DATA_TYPE_ALARM 3
50#define DATA_TYPE_AC_STATE 4
51
52extern struct proc_dir_entry *acpi_lock_ac_dir(void);
53extern struct proc_dir_entry *acpi_lock_battery_dir(void);
54extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
55extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
56
57#define ACPI_SBS_COMPONENT 0x00080000
58#define ACPI_SBS_CLASS "sbs"
59#define ACPI_AC_CLASS "ac_adapter"
60#define ACPI_BATTERY_CLASS "battery"
61#define ACPI_SBS_HID "ACPI0002"
62#define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver"
63#define ACPI_SBS_DEVICE_NAME "Smart Battery System"
64#define ACPI_SBS_FILE_INFO "info"
65#define ACPI_SBS_FILE_STATE "state"
66#define ACPI_SBS_FILE_ALARM "alarm"
67#define ACPI_BATTERY_DIR_NAME "BAT%i"
68#define ACPI_AC_DIR_NAME "AC0"
69#define ACPI_SBC_SMBUS_ADDR 0x9
70#define ACPI_SBSM_SMBUS_ADDR 0xa
71#define ACPI_SB_SMBUS_ADDR 0xb
72#define ACPI_SBS_AC_NOTIFY_STATUS 0x80
73#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
74#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
75
76#define _COMPONENT ACPI_SBS_COMPONENT
77
78#define MAX_SBS_BAT 4
79#define MAX_SMBUS_ERR 1
80
81ACPI_MODULE_NAME("acpi_sbs");
82
83MODULE_AUTHOR("Rich Townsend");
84MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
85MODULE_LICENSE("GPL");
86
87static struct semaphore sbs_sem;
88
89#define UPDATE_MODE QUEUE_UPDATE_MODE
90/* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */
91#define UPDATE_INFO_MODE 0
92#define UPDATE_TIME 60
93#define UPDATE_TIME2 0
94
95static int capacity_mode = CAPACITY_UNIT;
96static int update_mode = UPDATE_MODE;
97static int update_info_mode = UPDATE_INFO_MODE;
98static int update_time = UPDATE_TIME;
99static int update_time2 = UPDATE_TIME2;
100
101module_param(capacity_mode, int, CAPACITY_UNIT);
102module_param(update_mode, int, UPDATE_MODE);
103module_param(update_info_mode, int, UPDATE_INFO_MODE);
104module_param(update_time, int, UPDATE_TIME);
105module_param(update_time2, int, UPDATE_TIME2);
106
107static int acpi_sbs_add(struct acpi_device *device);
108static int acpi_sbs_remove(struct acpi_device *device, int type);
109static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus);
110static void acpi_sbs_update_queue(void *data);
111
112static struct acpi_driver acpi_sbs_driver = {
113 .name = ACPI_SBS_DRIVER_NAME,
114 .class = ACPI_SBS_CLASS,
115 .ids = ACPI_SBS_HID,
116 .ops = {
117 .add = acpi_sbs_add,
118 .remove = acpi_sbs_remove,
119 },
120};
121
122struct acpi_battery_info {
123 int capacity_mode;
124 s16 full_charge_capacity;
125 s16 design_capacity;
126 s16 design_voltage;
127 int vscale;
128 int ipscale;
129 s16 serial_number;
130 char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3];
131 char device_name[I2C_SMBUS_BLOCK_MAX + 3];
132 char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3];
133};
134
135struct acpi_battery_state {
136 s16 voltage;
137 s16 amperage;
138 s16 remaining_capacity;
139 s16 average_time_to_empty;
140 s16 average_time_to_full;
141 s16 battery_status;
142};
143
144struct acpi_battery_alarm {
145 s16 remaining_capacity;
146};
147
148struct acpi_battery {
149 int alive;
150 int battery_present;
151 int id;
152 int init_state;
153 struct acpi_sbs *sbs;
154 struct acpi_battery_info info;
155 struct acpi_battery_state state;
156 struct acpi_battery_alarm alarm;
157 struct proc_dir_entry *battery_entry;
158};
159
160struct acpi_sbs {
161 acpi_handle handle;
162 struct acpi_device *device;
163 struct acpi_ec_smbus *smbus;
164 int sbsm_present;
165 int sbsm_batteries_supported;
166 int ac_present;
167 struct proc_dir_entry *ac_entry;
168 struct acpi_battery battery[MAX_SBS_BAT];
169 int update_info_mode;
170 int zombie;
171 int update_time;
172 int update_time2;
173 struct timer_list update_timer;
174};
175
176static void acpi_update_delay(struct acpi_sbs *sbs);
177static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type);
178
179/* --------------------------------------------------------------------------
180 SMBus Communication
181 -------------------------------------------------------------------------- */
182
183static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus)
184{
185 union i2c_smbus_data data;
186 int result = 0;
187 char *err_str;
188 int err_number;
189
190 ACPI_FUNCTION_TRACE("acpi_battery_smbus_err_handler");
191
192 data.word = 0;
193
194 result = smbus->adapter.algo->
195 smbus_xfer(&smbus->adapter,
196 ACPI_SB_SMBUS_ADDR,
197 0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data);
198
199 err_number = (data.word & 0x000f);
200
201 switch (data.word & 0x000f) {
202 case 0x0000:
203 err_str = "unexpected bus error";
204 break;
205 case 0x0001:
206 err_str = "busy";
207 break;
208 case 0x0002:
209 err_str = "reserved command";
210 break;
211 case 0x0003:
212 err_str = "unsupported command";
213 break;
214 case 0x0004:
215 err_str = "access denied";
216 break;
217 case 0x0005:
218 err_str = "overflow/underflow";
219 break;
220 case 0x0006:
221 err_str = "bad size";
222 break;
223 case 0x0007:
224 err_str = "unknown error";
225 break;
226 default:
227 err_str = "unrecognized error";
228 }
229 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
230 "%s: ret %i, err %i\n", err_str, result, err_number));
231}
232
233static int
234acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func,
235 u16 * word,
236 void (*err_handler) (struct acpi_ec_smbus * smbus))
237{
238 union i2c_smbus_data data;
239 int result = 0;
240 int i;
241
242 ACPI_FUNCTION_TRACE("acpi_sbs_smbus_read_word");
243
244 if (err_handler == NULL) {
245 err_handler = acpi_battery_smbus_err_handler;
246 }
247
248 for (i = 0; i < MAX_SMBUS_ERR; i++) {
249 result =
250 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
251 I2C_SMBUS_READ, func,
252 I2C_SMBUS_WORD_DATA, &data);
253 if (result) {
254 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
255 "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
256 i));
257 if (err_handler) {
258 err_handler(smbus);
259 }
260 } else {
261 *word = data.word;
262 break;
263 }
264 }
265
266 return_VALUE(result);
267}
268
269static int
270acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func,
271 char *str,
272 void (*err_handler) (struct acpi_ec_smbus * smbus))
273{
274 union i2c_smbus_data data;
275 int result = 0;
276 int i;
277
278 ACPI_FUNCTION_TRACE("acpi_sbs_smbus_read_str");
279
280 if (err_handler == NULL) {
281 err_handler = acpi_battery_smbus_err_handler;
282 }
283
284 for (i = 0; i < MAX_SMBUS_ERR; i++) {
285 result =
286 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
287 I2C_SMBUS_READ, func,
288 I2C_SMBUS_BLOCK_DATA,
289 &data);
290 if (result) {
291 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
292 "try %i: smbus->adapter.algo->smbus_xfer() failed\n",
293 i));
294 if (err_handler) {
295 err_handler(smbus);
296 }
297 } else {
298 strncpy(str, (const char *)data.block + 1,
299 data.block[0]);
300 str[data.block[0]] = 0;
301 break;
302 }
303 }
304
305 return_VALUE(result);
306}
307
308static int
309acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func,
310 int word,
311 void (*err_handler) (struct acpi_ec_smbus * smbus))
312{
313 union i2c_smbus_data data;
314 int result = 0;
315 int i;
316
317 ACPI_FUNCTION_TRACE("acpi_sbs_smbus_write_word");
318
319 if (err_handler == NULL) {
320 err_handler = acpi_battery_smbus_err_handler;
321 }
322
323 data.word = word;
324
325 for (i = 0; i < MAX_SMBUS_ERR; i++) {
326 result =
327 smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0,
328 I2C_SMBUS_WRITE, func,
329 I2C_SMBUS_WORD_DATA, &data);
330 if (result) {
331 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
332 "try %i: smbus->adapter.algo"
333 "->smbus_xfer() failed\n", i));
334 if (err_handler) {
335 err_handler(smbus);
336 }
337 } else {
338 break;
339 }
340 }
341
342 return_VALUE(result);
343}
344
345/* --------------------------------------------------------------------------
346 Smart Battery System Management
347 -------------------------------------------------------------------------- */
348
349/* Smart Battery */
350
351static int acpi_sbs_generate_event(struct acpi_device *device,
352 int event, int state, char *bid, char *class)
353{
354 char bid_saved[5];
355 char class_saved[20];
356 int result = 0;
357
358 ACPI_FUNCTION_TRACE("acpi_sbs_generate_event");
359
360 strcpy(bid_saved, acpi_device_bid(device));
361 strcpy(class_saved, acpi_device_class(device));
362
363 strcpy(acpi_device_bid(device), bid);
364 strcpy(acpi_device_class(device), class);
365
366 result = acpi_bus_generate_event(device, event, state);
367
368 strcpy(acpi_device_bid(device), bid_saved);
369 strcpy(acpi_device_class(device), class_saved);
370
371 return_VALUE(result);
372}
373
374static int acpi_battery_get_present(struct acpi_battery *battery)
375{
376 s16 state;
377 int result = 0;
378 int is_present = 0;
379
380 ACPI_FUNCTION_TRACE("acpi_battery_get_present");
381
382 result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
383 ACPI_SBSM_SMBUS_ADDR, 0x01,
384 &state, NULL);
385 if (result) {
386 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
387 "acpi_sbs_smbus_read_word() failed"));
388 }
389 if (!result) {
390 is_present = (state & 0x000f) & (1 << battery->id);
391 }
392 battery->battery_present = is_present;
393
394 return_VALUE(result);
395}
396
397static int acpi_battery_is_present(struct acpi_battery *battery)
398{
399 return (battery->battery_present);
400}
401
402static int acpi_ac_is_present(struct acpi_sbs *sbs)
403{
404 return (sbs->ac_present);
405}
406
407static int acpi_battery_select(struct acpi_battery *battery)
408{
409 struct acpi_ec_smbus *smbus = battery->sbs->smbus;
410 int result = 0;
411 s16 state;
412 int foo;
413
414 ACPI_FUNCTION_TRACE("acpi_battery_select");
415
416 if (battery->sbs->sbsm_present) {
417
418 /* Take special care not to knobble other nibbles of
419 * state (aka selector_state), since
420 * it causes charging to halt on SBSELs */
421
422 result =
423 acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
424 &state, NULL);
425 if (result) {
426 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
427 "acpi_sbs_smbus_read_word() failed\n"));
428 goto end;
429 }
430
431 foo = (state & 0x0fff) | (1 << (battery->id + 12));
432 result =
433 acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01,
434 foo, NULL);
435 if (result) {
436 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
437 "acpi_sbs_smbus_write_word() failed\n"));
438 goto end;
439 }
440 }
441
442 end:
443 return_VALUE(result);
444}
445
446static int acpi_sbsm_get_info(struct acpi_sbs *sbs)
447{
448 struct acpi_ec_smbus *smbus = sbs->smbus;
449 int result = 0;
450 s16 battery_system_info;
451
452 ACPI_FUNCTION_TRACE("acpi_sbsm_get_info");
453
454 result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04,
455 &battery_system_info, NULL);
456 if (result) {
457 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
458 "acpi_sbs_smbus_read_word() failed\n"));
459 goto end;
460 }
461
462 sbs->sbsm_batteries_supported = battery_system_info & 0x000f;
463
464 end:
465
466 return_VALUE(result);
467}
468
469static int acpi_battery_get_info(struct acpi_battery *battery)
470{
471 struct acpi_ec_smbus *smbus = battery->sbs->smbus;
472 int result = 0;
473 s16 battery_mode;
474 s16 specification_info;
475
476 ACPI_FUNCTION_TRACE("acpi_battery_get_info");
477
478 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
479 &battery_mode,
480 &acpi_battery_smbus_err_handler);
481 if (result) {
482 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
483 "acpi_sbs_smbus_read_word() failed\n"));
484 goto end;
485 }
486 battery->info.capacity_mode = (battery_mode & 0x8000) >> 15;
487
488 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10,
489 &battery->info.full_charge_capacity,
490 &acpi_battery_smbus_err_handler);
491 if (result) {
492 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
493 "acpi_sbs_smbus_read_word() failed\n"));
494 goto end;
495 }
496
497 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18,
498 &battery->info.design_capacity,
499 &acpi_battery_smbus_err_handler);
500
501 if (result) {
502 goto end;
503 }
504
505 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19,
506 &battery->info.design_voltage,
507 &acpi_battery_smbus_err_handler);
508 if (result) {
509 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
510 "acpi_sbs_smbus_read_word() failed\n"));
511 goto end;
512 }
513
514 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a,
515 &specification_info,
516 &acpi_battery_smbus_err_handler);
517 if (result) {
518 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
519 "acpi_sbs_smbus_read_word() failed\n"));
520 goto end;
521 }
522
523 switch ((specification_info & 0x0f00) >> 8) {
524 case 1:
525 battery->info.vscale = 10;
526 break;
527 case 2:
528 battery->info.vscale = 100;
529 break;
530 case 3:
531 battery->info.vscale = 1000;
532 break;
533 default:
534 battery->info.vscale = 1;
535 }
536
537 switch ((specification_info & 0xf000) >> 12) {
538 case 1:
539 battery->info.ipscale = 10;
540 break;
541 case 2:
542 battery->info.ipscale = 100;
543 break;
544 case 3:
545 battery->info.ipscale = 1000;
546 break;
547 default:
548 battery->info.ipscale = 1;
549 }
550
551 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c,
552 &battery->info.serial_number,
553 &acpi_battery_smbus_err_handler);
554 if (result) {
555 goto end;
556 }
557
558 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20,
559 battery->info.manufacturer_name,
560 &acpi_battery_smbus_err_handler);
561 if (result) {
562 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
563 "acpi_sbs_smbus_read_str() failed\n"));
564 goto end;
565 }
566
567 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21,
568 battery->info.device_name,
569 &acpi_battery_smbus_err_handler);
570 if (result) {
571 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
572 "acpi_sbs_smbus_read_str() failed\n"));
573 goto end;
574 }
575
576 result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22,
577 battery->info.device_chemistry,
578 &acpi_battery_smbus_err_handler);
579 if (result) {
580 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
581 "acpi_sbs_smbus_read_str() failed\n"));
582 goto end;
583 }
584
585 end:
586 return_VALUE(result);
587}
588
589static void acpi_update_delay(struct acpi_sbs *sbs)
590{
591 ACPI_FUNCTION_TRACE("acpi_update_delay");
592 if (sbs->zombie) {
593 return;
594 }
595 if (sbs->update_time2 > 0) {
596 msleep(sbs->update_time2 * 1000);
597 }
598}
599
600static int acpi_battery_get_state(struct acpi_battery *battery)
601{
602 struct acpi_ec_smbus *smbus = battery->sbs->smbus;
603 int result = 0;
604
605 ACPI_FUNCTION_TRACE("acpi_battery_get_state");
606
607 acpi_update_delay(battery->sbs);
608 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09,
609 &battery->state.voltage,
610 &acpi_battery_smbus_err_handler);
611 if (result) {
612 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
613 "acpi_sbs_smbus_read_word() failed\n"));
614 goto end;
615 }
616
617 acpi_update_delay(battery->sbs);
618 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a,
619 &battery->state.amperage,
620 &acpi_battery_smbus_err_handler);
621 if (result) {
622 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
623 "acpi_sbs_smbus_read_word() failed\n"));
624 goto end;
625 }
626
627 acpi_update_delay(battery->sbs);
628 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f,
629 &battery->state.remaining_capacity,
630 &acpi_battery_smbus_err_handler);
631 if (result) {
632 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
633 "acpi_sbs_smbus_read_word() failed\n"));
634 goto end;
635 }
636
637 acpi_update_delay(battery->sbs);
638 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12,
639 &battery->state.average_time_to_empty,
640 &acpi_battery_smbus_err_handler);
641 if (result) {
642 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
643 "acpi_sbs_smbus_read_word() failed\n"));
644 goto end;
645 }
646
647 acpi_update_delay(battery->sbs);
648 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13,
649 &battery->state.average_time_to_full,
650 &acpi_battery_smbus_err_handler);
651 if (result) {
652 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
653 "acpi_sbs_smbus_read_word() failed\n"));
654 goto end;
655 }
656
657 acpi_update_delay(battery->sbs);
658 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16,
659 &battery->state.battery_status,
660 &acpi_battery_smbus_err_handler);
661 if (result) {
662 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
663 "acpi_sbs_smbus_read_word() failed\n"));
664 goto end;
665 }
666
667 acpi_update_delay(battery->sbs);
668
669 end:
670 return_VALUE(result);
671}
672
673static int acpi_battery_get_alarm(struct acpi_battery *battery)
674{
675 struct acpi_ec_smbus *smbus = battery->sbs->smbus;
676 int result = 0;
677
678 ACPI_FUNCTION_TRACE("acpi_battery_get_alarm");
679
680 result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
681 &battery->alarm.remaining_capacity,
682 &acpi_battery_smbus_err_handler);
683 if (result) {
684 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
685 "acpi_sbs_smbus_read_word() failed\n"));
686 goto end;
687 }
688
689 acpi_update_delay(battery->sbs);
690
691 end:
692
693 return_VALUE(result);
694}
695
696static int acpi_battery_set_alarm(struct acpi_battery *battery,
697 unsigned long alarm)
698{
699 struct acpi_ec_smbus *smbus = battery->sbs->smbus;
700 int result = 0;
701 s16 battery_mode;
702 int foo;
703
704 ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
705
706 result = acpi_battery_select(battery);
707 if (result) {
708 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
709 "acpi_battery_select() failed\n"));
710 goto end;
711 }
712
713 /* If necessary, enable the alarm */
714
715 if (alarm > 0) {
716 result =
717 acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03,
718 &battery_mode,
719 &acpi_battery_smbus_err_handler);
720 if (result) {
721 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
722 "acpi_sbs_smbus_read_word() failed\n"));
723 goto end;
724 }
725
726 result =
727 acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
728 battery_mode & 0xbfff,
729 &acpi_battery_smbus_err_handler);
730 if (result) {
731 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
732 "acpi_sbs_smbus_write_word() failed\n"));
733 goto end;
734 }
735 }
736
737 foo = alarm / (battery->info.capacity_mode ? 10 : 1);
738 result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01,
739 foo,
740 &acpi_battery_smbus_err_handler);
741 if (result) {
742 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
743 "acpi_sbs_smbus_write_word() failed\n"));
744 goto end;
745 }
746
747 end:
748
749 return_VALUE(result);
750}
751
752static int acpi_battery_set_mode(struct acpi_battery *battery)
753{
754 int result = 0;
755 s16 battery_mode;
756
757 ACPI_FUNCTION_TRACE("acpi_battery_set_mode");
758
759 if (capacity_mode == DEF_CAPACITY_UNIT) {
760 goto end;
761 }
762
763 result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
764 ACPI_SB_SMBUS_ADDR, 0x03,
765 &battery_mode, NULL);
766 if (result) {
767 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
768 "acpi_sbs_smbus_read_word() failed\n"));
769 goto end;
770 }
771
772 if (capacity_mode == MAH_CAPACITY_UNIT) {
773 battery_mode &= 0x7fff;
774 } else {
775 battery_mode |= 0x8000;
776 }
777 result = acpi_sbs_smbus_write_word(battery->sbs->smbus,
778 ACPI_SB_SMBUS_ADDR, 0x03,
779 battery_mode, NULL);
780 if (result) {
781 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
782 "acpi_sbs_smbus_write_word() failed\n"));
783 goto end;
784 }
785
786 result = acpi_sbs_smbus_read_word(battery->sbs->smbus,
787 ACPI_SB_SMBUS_ADDR, 0x03,
788 &battery_mode, NULL);
789 if (result) {
790 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
791 "acpi_sbs_smbus_read_word() failed\n"));
792 goto end;
793 }
794
795 end:
796 return_VALUE(result);
797}
798
799static int acpi_battery_init(struct acpi_battery *battery)
800{
801 int result = 0;
802
803 ACPI_FUNCTION_TRACE("acpi_battery_init");
804
805 result = acpi_battery_select(battery);
806 if (result) {
807 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
808 "acpi_battery_init() failed\n"));
809 goto end;
810 }
811
812 result = acpi_battery_set_mode(battery);
813 if (result) {
814 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
815 "acpi_battery_set_mode() failed\n"));
816 goto end;
817 }
818
819 result = acpi_battery_get_info(battery);
820 if (result) {
821 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
822 "acpi_battery_get_info() failed\n"));
823 goto end;
824 }
825
826 result = acpi_battery_get_state(battery);
827 if (result) {
828 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
829 "acpi_battery_get_state() failed\n"));
830 goto end;
831 }
832
833 result = acpi_battery_get_alarm(battery);
834 if (result) {
835 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
836 "acpi_battery_get_alarm() failed\n"));
837 goto end;
838 }
839
840 end:
841 return_VALUE(result);
842}
843
844static int acpi_ac_get_present(struct acpi_sbs *sbs)
845{
846 struct acpi_ec_smbus *smbus = sbs->smbus;
847 int result = 0;
848 s16 charger_status;
849
850 ACPI_FUNCTION_TRACE("acpi_ac_get_present");
851
852 result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13,
853 &charger_status, NULL);
854
855 if (result) {
856 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
857 "acpi_sbs_smbus_read_word() failed\n"));
858 goto end;
859 }
860
861 sbs->ac_present = (charger_status & 0x8000) >> 15;
862
863 end:
864
865 return_VALUE(result);
866}
867
868/* --------------------------------------------------------------------------
869 FS Interface (/proc/acpi)
870 -------------------------------------------------------------------------- */
871
872/* Generic Routines */
873
874static int
875acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
876 struct proc_dir_entry *parent_dir,
877 char *dir_name,
878 struct file_operations *info_fops,
879 struct file_operations *state_fops,
880 struct file_operations *alarm_fops, void *data)
881{
882 struct proc_dir_entry *entry = NULL;
883
884 ACPI_FUNCTION_TRACE("acpi_sbs_generic_add_fs");
885
886 if (!*dir) {
887 *dir = proc_mkdir(dir_name, parent_dir);
888 if (!*dir) {
889 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
890 "proc_mkdir() failed\n"));
891 return_VALUE(-ENODEV);
892 }
893 (*dir)->owner = THIS_MODULE;
894 }
895
896 /* 'info' [R] */
897 if (info_fops) {
898 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
899 if (!entry) {
900 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
901 "create_proc_entry() failed\n"));
902 } else {
903 entry->proc_fops = info_fops;
904 entry->data = data;
905 entry->owner = THIS_MODULE;
906 }
907 }
908
909 /* 'state' [R] */
910 if (state_fops) {
911 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
912 if (!entry) {
913 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
914 "create_proc_entry() failed\n"));
915 } else {
916 entry->proc_fops = state_fops;
917 entry->data = data;
918 entry->owner = THIS_MODULE;
919 }
920 }
921
922 /* 'alarm' [R/W] */
923 if (alarm_fops) {
924 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
925 if (!entry) {
926 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
927 "create_proc_entry() failed\n"));
928 } else {
929 entry->proc_fops = alarm_fops;
930 entry->data = data;
931 entry->owner = THIS_MODULE;
932 }
933 }
934
935 return_VALUE(0);
936}
937
938static void
939acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
940 struct proc_dir_entry *parent_dir)
941{
942 ACPI_FUNCTION_TRACE("acpi_sbs_generic_remove_fs");
943
944 if (*dir) {
945 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
946 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
947 remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
948 remove_proc_entry((*dir)->name, parent_dir);
949 *dir = NULL;
950 }
951
952}
953
954/* Smart Battery Interface */
955
956static struct proc_dir_entry *acpi_battery_dir = NULL;
957
958static int acpi_battery_read_info(struct seq_file *seq, void *offset)
959{
960 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
961 int cscale;
962 int result = 0;
963
964 ACPI_FUNCTION_TRACE("acpi_battery_read_info");
965
966 if (battery->sbs->zombie) {
967 return_VALUE(-ENODEV);
968 }
969
970 down(&sbs_sem);
971
972 if (update_mode == REQUEST_UPDATE_MODE) {
973 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO);
974 if (result) {
975 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
976 "acpi_sbs_update_run() failed\n"));
977 }
978 }
979
980 if (acpi_battery_is_present(battery)) {
981 seq_printf(seq, "present: yes\n");
982 } else {
983 seq_printf(seq, "present: no\n");
984 goto end;
985 }
986
987 if (battery->info.capacity_mode) {
988 cscale = battery->info.vscale * battery->info.ipscale;
989 } else {
990 cscale = battery->info.ipscale;
991 }
992 seq_printf(seq, "design capacity: %i%s",
993 battery->info.design_capacity * cscale,
994 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
995
996 seq_printf(seq, "last full capacity: %i%s",
997 battery->info.full_charge_capacity * cscale,
998 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
999
1000 seq_printf(seq, "battery technology: rechargeable\n");
1001
1002 seq_printf(seq, "design voltage: %i mV\n",
1003 battery->info.design_voltage * battery->info.vscale);
1004
1005 seq_printf(seq, "design capacity warning: unknown\n");
1006 seq_printf(seq, "design capacity low: unknown\n");
1007 seq_printf(seq, "capacity granularity 1: unknown\n");
1008 seq_printf(seq, "capacity granularity 2: unknown\n");
1009
1010 seq_printf(seq, "model number: %s\n",
1011 battery->info.device_name);
1012
1013 seq_printf(seq, "serial number: %i\n",
1014 battery->info.serial_number);
1015
1016 seq_printf(seq, "battery type: %s\n",
1017 battery->info.device_chemistry);
1018
1019 seq_printf(seq, "OEM info: %s\n",
1020 battery->info.manufacturer_name);
1021
1022 end:
1023
1024 up(&sbs_sem);
1025
1026 return_VALUE(result);
1027}
1028
1029static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
1030{
1031 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
1032}
1033
1034static int acpi_battery_read_state(struct seq_file *seq, void *offset)
1035{
1036 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
1037 int result = 0;
1038 int cscale;
1039 int foo;
1040
1041 ACPI_FUNCTION_TRACE("acpi_battery_read_state");
1042
1043 if (battery->sbs->zombie) {
1044 return_VALUE(-ENODEV);
1045 }
1046
1047 down(&sbs_sem);
1048
1049 if (update_mode == REQUEST_UPDATE_MODE) {
1050 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE);
1051 if (result) {
1052 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1053 "acpi_sbs_update_run() failed\n"));
1054 }
1055 }
1056
1057 if (acpi_battery_is_present(battery)) {
1058 seq_printf(seq, "present: yes\n");
1059 } else {
1060 seq_printf(seq, "present: no\n");
1061 goto end;
1062 }
1063
1064 if (battery->info.capacity_mode) {
1065 cscale = battery->info.vscale * battery->info.ipscale;
1066 } else {
1067 cscale = battery->info.ipscale;
1068 }
1069
1070 if (battery->state.battery_status & 0x0010) {
1071 seq_printf(seq, "capacity state: critical\n");
1072 } else {
1073 seq_printf(seq, "capacity state: ok\n");
1074 }
1075 if (battery->state.amperage < 0) {
1076 seq_printf(seq, "charging state: discharging\n");
1077 foo = battery->state.remaining_capacity * cscale * 60 /
1078 (battery->state.average_time_to_empty == 0 ? 1 :
1079 battery->state.average_time_to_empty);
1080 seq_printf(seq, "present rate: %i%s\n",
1081 foo, battery->info.capacity_mode ? "0 mW" : " mA");
1082 } else if (battery->state.amperage > 0) {
1083 seq_printf(seq, "charging state: charging\n");
1084 foo = (battery->info.full_charge_capacity -
1085 battery->state.remaining_capacity) * cscale * 60 /
1086 (battery->state.average_time_to_full == 0 ? 1 :
1087 battery->state.average_time_to_full);
1088 seq_printf(seq, "present rate: %i%s\n",
1089 foo, battery->info.capacity_mode ? "0 mW" : " mA");
1090 } else {
1091 seq_printf(seq, "charging state: charged\n");
1092 seq_printf(seq, "present rate: 0 %s\n",
1093 battery->info.capacity_mode ? "mW" : "mA");
1094 }
1095
1096 seq_printf(seq, "remaining capacity: %i%s",
1097 battery->state.remaining_capacity * cscale,
1098 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1099
1100 seq_printf(seq, "present voltage: %i mV\n",
1101 battery->state.voltage * battery->info.vscale);
1102
1103 end:
1104
1105 up(&sbs_sem);
1106
1107 return_VALUE(result);
1108}
1109
1110static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
1111{
1112 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
1113}
1114
1115static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
1116{
1117 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
1118 int result = 0;
1119 int cscale;
1120
1121 ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
1122
1123 if (battery->sbs->zombie) {
1124 return_VALUE(-ENODEV);
1125 }
1126
1127 down(&sbs_sem);
1128
1129 if (update_mode == REQUEST_UPDATE_MODE) {
1130 result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM);
1131 if (result) {
1132 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1133 "acpi_sbs_update_run() failed\n"));
1134 }
1135 }
1136
1137 if (!acpi_battery_is_present(battery)) {
1138 seq_printf(seq, "present: no\n");
1139 goto end;
1140 }
1141
1142 if (battery->info.capacity_mode) {
1143 cscale = battery->info.vscale * battery->info.ipscale;
1144 } else {
1145 cscale = battery->info.ipscale;
1146 }
1147
1148 seq_printf(seq, "alarm: ");
1149 if (battery->alarm.remaining_capacity) {
1150 seq_printf(seq, "%i%s",
1151 battery->alarm.remaining_capacity * cscale,
1152 battery->info.capacity_mode ? "0 mWh\n" : " mAh\n");
1153 } else {
1154 seq_printf(seq, "disabled\n");
1155 }
1156
1157 end:
1158
1159 up(&sbs_sem);
1160
1161 return_VALUE(result);
1162}
1163
1164static ssize_t
1165acpi_battery_write_alarm(struct file *file, const char __user * buffer,
1166 size_t count, loff_t * ppos)
1167{
1168 struct seq_file *seq = (struct seq_file *)file->private_data;
1169 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
1170 char alarm_string[12] = { '\0' };
1171 int result, old_alarm, new_alarm;
1172
1173 ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
1174
1175 if (battery->sbs->zombie) {
1176 return_VALUE(-ENODEV);
1177 }
1178
1179 down(&sbs_sem);
1180
1181 if (!acpi_battery_is_present(battery)) {
1182 result = -ENODEV;
1183 goto end;
1184 }
1185
1186 if (count > sizeof(alarm_string) - 1) {
1187 result = -EINVAL;
1188 goto end;
1189 }
1190
1191 if (copy_from_user(alarm_string, buffer, count)) {
1192 result = -EFAULT;
1193 goto end;
1194 }
1195
1196 alarm_string[count] = 0;
1197
1198 old_alarm = battery->alarm.remaining_capacity;
1199 new_alarm = simple_strtoul(alarm_string, NULL, 0);
1200
1201 result = acpi_battery_set_alarm(battery, new_alarm);
1202 if (result) {
1203 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1204 "acpi_battery_set_alarm() failed\n"));
1205 (void)acpi_battery_set_alarm(battery, old_alarm);
1206 goto end;
1207 }
1208 result = acpi_battery_get_alarm(battery);
1209 if (result) {
1210 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1211 "acpi_battery_get_alarm() failed\n"));
1212 (void)acpi_battery_set_alarm(battery, old_alarm);
1213 goto end;
1214 }
1215
1216 end:
1217 up(&sbs_sem);
1218
1219 if (result) {
1220 return_VALUE(result);
1221 } else {
1222 return_VALUE(count);
1223 }
1224}
1225
1226static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
1227{
1228 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
1229}
1230
1231static struct file_operations acpi_battery_info_fops = {
1232 .open = acpi_battery_info_open_fs,
1233 .read = seq_read,
1234 .llseek = seq_lseek,
1235 .release = single_release,
1236 .owner = THIS_MODULE,
1237};
1238
1239static struct file_operations acpi_battery_state_fops = {
1240 .open = acpi_battery_state_open_fs,
1241 .read = seq_read,
1242 .llseek = seq_lseek,
1243 .release = single_release,
1244 .owner = THIS_MODULE,
1245};
1246
1247static struct file_operations acpi_battery_alarm_fops = {
1248 .open = acpi_battery_alarm_open_fs,
1249 .read = seq_read,
1250 .write = acpi_battery_write_alarm,
1251 .llseek = seq_lseek,
1252 .release = single_release,
1253 .owner = THIS_MODULE,
1254};
1255
1256/* Legacy AC Adapter Interface */
1257
1258static struct proc_dir_entry *acpi_ac_dir = NULL;
1259
1260static int acpi_ac_read_state(struct seq_file *seq, void *offset)
1261{
1262 struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private;
1263 int result;
1264
1265 ACPI_FUNCTION_TRACE("acpi_ac_read_state");
1266
1267 if (sbs->zombie) {
1268 return_VALUE(-ENODEV);
1269 }
1270
1271 down(&sbs_sem);
1272
1273 if (update_mode == REQUEST_UPDATE_MODE) {
1274 result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE);
1275 if (result) {
1276 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1277 "acpi_sbs_update_run() failed\n"));
1278 }
1279 }
1280
1281 seq_printf(seq, "state: %s\n",
1282 sbs->ac_present ? "on-line" : "off-line");
1283
1284 up(&sbs_sem);
1285
1286 return_VALUE(0);
1287}
1288
1289static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
1290{
1291 return single_open(file, acpi_ac_read_state, PDE(inode)->data);
1292}
1293
1294static struct file_operations acpi_ac_state_fops = {
1295 .open = acpi_ac_state_open_fs,
1296 .read = seq_read,
1297 .llseek = seq_lseek,
1298 .release = single_release,
1299 .owner = THIS_MODULE,
1300};
1301
1302/* --------------------------------------------------------------------------
1303 Driver Interface
1304 -------------------------------------------------------------------------- */
1305
1306/* Smart Battery */
1307
1308static int acpi_battery_add(struct acpi_sbs *sbs, int id)
1309{
1310 int is_present;
1311 int result;
1312 char dir_name[32];
1313 struct acpi_battery *battery;
1314
1315 ACPI_FUNCTION_TRACE("acpi_battery_add");
1316
1317 battery = &sbs->battery[id];
1318
1319 battery->alive = 0;
1320
1321 battery->init_state = 0;
1322 battery->id = id;
1323 battery->sbs = sbs;
1324
1325 result = acpi_battery_select(battery);
1326 if (result) {
1327 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1328 "acpi_battery_select() failed\n"));
1329 goto end;
1330 }
1331
1332 result = acpi_battery_get_present(battery);
1333 if (result) {
1334 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1335 "acpi_battery_get_present() failed\n"));
1336 goto end;
1337 }
1338
1339 is_present = acpi_battery_is_present(battery);
1340
1341 if (is_present) {
1342 result = acpi_battery_init(battery);
1343 if (result) {
1344 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1345 "acpi_battery_init() failed\n"));
1346 goto end;
1347 }
1348 battery->init_state = 1;
1349 }
1350
1351 (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1352
1353 result = acpi_sbs_generic_add_fs(&battery->battery_entry,
1354 acpi_battery_dir,
1355 dir_name,
1356 &acpi_battery_info_fops,
1357 &acpi_battery_state_fops,
1358 &acpi_battery_alarm_fops, battery);
1359 if (result) {
1360 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1361 "acpi_sbs_generic_add_fs() failed\n"));
1362 goto end;
1363 }
1364 battery->alive = 1;
1365
1366 end:
1367 return_VALUE(result);
1368}
1369
1370static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
1371{
1372 ACPI_FUNCTION_TRACE("acpi_battery_remove");
1373
1374 if (sbs->battery[id].battery_entry) {
1375 acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry),
1376 acpi_battery_dir);
1377 }
1378}
1379
1380static int acpi_ac_add(struct acpi_sbs *sbs)
1381{
1382 int result;
1383
1384 ACPI_FUNCTION_TRACE("acpi_ac_add");
1385
1386 result = acpi_ac_get_present(sbs);
1387 if (result) {
1388 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1389 "acpi_ac_get_present() failed\n"));
1390 goto end;
1391 }
1392
1393 result = acpi_sbs_generic_add_fs(&sbs->ac_entry,
1394 acpi_ac_dir,
1395 ACPI_AC_DIR_NAME,
1396 NULL, &acpi_ac_state_fops, NULL, sbs);
1397 if (result) {
1398 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1399 "acpi_sbs_generic_add_fs() failed\n"));
1400 goto end;
1401 }
1402
1403 end:
1404
1405 return_VALUE(result);
1406}
1407
1408static void acpi_ac_remove(struct acpi_sbs *sbs)
1409{
1410 ACPI_FUNCTION_TRACE("acpi_ac_remove");
1411
1412 if (sbs->ac_entry) {
1413 acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir);
1414 }
1415}
1416
1417static void acpi_sbs_update_queue_run(unsigned long data)
1418{
1419 ACPI_FUNCTION_TRACE("acpi_sbs_update_queue_run");
1420 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data);
1421}
1422
1423static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type)
1424{
1425 struct acpi_battery *battery;
1426 int result = 0;
1427 int old_ac_present;
1428 int old_battery_present;
1429 int new_ac_present;
1430 int new_battery_present;
1431 int id;
1432 char dir_name[32];
1433 int do_battery_init, do_ac_init;
1434 s16 old_remaining_capacity;
1435
1436 ACPI_FUNCTION_TRACE("acpi_sbs_update_run");
1437
1438 if (sbs->zombie) {
1439 goto end;
1440 }
1441
1442 old_ac_present = acpi_ac_is_present(sbs);
1443
1444 result = acpi_ac_get_present(sbs);
1445 if (result) {
1446 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1447 "acpi_ac_get_present() failed\n"));
1448 }
1449
1450 new_ac_present = acpi_ac_is_present(sbs);
1451
1452 do_ac_init = (old_ac_present != new_ac_present);
1453
1454 if (data_type == DATA_TYPE_AC_STATE) {
1455 goto end;
1456 }
1457
1458 for (id = 0; id < MAX_SBS_BAT; id++) {
1459 battery = &sbs->battery[id];
1460 if (battery->alive == 0) {
1461 continue;
1462 }
1463
1464 old_remaining_capacity = battery->state.remaining_capacity;
1465
1466 old_battery_present = acpi_battery_is_present(battery);
1467
1468 result = acpi_battery_select(battery);
1469 if (result) {
1470 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1471 "acpi_battery_select() failed\n"));
1472 }
1473 if (sbs->zombie) {
1474 goto end;
1475 }
1476
1477 result = acpi_battery_get_present(battery);
1478 if (result) {
1479 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1480 "acpi_battery_get_present() failed\n"));
1481 }
1482 if (sbs->zombie) {
1483 goto end;
1484 }
1485
1486 new_battery_present = acpi_battery_is_present(battery);
1487
1488 do_battery_init = ((old_battery_present != new_battery_present)
1489 && new_battery_present);
1490
1491 if (sbs->zombie) {
1492 goto end;
1493 }
1494 if (do_ac_init || do_battery_init ||
1495 update_info_mode || sbs->update_info_mode) {
1496 if (sbs->update_info_mode) {
1497 sbs->update_info_mode = 0;
1498 } else {
1499 sbs->update_info_mode = 1;
1500 }
1501 result = acpi_battery_init(battery);
1502 if (result) {
1503 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1504 "acpi_battery_init() "
1505 "failed\n"));
1506 }
1507 }
1508 if (data_type == DATA_TYPE_INFO) {
1509 continue;
1510 }
1511
1512 if (sbs->zombie) {
1513 goto end;
1514 }
1515 if (new_battery_present) {
1516 result = acpi_battery_get_alarm(battery);
1517 if (result) {
1518 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1519 "acpi_battery_get_alarm() "
1520 "failed\n"));
1521 }
1522 if (data_type == DATA_TYPE_ALARM) {
1523 continue;
1524 }
1525
1526 result = acpi_battery_get_state(battery);
1527 if (result) {
1528 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1529 "acpi_battery_get_state() "
1530 "failed\n"));
1531 }
1532 }
1533 if (sbs->zombie) {
1534 goto end;
1535 }
1536 if (data_type != DATA_TYPE_COMMON) {
1537 continue;
1538 }
1539
1540 if (old_battery_present != new_battery_present) {
1541 (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1542 result = acpi_sbs_generate_event(sbs->device,
1543 ACPI_SBS_BATTERY_NOTIFY_STATUS,
1544 new_battery_present,
1545 dir_name,
1546 ACPI_BATTERY_CLASS);
1547 if (result) {
1548 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1549 "acpi_sbs_generate_event() "
1550 "failed\n"));
1551 }
1552 }
1553 if (old_remaining_capacity != battery->state.remaining_capacity) {
1554 (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1555 result = acpi_sbs_generate_event(sbs->device,
1556 ACPI_SBS_BATTERY_NOTIFY_STATUS,
1557 new_battery_present,
1558 dir_name,
1559 ACPI_BATTERY_CLASS);
1560 if (result) {
1561 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1562 "acpi_sbs_generate_event() failed\n"));
1563 }
1564 }
1565
1566 }
1567 if (sbs->zombie) {
1568 goto end;
1569 }
1570 if (data_type != DATA_TYPE_COMMON) {
1571 goto end;
1572 }
1573
1574 if (old_ac_present != new_ac_present) {
1575 result = acpi_sbs_generate_event(sbs->device,
1576 ACPI_SBS_AC_NOTIFY_STATUS,
1577 new_ac_present,
1578 ACPI_AC_DIR_NAME,
1579 ACPI_AC_CLASS);
1580 if (result) {
1581 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1582 "acpi_sbs_generate_event() failed\n"));
1583 }
1584 }
1585
1586 end:
1587 return_VALUE(result);
1588}
1589
1590static void acpi_sbs_update_queue(void *data)
1591{
1592 struct acpi_sbs *sbs = data;
1593 unsigned long delay = -1;
1594 int result;
1595
1596 ACPI_FUNCTION_TRACE("acpi_sbs_update_queue");
1597
1598 if (sbs->zombie) {
1599 goto end;
1600 }
1601
1602 result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON);
1603 if (result) {
1604 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1605 "acpi_sbs_update_run() failed\n"));
1606 }
1607
1608 if (sbs->zombie) {
1609 goto end;
1610 }
1611
1612 if (update_mode == REQUEST_UPDATE_MODE) {
1613 goto end;
1614 }
1615
1616 delay = jiffies + HZ * update_time;
1617 sbs->update_timer.data = (unsigned long)data;
1618 sbs->update_timer.function = acpi_sbs_update_queue_run;
1619 sbs->update_timer.expires = delay;
1620 add_timer(&sbs->update_timer);
1621 end:
1622 ;
1623}
1624
1625static int acpi_sbs_add(struct acpi_device *device)
1626{
1627 struct acpi_sbs *sbs = NULL;
1628 struct acpi_ec_hc *ec_hc = NULL;
1629 int result, remove_result = 0;
1630 unsigned long sbs_obj;
1631 int id, cnt;
1632 acpi_status status = AE_OK;
1633
1634 ACPI_FUNCTION_TRACE("acpi_sbs_add");
1635
1636 sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
1637 if (!sbs) {
1638 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n"));
1639 return_VALUE(-ENOMEM);
1640 }
1641 memset(sbs, 0, sizeof(struct acpi_sbs));
1642
1643 cnt = 0;
1644 while (cnt < 10) {
1645 cnt++;
1646 ec_hc = acpi_get_ec_hc(device);
1647 if (ec_hc) {
1648 break;
1649 }
1650 msleep(1000);
1651 }
1652
1653 if (!ec_hc) {
1654 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1655 "acpi_get_ec_hc() failed: "
1656 "NO driver found for EC HC SMBus\n"));
1657 result = -ENODEV;
1658 goto end;
1659 }
1660
1661 sbs->device = device;
1662 sbs->smbus = ec_hc->smbus;
1663
1664 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
1665 strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
1666 acpi_driver_data(device) = sbs;
1667
1668 sbs->update_time = 0;
1669 sbs->update_time2 = 0;
1670
1671 result = acpi_ac_add(sbs);
1672 if (result) {
1673 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n"));
1674 goto end;
1675 }
1676 result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj);
1677 if (ACPI_FAILURE(result)) {
1678 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1679 "acpi_evaluate_integer() failed\n"));
1680 result = -EIO;
1681 goto end;
1682 }
1683
1684 if (sbs_obj > 0) {
1685 result = acpi_sbsm_get_info(sbs);
1686 if (result) {
1687 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1688 "acpi_sbsm_get_info() failed\n"));
1689 goto end;
1690 }
1691 sbs->sbsm_present = 1;
1692 }
1693 if (sbs->sbsm_present == 0) {
1694 result = acpi_battery_add(sbs, 0);
1695 if (result) {
1696 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1697 "acpi_battery_add() failed\n"));
1698 goto end;
1699 }
1700 } else {
1701 for (id = 0; id < MAX_SBS_BAT; id++) {
1702 if ((sbs->sbsm_batteries_supported & (1 << id))) {
1703 result = acpi_battery_add(sbs, id);
1704 if (result) {
1705 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1706 "acpi_battery_add() "
1707 "failed\n"));
1708 goto end;
1709 }
1710 }
1711 }
1712 }
1713
1714 sbs->handle = device->handle;
1715
1716 init_timer(&sbs->update_timer);
1717 if (update_mode == QUEUE_UPDATE_MODE) {
1718 status = acpi_os_execute(OSL_GPE_HANDLER,
1719 acpi_sbs_update_queue, (void *)sbs);
1720 if (status != AE_OK) {
1721 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1722 "acpi_os_execute() failed\n"));
1723 }
1724 }
1725 sbs->update_time = update_time;
1726 sbs->update_time2 = update_time2;
1727
1728 printk(KERN_INFO PREFIX "%s [%s]\n",
1729 acpi_device_name(device), acpi_device_bid(device));
1730
1731 end:
1732 if (result) {
1733 remove_result = acpi_sbs_remove(device, 0);
1734 if (remove_result) {
1735 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1736 "acpi_sbs_remove() failed\n"));
1737 }
1738 }
1739
1740 return_VALUE(result);
1741}
1742
1743int acpi_sbs_remove(struct acpi_device *device, int type)
1744{
1745 struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device);
1746 int id;
1747
1748 ACPI_FUNCTION_TRACE("acpi_sbs_remove");
1749
1750 if (!device || !sbs) {
1751 return_VALUE(-EINVAL);
1752 }
1753
1754 sbs->zombie = 1;
1755 sbs->update_time = 0;
1756 sbs->update_time2 = 0;
1757 del_timer_sync(&sbs->update_timer);
1758 acpi_os_wait_events_complete(NULL);
1759 del_timer_sync(&sbs->update_timer);
1760
1761 for (id = 0; id < MAX_SBS_BAT; id++) {
1762 acpi_battery_remove(sbs, id);
1763 }
1764
1765 acpi_ac_remove(sbs);
1766
1767 kfree(sbs);
1768
1769 return_VALUE(0);
1770}
1771
1772static int __init acpi_sbs_init(void)
1773{
1774 int result = 0;
1775
1776 ACPI_FUNCTION_TRACE("acpi_sbs_init");
1777
1778 init_MUTEX(&sbs_sem);
1779
1780 if (capacity_mode != DEF_CAPACITY_UNIT
1781 && capacity_mode != MAH_CAPACITY_UNIT
1782 && capacity_mode != MWH_CAPACITY_UNIT) {
1783 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: "
1784 "invalid capacity_mode = %d\n",
1785 capacity_mode));
1786 return_VALUE(-EINVAL);
1787 }
1788
1789 acpi_ac_dir = acpi_lock_ac_dir();
1790 if (!acpi_ac_dir) {
1791 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1792 "acpi_lock_ac_dir() failed\n"));
1793 return_VALUE(-ENODEV);
1794 }
1795
1796 acpi_battery_dir = acpi_lock_battery_dir();
1797 if (!acpi_battery_dir) {
1798 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1799 "acpi_lock_battery_dir() failed\n"));
1800 return_VALUE(-ENODEV);
1801 }
1802
1803 result = acpi_bus_register_driver(&acpi_sbs_driver);
1804 if (result < 0) {
1805 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
1806 "acpi_bus_register_driver() failed\n"));
1807 return_VALUE(-ENODEV);
1808 }
1809
1810 return_VALUE(0);
1811}
1812
1813static void __exit acpi_sbs_exit(void)
1814{
1815 ACPI_FUNCTION_TRACE("acpi_sbs_exit");
1816
1817 acpi_bus_unregister_driver(&acpi_sbs_driver);
1818
1819 acpi_unlock_ac_dir(acpi_ac_dir);
1820 acpi_ac_dir = NULL;
1821 acpi_unlock_battery_dir(acpi_battery_dir);
1822 acpi_battery_dir = NULL;
1823
1824 return_VOID;
1825}
1826
1827module_init(acpi_sbs_init);
1828module_exit(acpi_sbs_exit);