Blame view

drivers/acpi/sbs.c 28.5 KB
3f86b8324   Rich Townsend   ACPI: add support...
1
  /*
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
2
   *  sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3f86b8324   Rich Townsend   ACPI: add support...
3
   *
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
4
5
   *  Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
   *  Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
3f86b8324   Rich Townsend   ACPI: add support...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   *  Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
3f86b8324   Rich Townsend   ACPI: add support...
29
30
31
  #include <linux/module.h>
  #include <linux/moduleparam.h>
  #include <linux/kernel.h>
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
32

fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
33
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
34
35
36
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
  #include <asm/uaccess.h>
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
37
  #endif
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
38

3f86b8324   Rich Townsend   ACPI: add support...
39
  #include <linux/acpi.h>
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
40
  #include <linux/timer.h>
722062334   Vladimir Lebedev   ACPI: sbs: Common...
41
  #include <linux/jiffies.h>
3f86b8324   Rich Townsend   ACPI: add support...
42
  #include <linux/delay.h>
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
43
  #include <linux/power_supply.h>
91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
44
  #include "sbshc.h"
a192a9580   Len Brown   ACPI: Move defini...
45
  #define PREFIX "ACPI: "
3f86b8324   Rich Townsend   ACPI: add support...
46
47
48
  #define ACPI_SBS_CLASS			"sbs"
  #define ACPI_AC_CLASS			"ac_adapter"
  #define ACPI_BATTERY_CLASS		"battery"
3f86b8324   Rich Townsend   ACPI: add support...
49
50
51
52
53
54
  #define ACPI_SBS_DEVICE_NAME		"Smart Battery System"
  #define ACPI_SBS_FILE_INFO		"info"
  #define ACPI_SBS_FILE_STATE		"state"
  #define ACPI_SBS_FILE_ALARM		"alarm"
  #define ACPI_BATTERY_DIR_NAME		"BAT%i"
  #define ACPI_AC_DIR_NAME		"AC0"
3f86b8324   Rich Townsend   ACPI: add support...
55

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
56
57
  #define ACPI_SBS_NOTIFY_STATUS		0x80
  #define ACPI_SBS_NOTIFY_INFO		0x81
3f86b8324   Rich Townsend   ACPI: add support...
58

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
59
  MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
3f86b8324   Rich Townsend   ACPI: add support...
60
61
  MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
  MODULE_LICENSE("GPL");
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
62
63
64
  static unsigned int cache_time = 1000;
  module_param(cache_time, uint, 0644);
  MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
65
66
67
68
69
  
  extern struct proc_dir_entry *acpi_lock_ac_dir(void);
  extern struct proc_dir_entry *acpi_lock_battery_dir(void);
  extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
  extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
70
  #define MAX_SBS_BAT			4
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
71
  #define ACPI_SBS_BLOCK_MAX		32
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
72
  static const struct acpi_device_id sbs_device_ids[] = {
91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
73
  	{"ACPI0002", 0},
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
74
75
76
  	{"", 0},
  };
  MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
3f86b8324   Rich Townsend   ACPI: add support...
77
  struct acpi_battery {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
78
  	struct power_supply bat;
3f86b8324   Rich Townsend   ACPI: add support...
79
  	struct acpi_sbs *sbs;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
80
  #ifdef CONFIG_ACPI_PROCFS_POWER
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
81
  	struct proc_dir_entry *proc_entry;
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
82
  #endif
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
83
84
  	unsigned long update_time;
  	char name[8];
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
85
86
87
  	char manufacturer_name[ACPI_SBS_BLOCK_MAX];
  	char device_name[ACPI_SBS_BLOCK_MAX];
  	char device_chemistry[ACPI_SBS_BLOCK_MAX];
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
88
  	u16 alarm_capacity;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
89
90
91
92
  	u16 full_charge_capacity;
  	u16 design_capacity;
  	u16 design_voltage;
  	u16 serial_number;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
93
94
  	u16 cycle_count;
  	u16 temp_now;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
95
  	u16 voltage_now;
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
96
97
  	s16 rate_now;
  	s16 rate_avg;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
98
  	u16 capacity_now;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
99
  	u16 state_of_charge;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
100
  	u16 state;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
101
  	u16 mode;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
102
  	u16 spec;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
103
  	u8 id;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
104
  	u8 present:1;
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
105
  	u8 have_sysfs_alarm:1;
3f86b8324   Rich Townsend   ACPI: add support...
106
  };
497888cf6   Phil Carmody   treewide: fix pot...
107
  #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
108

3f86b8324   Rich Townsend   ACPI: add support...
109
  struct acpi_sbs {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
110
  	struct power_supply charger;
3f86b8324   Rich Townsend   ACPI: add support...
111
  	struct acpi_device *device;
91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
112
  	struct acpi_smb_hc *hc;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
113
  	struct mutex lock;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
114
  #ifdef CONFIG_ACPI_PROCFS_POWER
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
115
  	struct proc_dir_entry *charger_entry;
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
116
  #endif
3f86b8324   Rich Townsend   ACPI: add support...
117
  	struct acpi_battery battery[MAX_SBS_BAT];
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
118
  	u8 batteries_supported:4;
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
119
120
  	u8 manager_present:1;
  	u8 charger_present:1;
3f86b8324   Rich Townsend   ACPI: add support...
121
  };
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
122
  #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger)
1dd5c715e   Lan Tianyu   ACPI / SBS: Add g...
123
124
  static int acpi_sbs_remove(struct acpi_device *device, int type);
  static int acpi_battery_get_state(struct acpi_battery *battery);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
125
  static inline int battery_scale(int log)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
126
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
127
128
129
130
  	int scale = 1;
  	while (log--)
  		scale *= 10;
  	return scale;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
131
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
132
  static inline int acpi_battery_vscale(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
133
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
134
  	return battery_scale((battery->spec & 0x0f00) >> 8);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
135
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
136
  static inline int acpi_battery_ipscale(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
137
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
138
  	return battery_scale((battery->spec & 0xf000) >> 12);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
139
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
140
  static inline int acpi_battery_mode(struct acpi_battery *battery)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
141
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
142
  	return (battery->mode & 0x8000);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
143
  }
3f86b8324   Rich Townsend   ACPI: add support...
144

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
145
  static inline int acpi_battery_scale(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
146
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
147
148
  	return (acpi_battery_mode(battery) ? 10 : 1) *
  	    acpi_battery_ipscale(battery);
3f86b8324   Rich Townsend   ACPI: add support...
149
  }
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  static int sbs_get_ac_property(struct power_supply *psy,
  			       enum power_supply_property psp,
  			       union power_supply_propval *val)
  {
  	struct acpi_sbs *sbs = to_acpi_sbs(psy);
  	switch (psp) {
  	case POWER_SUPPLY_PROP_ONLINE:
  		val->intval = sbs->charger_present;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static int acpi_battery_technology(struct acpi_battery *battery)
  {
  	if (!strcasecmp("NiCd", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_NiCd;
  	if (!strcasecmp("NiMH", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_NiMH;
  	if (!strcasecmp("LION", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_LION;
  	if (!strcasecmp("LiP", battery->device_chemistry))
  		return POWER_SUPPLY_TECHNOLOGY_LIPO;
  	return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
  }
  
  static int acpi_sbs_battery_get_property(struct power_supply *psy,
  					 enum power_supply_property psp,
  					 union power_supply_propval *val)
  {
  	struct acpi_battery *battery = to_acpi_battery(psy);
  
  	if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT)
  		return -ENODEV;
1dd5c715e   Lan Tianyu   ACPI / SBS: Add g...
186
187
  
  	acpi_battery_get_state(battery);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
188
189
  	switch (psp) {
  	case POWER_SUPPLY_PROP_STATUS:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
190
  		if (battery->rate_now < 0)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
191
  			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
192
  		else if (battery->rate_now > 0)
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
193
194
195
196
197
198
199
200
201
202
  			val->intval = POWER_SUPPLY_STATUS_CHARGING;
  		else
  			val->intval = POWER_SUPPLY_STATUS_FULL;
  		break;
  	case POWER_SUPPLY_PROP_PRESENT:
  		val->intval = battery->present;
  		break;
  	case POWER_SUPPLY_PROP_TECHNOLOGY:
  		val->intval = acpi_battery_technology(battery);
  		break;
16698857f   Alexey Starikovskiy   ACPI: SBS: Export...
203
204
205
  	case POWER_SUPPLY_PROP_CYCLE_COUNT:
  		val->intval = battery->cycle_count;
  		break;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
206
207
208
209
210
211
212
213
214
  	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
  		val->intval = battery->design_voltage *
  			acpi_battery_vscale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
  		val->intval = battery->voltage_now *
  				acpi_battery_vscale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_NOW:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
215
216
  	case POWER_SUPPLY_PROP_POWER_NOW:
  		val->intval = abs(battery->rate_now) *
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
217
  				acpi_battery_ipscale(battery) * 1000;
e4108292c   Lan Tianyu   ACPI / SBS: Corre...
218
219
220
  		val->intval *= (acpi_battery_mode(battery)) ?
  				(battery->voltage_now *
  				acpi_battery_vscale(battery) / 1000) : 1;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
221
222
  		break;
  	case POWER_SUPPLY_PROP_CURRENT_AVG:
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
223
224
  	case POWER_SUPPLY_PROP_POWER_AVG:
  		val->intval = abs(battery->rate_avg) *
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
225
  				acpi_battery_ipscale(battery) * 1000;
e4108292c   Lan Tianyu   ACPI / SBS: Corre...
226
227
228
  		val->intval *= (acpi_battery_mode(battery)) ?
  				(battery->voltage_now *
  				acpi_battery_vscale(battery) / 1000) : 1;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
  		break;
  	case POWER_SUPPLY_PROP_CAPACITY:
  		val->intval = battery->state_of_charge;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
  	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
  		val->intval = battery->design_capacity *
  			acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_FULL:
  	case POWER_SUPPLY_PROP_ENERGY_FULL:
  		val->intval = battery->full_charge_capacity *
  			acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_CHARGE_NOW:
  	case POWER_SUPPLY_PROP_ENERGY_NOW:
  		val->intval = battery->capacity_now *
  				acpi_battery_scale(battery) * 1000;
  		break;
  	case POWER_SUPPLY_PROP_TEMP:
  		val->intval = battery->temp_now - 2730;	// dK -> dC
  		break;
  	case POWER_SUPPLY_PROP_MODEL_NAME:
  		val->strval = battery->device_name;
  		break;
  	case POWER_SUPPLY_PROP_MANUFACTURER:
  		val->strval = battery->manufacturer_name;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  static enum power_supply_property sbs_ac_props[] = {
  	POWER_SUPPLY_PROP_ONLINE,
  };
  
  static enum power_supply_property sbs_charge_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
16698857f   Alexey Starikovskiy   ACPI: SBS: Export...
271
  	POWER_SUPPLY_PROP_CYCLE_COUNT,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CURRENT_AVG,
  	POWER_SUPPLY_PROP_CAPACITY,
  	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
  	POWER_SUPPLY_PROP_CHARGE_FULL,
  	POWER_SUPPLY_PROP_CHARGE_NOW,
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
  };
  
  static enum power_supply_property sbs_energy_battery_props[] = {
  	POWER_SUPPLY_PROP_STATUS,
  	POWER_SUPPLY_PROP_PRESENT,
  	POWER_SUPPLY_PROP_TECHNOLOGY,
  	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
  	POWER_SUPPLY_PROP_VOLTAGE_NOW,
  	POWER_SUPPLY_PROP_CURRENT_NOW,
  	POWER_SUPPLY_PROP_CURRENT_AVG,
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
293
294
  	POWER_SUPPLY_PROP_POWER_NOW,
  	POWER_SUPPLY_PROP_POWER_AVG,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
295
296
297
298
299
300
301
302
  	POWER_SUPPLY_PROP_CAPACITY,
  	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
  	POWER_SUPPLY_PROP_ENERGY_FULL,
  	POWER_SUPPLY_PROP_ENERGY_NOW,
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_MODEL_NAME,
  	POWER_SUPPLY_PROP_MANUFACTURER,
  };
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
303

94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
304

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
305
306
307
  /* --------------------------------------------------------------------------
                              Smart Battery System Management
     -------------------------------------------------------------------------- */
