Version:  2.0.40 2.2.26 2.4.37 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17

Linux/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/slab.h>
 29 #include <linux/module.h>
 30 #include <linux/moduleparam.h>
 31 #include <linux/kernel.h>
 32 
 33 #include <linux/acpi.h>
 34 #include <linux/timer.h>
 35 #include <linux/jiffies.h>
 36 #include <linux/delay.h>
 37 #include <linux/power_supply.h>
 38 
 39 #include "sbshc.h"
 40 #include "battery.h"
 41 
 42 #define PREFIX "ACPI: "
 43 
 44 #define ACPI_SBS_CLASS                  "sbs"
 45 #define ACPI_AC_CLASS                   "ac_adapter"
 46 #define ACPI_SBS_DEVICE_NAME            "Smart Battery System"
 47 #define ACPI_SBS_FILE_INFO              "info"
 48 #define ACPI_SBS_FILE_STATE             "state"
 49 #define ACPI_SBS_FILE_ALARM             "alarm"
 50 #define ACPI_BATTERY_DIR_NAME           "BAT%i"
 51 #define ACPI_AC_DIR_NAME                "AC0"
 52 
 53 #define ACPI_SBS_NOTIFY_STATUS          0x80
 54 #define ACPI_SBS_NOTIFY_INFO            0x81
 55 
 56 MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
 57 MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
 58 MODULE_LICENSE("GPL");
 59 
 60 static unsigned int cache_time = 1000;
 61 module_param(cache_time, uint, 0644);
 62 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 63 
 64 #define MAX_SBS_BAT                     4
 65 #define ACPI_SBS_BLOCK_MAX              32
 66 
 67 static const struct acpi_device_id sbs_device_ids[] = {
 68         {"ACPI0002", 0},
 69         {"", 0},
 70 };
 71 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 72 
 73 struct acpi_battery {
 74         struct power_supply bat;
 75         struct acpi_sbs *sbs;
 76         unsigned long update_time;
 77         char name[8];
 78         char manufacturer_name[ACPI_SBS_BLOCK_MAX];
 79         char device_name[ACPI_SBS_BLOCK_MAX];
 80         char device_chemistry[ACPI_SBS_BLOCK_MAX];
 81         u16 alarm_capacity;
 82         u16 full_charge_capacity;
 83         u16 design_capacity;
 84         u16 design_voltage;
 85         u16 serial_number;
 86         u16 cycle_count;
 87         u16 temp_now;
 88         u16 voltage_now;
 89         s16 rate_now;
 90         s16 rate_avg;
 91         u16 capacity_now;
 92         u16 state_of_charge;
 93         u16 state;
 94         u16 mode;
 95         u16 spec;
 96         u8 id;
 97         u8 present:1;
 98         u8 have_sysfs_alarm:1;
 99 };
