ACPI: SBS: Add support for power_supply class (and sysfs)
[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
32 #include <linux/proc_fs.h>
33 #include <linux/seq_file.h>
34 #include <asm/uaccess.h>
35
36 #include <linux/acpi.h>
37 #include <linux/timer.h>
38 #include <linux/jiffies.h>
39 #include <linux/delay.h>
40
41 #include <linux/power_supply.h>
42
43 #include "sbshc.h"
44
45 #define ACPI_SBS_CLASS                  "sbs"
46 #define ACPI_AC_CLASS                   "ac_adapter"
47 #define ACPI_BATTERY_CLASS              "battery"
48 #define ACPI_SBS_DEVICE_NAME            "Smart Battery System"
49 #define ACPI_SBS_FILE_INFO              "info"
50 #define ACPI_SBS_FILE_STATE             "state"
51 #define ACPI_SBS_FILE_ALARM             "alarm"
52 #define ACPI_BATTERY_DIR_NAME           "BAT%i"
53 #define ACPI_AC_DIR_NAME                "AC0"
54
55 enum acpi_sbs_device_addr {
56         ACPI_SBS_CHARGER = 0x9,
57         ACPI_SBS_MANAGER = 0xa,
58         ACPI_SBS_BATTERY = 0xb,
59 };
60
61 #define ACPI_SBS_NOTIFY_STATUS          0x80
62 #define ACPI_SBS_NOTIFY_INFO            0x81
63
64 MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
65 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
66 MODULE_LICENSE("GPL");
67
68 static unsigned int cache_time = 1000;
69 module_param(cache_time, uint, 0644);
70 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
71
72 extern struct proc_dir_entry *acpi_lock_ac_dir(void);
73 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
74 extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
75 extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
76
77 #define MAX_SBS_BAT                     4
78 #define ACPI_SBS_BLOCK_MAX              32
79
80 static const struct acpi_device_id sbs_device_ids[] = {
81         {"ACPI0002", 0},
82         {"", 0},
83 };
84 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
85
86 struct acpi_battery {
87         struct power_supply bat;
88         struct acpi_sbs *sbs;
89         struct proc_dir_entry *proc_entry;
90         unsigned long update_time;
91         char name[8];
92         char manufacturer_name[ACPI_SBS_BLOCK_MAX];
93         char device_name[ACPI_SBS_BLOCK_MAX];
94         char device_chemistry[ACPI_SBS_BLOCK_MAX];
95         u16 alarm_capacity;
96         u16 full_charge_capacity;
97         u16 design_capacity;
98         u16 design_voltage;
99         u16 serial_number;
100         u16 cycle_count;
101         u16 temp_now;
102         u16 voltage_now;
103         s16 current_now;
104         s16 current_avg;
105         u16 capacity_now;
106         u16 state_of_charge;
107         u16 state;
108         u16 mode;
109         u16 spec;
110         u8 id;
111         u8 present:1;
112 };
113
114 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
115
116 struct acpi_sbs {
117         struct power_supply charger;
118         struct acpi_device *device;
119         struct acpi_smb_hc *hc;
120         struct mutex lock;
121         struct proc_dir_entry *charger_entry;
122         struct acpi_battery battery[MAX_SBS_BAT];
123         u8 batteries_supported:4;
124         u8 manager_present:1;
125         u8 charger_present:1;
126 };
127
128 #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
129
130 static inline int battery_scale(int log)
131 {
132         int scale = 1;
133         while (log--)
134                 scale *= 10;
135         return scale;
136 }
137
138 static inline int acpi_battery_vscale(struct acpi_battery *battery)
139 {
140         return battery_scale((battery->spec & 0x0f00) >> 8);
141 }
142
143 static inline int acpi_battery_ipscale(struct acpi_battery *battery)
144 {
145         return battery_scale((battery->spec & 0xf000) >> 12);
146 }
147
148 static inline int acpi_battery_mode(struct acpi_battery *battery)
149 {
150         return (battery->mode & 0x8000);
151 }
152
153 static inline int acpi_battery_scale(struct acpi_battery *battery)
154 {
155         return (acpi_battery_mode(battery) ? 10 : 1) *
156             acpi_battery_ipscale(battery);
157 }
158
159 static int sbs_get_ac_property(struct power_supply *psy,
160                                enum power_supply_property psp,
161                                union power_supply_propval *val)
162 {
163         struct acpi_sbs *sbs = to_acpi_sbs(psy);
164         switch (psp) {
165         case POWER_SUPPLY_PROP_ONLINE:
166                 val->intval = sbs->charger_present;
167                 break;
168         default:
169                 return -EINVAL;
170         }
171         return 0;
172 }
173
174 static int acpi_battery_technology(struct acpi_battery *battery)
175 {
176         if (!strcasecmp("NiCd", battery->device_chemistry))
177                 return POWER_SUPPLY_TECHNOLOGY_NiCd;
178         if (!strcasecmp("NiMH", battery->device_chemistry))
179                 return POWER_SUPPLY_TECHNOLOGY_NiMH;
180         if (!strcasecmp("LION", battery->device_chemistry))
181                 return POWER_SUPPLY_TECHNOLOGY_LION;
182         if (!strcasecmp("LiP", battery->device_chemistry))
183                 return POWER_SUPPLY_TECHNOLOGY_LIPO;
184         return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
185 }
186
187 static int acpi_sbs_battery_get_property(struct power_supply *psy,
188                                          enum power_supply_property psp,
189                                          union power_supply_propval *val)
190 {
191         struct acpi_battery *battery = to_acpi_battery(psy);
192
193         if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
194                 return -ENODEV;
195         switch (psp) {
196         case POWER_SUPPLY_PROP_STATUS:
197                 if (battery->current_now < 0)
198                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
199                 else if (battery->current_now > 0)
200                         val->intval = POWER_SUPPLY_STATUS_CHARGING;
201                 else
202                         val->intval = POWER_SUPPLY_STATUS_FULL;
203                 break;
204         case POWER_SUPPLY_PROP_PRESENT:
205                 val->intval = battery->present;
206                 break;
207         case POWER_SUPPLY_PROP_TECHNOLOGY:
208                 val->intval = acpi_battery_technology(battery);
209                 break;
210         case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
211                 val->intval = battery->design_voltage *
212                         acpi_battery_vscale(battery) * 1000;
213                 break;
214         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
215                 val->intval = battery->voltage_now *
216                                 acpi_battery_vscale(battery) * 1000;
217                 break;
218         case POWER_SUPPLY_PROP_CURRENT_NOW:
219                 val->intval = abs(battery->current_now) *
220                                 acpi_battery_ipscale(battery) * 1000;
221                 break;
222         case POWER_SUPPLY_PROP_CURRENT_AVG:
223                 val->intval = abs(battery->current_avg) *
224                                 acpi_battery_ipscale(battery) * 1000;
225                 break;
226         case POWER_SUPPLY_PROP_CAPACITY:
227                 val->intval = battery->state_of_charge;
228                 break;
229         case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
230         case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
231                 val->intval = battery->design_capacity *
232                         acpi_battery_scale(battery) * 1000;
233                 break;
234         case POWER_SUPPLY_PROP_CHARGE_FULL:
235         case POWER_SUPPLY_PROP_ENERGY_FULL:
236                 val->intval = battery->full_charge_capacity *
237                         acpi_battery_scale(battery) * 1000;
238                 break;
239         case POWER_SUPPLY_PROP_CHARGE_NOW:
240         case POWER_SUPPLY_PROP_ENERGY_NOW:
241                 val->intval = battery->capacity_now *
242                                 acpi_battery_scale(battery) * 1000;
243                 break;
244         case POWER_SUPPLY_PROP_TEMP:
245                 val->intval = battery->temp_now - 2730; // dK -> dC
246                 break;
247         case POWER_SUPPLY_PROP_MODEL_NAME:
248                 val->strval = battery->device_name;
249                 break;
250         case POWER_SUPPLY_PROP_MANUFACTURER:
251                 val->strval = battery->manufacturer_name;
252                 break;
253         default:
254                 return -EINVAL;
255         }
256         return 0;
257 }
258
259 static enum power_supply_property sbs_ac_props[] = {
260         POWER_SUPPLY_PROP_ONLINE,
261 };
262
263 static enum power_supply_property sbs_charge_battery_props[] = {
264         POWER_SUPPLY_PROP_STATUS,
265         POWER_SUPPLY_PROP_PRESENT,
266         POWER_SUPPLY_PROP_TECHNOLOGY,
267         POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
268         POWER_SUPPLY_PROP_VOLTAGE_NOW,
269         POWER_SUPPLY_PROP_CURRENT_NOW,
270         POWER_SUPPLY_PROP_CURRENT_AVG,
271         POWER_SUPPLY_PROP_CAPACITY,
272         POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
273         POWER_SUPPLY_PROP_CHARGE_FULL,
274         POWER_SUPPLY_PROP_CHARGE_NOW,
275         POWER_SUPPLY_PROP_TEMP,
276         POWER_SUPPLY_PROP_MODEL_NAME,
277         POWER_SUPPLY_PROP_MANUFACTURER,
278 };
279
280 static enum power_supply_property sbs_energy_battery_props[] = {
281         POWER_SUPPLY_PROP_STATUS,
282         POWER_SUPPLY_PROP_PRESENT,
283         POWER_SUPPLY_PROP_TECHNOLOGY,
284         POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
285         POWER_SUPPLY_PROP_VOLTAGE_NOW,
286         POWER_SUPPLY_PROP_CURRENT_NOW,
287         POWER_SUPPLY_PROP_CURRENT_AVG,
288         POWER_SUPPLY_PROP_CAPACITY,
289         POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
290         POWER_SUPPLY_PROP_ENERGY_FULL,
291         POWER_SUPPLY_PROP_ENERGY_NOW,
292         POWER_SUPPLY_PROP_TEMP,
293         POWER_SUPPLY_PROP_MODEL_NAME,
294         POWER_SUPPLY_PROP_MANUFACTURER,
295 };
296
297 /* --------------------------------------------------------------------------
298                             Smart Battery System Management
299    -------------------------------------------------------------------------- */
300
301 struct acpi_battery_reader {
302         u8 command;             /* command for battery */
303         u8 mode;                /* word or block? */
304         size_t offset;          /* offset inside struct acpi_sbs_battery */
305 };
306
307 static struct acpi_battery_reader info_readers[] = {
308         {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
309         {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
310         {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
311         {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
312         {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
313         {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
314         {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
315         {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
316         {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
317         {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
318         {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
319 };
320
321 static struct acpi_battery_reader state_readers[] = {
322         {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
323         {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
324         {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
325         {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
326         {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
327         {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
328         {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
329 };
330
331 static int acpi_manager_get_info(struct acpi_sbs *sbs)
332 {
333         int result = 0;
334         u16 battery_system_info;
335
336         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
337                                  0x04, (u8 *)&battery_system_info);
338         if (!result)
339                 sbs->batteries_supported = battery_system_info & 0x000f;
340         return result;
341 }
342
343 static int acpi_battery_get_info(struct acpi_battery *battery)
344 {
345         int i, result = 0;
346
347         for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
348                 result = acpi_smbus_read(battery->sbs->hc,
349                                          info_readers[i].mode,
350                                          ACPI_SBS_BATTERY,
351                                          info_readers[i].command,
352                                          (u8 *) battery +
353                                                 info_readers[i].offset);
354                 if (result)
355                         break;
356         }
357         return result;
358 }
359
360 static int acpi_battery_get_state(struct acpi_battery *battery)
361 {
362         int i, result = 0;
363
364         if (battery->update_time &&
365             time_before(jiffies, battery->update_time +
366                                 msecs_to_jiffies(cache_time)))
367                 return 0;
368         for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
369                 result = acpi_smbus_read(battery->sbs->hc,
370                                          state_readers[i].mode,
371                                          ACPI_SBS_BATTERY,
372                                          state_readers[i].command,
373                                          (u8 *)battery +
374                                                 state_readers[i].offset);
375                 if (result)
376                         goto end;
377         }
378       end:
379         battery->update_time = jiffies;
380         return result;
381 }
382
383 static int acpi_battery_get_alarm(struct acpi_battery *battery)
384 {
385         return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
386                                  ACPI_SBS_BATTERY, 0x01,
387                                  (u8 *)&battery->alarm_capacity);
388 }
389
390 static int acpi_battery_set_alarm(struct acpi_battery *battery)
391 {
392         struct acpi_sbs *sbs = battery->sbs;
393         u16 value, sel = 1 << (battery->id + 12);
394
395         int ret;
396
397
398         if (sbs->manager_present) {
399                 ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
400                                 0x01, (u8 *)&value);
401                 if (ret)
402                         goto end;
403                 if ((value & 0xf000) != sel) {
404                         value &= 0x0fff;
405                         value |= sel;
406                 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
407                                          ACPI_SBS_MANAGER,
408                                          0x01, (u8 *)&value, 2);
409                 if (ret)
410                         goto end;
411                 }
412         }
413         ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
414                                 0x01, (u8 *)&battery->alarm_capacity, 2);
415       end:
416         return ret;
417 }
418
419 static int acpi_ac_get_present(struct acpi_sbs *sbs)
420 {
421         int result;
422         u16 status;
423
424         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
425                                  0x13, (u8 *) & status);
426         if (!result)
427                 sbs->charger_present = (status >> 15) & 0x1;
428         return result;
429 }
430
431 /* --------------------------------------------------------------------------
432                               FS Interface (/proc/acpi)
433    -------------------------------------------------------------------------- */
434
435 /* Generic Routines */
436 static int
437 acpi_sbs_add_fs(struct proc_dir_entry **dir,
438                 struct proc_dir_entry *parent_dir,
439                 char *dir_name,
440                 struct file_operations *info_fops,
441                 struct file_operations *state_fops,
442                 struct file_operations *alarm_fops, void *data)
443 {
444         struct proc_dir_entry *entry = NULL;
445
446         if (!*dir) {
447                 *dir = proc_mkdir(dir_name, parent_dir);
448                 if (!*dir) {
449                         return -ENODEV;
450                 }
451                 (*dir)->owner = THIS_MODULE;
452         }
453
454         /* 'info' [R] */
455         if (info_fops) {
456                 entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir);
457                 if (entry) {
458                         entry->proc_fops = info_fops;
459                         entry->data = data;
460                         entry->owner = THIS_MODULE;
461                 }
462         }
463
464         /* 'state' [R] */
465         if (state_fops) {
466                 entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir);
467                 if (entry) {
468                         entry->proc_fops = state_fops;
469                         entry->data = data;
470                         entry->owner = THIS_MODULE;
471                 }
472         }
473
474         /* 'alarm' [R/W] */
475         if (alarm_fops) {
476                 entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir);
477                 if (entry) {
478                         entry->proc_fops = alarm_fops;
479                         entry->data = data;
480                         entry->owner = THIS_MODULE;
481                 }
482         }
483         return 0;
484 }
485
486 static void
487 acpi_sbs_remove_fs(struct proc_dir_entry **dir,
488                            struct proc_dir_entry *parent_dir)
489 {
490         if (*dir) {
491                 remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
492                 remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
493                 remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
494                 remove_proc_entry((*dir)->name, parent_dir);
495                 *dir = NULL;
496         }
497 }
498
499 /* Smart Battery Interface */
500 static struct proc_dir_entry *acpi_battery_dir = NULL;
501
502 static inline char *acpi_battery_units(struct acpi_battery *battery)
503 {
504         return acpi_battery_mode(battery) ? " mWh" : " mAh";
505 }
506
507
508 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
509 {
510         struct acpi_battery *battery = seq->private;
511         struct acpi_sbs *sbs = battery->sbs;
512         int result = 0;
513
514         mutex_lock(&sbs->lock);
515
516         seq_printf(seq, "present:                 %s\n",
517                    (battery->present) ? "yes" : "no");
518         if (!battery->present)
519                 goto end;
520
521         seq_printf(seq, "design capacity:         %i%s\n",
522                    battery->design_capacity * acpi_battery_scale(battery),
523                    acpi_battery_units(battery));
524         seq_printf(seq, "last full capacity:      %i%s\n",
525                    battery->full_charge_capacity * acpi_battery_scale(battery),
526                    acpi_battery_units(battery));
527         seq_printf(seq, "battery technology:      rechargeable\n");
528         seq_printf(seq, "design voltage:          %i mV\n",
529                    battery->design_voltage * acpi_battery_vscale(battery));
530         seq_printf(seq, "design capacity warning: unknown\n");
531         seq_printf(seq, "design capacity low:     unknown\n");
532         seq_printf(seq, "capacity granularity 1:  unknown\n");
533         seq_printf(seq, "capacity granularity 2:  unknown\n");
534         seq_printf(seq, "model number:            %s\n", battery->device_name);
535         seq_printf(seq, "serial number:           %i\n",
536                    battery->serial_number);
537         seq_printf(seq, "battery type:            %s\n",
538                    battery->device_chemistry);
539         seq_printf(seq, "OEM info:                %s\n",
540                    battery->manufacturer_name);
541       end:
542         mutex_unlock(&sbs->lock);
543         return result;
544 }
545
546 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
547 {
548         return single_open(file, acpi_battery_read_info, PDE(inode)->data);
549 }
550
551 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
552 {
553         struct acpi_battery *battery = seq->private;
554         struct acpi_sbs *sbs = battery->sbs;
555         int result = 0;
556
557         mutex_lock(&sbs->lock);
558         seq_printf(seq, "present:                 %s\n",
559                    (battery->present) ? "yes" : "no");
560         if (!battery->present)
561                 goto end;
562
563         acpi_battery_get_state(battery);
564         seq_printf(seq, "capacity state:          %s\n",
565                    (battery->state & 0x0010) ? "critical" : "ok");
566         seq_printf(seq, "charging state:          %s\n",
567                    (battery->current_now < 0) ? "discharging" :
568                    ((battery->current_now > 0) ? "charging" : "charged"));
569         seq_printf(seq, "present rate:            %d mA\n",
570                    abs(battery->current_now) * acpi_battery_ipscale(battery));
571         seq_printf(seq, "remaining capacity:      %i%s\n",
572                    battery->capacity_now * acpi_battery_scale(battery),
573                    acpi_battery_units(battery));
574         seq_printf(seq, "present voltage:         %i mV\n",
575                    battery->voltage_now * acpi_battery_vscale(battery));
576
577       end:
578         mutex_unlock(&sbs->lock);
579         return result;
580 }
581
582 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
583 {
584         return single_open(file, acpi_battery_read_state, PDE(inode)->data);
585 }
586
587 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
588 {
589         struct acpi_battery *battery = seq->private;
590         struct acpi_sbs *sbs = battery->sbs;
591         int result = 0;
592
593         mutex_lock(&sbs->lock);
594
595         if (!battery->present) {
596                 seq_printf(seq, "present:                 no\n");
597                 goto end;
598         }
599
600         acpi_battery_get_alarm(battery);
601         seq_printf(seq, "alarm:                   ");
602         if (battery->alarm_capacity)
603                 seq_printf(seq, "%i%s\n",
604                            battery->alarm_capacity *
605                            acpi_battery_scale(battery),
606                            acpi_battery_units(battery));
607         else
608                 seq_printf(seq, "disabled\n");
609       end:
610         mutex_unlock(&sbs->lock);
611         return result;
612 }
613
614 static ssize_t
615 acpi_battery_write_alarm(struct file *file, const char __user * buffer,
616                          size_t count, loff_t * ppos)
617 {
618         struct seq_file *seq = file->private_data;
619         struct acpi_battery *battery = seq->private;
620         struct acpi_sbs *sbs = battery->sbs;
621         char alarm_string[12] = { '\0' };
622         int result = 0;
623         mutex_lock(&sbs->lock);
624         if (!battery->present) {
625                 result = -ENODEV;
626                 goto end;
627         }
628         if (count > sizeof(alarm_string) - 1) {
629                 result = -EINVAL;
630                 goto end;
631         }
632         if (copy_from_user(alarm_string, buffer, count)) {
633                 result = -EFAULT;
634                 goto end;
635         }
636         alarm_string[count] = 0;
637         battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
638                                         acpi_battery_scale(battery);
639         acpi_battery_set_alarm(battery);
640       end:
641         mutex_unlock(&sbs->lock);
642         if (result)
643                 return result;
644         return count;
645 }
646
647 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
648 {
649         return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
650 }
651
652 static struct file_operations acpi_battery_info_fops = {
653         .open = acpi_battery_info_open_fs,
654         .read = seq_read,
655         .llseek = seq_lseek,
656         .release = single_release,
657         .owner = THIS_MODULE,
658 };
659
660 static struct file_operations acpi_battery_state_fops = {
661         .open = acpi_battery_state_open_fs,
662         .read = seq_read,
663         .llseek = seq_lseek,
664         .release = single_release,
665         .owner = THIS_MODULE,
666 };
667
668 static struct file_operations acpi_battery_alarm_fops = {
669         .open = acpi_battery_alarm_open_fs,
670         .read = seq_read,
671         .write = acpi_battery_write_alarm,
672         .llseek = seq_lseek,
673         .release = single_release,
674         .owner = THIS_MODULE,
675 };
676
677 /* Legacy AC Adapter Interface */
678
679 static struct proc_dir_entry *acpi_ac_dir = NULL;
680
681 static int acpi_ac_read_state(struct seq_file *seq, void *offset)
682 {
683
684         struct acpi_sbs *sbs = seq->private;
685
686         mutex_lock(&sbs->lock);
687
688         seq_printf(seq, "state:                   %s\n",
689                    sbs->charger_present ? "on-line" : "off-line");
690
691         mutex_unlock(&sbs->lock);
692         return 0;
693 }
694
695 static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
696 {
697         return single_open(file, acpi_ac_read_state, PDE(inode)->data);
698 }
699
700 static struct file_operations acpi_ac_state_fops = {
701         .open = acpi_ac_state_open_fs,
702         .read = seq_read,
703         .llseek = seq_lseek,
704         .release = single_release,
705         .owner = THIS_MODULE,
706 };
707
708 /* --------------------------------------------------------------------------
709                                  Driver Interface
710    -------------------------------------------------------------------------- */
711 static int acpi_battery_read(struct acpi_battery *battery)
712 {
713         int result = 0, saved_present = battery->present;
714         u16 state;
715
716         if (battery->sbs->manager_present) {
717                 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
718                                 ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
719                 if (!result)
720                         battery->present = state & (1 << battery->id);
721                 state &= 0x0fff;
722                 state |= 1 << (battery->id + 12);
723                 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
724                                   ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
725         } else if (battery->id == 0)
726                 battery->present = 1;
727         if (result || !battery->present)
728                 return result;
729
730         if (saved_present != battery->present) {
731                 battery->update_time = 0;
732                 result = acpi_battery_get_info(battery);
733                 if (result)
734                         return result;
735         }
736         result = acpi_battery_get_state(battery);
737         return result;
738 }
739
740 /* Smart Battery */
741 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
742 {
743         struct acpi_battery *battery = &sbs->battery[id];
744         int result;
745
746         battery->id = id;
747         battery->sbs = sbs;
748         result = acpi_battery_read(battery);
749         if (result)
750                 return result;
751
752         sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
753         acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
754                         battery->name, &acpi_battery_info_fops,
755                         &acpi_battery_state_fops, &acpi_battery_alarm_fops,
756                         battery);
757         battery->bat.name = battery->name;
758         battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
759         if (!acpi_battery_mode(battery)) {
760                 battery->bat.properties = sbs_charge_battery_props;
761                 battery->bat.num_properties =
762                     ARRAY_SIZE(sbs_charge_battery_props);
763         } else {
764                 battery->bat.properties = sbs_energy_battery_props;
765                 battery->bat.num_properties =
766                     ARRAY_SIZE(sbs_energy_battery_props);
767         }
768         battery->bat.get_property = acpi_sbs_battery_get_property;
769         result = power_supply_register(&sbs->device->dev, &battery->bat);
770         printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
771                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
772                battery->name, sbs->battery->present ? "present" : "absent");
773         return result;
774 }
775
776 static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
777 {
778         if (sbs->battery[id].bat.dev)
779                 power_supply_unregister(&sbs->battery[id].bat);
780         if (sbs->battery[id].proc_entry) {
781                 acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
782                                    acpi_battery_dir);
783         }
784 }
785
786 static int acpi_charger_add(struct acpi_sbs *sbs)
787 {
788         int result;
789
790         result = acpi_ac_get_present(sbs);
791         if (result)
792                 goto end;
793         result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
794                                  ACPI_AC_DIR_NAME, NULL,
795                                  &acpi_ac_state_fops, NULL, sbs);
796         if (result)
797                 goto end;
798         sbs->charger.name = "sbs-charger";
799         sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
800         sbs->charger.properties = sbs_ac_props;
801         sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
802         sbs->charger.get_property = sbs_get_ac_property;
803         power_supply_register(&sbs->device->dev, &sbs->charger);
804         printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
805                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
806                ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
807       end:
808         return result;
809 }
810
811 static void acpi_charger_remove(struct acpi_sbs *sbs)
812 {
813         if (sbs->charger.dev)
814                 power_supply_unregister(&sbs->charger);
815         if (sbs->charger_entry)
816                 acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
817 }
818
819 void acpi_sbs_callback(void *context)
820 {
821         int id;
822         struct acpi_sbs *sbs = context;
823         struct acpi_battery *bat;
824         u8 saved_charger_state = sbs->charger_present;
825         u8 saved_battery_state;
826         acpi_ac_get_present(sbs);
827         if (sbs->charger_present != saved_charger_state) {
828 #ifdef CONFIG_ACPI_PROC_EVENT
829                 acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
830                                               ACPI_SBS_NOTIFY_STATUS,
831                                               sbs->charger_present);
832 #endif
833                 kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
834         }
835         if (sbs->manager_present) {
836                 for (id = 0; id < MAX_SBS_BAT; ++id) {
837                         if (!(sbs->batteries_supported & (1 << id)))
838                                 continue;
839                         bat = &sbs->battery[id];
840                         saved_battery_state = bat->present;
841                         acpi_battery_read(bat);
842                         if (saved_battery_state == bat->present)
843                                 continue;
844 #ifdef CONFIG_ACPI_PROC_EVENT
845                         acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
846                                                       bat->name,
847                                                       ACPI_SBS_NOTIFY_STATUS,
848                                                       bat->present);
849 #endif
850                         kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
851                 }
852         }
853 }
854
855 static int acpi_sbs_remove(struct acpi_device *device, int type);
856
857 static int acpi_sbs_add(struct acpi_device *device)
858 {
859         struct acpi_sbs *sbs;
860         int result = 0;
861         int id;
862
863         sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
864         if (!sbs) {
865                 result = -ENOMEM;
866                 goto end;
867         }
868
869         mutex_init(&sbs->lock);
870
871         sbs->hc = acpi_driver_data(device->parent);
872         sbs->device = device;
873         strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
874         strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
875         acpi_driver_data(device) = sbs;
876
877         result = acpi_charger_add(sbs);
878         if (result)
879                 goto end;
880
881         result = acpi_manager_get_info(sbs);
882         if (!result) {
883                 sbs->manager_present = 1;
884                 for (id = 0; id < MAX_SBS_BAT; ++id)
885                         if ((sbs->batteries_supported & (1 << id)))
886                                 acpi_battery_add(sbs, id);
887         } else
888                 acpi_battery_add(sbs, 0);
889         acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
890       end:
891         if (result)
892                 acpi_sbs_remove(device, 0);
893         return result;
894 }
895
896 static int acpi_sbs_remove(struct acpi_device *device, int type)
897 {
898         struct acpi_sbs *sbs;
899         int id;
900
901         if (!device)
902                 return -EINVAL;
903         sbs = acpi_driver_data(device);
904         if (!sbs)
905                 return -EINVAL;
906         mutex_lock(&sbs->lock);
907         acpi_smbus_unregister_callback(sbs->hc);
908         for (id = 0; id < MAX_SBS_BAT; ++id)
909                 acpi_battery_remove(sbs, id);
910         acpi_charger_remove(sbs);
911         mutex_unlock(&sbs->lock);
912         mutex_destroy(&sbs->lock);
913         kfree(sbs);
914         return 0;
915 }
916
917 static void acpi_sbs_rmdirs(void)
918 {
919         if (acpi_ac_dir) {
920                 acpi_unlock_ac_dir(acpi_ac_dir);
921                 acpi_ac_dir = NULL;
922         }
923         if (acpi_battery_dir) {
924                 acpi_unlock_battery_dir(acpi_battery_dir);
925                 acpi_battery_dir = NULL;
926         }
927 }
928
929 static int acpi_sbs_resume(struct acpi_device *device)
930 {
931         struct acpi_sbs *sbs;
932         if (!device)
933                 return -EINVAL;
934         sbs = device->driver_data;
935         acpi_sbs_callback(sbs);
936         return 0;
937 }
938
939 static struct acpi_driver acpi_sbs_driver = {
940         .name = "sbs",
941         .class = ACPI_SBS_CLASS,
942         .ids = sbs_device_ids,
943         .ops = {
944                 .add = acpi_sbs_add,
945                 .remove = acpi_sbs_remove,
946                 .resume = acpi_sbs_resume,
947                 },
948 };
949
950 static int __init acpi_sbs_init(void)
951 {
952         int result = 0;
953
954         if (acpi_disabled)
955                 return -ENODEV;
956         acpi_ac_dir = acpi_lock_ac_dir();
957         if (!acpi_ac_dir)
958                 return -ENODEV;
959         acpi_battery_dir = acpi_lock_battery_dir();
960         if (!acpi_battery_dir) {
961                 acpi_sbs_rmdirs();
962                 return -ENODEV;
963         }
964         result = acpi_bus_register_driver(&acpi_sbs_driver);
965         if (result < 0) {
966                 acpi_sbs_rmdirs();
967                 return -ENODEV;
968         }
969         return 0;
970 }
971
972 static void __exit acpi_sbs_exit(void)
973 {
974         acpi_bus_unregister_driver(&acpi_sbs_driver);
975         acpi_sbs_rmdirs();
976         return;
977 }
978
979 module_init(acpi_sbs_init);
980 module_exit(acpi_sbs_exit);