3f86b8324   Rich Townsend   ACPI: add support...
308

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
309
310
311
312
313
  struct acpi_battery_reader {
  	u8 command;		/* command for battery */
  	u8 mode;		/* word or block? */
  	size_t offset;		/* offset inside struct acpi_sbs_battery */
  };
3f86b8324   Rich Townsend   ACPI: add support...
314

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
315
316
317
318
319
320
321
322
323
324
325
326
327
  static struct acpi_battery_reader info_readers[] = {
  	{0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
  	{0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
  	{0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
  	{0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
  	{0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
  	{0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
  	{0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
  	{0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
  	{0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
  	{0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
  	{0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
  };
3f86b8324   Rich Townsend   ACPI: add support...
328

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
329
330
331
  static struct acpi_battery_reader state_readers[] = {
  	{0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
  	{0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
332
333
  	{0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)},
  	{0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)},
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
334
335
336
337
  	{0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
  	{0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
  	{0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
  };
3f86b8324   Rich Townsend   ACPI: add support...
338

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
339
  static int acpi_manager_get_info(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
340
  {
3f86b8324   Rich Townsend   ACPI: add support...
341
  	int result = 0;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
342
  	u16 battery_system_info;
3f86b8324   Rich Townsend   ACPI: add support...
343

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
344
  	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
345
  				 0x04, (u8 *)&battery_system_info);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
346
347
  	if (!result)
  		sbs->batteries_supported = battery_system_info & 0x000f;
635227ee8   Len Brown   ACPI: remove func...
348
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
349
350
351
352
  }
  
  static int acpi_battery_get_info(struct acpi_battery *battery)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
353
  	int i, result = 0;
3f86b8324   Rich Townsend   ACPI: add support...
354

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
355
  	for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
356
357
358
359
360
361
  		result = acpi_smbus_read(battery->sbs->hc,
  					 info_readers[i].mode,
  					 ACPI_SBS_BATTERY,
  					 info_readers[i].command,
  					 (u8 *) battery +
  						info_readers[i].offset);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
362
363
  		if (result)
  			break;
3f86b8324   Rich Townsend   ACPI: add support...
364
  	}
635227ee8   Len Brown   ACPI: remove func...
365
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
366
  }
3f86b8324   Rich Townsend   ACPI: add support...
367
368
  static int acpi_battery_get_state(struct acpi_battery *battery)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
369
  	int i, result = 0;
3f86b8324   Rich Townsend   ACPI: add support...
370

94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
371
372
  	if (battery->update_time &&
  	    time_before(jiffies, battery->update_time +
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
373
374
375
376
377
378
379
380
381
382
  				msecs_to_jiffies(cache_time)))
  		return 0;
  	for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
  		result = acpi_smbus_read(battery->sbs->hc,
  					 state_readers[i].mode,
  					 ACPI_SBS_BATTERY,
  					 state_readers[i].command,
  				         (u8 *)battery +
  						state_readers[i].offset);
  		if (result)
3f86b8324   Rich Townsend   ACPI: add support...
383
  			goto end;
3f86b8324   Rich Townsend   ACPI: add support...
384
  	}
3f86b8324   Rich Townsend   ACPI: add support...
385
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
386
  	battery->update_time = jiffies;
635227ee8   Len Brown   ACPI: remove func...
387
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
388
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
389
  static int acpi_battery_get_alarm(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
390
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
391
392
  	return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
  				 ACPI_SBS_BATTERY, 0x01,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
393
  				 (u8 *)&battery->alarm_capacity);
3f86b8324   Rich Townsend   ACPI: add support...
394
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
395
  static int acpi_battery_set_alarm(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
396
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
397
  	struct acpi_sbs *sbs = battery->sbs;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
398
399
400
  	u16 value, sel = 1 << (battery->id + 12);
  
  	int ret;
3f86b8324   Rich Townsend   ACPI: add support...
401

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
402
  	if (sbs->manager_present) {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
403
  		ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
404
  				0x01, (u8 *)&value);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
405
406
407
408
409
410
411
412
413
414
415
  		if (ret)
  			goto end;
  		if ((value & 0xf000) != sel) {
  			value &= 0x0fff;
  			value |= sel;
  		ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
  					 ACPI_SBS_MANAGER,
  					 0x01, (u8 *)&value, 2);
  		if (ret)
  			goto end;
  		}
3f86b8324   Rich Townsend   ACPI: add support...
416
  	}
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
417
418
419
420
  	ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
  				0x01, (u8 *)&battery->alarm_capacity, 2);
        end:
  	return ret;
3f86b8324   Rich Townsend   ACPI: add support...
421
422
423
424
  }
  
  static int acpi_ac_get_present(struct acpi_sbs *sbs)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
425
426
  	int result;
  	u16 status;
3f86b8324   Rich Townsend   ACPI: add support...
427

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
428
429
430
431
  	result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
  				 0x13, (u8 *) & status);
  	if (!result)
  		sbs->charger_present = (status >> 15) & 0x1;
635227ee8   Len Brown   ACPI: remove func...
432
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
433
  }
8bd955320   Alexey Starikovskiy   ACPI: SBS: Add sy...
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  static ssize_t acpi_battery_alarm_show(struct device *dev,
  					struct device_attribute *attr,
  					char *buf)
  {
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
  	acpi_battery_get_alarm(battery);
  	return sprintf(buf, "%d
  ", battery->alarm_capacity *
  				acpi_battery_scale(battery) * 1000);
  }
  
  static ssize_t acpi_battery_alarm_store(struct device *dev,
  					struct device_attribute *attr,
  					const char *buf, size_t count)
  {
  	unsigned long x;
  	struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
  	if (sscanf(buf, "%ld
  ", &x) == 1)
  		battery->alarm_capacity = x /
  			(1000 * acpi_battery_scale(battery));
  	if (battery->present)
  		acpi_battery_set_alarm(battery);
  	return count;
  }
  
  static struct device_attribute alarm_attr = {
01e8ef11b   Parag Warudkar   x86: sysfs: kill ...
461
  	.attr = {.name = "alarm", .mode = 0644},
8bd955320   Alexey Starikovskiy   ACPI: SBS: Add sy...
462
463
464
  	.show = acpi_battery_alarm_show,
  	.store = acpi_battery_alarm_store,
  };
3f86b8324   Rich Townsend   ACPI: add support...
465
466
467
  /* --------------------------------------------------------------------------
                                FS Interface (/proc/acpi)
     -------------------------------------------------------------------------- */
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
468
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
469
  /* Generic Routines */
3f86b8324   Rich Townsend   ACPI: add support...
470
  static int
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
471
  acpi_sbs_add_fs(struct proc_dir_entry **dir,
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
472
473
  		struct proc_dir_entry *parent_dir,
  		char *dir_name,
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
474
475
476
  		const struct file_operations *info_fops,
  		const struct file_operations *state_fops,
  		const struct file_operations *alarm_fops, void *data)
3f86b8324   Rich Townsend   ACPI: add support...
477
  {
6d855fcdd   Zhang Rui   ACPI: delete CONF...
478
479
480
  	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded,"
  			" please retry with CONFIG_ACPI_PROCFS_POWER cleared
  ");
3f86b8324   Rich Townsend   ACPI: add support...
481
482
483
  	if (!*dir) {
  		*dir = proc_mkdir(dir_name, parent_dir);
  		if (!*dir) {
635227ee8   Len Brown   ACPI: remove func...
484
  			return -ENODEV;
3f86b8324   Rich Townsend   ACPI: add support...
485
  		}
3f86b8324   Rich Townsend   ACPI: add support...
486
487
488
  	}
  
  	/* 'info' [R] */
cf7acfab0   Denis V. Lunev   acpi: use non-rac...
489
490
491
  	if (info_fops)
  		proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir,
  				 info_fops, data);
3f86b8324   Rich Townsend   ACPI: add support...
492
493
  
  	/* 'state' [R] */
cf7acfab0   Denis V. Lunev   acpi: use non-rac...
494
495
496
  	if (state_fops)
  		proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir,
  				 state_fops, data);
3f86b8324   Rich Townsend   ACPI: add support...
497
498
  
  	/* 'alarm' [R/W] */
cf7acfab0   Denis V. Lunev   acpi: use non-rac...
499
500
501
  	if (alarm_fops)
  		proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir,
  				 alarm_fops, data);
635227ee8   Len Brown   ACPI: remove func...
502
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
503
504
505
  }
  
  static void
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
506
  acpi_sbs_remove_fs(struct proc_dir_entry **dir,
3f86b8324   Rich Townsend   ACPI: add support...
507
508
  			   struct proc_dir_entry *parent_dir)
  {
3f86b8324   Rich Townsend   ACPI: add support...
509
510
511
512
513
514
515
  	if (*dir) {
  		remove_proc_entry(ACPI_SBS_FILE_INFO, *dir);
  		remove_proc_entry(ACPI_SBS_FILE_STATE, *dir);
  		remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir);
  		remove_proc_entry((*dir)->name, parent_dir);
  		*dir = NULL;
  	}
3f86b8324   Rich Townsend   ACPI: add support...
516
517
518
  }
  
  /* Smart Battery Interface */
3f86b8324   Rich Townsend   ACPI: add support...
519
  static struct proc_dir_entry *acpi_battery_dir = NULL;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
520
521
  static inline char *acpi_battery_units(struct acpi_battery *battery)
  {
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
522
  	return acpi_battery_mode(battery) ? " mW" : " mA";
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
523
  }
3f86b8324   Rich Townsend   ACPI: add support...
524
525
  static int acpi_battery_read_info(struct seq_file *seq, void *offset)
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
526
  	struct acpi_battery *battery = seq->private;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
527
  	struct acpi_sbs *sbs = battery->sbs;
3f86b8324   Rich Townsend   ACPI: add support...
528
  	int result = 0;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
529
  	mutex_lock(&sbs->lock);
3f86b8324   Rich Townsend   ACPI: add support...
530

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
531
532
533
534
  	seq_printf(seq, "present:                 %s
  ",
  		   (battery->present) ? "yes" : "no");
  	if (!battery->present)
722062334   Vladimir Lebedev   ACPI: sbs: Common...
535
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
536

5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
537
538
  	seq_printf(seq, "design capacity:         %i%sh
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
539
540
  		   battery->design_capacity * acpi_battery_scale(battery),
  		   acpi_battery_units(battery));
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
541
542
  	seq_printf(seq, "last full capacity:      %i%sh
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
543
544
  		   battery->full_charge_capacity * acpi_battery_scale(battery),
  		   acpi_battery_units(battery));
3f86b8324   Rich Townsend   ACPI: add support...
545
546
  	seq_printf(seq, "battery technology:      rechargeable
  ");
3f86b8324   Rich Townsend   ACPI: add support...
547
548
  	seq_printf(seq, "design voltage:          %i mV
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
549
  		   battery->design_voltage * acpi_battery_vscale(battery));
3f86b8324   Rich Townsend   ACPI: add support...
550
551
552
553
  	seq_printf(seq, "design capacity warning: unknown
  ");
  	seq_printf(seq, "design capacity low:     unknown
  ");
16698857f   Alexey Starikovskiy   ACPI: SBS: Export...
554
555
  	seq_printf(seq, "cycle count:		  %i
  ", battery->cycle_count);
3f86b8324   Rich Townsend   ACPI: add support...
556
557
558
559
  	seq_printf(seq, "capacity granularity 1:  unknown
  ");
  	seq_printf(seq, "capacity granularity 2:  unknown
  ");
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
560
561
  	seq_printf(seq, "model number:            %s
  ", battery->device_name);
3f86b8324   Rich Townsend   ACPI: add support...
562
563
  	seq_printf(seq, "serial number:           %i
  ",
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
564
  		   battery->serial_number);
3f86b8324   Rich Townsend   ACPI: add support...
565
566
  	seq_printf(seq, "battery type:            %s
  ",
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
567
  		   battery->device_chemistry);
3f86b8324   Rich Townsend   ACPI: add support...
568
569
  	seq_printf(seq, "OEM info:                %s
  ",
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
570
  		   battery->manufacturer_name);
3f86b8324   Rich Townsend   ACPI: add support...
571
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
572
  	mutex_unlock(&sbs->lock);
635227ee8   Len Brown   ACPI: remove func...
573
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
574
575
576
577
578
579
580
581
582
  }
  
  static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_battery_read_info, PDE(inode)->data);
  }
  
  static int acpi_battery_read_state(struct seq_file *seq, void *offset)
  {
722062334   Vladimir Lebedev   ACPI: sbs: Common...
583
584
  	struct acpi_battery *battery = seq->private;
  	struct acpi_sbs *sbs = battery->sbs;
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
585
  	int rate;
3f86b8324   Rich Townsend   ACPI: add support...
586

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
587
588
589
590
591
  	mutex_lock(&sbs->lock);
  	seq_printf(seq, "present:                 %s
  ",
  		   (battery->present) ? "yes" : "no");
  	if (!battery->present)
3f86b8324   Rich Townsend   ACPI: add support...
592
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
593

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
594
595
596
597
598
599
  	acpi_battery_get_state(battery);
  	seq_printf(seq, "capacity state:          %s
  ",
  		   (battery->state & 0x0010) ? "critical" : "ok");
  	seq_printf(seq, "charging state:          %s
  ",
7faa144a5   Alexey Starikovskiy   ACPI: battery: ad...
600
601
602
  		   (battery->rate_now < 0) ? "discharging" :
  		   ((battery->rate_now > 0) ? "charging" : "charged"));
  	rate = abs(battery->rate_now) * acpi_battery_ipscale(battery);
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
603
604
605
606
607
608
609
  	rate *= (acpi_battery_mode(battery))?(battery->voltage_now *
  			acpi_battery_vscale(battery)/1000):1;
  	seq_printf(seq, "present rate:            %d%s
  ", rate,
  		   acpi_battery_units(battery));
  	seq_printf(seq, "remaining capacity:      %i%sh
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
610
611
  		   battery->capacity_now * acpi_battery_scale(battery),
  		   acpi_battery_units(battery));
3f86b8324   Rich Townsend   ACPI: add support...
612
613
  	seq_printf(seq, "present voltage:         %i mV
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
614
  		   battery->voltage_now * acpi_battery_vscale(battery));
3f86b8324   Rich Townsend   ACPI: add support...
615
616
  
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
617
  	mutex_unlock(&sbs->lock);
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
618
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
619
620
621
622
623
624
625
626
627
  }
  
  static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_battery_read_state, PDE(inode)->data);
  }
  
  static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
628
  	struct acpi_battery *battery = seq->private;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
629
  	struct acpi_sbs *sbs = battery->sbs;
3f86b8324   Rich Townsend   ACPI: add support...
630
  	int result = 0;
3f86b8324   Rich Townsend   ACPI: add support...
631

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
632
  	mutex_lock(&sbs->lock);
3f86b8324   Rich Townsend   ACPI: add support...
633

89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
634
  	if (!battery->present) {
3f86b8324   Rich Townsend   ACPI: add support...
635
636
637
638
  		seq_printf(seq, "present:                 no
  ");
  		goto end;
  	}
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
639
  	acpi_battery_get_alarm(battery);
3f86b8324   Rich Townsend   ACPI: add support...
640
  	seq_printf(seq, "alarm:                   ");
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
641
  	if (battery->alarm_capacity)
5a21e4fe5   Alexey Starikovskiy   ACPI: SBS: Return...
642
643
  		seq_printf(seq, "%i%sh
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
644
645
646
647
  			   battery->alarm_capacity *
  			   acpi_battery_scale(battery),
  			   acpi_battery_units(battery));
  	else
3f86b8324   Rich Townsend   ACPI: add support...
648
649
  		seq_printf(seq, "disabled
  ");
3f86b8324   Rich Townsend   ACPI: add support...
650
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
651
  	mutex_unlock(&sbs->lock);
635227ee8   Len Brown   ACPI: remove func...
652
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
653
654
655
656
657
658
  }
  
  static ssize_t
  acpi_battery_write_alarm(struct file *file, const char __user * buffer,
  			 size_t count, loff_t * ppos)
  {
50dd09697   Jan Engelhardt   ACPI: Remove unne...
659
660
  	struct seq_file *seq = file->private_data;
  	struct acpi_battery *battery = seq->private;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
661
  	struct acpi_sbs *sbs = battery->sbs;
3f86b8324   Rich Townsend   ACPI: add support...
662
  	char alarm_string[12] = { '\0' };
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
663
664
  	int result = 0;
  	mutex_lock(&sbs->lock);
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
665
  	if (!battery->present) {
3f86b8324   Rich Townsend   ACPI: add support...
666
667
668
  		result = -ENODEV;
  		goto end;
  	}
3f86b8324   Rich Townsend   ACPI: add support...
669
670
671
672
  	if (count > sizeof(alarm_string) - 1) {
  		result = -EINVAL;
  		goto end;
  	}
3f86b8324   Rich Townsend   ACPI: add support...
673
674
675
676
  	if (copy_from_user(alarm_string, buffer, count)) {
  		result = -EFAULT;
  		goto end;
  	}
3f86b8324   Rich Townsend   ACPI: add support...
677
  	alarm_string[count] = 0;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
678
679
  	battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
  					acpi_battery_scale(battery);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
680
  	acpi_battery_set_alarm(battery);
3f86b8324   Rich Townsend   ACPI: add support...
681
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
682
683
  	mutex_unlock(&sbs->lock);
  	if (result)
635227ee8   Len Brown   ACPI: remove func...
684
  		return result;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
685
  	return count;
3f86b8324   Rich Townsend   ACPI: add support...
686
687
688
689
690
691
  }
  
  static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
  }
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
692
  static const struct file_operations acpi_battery_info_fops = {
3f86b8324   Rich Townsend   ACPI: add support...
693
694
695
696
697
698
  	.open = acpi_battery_info_open_fs,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
  	.owner = THIS_MODULE,
  };
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
699
  static const struct file_operations acpi_battery_state_fops = {
3f86b8324   Rich Townsend   ACPI: add support...
700
701
702
703
704
705
  	.open = acpi_battery_state_open_fs,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
  	.owner = THIS_MODULE,
  };
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
706
  static const struct file_operations acpi_battery_alarm_fops = {
3f86b8324   Rich Townsend   ACPI: add support...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
  	.open = acpi_battery_alarm_open_fs,
  	.read = seq_read,
  	.write = acpi_battery_write_alarm,
  	.llseek = seq_lseek,
  	.release = single_release,
  	.owner = THIS_MODULE,
  };
  
  /* Legacy AC Adapter Interface */
  
  static struct proc_dir_entry *acpi_ac_dir = NULL;
  
  static int acpi_ac_read_state(struct seq_file *seq, void *offset)
  {
3f86b8324   Rich Townsend   ACPI: add support...
721

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
722
  	struct acpi_sbs *sbs = seq->private;
3f86b8324   Rich Townsend   ACPI: add support...
723

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
724
  	mutex_lock(&sbs->lock);
3f86b8324   Rich Townsend   ACPI: add support...
725
726
727
  
  	seq_printf(seq, "state:                   %s
  ",
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
728
  		   sbs->charger_present ? "on-line" : "off-line");
3f86b8324   Rich Townsend   ACPI: add support...
729

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
730
  	mutex_unlock(&sbs->lock);
635227ee8   Len Brown   ACPI: remove func...
731
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
732
733
734
735
736
737
  }
  
  static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
  {
  	return single_open(file, acpi_ac_read_state, PDE(inode)->data);
  }
070d8eb1f   Jan Engelhardt   ACPI: constify VF...
738
  static const struct file_operations acpi_ac_state_fops = {
3f86b8324   Rich Townsend   ACPI: add support...
739
740
741
742
743
744
  	.open = acpi_ac_state_open_fs,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
  	.owner = THIS_MODULE,
  };
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
745
  #endif
3f86b8324   Rich Townsend   ACPI: add support...
746
747
748
  /* --------------------------------------------------------------------------
                                   Driver Interface
     -------------------------------------------------------------------------- */
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
749
  static int acpi_battery_read(struct acpi_battery *battery)
3f86b8324   Rich Townsend   ACPI: add support...
750
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
751
752
  	int result = 0, saved_present = battery->present;
  	u16 state;
3f86b8324   Rich Townsend   ACPI: add support...
753

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
754
755
756
757
758
759
760
761
762
763
764
765
766
  	if (battery->sbs->manager_present) {
  		result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
  				ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
  		if (!result)
  			battery->present = state & (1 << battery->id);
  		state &= 0x0fff;
  		state |= 1 << (battery->id + 12);
  		acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
  				  ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
  	} else if (battery->id == 0)
  		battery->present = 1;
  	if (result || !battery->present)
  		return result;
3f86b8324   Rich Townsend   ACPI: add support...
767

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
768
769
770
771
772
773
774
775
776
  	if (saved_present != battery->present) {
  		battery->update_time = 0;
  		result = acpi_battery_get_info(battery);
  		if (result)
  			return result;
  	}
  	result = acpi_battery_get_state(battery);
  	return result;
  }
3f86b8324   Rich Townsend   ACPI: add support...
777

94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
778
  /* Smart Battery */
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
779
780
  static int acpi_battery_add(struct acpi_sbs *sbs, int id)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
781
  	struct acpi_battery *battery = &sbs->battery[id];
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
782
  	int result;
3f86b8324   Rich Townsend   ACPI: add support...
783
784
  	battery->id = id;
  	battery->sbs = sbs;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
785
786
787
  	result = acpi_battery_read(battery);
  	if (result)
  		return result;
3f86b8324   Rich Townsend   ACPI: add support...
788

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
789
  	sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
790
  #ifdef CONFIG_ACPI_PROCFS_POWER
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
791
792
793
794
  	acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
  			battery->name, &acpi_battery_info_fops,
  			&acpi_battery_state_fops, &acpi_battery_alarm_fops,
  			battery);
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
795
  #endif
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
796
797
798
799
800
801
802
803
804
805
806
807
808
  	battery->bat.name = battery->name;
  	battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
  	if (!acpi_battery_mode(battery)) {
  		battery->bat.properties = sbs_charge_battery_props;
  		battery->bat.num_properties =
  		    ARRAY_SIZE(sbs_charge_battery_props);
  	} else {
  		battery->bat.properties = sbs_energy_battery_props;
  		battery->bat.num_properties =
  		    ARRAY_SIZE(sbs_energy_battery_props);
  	}
  	battery->bat.get_property = acpi_sbs_battery_get_property;
  	result = power_supply_register(&sbs->device->dev, &battery->bat);
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
809
810
811
812
813
814
815
  	if (result)
  		goto end;
  	result = device_create_file(battery->bat.dev, &alarm_attr);
  	if (result)
  		goto end;
  	battery->have_sysfs_alarm = 1;
        end:
722062334   Vladimir Lebedev   ACPI: sbs: Common...
816
817
  	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)
  ",
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
818
  	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
bbafbecb2   Alexey Starikovskiy   ACPI: SBS: Host c...
819
  	       battery->name, battery->present ? "present" : "absent");
635227ee8   Len Brown   ACPI: remove func...
820
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
821
822
823
824
  }
  
  static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
  {
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
825
  	struct acpi_battery *battery = &sbs->battery[id];
c19bdb612   Rakib Mullick   ACPI: Fix unused ...
826

037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
827
828
829
830
  	if (battery->bat.dev) {
  		if (battery->have_sysfs_alarm)
  			device_remove_file(battery->bat.dev, &alarm_attr);
  		power_supply_unregister(&battery->bat);
3f86b8324   Rich Townsend   ACPI: add support...
831
  	}
c2e46d2e2   Len Brown   Pull procfs-defau...
832
  #ifdef CONFIG_ACPI_PROCFS_POWER
037cbc63f   Jeff Garzik   ACPI: SBS: Fix re...
833
834
  	if (battery->proc_entry)
  		acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
835
  #endif
3f86b8324   Rich Townsend   ACPI: add support...
836
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
837
  static int acpi_charger_add(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
838
839
  {
  	int result;
3f86b8324   Rich Townsend   ACPI: add support...
840
  	result = acpi_ac_get_present(sbs);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
841
  	if (result)
3f86b8324   Rich Townsend   ACPI: add support...
842
  		goto end;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
843
  #ifdef CONFIG_ACPI_PROCFS_POWER
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
844
845
846
847
  	result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
  				 ACPI_AC_DIR_NAME, NULL,
  				 &acpi_ac_state_fops, NULL, sbs);
  	if (result)
3f86b8324   Rich Townsend   ACPI: add support...
848
  		goto end;
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
849
  #endif
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
850
851
852
853
854
855
  	sbs->charger.name = "sbs-charger";
  	sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
  	sbs->charger.properties = sbs_ac_props;
  	sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
  	sbs->charger.get_property = sbs_get_ac_property;
  	power_supply_register(&sbs->device->dev, &sbs->charger);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
856
857
858
  	printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)
  ",
  	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
89862e3be   Alexey Starikovskiy   ACPI: SBS: Simpli...
859
  	       ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
3f86b8324   Rich Townsend   ACPI: add support...
860
        end:
635227ee8   Len Brown   ACPI: remove func...
861
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
862
  }
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
863
  static void acpi_charger_remove(struct acpi_sbs *sbs)
3f86b8324   Rich Townsend   ACPI: add support...
864
  {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
865
866
  	if (sbs->charger.dev)
  		power_supply_unregister(&sbs->charger);
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
867
  #ifdef CONFIG_ACPI_PROCFS_POWER
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
868
869
  	if (sbs->charger_entry)
  		acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
870
  #endif
3f86b8324   Rich Townsend   ACPI: add support...
871
  }
e5685b9d3   Adrian Bunk   ACPI: misc cleanups
872
  static void acpi_sbs_callback(void *context)
3f86b8324   Rich Townsend   ACPI: add support...
873
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
874
875
876
877
878
879
880
  	int id;
  	struct acpi_sbs *sbs = context;
  	struct acpi_battery *bat;
  	u8 saved_charger_state = sbs->charger_present;
  	u8 saved_battery_state;
  	acpi_ac_get_present(sbs);
  	if (sbs->charger_present != saved_charger_state) {
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
881
  #ifdef CONFIG_ACPI_PROC_EVENT
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
882
883
884
  		acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
  					      ACPI_SBS_NOTIFY_STATUS,
  					      sbs->charger_present);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
885
886
  #endif
  		kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
3f86b8324   Rich Townsend   ACPI: add support...
887
  	}
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
888
889
890
891
892
893
894
895
896
  	if (sbs->manager_present) {
  		for (id = 0; id < MAX_SBS_BAT; ++id) {
  			if (!(sbs->batteries_supported & (1 << id)))
  				continue;
  			bat = &sbs->battery[id];
  			saved_battery_state = bat->present;
  			acpi_battery_read(bat);
  			if (saved_battery_state == bat->present)
  				continue;
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
897
  #ifdef CONFIG_ACPI_PROC_EVENT
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
898
899
900
901
  			acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
  						      bat->name,
  						      ACPI_SBS_NOTIFY_STATUS,
  						      bat->present);
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
902
903
  #endif
  			kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
3f86b8324   Rich Townsend   ACPI: add support...
904
  		}