100 
101 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
102 
103 struct acpi_sbs {
104         struct power_supply charger;
105         struct acpi_device *device;
106         struct acpi_smb_hc *hc;
107         struct mutex lock;
108         struct acpi_battery battery[MAX_SBS_BAT];
109         u8 batteries_supported:4;
110         u8 manager_present:1;
111         u8 charger_present:1;
112 };
113 
114 #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
115 
116 static int acpi_sbs_remove(struct acpi_device *device);
117 static int acpi_battery_get_state(struct acpi_battery *battery);
118 
119 static inline int battery_scale(int log)
120 {
121         int scale = 1;
122         while (log--)
123                 scale *= 10;
124         return scale;
125 }
126 
127 static inline int acpi_battery_vscale(struct acpi_battery *battery)
128 {
129         return battery_scale((battery->spec & 0x0f00) >> 8);
130 }
131 
132 static inline int acpi_battery_ipscale(struct acpi_battery *battery)
133 {
134         return battery_scale((battery->spec & 0xf000) >> 12);
135 }
136 
137 static inline int acpi_battery_mode(struct acpi_battery *battery)
138 {
139         return (battery->mode & 0x8000);
140 }
141 
142 static inline int acpi_battery_scale(struct acpi_battery *battery)
143 {
144         return (acpi_battery_mode(battery) ? 10 : 1) *
145             acpi_battery_ipscale(battery);
146 }
147 
148 static int sbs_get_ac_property(struct power_supply *psy,
149                                enum power_supply_property psp,
150                                union power_supply_propval *val)
151 {
152         struct acpi_sbs *sbs = to_acpi_sbs(psy);
153         switch (psp) {
154         case POWER_SUPPLY_PROP_ONLINE:
155                 val->intval = sbs->charger_present;
156                 break;
157         default:
158                 return -EINVAL;
159         }
160         return 0;
161 }
162 
163 static int acpi_battery_technology(struct acpi_battery *battery)
164 {
165         if (!strcasecmp("NiCd", battery->device_chemistry))
166                 return POWER_SUPPLY_TECHNOLOGY_NiCd;
167         if (!strcasecmp("NiMH", battery->device_chemistry))
168                 return POWER_SUPPLY_TECHNOLOGY_NiMH;
169         if (!strcasecmp("LION", battery->device_chemistry))
170                 return POWER_SUPPLY_TECHNOLOGY_LION;
171         if (!strcasecmp("LiP", battery->device_chemistry))
172                 return POWER_SUPPLY_TECHNOLOGY_LIPO;
173         return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
174 }
175 
176 static int acpi_sbs_battery_get_property(struct power_supply *psy,
177                                          enum power_supply_property psp,
178                                          union power_supply_propval *val)
179 {
180         struct acpi_battery *battery = to_acpi_battery(psy);
181 
182         if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
183                 return -ENODEV;
184 
185         acpi_battery_get_state(battery);
186         switch (psp) {
187         case POWER_SUPPLY_PROP_STATUS:
188                 if (battery->rate_now < 0)
189                         val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
190                 else if (battery->rate_now > 0)
191                         val->intval = POWER_SUPPLY_STATUS_CHARGING;
192                 else
193                         val->intval = POWER_SUPPLY_STATUS_FULL;
194                 break;
195         case POWER_SUPPLY_PROP_PRESENT:
196                 val->intval = battery->present;
197                 break;
198         case POWER_SUPPLY_PROP_TECHNOLOGY:
199                 val->intval = acpi_battery_technology(battery);
200                 break;
201         case POWER_SUPPLY_PROP_CYCLE_COUNT:
202                 val->intval = battery->cycle_count;
203                 break;
204         case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
205                 val->intval = battery->design_voltage *
206                         acpi_battery_vscale(battery) * 1000;
207                 break;
208         case POWER_SUPPLY_PROP_VOLTAGE_NOW:
209                 val->intval = battery->voltage_now *
210                                 acpi_battery_vscale(battery) * 1000;
211                 break;
212         case POWER_SUPPLY_PROP_CURRENT_NOW:
213         case POWER_SUPPLY_PROP_POWER_NOW:
214                 val->intval = abs(battery->rate_now) *
215                                 acpi_battery_ipscale(battery) * 1000;
216                 val->intval *= (acpi_battery_mode(battery)) ?
217                                 (battery->voltage_now *
218                                 acpi_battery_vscale(battery) / 1000) : 1;
219                 break;
220         case POWER_SUPPLY_PROP_CURRENT_AVG:
221         case POWER_SUPPLY_PROP_POWER_AVG:
222                 val->intval = abs(battery->rate_avg) *
223                                 acpi_battery_ipscale(battery) * 1000;
224                 val->intval *= (acpi_battery_mode(battery)) ?
225                                 (battery->voltage_now *
226                                 acpi_battery_vscale(battery) / 1000) : 1;
227                 break;
228         case POWER_SUPPLY_PROP_CAPACITY:
229                 val->intval = battery->state_of_charge;
230                 break;
231         case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
232         case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
233                 val->intval = battery->design_capacity *
234                         acpi_battery_scale(battery) * 1000;
235                 break;
236         case POWER_SUPPLY_PROP_CHARGE_FULL:
237         case POWER_SUPPLY_PROP_ENERGY_FULL:
238                 val->intval = battery->full_charge_capacity *
239                         acpi_battery_scale(battery) * 1000;
240                 break;
241         case POWER_SUPPLY_PROP_CHARGE_NOW:
242         case POWER_SUPPLY_PROP_ENERGY_NOW:
243                 val->intval = battery->capacity_now *
244                                 acpi_battery_scale(battery) * 1000;
245                 break;
246         case POWER_SUPPLY_PROP_TEMP:
247                 val->intval = battery->temp_now - 2730; // dK -> dC
248                 break;
249         case POWER_SUPPLY_PROP_MODEL_NAME:
250                 val->strval = battery->device_name;
251                 break;
252         case POWER_SUPPLY_PROP_MANUFACTURER:
253                 val->strval = battery->manufacturer_name;
254                 break;
255         default:
256                 return -EINVAL;
257         }
258         return 0;
259 }
260 
261 static enum power_supply_property sbs_ac_props[] = {
262         POWER_SUPPLY_PROP_ONLINE,
263 };
264 
265 static enum power_supply_property sbs_charge_battery_props[] = {
266         POWER_SUPPLY_PROP_STATUS,
267         POWER_SUPPLY_PROP_PRESENT,
268         POWER_SUPPLY_PROP_TECHNOLOGY,
269         POWER_SUPPLY_PROP_CYCLE_COUNT,
270         POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
271         POWER_SUPPLY_PROP_VOLTAGE_NOW,
272         POWER_SUPPLY_PROP_CURRENT_NOW,
273         POWER_SUPPLY_PROP_CURRENT_AVG,
274         POWER_SUPPLY_PROP_CAPACITY,
275         POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
276         POWER_SUPPLY_PROP_CHARGE_FULL,
277         POWER_SUPPLY_PROP_CHARGE_NOW,
278         POWER_SUPPLY_PROP_TEMP,
279         POWER_SUPPLY_PROP_MODEL_NAME,
280         POWER_SUPPLY_PROP_MANUFACTURER,
281 };
282 
283 static enum power_supply_property sbs_energy_battery_props[] = {
284         POWER_SUPPLY_PROP_STATUS,
285         POWER_SUPPLY_PROP_PRESENT,
286         POWER_SUPPLY_PROP_TECHNOLOGY,
287         POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
288         POWER_SUPPLY_PROP_VOLTAGE_NOW,
289         POWER_SUPPLY_PROP_CURRENT_NOW,
290         POWER_SUPPLY_PROP_CURRENT_AVG,
291         POWER_SUPPLY_PROP_POWER_NOW,
292         POWER_SUPPLY_PROP_POWER_AVG,
293         POWER_SUPPLY_PROP_CAPACITY,
294         POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
295         POWER_SUPPLY_PROP_ENERGY_FULL,
296         POWER_SUPPLY_PROP_ENERGY_NOW,
297         POWER_SUPPLY_PROP_TEMP,
298         POWER_SUPPLY_PROP_MODEL_NAME,
299         POWER_SUPPLY_PROP_MANUFACTURER,
300 };
301 
302 
303 /* --------------------------------------------------------------------------
304                             Smart Battery System Management
305    -------------------------------------------------------------------------- */
306 
307 struct acpi_battery_reader {
308         u8 command;             /* command for battery */
309         u8 mode;                /* word or block? */
310         size_t offset;          /* offset inside struct acpi_sbs_battery */
311 };
312 
313 static struct acpi_battery_reader info_readers[] = {
314         {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
315         {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
316         {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
317         {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
318         {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
319         {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
320         {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
321         {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
322         {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
323         {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
324         {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
325 };
326 
327 static struct acpi_battery_reader state_readers[] = {
328         {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
329         {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
330         {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)},
331         {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)},
332         {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
333         {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
334         {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
335 };
336 
337 static int acpi_manager_get_info(struct acpi_sbs *sbs)
338 {
339         int result = 0;
340         u16 battery_system_info;
341 
342         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
343                                  0x04, (u8 *)&battery_system_info);
344         if (!result)
345                 sbs->batteries_supported = battery_system_info & 0x000f;
346         return result;
347 }
348 
349 static int acpi_battery_get_info(struct acpi_battery *battery)
350 {
351         int i, result = 0;
352 
353         for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
354                 result = acpi_smbus_read(battery->sbs->hc,
355                                          info_readers[i].mode,
356                                          ACPI_SBS_BATTERY,
357                                          info_readers[i].command,
358                                          (u8 *) battery +
359                                                 info_readers[i].offset);
360                 if (result)
361                         break;
362         }
363         return result;
364 }
365 
366 static int acpi_battery_get_state(struct acpi_battery *battery)
367 {
368         int i, result = 0;
369 
370         if (battery->update_time &&
371             time_before(jiffies, battery->update_time +
372                                 msecs_to_jiffies(cache_time)))
373                 return 0;
374         for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
375                 result = acpi_smbus_read(battery->sbs->hc,
376                                          state_readers[i].mode,
377                                          ACPI_SBS_BATTERY,
378                                          state_readers[i].command,
379                                          (u8 *)battery +
380                                                 state_readers[i].offset);
381                 if (result)
382                         goto end;
383         }
384       end:
385         battery->update_time = jiffies;
386         return result;
387 }
388 
389 static int acpi_battery_get_alarm(struct acpi_battery *battery)
390 {
391         return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
392                                  ACPI_SBS_BATTERY, 0x01,
393                                  (u8 *)&battery->alarm_capacity);
394 }
395 
396 static int acpi_battery_set_alarm(struct acpi_battery *battery)
397 {
398         struct acpi_sbs *sbs = battery->sbs;
399         u16 value, sel = 1 << (battery->id + 12);
400 
401         int ret;
402 
403 
404         if (sbs->manager_present) {
405                 ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
406                                 0x01, (u8 *)&value);
407                 if (ret)
408                         goto end;
409                 if ((value & 0xf000) != sel) {
410                         value &= 0x0fff;
411                         value |= sel;
412                 ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
413                                          ACPI_SBS_MANAGER,
414                                          0x01, (u8 *)&value, 2);
415                 if (ret)
416                         goto end;
417                 }
418         }
419         ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
420                                 0x01, (u8 *)&battery->alarm_capacity, 2);
421       end:
422         return ret;
423 }
424 
425 static int acpi_ac_get_present(struct acpi_sbs *sbs)
426 {
427         int result;
428         u16 status;
429 
430         result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
431                                  0x13, (u8 *) & status);
432         if (!result)
433                 sbs->charger_present = (status >> 15) & 0x1;
434         return result;
435 }
436 
437 static ssize_t acpi_battery_alarm_show(struct device *dev,
438                                         struct device_attribute *attr,
439                                         char *buf)
440 {
441         struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
442         acpi_battery_get_alarm(battery);
443         return sprintf(buf, "%d\n", battery->alarm_capacity *
444                                 acpi_battery_scale(battery) * 1000);
445 }
446 
447 static ssize_t acpi_battery_alarm_store(struct device *dev,
448                                         struct device_attribute *attr,
449                                         const char *buf, size_t count)
450 {
451         unsigned long x;
452         struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
453         if (sscanf(buf, "%lu\n", &x) == 1)
454                 battery->alarm_capacity = x /
455                         (1000 * acpi_battery_scale(battery));
456         if (battery->present)
457                 acpi_battery_set_alarm(battery);
458         return count;
459 }
460 
461 static struct device_attribute alarm_attr = {
462         .attr = {.name = "alarm", .mode = 0644},
463         .show = acpi_battery_alarm_show,
464         .store = acpi_battery_alarm_store,
465 };
466 
467 /* --------------------------------------------------------------------------
468                                  Driver Interface
469    -------------------------------------------------------------------------- */
470 static int acpi_battery_read(struct acpi_battery *battery)
471 {
472         int result = 0, saved_present = battery->present;
473         u16 state;
474 
475         if (battery->sbs->manager_present) {
476                 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
477                                 ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
478                 if (!result)
479                         battery->present = state & (1 << battery->id);
480                 state &= 0x0fff;
481                 state |= 1 << (battery->id + 12);
482                 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
483                                   ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
484         } else if (battery->id == 0)
485                 battery->present = 1;
486         if (result || !battery->present)
487                 return result;
488 
489         if (saved_present != battery->present) {
490                 battery->update_time = 0;
491                 result = acpi_battery_get_info(battery);
492                 if (result)
493                         return result;
494         }
495         result = acpi_battery_get_state(battery);
496         return result;
497 }
498 
499 /* Smart Battery */
500 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
501 {
502         struct acpi_battery *battery = &sbs->battery[id];
503         int result;
504 
505         battery->id = id;
506         battery->sbs = sbs;
507         result = acpi_battery_read(battery);
508         if (result)
509                 return result;
510 
511         sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
512         battery->bat.name = battery->name;
513         battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
514         if (!acpi_battery_mode(battery)) {
515                 battery->bat.properties = sbs_charge_battery_props;
516                 battery->bat.num_properties =
517                     ARRAY_SIZE(sbs_charge_battery_props);
518         } else {
519                 battery->bat.properties = sbs_energy_battery_props;
520                 battery->bat.num_properties =
521                     ARRAY_SIZE(sbs_energy_battery_props);
522         }
523         battery->bat.get_property = acpi_sbs_battery_get_property;
524         result = power_supply_register(&sbs->device->dev, &battery->bat);
525         if (result)
526                 goto end;
527         result = device_create_file(battery->bat.dev, &alarm_attr);
528         if (result)
529                 goto end;
530         battery->have_sysfs_alarm = 1;
531       end:
532         printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
533                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
534                battery->name, battery->present ? "present" : "absent");
535         return result;
536 }
537 
538 static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
539 {
540         struct acpi_battery *battery = &sbs->battery[id];
541 
542         if (battery->bat.dev) {
543                 if (battery->have_sysfs_alarm)
544                         device_remove_file(battery->bat.dev, &alarm_attr);
545                 power_supply_unregister(&battery->bat);
546         }
547 }
548 
549 static int acpi_charger_add(struct acpi_sbs *sbs)
550 {
551         int result;
552 
553         result = acpi_ac_get_present(sbs);
554         if (result)
555                 goto end;
556 
557         sbs->charger.name = "sbs-charger";
558         sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
559         sbs->charger.properties = sbs_ac_props;
560         sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
561         sbs->charger.get_property = sbs_get_ac_property;
562         power_supply_register(&sbs->device->dev, &sbs->charger);
563         printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
564                ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
565                ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
566       end:
567         return result;
568 }
569 
570 static void acpi_charger_remove(struct acpi_sbs *sbs)
571 {
572         if (sbs->charger.dev)
573                 power_supply_unregister(&sbs->charger);
574 }
575 
576 static void acpi_sbs_callback(void *context)
577 {
578         int id;
579         struct acpi_sbs *sbs = context;
580         struct acpi_battery *bat;
581         u8 saved_charger_state = sbs->charger_present;
582         u8 saved_battery_state;
583         acpi_ac_get_present(sbs);
584         if (sbs->charger_present != saved_charger_state)
585                 kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
586 
587         if (sbs->manager_present) {
588                 for (id = 0; id < MAX_SBS_BAT; ++id) {
589                         if (!(sbs->batteries_supported & (1 << id)))
590                                 continue;
591                         bat = &sbs->battery[id];
592                         saved_battery_state = bat->present;
593                         acpi_battery_read(bat);
594                         if (saved_battery_state == bat->present)
595                                 continue;
596                         kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
597                 }
598         }
599 }
600 
601 static int acpi_sbs_add(struct acpi_device *device)
602 {
603         struct acpi_sbs *sbs;
604         int result = 0;
605         int id;
606 
607         sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
608         if (!sbs) {
609                 result = -ENOMEM;
610                 goto end;
611         }
612 
613         mutex_init(&sbs->lock);
614 
615         sbs->hc = acpi_driver_data(device->parent);
616         sbs->device = device;
617         strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
618         strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
619         device->driver_data = sbs;
620 
621         result = acpi_charger_add(sbs);
622         if (result)
623                 goto end;
624 
625         result = acpi_manager_get_info(sbs);
626         if (!result) {
627                 sbs->manager_present = 1;
628                 for (id = 0; id < MAX_SBS_BAT; ++id)
629                         if ((sbs->batteries_supported & (1 << id)))
630                                 acpi_battery_add(sbs, id);
631         } else
632                 acpi_battery_add(sbs, 0);
633         acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
634       end:
635         if (result)
636                 acpi_sbs_remove(device);
637         return result;
638 }
639 
640 static int acpi_sbs_remove(struct acpi_device *device)
641 {
642         struct acpi_sbs *sbs;
643         int id;
644 
645         if (!device)
646                 return -EINVAL;
647         sbs = acpi_driver_data(device);
648         if (!sbs)
649                 return -EINVAL;
650         mutex_lock(&sbs->lock);
651         acpi_smbus_unregister_callback(sbs->hc);
652         for (id = 0; id < MAX_SBS_BAT; ++id)
653                 acpi_battery_remove(sbs, id);
654         acpi_charger_remove(sbs);
655         mutex_unlock(&sbs->lock);
656         mutex_destroy(&sbs->lock);
657         kfree(sbs);
658         return 0;
659 }
660 
661 #ifdef CONFIG_PM_SLEEP
662 static int acpi_sbs_resume(struct device *dev)
663 {
664         struct acpi_sbs *sbs;
665         if (!dev)
666                 return -EINVAL;
667         sbs = to_acpi_device(dev)->driver_data;
668         acpi_sbs_callback(sbs);
669         return 0;
670 }
671 #else
672 #define acpi_sbs_resume NULL
673 #endif
674 
675 static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
676 
677 static struct acpi_driver acpi_sbs_driver = {
678         .name = "sbs",
679         .class = ACPI_SBS_CLASS,
680         .ids = sbs_device_ids,
681         .ops = {
682                 .add = acpi_sbs_add,
683                 .remove = acpi_sbs_remove,
684                 },
685         .drv.pm = &acpi_sbs_pm,
686 };
687 
688 static int __init acpi_sbs_init(void)
689 {
690         int result = 0;
691 
692         if (acpi_disabled)
693                 return -ENODEV;
694 
695         result = acpi_bus_register_driver(&acpi_sbs_driver);
696         if (result < 0)
697                 return -ENODEV;
698 
699         return 0;
700 }
701 
702 static void __exit acpi_sbs_exit(void)
703 {
704         acpi_bus_unregister_driver(&acpi_sbs_driver);
705         return;
706 }
707 
708 module_init(acpi_sbs_init);
709 module_exit(acpi_sbs_exit);
710 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us