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