3f86b8324   Rich Townsend   ACPI: add support...
905
  	}
3f86b8324   Rich Townsend   ACPI: add support...
906
  }
3f86b8324   Rich Townsend   ACPI: add support...
907
908
  static int acpi_sbs_add(struct acpi_device *device)
  {
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
909
910
  	struct acpi_sbs *sbs;
  	int result = 0;
6d15702cc   Vladimir Lebedev   ACPI: sbs: use EC...
911
  	int id;
3f86b8324   Rich Townsend   ACPI: add support...
912

36bcbec7c   Burman Yan   ACPI: replace kma...
913
  	sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
3f86b8324   Rich Townsend   ACPI: add support...
914
  	if (!sbs) {
722062334   Vladimir Lebedev   ACPI: sbs: Common...
915
916
  		result = -ENOMEM;
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
917
  	}
3f86b8324   Rich Townsend   ACPI: add support...
918

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
919
  	mutex_init(&sbs->lock);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
920

91087dfa5   Alexey Starikovskiy   ACPI: SBS: Split ...
921
  	sbs->hc = acpi_driver_data(device->parent);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
922
  	sbs->device = device;
3f86b8324   Rich Townsend   ACPI: add support...
923
924
  	strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
925
  	device->driver_data = sbs;
3f86b8324   Rich Townsend   ACPI: add support...
926

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
927
  	result = acpi_charger_add(sbs);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
928
929
  	if (result)
  		goto end;
3f86b8324   Rich Townsend   ACPI: add support...
930

db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
931
932
933
934
935
936
937
938
939
  	result = acpi_manager_get_info(sbs);
  	if (!result) {
  		sbs->manager_present = 1;
  		for (id = 0; id < MAX_SBS_BAT; ++id)
  			if ((sbs->batteries_supported & (1 << id)))
  				acpi_battery_add(sbs, id);
  	} else
  		acpi_battery_add(sbs, 0);
  	acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
3f86b8324   Rich Townsend   ACPI: add support...
940
        end:
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
941
942
  	if (result)
  		acpi_sbs_remove(device, 0);
635227ee8   Len Brown   ACPI: remove func...
943
  	return result;
3f86b8324   Rich Townsend   ACPI: add support...
944
  }
