ACPI: SBS: Make SBS reads table-driven.
[safe/jmp/linux-2.6] / drivers / acpi / sbs.c
1 /*
2  *  sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3  *
4  *  Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
5  *  Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
6  *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
7  *
8  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or (at
13  *  your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful, but
16  *  WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  *  General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with this program; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23  *
24  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25  */
26
27 #include <linux/init.h>
28 #include <linux/module.h>
29 #include <linux/moduleparam.h>
30 #include <linux/kernel.h>
31 #include <linux/proc_fs.h>
32 #include <linux/seq_file.h>
33 #include <asm/uaccess.h>
34 #include <linux/acpi.h>
35 #include <linux/timer.h>
36 #include <linux/jiffies.h>
37 #include <linux/delay.h>
38
39 #include "sbshc.h"
40
41 #define ACPI_SBS_COMPONENT              0x00080000
42 #define ACPI_SBS_CLASS                  "sbs"
43 #define ACPI_AC_CLASS                   "ac_adapter"
44 #define ACPI_BATTERY_CLASS              "battery"
45 #define ACPI_SBS_DEVICE_NAME            "Smart Battery System"
46 #define ACPI_SBS_FILE_INFO              "info"
47 #define ACPI_SBS_FILE_STATE             "state"
48 #define ACPI_SBS_FILE_ALARM             "alarm"
49 #define ACPI_BATTERY_DIR_NAME           "BAT%i"
50 #define ACPI_AC_DIR_NAME                "AC0"
51
52 enum acpi_sbs_device_addr {
53         ACPI_SBS_CHARGER = 0x9,
54         ACPI_SBS_MANAGER = 0xa,
55         ACPI_SBS_BATTERY = 0xb,
56 };
57
58 #define ACPI_SBS_NOTIFY_STATUS          0x80
59 #define ACPI_SBS_NOTIFY_INFO            0x81
60
61 ACPI_MODULE_NAME("sbs");
62
63 MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
64 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
65 MODULE_LICENSE("GPL");
66
67 static unsigned int cache_time = 1000;
68 module_param(cache_time, uint, 0644);
69 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
70
71 extern struct proc_dir_entry *acpi_lock_ac_dir(void);
72 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
73 extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
74 extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
75
76 #define MAX_SBS_BAT                     4
77 #define ACPI_SBS_BLOCK_MAX              32
78
79 static int acpi_sbs_add(struct acpi_device *device);
80 static int acpi_sbs_remove(struct acpi_device *device, int type);
81 static int acpi_sbs_resume(struct acpi_device *device);
82
83 static const struct acpi_device_id sbs_device_ids[] = {
84         {"ACPI0002", 0},
85         {"", 0},
86 };
87 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
88
89 static struct acpi_driver acpi_sbs_driver = {
90         .name = "sbs",
91         .class = ACPI_SBS_CLASS,
92         .ids = sbs_device_ids,
93         .ops = {
94                 .add = acpi_sbs_add,
95                 .remove = acpi_sbs_remove,
96                 .resume = acpi_sbs_resume,
97                 },
98 };
99
100 struct acpi_battery {
101         struct acpi_sbs *sbs;
102         struct proc_dir_entry *proc_entry;
103         unsigned long update_time;
104         char name[8];
105         char manufacturer_name[ACPI_SBS_BLOCK_MAX];
106         char device_name[ACPI_SBS_BLOCK_MAX];
107         char device_chemistry[ACPI_SBS_BLOCK_MAX];
108         u32 alarm_capacity;
109         u16 full_charge_capacity;
110         u16 design_capacity;
111         u16 design_voltage;
112         u16 serial_number;
113         u16 cycle_count;
114         u16 temp_now;
115         u16 voltage_now;
116         s16 current_now;
117         s16 current_avg;
118         u16 capacity_now;
119         u16 state_of_charge;
120         u16 state;
121         u16 mode;
122         u16 spec;
123         u8 id;
124         u8 present:1;
125 };
126
127 struct acpi_sbs {
128         struct acpi_device *device;
129         struct acpi_smb_hc *hc;
130         struct mutex lock;
131         struct proc_dir_entry *charger_entry;
132         struct acpi_battery battery[MAX_SBS_BAT];
133         u8 batteries_supported:4;
134         u8 manager_present:1;
135         u8 charger_present:1;
136 };
137
138 static inline int battery_scale(int log)
139 {
140         int scale = 1;
141         while (log--)
142                 scale *= 10;
143         return scale;
144 }
145
146 static inline int acpi_battery_vscale(struct acpi_battery *battery)
147 {
148         return battery_scale((battery->spec & 0x0f00) >> 8);
149 }
150
151 static inline int acpi_battery_ipscale(struct acpi_battery *battery)
152 {
153         return battery_scale((battery->spec & 0xf000) >> 12);
154 }
155
156 static inline int acpi_battery_mode(struct acpi_battery *battery)
157 {
158         return (battery->mode & 0x8000);
159 }
160
161 static inline int acpi_battery_scale(struct acpi_battery *battery)
162 {
163         return (acpi_battery_mode(battery) ? 10 : 1) *
164             acpi_battery_ipscale(battery);
165 }
166
167 /* --------------------------------------------------------------------------
168                             Smart Battery System Management
169    -------------------------------------------------------------------------- */
170
171 struct acpi_battery_reader {
172         u8 command;             /* command for battery */
173         u8 mode;                /* word or block? */
174         size_t offset;          /* offset inside struct acpi_sbs_battery */
175 };
176
177 static struct acpi_battery_reader info_readers[] = {
178         {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
179         {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
180         {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
181         {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
182         {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
183         {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
184         {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
185         {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
186         {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
187         {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
188         {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
189 };
190
191 static struct acpi_battery_reader state_readers[] = {
192         {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
193         {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
194         {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
195         {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
196         {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
197         {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
198         {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
199 };
200
201 static int acpi_manager_get_info(struct acpi_sbs *sbs)
202 {
203         int result = 0;
204         u16 battery_system_info;
205
206         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
207                                  0x04, (u8 *) & battery_system_info);
208         if (!result)
209                 sbs->batteries_supported = battery_system_info & 0x000f;
210         return result;
211 }
212
213 static int acpi_battery_get_info(struct acpi_battery *battery)
214 {
215         int i, result = 0;
216
217         for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
218                 result = acpi_smbus_read(battery->sbs->hc, info_readers[i].mode,
219                                     ACPI_SBS_BATTERY, info_readers[i].command,
220                                     (u8 *) battery + info_readers[i].offset);
221                 if (result)
222                         break;
223         }
224         return result;
225 }
226
227 static int acpi_battery_get_state(struct acpi_battery *battery)
228 {
229         int i, result = 0;
230
231         if (time_before(jiffies, battery->update_time +
232                                 msecs_to_jiffies(cache_time)))
233                 return 0;
234         for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
235                 result = acpi_smbus_read(battery->sbs->hc,
236                                          state_readers[i].mode,
237                                          ACPI_SBS_BATTERY,
238                                          state_readers[i].command,
239                                          (u8 *)battery +
240                                                 state_readers[i].offset);
241                 if (result)
242                         goto end;
243         }
244       end:
245         battery->update_time = jiffies;
246         return result;
247 }
248
249 static int acpi_battery_get_alarm(struct acpi_battery *battery)
250 {
251         return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
252                                  ACPI_SBS_BATTERY, 0x01,
253                                  (u8 *) & battery->alarm_capacity);
254 }
255
256 static int acpi_battery_set_alarm(struct acpi_battery *battery)
257 {
258         struct acpi_sbs *sbs = battery->sbs;
259         u16 value;
260         return 0;
261
262         if (sbs->manager_present) {
263                 acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
264                                 0x01, (u8 *)&value);
265                 value &= 0x0fff;
266                 value |= 1 << (battery->id + 12);
267                 acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_MANAGER,
268                                 0x01, (u8 *)&value, 2);
269         }
270         value = battery->alarm_capacity / (acpi_battery_mode(battery) ? 10 : 1);
271         return acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
272                                 0x01, (u8 *)&value, 2);
273 }
274
275 static int acpi_ac_get_present(struct acpi_sbs *sbs)
276 {
277         int result;
278         u16 status;
279
280         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
281                                  0x13, (u8 *) & status);
282         if (!result)
283                 sbs->charger_present = (status >> 15) & 0x1;
284         return result;
285 }
286
287 /* --------------------------------------------------------------------------
288                               FS Interface (/proc/acpi)
289    -------------------------------------------------------------------------- */
290
291 /* Generic Routines */
292
293 static int
294 acpi_sbs_add_fs(struct proc_dir_entry **dir,
295                         struct proc_dir_entry *parent_dir,
296                         char *dir_name,
297                         struct file_operations *info_fops,
298                         struct file_operations *state_fops,
299                         struct file_operations *alarm_fops, void *data)
300 {
301         struct proc_dir_entry *entry = NULL;
302
303         if (!*dir) {
304                 *dir = proc_mkdir(dir_name, parent_dir);
305                 if (!*dir) {
306                         ACPI_EXCEPTION((AE_INFO, AE_ERROR,
307                                         "proc_mkdir() failed"));
308                         return -ENODEV;
309                 }
310                 (*dir)->owner = THIS_MODULE;
311         }
312
313         /* 'info' [R] */
314         if (info_fops) {
315                 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
316                 if (!entry) {
317                         ACPI_EXCEPTION((AE_INFO, AE_ERROR,
318                                         "create_proc_entry() failed"));
319                 } else {
320                         entry->proc_fops = info_fops;
321                         entry->data = data;
322                         entry->owner = THIS_MODULE;
323                 }
324         }
325
326         /* 'state' [R] */
327         if (state_fops) {
328                 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
329                 if (!entry) {
330                         ACPI_EXCEPTION((AE_INFO, AE_ERROR,
331                                         "create_proc_entry() failed"));
332                 } else {
333                         entry->proc_fops = state_fops;
334                         entry->data = data;
335                         entry->owner = THIS_MODULE;
336                 }
337         }
338
339         /* 'alarm' [R/W] */
340         if (alarm_fops) {
341                 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
342                 if (!entry) {
343                         ACPI_EXCEPTION((AE_INFO, AE_ERROR,
344                                         "create_proc_entry() failed"));
345                 } else {
346                         entry->proc_fops = alarm_fops;
347                         entry->data = data;
348                         entry->owner = THIS_MODULE;
349                 }
350         }
351
352         return 0;
353 }
354
355 static void
356 acpi_sbs_remove_fs(struct proc_dir_entry **dir,
357                            struct proc_dir_entry *parent_dir)
358 {
359
360         if (*dir) {
361                 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
362                 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
363                 remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
364                 remove_proc_entry((*dir)->name, parent_dir);
365                 *dir = NULL;
366         }
367
368 }
369
370 /* Smart Battery Interface */
371
372 static struct proc_dir_entry *acpi_battery_dir = NULL;
373
374 static inline char *acpi_battery_units(struct acpi_battery *battery)
375 {
376         return acpi_battery_mode(battery) ? " mWh" : " mAh";
377 }
378
379
380 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
381 {
382         struct acpi_battery *battery = seq->private;
383         struct acpi_sbs *sbs = battery->sbs;
384         int result = 0;
385
386         mutex_lock(&sbs->lock);
387
388         seq_printf(seq, "present:                 %s\n",
389                    (battery->present) ? "yes" : "no");
390         if (!battery->present)
391                 goto end;
392
393         seq_printf(seq, "design capacity:         %i%s\n",
394                    battery->design_capacity * acpi_battery_scale(battery),
395                    acpi_battery_units(battery));
396         seq_printf(seq, "last full capacity:      %i%s\n",
397                    battery->full_charge_capacity * acpi_battery_scale(battery),
398                    acpi_battery_units(battery));
399         seq_printf(seq, "battery technology:      rechargeable\n");
400         seq_printf(seq, "design voltage:          %i mV\n",
401                    battery->design_voltage * acpi_battery_vscale(battery));
402         seq_printf(seq, "design capacity warning: unknown\n");
403         seq_printf(seq, "design capacity low:     unknown\n");
404         seq_printf(seq, "capacity granularity 1:  unknown\n");
405         seq_printf(seq, "capacity granularity 2:  unknown\n");
406         seq_printf(seq, "model number:            %s\n", battery->device_name);
407         seq_printf(seq, "serial number:           %i\n",
408                    battery->serial_number);
409         seq_printf(seq, "battery type:            %s\n",
410                    battery->device_chemistry);
411         seq_printf(seq, "OEM info:                %s\n",
412                    battery->manufacturer_name);
413       end:
414         mutex_unlock(&sbs->lock);
415         return result;
416 }
417
418 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
419 {
420         return single_open(file, acpi_battery_read_info, PDE(inode)->data);
421 }
422
423 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
424 {
425         struct acpi_battery *battery = seq->private;
426         struct acpi_sbs *sbs = battery->sbs;
427         int result = 0;
428
429         mutex_lock(&sbs->lock);
430         seq_printf(seq, "present:                 %s\n",
431                    (battery->present) ? "yes" : "no");
432         if (!battery->present)
433                 goto end;
434
435         acpi_battery_get_state(battery);
436         seq_printf(seq, "capacity state:          %s\n",
437                    (battery->state & 0x0010) ? "critical" : "ok");
438         seq_printf(seq, "charging state:          %s\n",
439                    (battery->current_now < 0) ? "discharging" :
440                    ((battery->current_now > 0) ? "charging" : "charged"));
441         seq_printf(seq, "present rate:            %d mA\n",
442                    abs(battery->current_now) * acpi_battery_ipscale(battery));
443         seq_printf(seq, "remaining capacity:      %i%s\n",
444                    battery->capacity_now * acpi_battery_scale(battery),
445                    acpi_battery_units(battery));
446         seq_printf(seq, "present voltage:         %i mV\n",
447                    battery->voltage_now * acpi_battery_vscale(battery));
448
449       end:
450         mutex_unlock(&sbs->lock);
451         return result;
452 }
453
454 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
455 {
456         return single_open(file, acpi_battery_read_state, PDE(inode)->data);
457 }
458
459 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
460 {
461         struct acpi_battery *battery = seq->private;
462         struct acpi_sbs *sbs = battery->sbs;
463         int result = 0;
464
465         mutex_lock(&sbs->lock);
466
467         if (!battery->present) {
468                 seq_printf(seq, "present:                 no\n");
469                 goto end;
470         }
471
472         acpi_battery_get_alarm(battery);
473         seq_printf(seq, "alarm:                   ");
474         if (battery->alarm_capacity)
475                 seq_printf(seq, "%i%s\n",
476                            battery->alarm_capacity *
477                            acpi_battery_scale(battery),
478                            acpi_battery_units(battery));
479         else
480                 seq_printf(seq, "disabled\n");
481       end:
482         mutex_unlock(&sbs->lock);
483         return result;
484 }
485
486 static ssize_t
487 acpi_battery_write_alarm(struct file *file, const char __user * buffer,
488                          size_t count, loff_t * ppos)
489 {
490         struct seq_file *seq = file->private_data;
491         struct acpi_battery *battery = seq->private;
492         struct acpi_sbs *sbs = battery->sbs;
493         char alarm_string[12] = { '\0' };
494         int result = 0;
495         mutex_lock(&sbs->lock);
496         if (!battery->present) {
497                 result = -ENODEV;
498                 goto end;
499         }
500         if (count > sizeof(alarm_string) - 1) {
501                 result = -EINVAL;
502                 goto end;
503         }
504         if (copy_from_user(alarm_string, buffer, count)) {
505                 result = -EFAULT;
506                 goto end;
507         }
508         alarm_string[count] = 0;
509         battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0);
510         acpi_battery_set_alarm(battery);
511       end:
512         mutex_unlock(&sbs->lock);
513         if (result)
514                 return result;
515         return count;
516 }
517
518 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
519 {
520         return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
521 }
522
523 static struct file_operations acpi_battery_info_fops = {
524         .open = acpi_battery_info_open_fs,
525         .read = seq_read,
526         .llseek = seq_lseek,
527         .release = single_release,
528         .owner = THIS_MODULE,
529 };
530
531 static struct file_operations acpi_battery_state_fops = {
532         .open = acpi_battery_state_open_fs,
533         .read = seq_read,
534         .llseek = seq_lseek,
535         .release = single_release,
536         .owner = THIS_MODULE,
537 };
538
539 static struct file_operations acpi_battery_alarm_fops = {
540         .open = acpi_battery_alarm_open_fs,
541         .read = seq_read,
542         .write = acpi_battery_write_alarm,
543         .llseek = seq_lseek,
544         .release = single_release,
545         .owner = THIS_MODULE,
546 };
547
548 /* Legacy AC Adapter Interface */
549
550 static struct proc_dir_entry *acpi_ac_dir = NULL;
551
552 static int acpi_ac_read_state(struct seq_file *seq, void *offset)
553 {
554
555         struct acpi_sbs *sbs = seq->private;
556
557         mutex_lock(&sbs->lock);
558
559         seq_printf(seq, "state:                   %s\n",
560                    sbs->charger_present ? "on-line" : "off-line");
561
562         mutex_unlock(&sbs->lock);
563         return 0;
564 }
565
566 static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
567 {
568         return single_open(file, acpi_ac_read_state, PDE(inode)->data);
569 }
570
571 static struct file_operations acpi_ac_state_fops = {
572         .open = acpi_ac_state_open_fs,
573         .read = seq_read,
574         .llseek = seq_lseek,
575         .release = single_release,
576         .owner = THIS_MODULE,
577 };
578
579 /* --------------------------------------------------------------------------
580                                  Driver Interface
581    -------------------------------------------------------------------------- */
582
583 /* Smart Battery */
584
585 static int acpi_battery_read(struct acpi_battery *battery)
586 {
587         int result = 0, saved_present = battery->present;
588         u16 state;
589
590         if (battery->sbs->manager_present) {
591                 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
592                                 ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
593                 if (!result)
594                         battery->present = state & (1 << battery->id);
595                 state &= 0x0fff;
596                 state |= 1 << (battery->id + 12);
597                 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
598                                   ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
599         } else if (battery->id == 0)
600                 battery->present = 1;
601         if (result || !battery->present)
602                 return result;
603
604         if (saved_present != battery->present) {
605                 battery->update_time = 0;
606                 result = acpi_battery_get_info(battery);
607                 if (result)
608                         return result;
609         }
610         result = acpi_battery_get_state(battery);
611         return result;
612 }
613
614 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
615 {
616         int result;
617         struct acpi_battery *battery = &sbs->battery[id];
618         battery->id = id;
619         battery->sbs = sbs;
620         battery->update_time = 0;
621         result = acpi_battery_read(battery);
622         if (result)
623                 return result;
624
625         sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
626         acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
627                         battery->name, &acpi_battery_info_fops,
628                         &acpi_battery_state_fops, &acpi_battery_alarm_fops,
629                         battery);
630         printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
631                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
632                battery->name, sbs->battery->present ? "present" : "absent");
633         return result;
634 }
635
636 static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
637 {
638
639         if (sbs->battery[id].proc_entry) {
640                 acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
641                                    acpi_battery_dir);
642         }
643 }
644
645 static int acpi_charger_add(struct acpi_sbs *sbs)
646 {
647         int result;
648
649         result = acpi_ac_get_present(sbs);
650         if (result)
651                 goto end;
652         result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
653                                  ACPI_AC_DIR_NAME, NULL,
654                                  &acpi_ac_state_fops, NULL, sbs);
655         if (result)
656                 goto end;
657         printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
658                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
659                ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
660       end:
661         return result;
662 }
663
664 static void acpi_charger_remove(struct acpi_sbs *sbs)
665 {
666
667         if (sbs->charger_entry)
668                 acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
669 }
670
671 void acpi_sbs_callback(void *context)
672 {
673         int id;
674         struct acpi_sbs *sbs = context;
675         struct acpi_battery *bat;
676         u8 saved_charger_state = sbs->charger_present;
677         u8 saved_battery_state;
678         acpi_ac_get_present(sbs);
679         if (sbs->charger_present != saved_charger_state) {
680                 acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
681                                               ACPI_SBS_NOTIFY_STATUS,
682                                               sbs->charger_present);
683         }
684         if (sbs->manager_present) {
685                 for (id = 0; id < MAX_SBS_BAT; ++id) {
686                         if (!(sbs->batteries_supported & (1 << id)))
687                                 continue;
688                         bat = &sbs->battery[id];
689                         saved_battery_state = bat->present;
690                         acpi_battery_read(bat);
691                         if (saved_battery_state == bat->present)
692                                 continue;
693                         acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
694                                                       bat->name,
695                                                       ACPI_SBS_NOTIFY_STATUS,
696                                                       bat->present);
697                 }
698         }
699 }
700
701 static int acpi_sbs_remove(struct acpi_device *device, int type);
702
703 static int acpi_sbs_add(struct acpi_device *device)
704 {
705         struct acpi_sbs *sbs;
706         int result = 0;
707         int id;
708
709         sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
710         if (!sbs) {
711                 result = -ENOMEM;
712                 goto end;
713         }
714
715         mutex_init(&sbs->lock);
716
717         sbs->hc = acpi_driver_data(device->parent);
718         sbs->device = device;
719         strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
720         strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
721         acpi_driver_data(device) = sbs;
722
723         result = acpi_charger_add(sbs);
724         if (result)
725                 goto end;
726
727         result = acpi_manager_get_info(sbs);
728         if (!result) {
729                 sbs->manager_present = 1;
730                 for (id = 0; id < MAX_SBS_BAT; ++id)
731                         if ((sbs->batteries_supported & (1 << id)))
732                                 acpi_battery_add(sbs, id);
733         } else
734                 acpi_battery_add(sbs, 0);
735         acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
736       end:
737         if (result)
738                 acpi_sbs_remove(device, 0);
739         return result;
740 }
741
742 static int acpi_sbs_remove(struct acpi_device *device, int type)
743 {
744         struct acpi_sbs *sbs;
745         int id;
746
747         if (!device)
748                 return -EINVAL;
749         sbs = acpi_driver_data(device);
750         if (!sbs)
751                 return -EINVAL;
752         mutex_lock(&sbs->lock);
753         acpi_smbus_unregister_callback(sbs->hc);
754         for (id = 0; id < MAX_SBS_BAT; ++id)
755                 acpi_battery_remove(sbs, id);
756         acpi_charger_remove(sbs);
757         mutex_unlock(&sbs->lock);
758         mutex_destroy(&sbs->lock);
759         kfree(sbs);
760         return 0;
761 }
762
763 static void acpi_sbs_rmdirs(void)
764 {
765         if (acpi_ac_dir) {
766                 acpi_unlock_ac_dir(acpi_ac_dir);
767                 acpi_ac_dir = NULL;
768         }
769         if (acpi_battery_dir) {
770                 acpi_unlock_battery_dir(acpi_battery_dir);
771                 acpi_battery_dir = NULL;
772         }
773 }
774
775 static int acpi_sbs_resume(struct acpi_device *device)
776 {
777         struct acpi_sbs *sbs;
778         if (!device)
779                 return -EINVAL;
780         sbs = device->driver_data;
781         acpi_sbs_callback(sbs);
782         return 0;
783 }
784
785 static int __init acpi_sbs_init(void)
786 {
787         int result = 0;
788
789         if (acpi_disabled)
790                 return -ENODEV;
791
792         acpi_ac_dir = acpi_lock_ac_dir();
793         if (!acpi_ac_dir) {
794                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
795                                 "acpi_lock_ac_dir() failed"));
796                 return -ENODEV;
797         }
798
799         acpi_battery_dir = acpi_lock_battery_dir();
800         if (!acpi_battery_dir) {
801                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
802                                 "acpi_lock_battery_dir() failed"));
803                 acpi_sbs_rmdirs();
804                 return -ENODEV;
805         }
806
807         result = acpi_bus_register_driver(&acpi_sbs_driver);
808         if (result < 0) {
809                 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
810                                 "acpi_bus_register_driver() failed"));
811                 acpi_sbs_rmdirs();
812                 return -ENODEV;
813         }
814
815         return 0;
816 }
817
818 static void __exit acpi_sbs_exit(void)
819 {
820         acpi_bus_unregister_driver(&acpi_sbs_driver);
821
822         acpi_sbs_rmdirs();
823
824         return;
825 }
826
827 module_init(acpi_sbs_init);
828 module_exit(acpi_sbs_exit);