722062334   Vladimir Lebedev   ACPI: sbs: Common...
945
  static int acpi_sbs_remove(struct acpi_device *device, int type)
3f86b8324   Rich Townsend   ACPI: add support...
946
  {
cece90148   Len Brown   Pull style into t...
947
  	struct acpi_sbs *sbs;
3f86b8324   Rich Townsend   ACPI: add support...
948
  	int id;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
949
  	if (!device)
963497c12   Lebedev, Vladimir P   ACPI: sbs: check ...
950
  		return -EINVAL;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
951
  	sbs = acpi_driver_data(device);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
952
  	if (!sbs)
635227ee8   Len Brown   ACPI: remove func...
953
  		return -EINVAL;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
954
955
956
  	mutex_lock(&sbs->lock);
  	acpi_smbus_unregister_callback(sbs->hc);
  	for (id = 0; id < MAX_SBS_BAT; ++id)
3f86b8324   Rich Townsend   ACPI: add support...
957
  		acpi_battery_remove(sbs, id);
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
958
959
960
  	acpi_charger_remove(sbs);
  	mutex_unlock(&sbs->lock);
  	mutex_destroy(&sbs->lock);
3f86b8324   Rich Townsend   ACPI: add support...
961
  	kfree(sbs);
635227ee8   Len Brown   ACPI: remove func...
962
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
963
  }
722062334   Vladimir Lebedev   ACPI: sbs: Common...
964
965
  static void acpi_sbs_rmdirs(void)
  {
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
966
  #ifdef CONFIG_ACPI_PROCFS_POWER
722062334   Vladimir Lebedev   ACPI: sbs: Common...
967
968
969
970
971
972
973
974
  	if (acpi_ac_dir) {
  		acpi_unlock_ac_dir(acpi_ac_dir);
  		acpi_ac_dir = NULL;
  	}
  	if (acpi_battery_dir) {
  		acpi_unlock_battery_dir(acpi_battery_dir);
  		acpi_battery_dir = NULL;
  	}
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
975
  #endif
722062334   Vladimir Lebedev   ACPI: sbs: Common...
976
977
978
979
980
  }
  
  static int acpi_sbs_resume(struct acpi_device *device)
  {
  	struct acpi_sbs *sbs;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
981
982
  	if (!device)
  		return -EINVAL;
722062334   Vladimir Lebedev   ACPI: sbs: Common...
983
  	sbs = device->driver_data;
db1c291af   Alexey Starikovskiy   ACPI: SBS: Make S...
984
  	acpi_sbs_callback(sbs);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
985
986
  	return 0;
  }
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
987
988
989
990
991
992
993
994
995
996
  static struct acpi_driver acpi_sbs_driver = {
  	.name = "sbs",
  	.class = ACPI_SBS_CLASS,
  	.ids = sbs_device_ids,
  	.ops = {
  		.add = acpi_sbs_add,
  		.remove = acpi_sbs_remove,
  		.resume = acpi_sbs_resume,
  		},
  };
3f86b8324   Rich Townsend   ACPI: add support...
997
998
999
  static int __init acpi_sbs_init(void)
  {
  	int result = 0;
b20d2aeb0   Len Brown   ACPI: skip smart ...
1000
1001
  	if (acpi_disabled)
  		return -ENODEV;
fdcedbba2   Alexey Starikovskiy   ACPI: Split out c...
1002
  #ifdef CONFIG_ACPI_PROCFS_POWER
3f86b8324   Rich Townsend   ACPI: add support...
1003
  	acpi_ac_dir = acpi_lock_ac_dir();
94f6c0860   Alexey Starikovskiy   ACPI: SBS: Add su...
1004
  	if (!acpi_ac_dir)
635227ee8   Len Brown   ACPI: remove func...
1005
  		return -ENODEV;
3f86b8324   Rich Townsend   ACPI: add support...
1006
1007
  	acpi_battery_dir = acpi_lock_battery_dir();
  	if (!acpi_battery_dir) {
722062334   Vladimir Lebedev   ACPI: sbs: Common...
1008
  		acpi_sbs_rmdirs();
635227ee8   Len Brown   ACPI: remove func...
1009
  		return -ENODEV;
3f86b8324   Rich Townsend   ACPI: add support...
1010
  	}
66e4b72bf   Alexey Starikovskiy   ACPI: SBS: Add AC...
1011
  #endif
3f86b8324   Rich Townsend   ACPI: add support...
1012
1013
  	result = acpi_bus_register_driver(&acpi_sbs_driver);
  	if (result < 0) {
722062334   Vladimir Lebedev   ACPI: sbs: Common...
1014
  		acpi_sbs_rmdirs();
635227ee8   Len Brown   ACPI: remove func...
1015
  		return -ENODEV;
3f86b8324   Rich Townsend   ACPI: add support...
1016
  	}
635227ee8   Len Brown   ACPI: remove func...
1017
  	return 0;
3f86b8324   Rich Townsend   ACPI: add support...
1018
1019
1020
1021
  }
  
  static void __exit acpi_sbs_exit(void)
  {
3f86b8324   Rich Townsend   ACPI: add support...
1022
  	acpi_bus_unregister_driver(&acpi_sbs_driver);
722062334   Vladimir Lebedev   ACPI: sbs: Common...
1023
  	acpi_sbs_rmdirs();
635227ee8   Len Brown   ACPI: remove func...
1024
  	return;
3f86b8324   Rich Townsend   ACPI: add support...
1025
1026
1027
1028
  }
  
  module_init(acpi_sbs_init);
  module_exit(acpi_sbs_exit);