aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/sbs.c
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-09-26 11:43:41 -0400
committerLen Brown <len.brown@intel.com>2007-09-27 15:50:22 -0400
commitdb1c291af7ad748777371f25b9ff92e3e5aba38e (patch)
tree6d80e183b881e4fb3879d32d813a9d617070df66 /drivers/acpi/sbs.c
parent89862e3be1ba387c738fc2c3a5875cfd7e51c5a8 (diff)
ACPI: SBS: Make SBS reads table-driven.
Re-factor SBS functions to use tables and cycles for repeated operations. Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/sbs.c')
-rw-r--r--drivers/acpi/sbs.c1292
1 files changed, 275 insertions, 1017 deletions
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index f35fe63cef3d..3351dea11ff0 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) 2 * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $)
3 * 3 *
4 * Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
5 * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
4 * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> 6 * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu>
5 * 7 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -46,53 +48,34 @@
46#define ACPI_SBS_FILE_ALARM "alarm" 48#define ACPI_SBS_FILE_ALARM "alarm"
47#define ACPI_BATTERY_DIR_NAME "BAT%i" 49#define ACPI_BATTERY_DIR_NAME "BAT%i"
48#define ACPI_AC_DIR_NAME "AC0" 50#define ACPI_AC_DIR_NAME "AC0"
49#define ACPI_SBC_SMBUS_ADDR 0x9
50#define ACPI_SBSM_SMBUS_ADDR 0xa
51#define ACPI_SB_SMBUS_ADDR 0xb
52#define ACPI_SBS_AC_NOTIFY_STATUS 0x80
53#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80
54#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81
55 51
56#define _COMPONENT ACPI_SBS_COMPONENT 52enum acpi_sbs_device_addr {
53 ACPI_SBS_CHARGER = 0x9,
54 ACPI_SBS_MANAGER = 0xa,
55 ACPI_SBS_BATTERY = 0xb,
56};
57
58#define ACPI_SBS_NOTIFY_STATUS 0x80
59#define ACPI_SBS_NOTIFY_INFO 0x81
57 60
58ACPI_MODULE_NAME("sbs"); 61ACPI_MODULE_NAME("sbs");
59 62
60MODULE_AUTHOR("Rich Townsend"); 63MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
61MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); 64MODULE_DESCRIPTION("Smart Battery System ACPI interface driver");
62MODULE_LICENSE("GPL"); 65MODULE_LICENSE("GPL");
63 66
64#define DEF_CAPACITY_UNIT 3 67static unsigned int cache_time = 1000;
65#define MAH_CAPACITY_UNIT 1 68module_param(cache_time, uint, 0644);
66#define MWH_CAPACITY_UNIT 2 69MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
67#define CAPACITY_UNIT DEF_CAPACITY_UNIT
68
69#define REQUEST_UPDATE_MODE 1
70#define QUEUE_UPDATE_MODE 2
71
72#define DATA_TYPE_COMMON 0
73#define DATA_TYPE_INFO 1
74#define DATA_TYPE_STATE 2
75#define DATA_TYPE_ALARM 3
76#define DATA_TYPE_AC_STATE 4
77 70
78extern struct proc_dir_entry *acpi_lock_ac_dir(void); 71extern struct proc_dir_entry *acpi_lock_ac_dir(void);
79extern struct proc_dir_entry *acpi_lock_battery_dir(void); 72extern struct proc_dir_entry *acpi_lock_battery_dir(void);
80extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 73extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
81extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 74extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
82 75
83#define MAX_SBS_BAT 4 76#define MAX_SBS_BAT 4
84#define ACPI_SBS_BLOCK_MAX 32 77#define ACPI_SBS_BLOCK_MAX 32
85 78
86#define UPDATE_DELAY 10
87
88/* 0 - every time, > 0 - by update_time */
89static unsigned int update_time = 120;
90
91static unsigned int mode = CAPACITY_UNIT;
92
93module_param(update_time, uint, 0644);
94module_param(mode, uint, 0444);
95
96static int acpi_sbs_add(struct acpi_device *device); 79static int acpi_sbs_add(struct acpi_device *device);
97static int acpi_sbs_remove(struct acpi_device *device, int type); 80static int acpi_sbs_remove(struct acpi_device *device, int type);
98static int acpi_sbs_resume(struct acpi_device *device); 81static int acpi_sbs_resume(struct acpi_device *device);
@@ -117,486 +100,187 @@ static struct acpi_driver acpi_sbs_driver = {
117struct acpi_battery { 100struct acpi_battery {
118 struct acpi_sbs *sbs; 101 struct acpi_sbs *sbs;
119 struct proc_dir_entry *proc_entry; 102 struct proc_dir_entry *proc_entry;
120 int vscale; 103 unsigned long update_time;
121 int ipscale; 104 char name[8];
122 char manufacturer_name[ACPI_SBS_BLOCK_MAX]; 105 char manufacturer_name[ACPI_SBS_BLOCK_MAX];
123 char device_name[ACPI_SBS_BLOCK_MAX]; 106 char device_name[ACPI_SBS_BLOCK_MAX];
124 char device_chemistry[ACPI_SBS_BLOCK_MAX]; 107 char device_chemistry[ACPI_SBS_BLOCK_MAX];
108 u32 alarm_capacity;
125 u16 full_charge_capacity; 109 u16 full_charge_capacity;
126 u16 design_capacity; 110 u16 design_capacity;
127 u16 design_voltage; 111 u16 design_voltage;
128 u16 serial_number; 112 u16 serial_number;
113 u16 cycle_count;
114 u16 temp_now;
129 u16 voltage_now; 115 u16 voltage_now;
130 s16 current_now; 116 s16 current_now;
117 s16 current_avg;
131 u16 capacity_now; 118 u16 capacity_now;
119 u16 state_of_charge;
132 u16 state; 120 u16 state;
133 u16 alarm_capacity;
134 u16 mode; 121 u16 mode;
122 u16 spec;
135 u8 id; 123 u8 id;
136 u8 alive:1;
137 u8 init_state:1;
138 u8 present:1; 124 u8 present:1;
139}; 125};
140 126
141struct acpi_sbs { 127struct acpi_sbs {
142 struct acpi_device *device; 128 struct acpi_device *device;
143 struct acpi_smb_hc *hc; 129 struct acpi_smb_hc *hc;
144 struct mutex mutex; 130 struct mutex lock;
145 struct proc_dir_entry *ac_entry; 131 struct proc_dir_entry *charger_entry;
146 struct acpi_battery battery[MAX_SBS_BAT]; 132 struct acpi_battery battery[MAX_SBS_BAT];
147 int zombie; 133 u8 batteries_supported:4;
148 struct timer_list update_timer;
149 int run_cnt;
150 int update_proc_flg;
151 u8 batteries_supported;
152 u8 manager_present:1; 134 u8 manager_present:1;
153 u8 charger_present:1; 135 u8 charger_present:1;
154}; 136};
155 137
156static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); 138static inline int battery_scale(int log)
157static void acpi_sbs_update_time(void *data);
158
159static int sbs_zombie(struct acpi_sbs *sbs)
160{ 139{
161 return (sbs->zombie); 140 int scale = 1;
141 while (log--)
142 scale *= 10;
143 return scale;
162} 144}
163 145
164static int sbs_mutex_lock(struct acpi_sbs *sbs) 146static inline int acpi_battery_vscale(struct acpi_battery *battery)
165{ 147{
166 if (sbs_zombie(sbs)) { 148 return battery_scale((battery->spec & 0x0f00) >> 8);
167 return -ENODEV;
168 }
169 mutex_lock(&sbs->mutex);
170 return 0;
171} 149}
172 150
173static void sbs_mutex_unlock(struct acpi_sbs *sbs) 151static inline int acpi_battery_ipscale(struct acpi_battery *battery)
174{ 152{
175 mutex_unlock(&sbs->mutex); 153 return battery_scale((battery->spec & 0xf000) >> 12);
176} 154}
177 155
178/* -------------------------------------------------------------------------- 156static inline int acpi_battery_mode(struct acpi_battery *battery)
179 Smart Battery System Management
180 -------------------------------------------------------------------------- */
181
182static int acpi_check_update_proc(struct acpi_sbs *sbs)
183{ 157{
184 acpi_status status = AE_OK; 158 return (battery->mode & 0x8000);
185
186 if (update_time == 0) {
187 sbs->update_proc_flg = 0;
188 return 0;
189 }
190 if (sbs->update_proc_flg == 0) {
191 status = acpi_os_execute(OSL_GPE_HANDLER,
192 acpi_sbs_update_time, sbs);
193 if (status != AE_OK) {
194 ACPI_EXCEPTION((AE_INFO, status,
195 "acpi_os_execute() failed"));
196 return 1;
197 }
198 sbs->update_proc_flg = 1;
199 }
200 return 0;
201} 159}
202 160
203static int acpi_battery_get_present(struct acpi_battery *battery) 161static inline int acpi_battery_scale(struct acpi_battery *battery)
204{ 162{
205 s16 state; 163 return (acpi_battery_mode(battery) ? 10 : 1) *
206 int result = 0; 164 acpi_battery_ipscale(battery);
207 int is_present = 0;
208
209 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
210 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state);
211 if (result) {
212 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
213 "acpi_smbus_read() failed"));
214 }
215 if (!result) {
216 is_present = (state & 0x000f) & (1 << battery->id);
217 }
218 battery->present = is_present;
219
220 return result;
221} 165}
222 166
223static int acpi_battery_select(struct acpi_battery *battery) 167/* --------------------------------------------------------------------------
224{ 168 Smart Battery System Management
225 struct acpi_sbs *sbs = battery->sbs; 169 -------------------------------------------------------------------------- */
226 int result = 0;
227 s16 state;
228 int foo;
229
230 if (sbs->manager_present) {
231
232 /* Take special care not to knobble other nibbles of
233 * state (aka selector_state), since
234 * it causes charging to halt on SBSELs */
235 170
236 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, 171struct acpi_battery_reader {
237 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); 172 u8 command; /* command for battery */
238 if (result) { 173 u8 mode; /* word or block? */
239 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 174 size_t offset; /* offset inside struct acpi_sbs_battery */
240 "acpi_smbus_read() failed")); 175};
241 goto end;
242 }
243 176
244 foo = (state & 0x0fff) | (1 << (battery->id + 12)); 177static struct acpi_battery_reader info_readers[] = {
245 result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, 178 {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)},
246 ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); 179 {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)},
247 if (result) { 180 {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)},
248 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 181 {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)},
249 "acpi_smbus_write() failed")); 182 {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)},
250 goto end; 183 {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)},
251 } 184 {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)},
252 } 185 {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)},
186 {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)},
187 {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)},
188 {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)},
189};
253 190
254 end: 191static struct acpi_battery_reader state_readers[] = {
255 return result; 192 {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)},
256} 193 {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)},
194 {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)},
195 {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)},
196 {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)},
197 {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)},
198 {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)},
199};
257 200
258static int acpi_sbsm_get_info(struct acpi_sbs *sbs) 201static int acpi_manager_get_info(struct acpi_sbs *sbs)
259{ 202{
260 int result = 0; 203 int result = 0;
261 s16 battery_system_info; 204 u16 battery_system_info;
262
263 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x04,
264 (u8 *)&battery_system_info);
265 if (result) {
266 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
267 "acpi_smbus_read() failed"));
268 goto end;
269 }
270 sbs->manager_present = 1;
271
272 end:
273 205
206 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
207 0x04, (u8 *) & battery_system_info);
208 if (!result)
209 sbs->batteries_supported = battery_system_info & 0x000f;
274 return result; 210 return result;
275} 211}
276 212
277static int acpi_battery_get_info(struct acpi_battery *battery) 213static int acpi_battery_get_info(struct acpi_battery *battery)
278{ 214{
279 int result = 0; 215 int i, result = 0;
280 s16 battery_mode;
281 s16 specification_info;
282
283 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03,
284 (u8 *)&battery_mode);
285 if (result) {
286 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
287 "acpi_smbus_read() failed"));
288 goto end;
289 }
290 battery->mode = (battery_mode & 0x8000) >> 15;
291
292 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x10,
293 (u8 *)&battery->full_charge_capacity);
294 if (result) {
295 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
296 "acpi_smbus_read() failed"));
297 goto end;
298 }
299
300 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x18,
301 (u8 *)&battery->design_capacity);
302 216
303 if (result) { 217 for (i = 0; i < ARRAY_SIZE(info_readers); ++i) {
304 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 218 result = acpi_smbus_read(battery->sbs->hc, info_readers[i].mode,
305 "acpi_smbus_read() failed")); 219 ACPI_SBS_BATTERY, info_readers[i].command,
306 goto end; 220 (u8 *) battery + info_readers[i].offset);
307 } 221 if (result)
308 222 break;
309 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x19,
310 (u8 *)&battery->design_voltage);
311 if (result) {
312 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
313 "acpi_smbus_read() failed"));
314 goto end;
315 } 223 }
316
317 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1a,
318 (u8 *)&specification_info);
319 if (result) {
320 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
321 "acpi_smbus_read() failed"));
322 goto end;
323 }
324
325 switch ((specification_info & 0x0f00) >> 8) {
326 case 1:
327 battery->vscale = 10;
328 break;
329 case 2:
330 battery->vscale = 100;
331 break;
332 case 3:
333 battery->vscale = 1000;
334 break;
335 default:
336 battery->vscale = 1;
337 }
338
339 switch ((specification_info & 0xf000) >> 12) {
340 case 1:
341 battery->ipscale = 10;
342 break;
343 case 2:
344 battery->ipscale = 100;
345 break;
346 case 3:
347 battery->ipscale = 1000;
348 break;
349 default:
350 battery->ipscale = 1;
351 }
352
353 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1c,
354 (u8 *)&battery->serial_number);
355 if (result) {
356 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
357 "acpi_smbus_read() failed"));
358 goto end;
359 }
360
361 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x20,
362 (u8 *)battery->manufacturer_name);
363 if (result) {
364 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
365 "acpi_sbs_read_str() failed"));
366 goto end;
367 }
368
369 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x21,
370 (u8 *)battery->device_name);
371 if (result) {
372 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
373 "acpi_sbs_read_str() failed"));
374 goto end;
375 }
376
377 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x22,
378 (u8 *)battery->device_chemistry);
379 if (result) {
380 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
381 "acpi_sbs_read_str() failed"));
382 goto end;
383 }
384
385 end:
386 return result; 224 return result;
387} 225}
388 226
389static int acpi_battery_get_state(struct acpi_battery *battery) 227static int acpi_battery_get_state(struct acpi_battery *battery)
390{ 228{
391 int result = 0; 229 int i, result = 0;
392
393 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x09,
394 (u8 *)&battery->voltage_now);
395 if (result) {
396 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
397 "acpi_smbus_read() failed"));
398 goto end;
399 }
400
401 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0a,
402 (u8 *)&battery->current_now);
403 if (result) {
404 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
405 "acpi_smbus_read() failed"));
406 goto end;
407 }
408
409 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0f,
410 (u8 *)&battery->capacity_now);
411 if (result) {
412 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
413 "acpi_smbus_read() failed"));
414 goto end;
415 }
416
417 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x16,
418 (u8 *)&battery->state);
419 if (result) {
420 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
421 "acpi_smbus_read() failed"));
422 goto end;
423 }
424
425 end:
426 return result;
427}
428
429static int acpi_battery_get_alarm(struct acpi_battery *battery)
430{
431 int result = 0;
432
433 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
434 (u8 *)&battery->alarm_capacity);
435 if (result) {
436 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
437 "acpi_smbus_read() failed"));
438 goto end;
439 }
440
441 end:
442
443 return result;
444}
445
446static int acpi_battery_set_alarm(struct acpi_battery *battery,
447 unsigned long alarm)
448{
449 int result = 0;
450 s16 battery_mode;
451 int foo;
452 230
453 result = acpi_battery_select(battery); 231 if (time_before(jiffies, battery->update_time +
454 if (result) { 232 msecs_to_jiffies(cache_time)))
455 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 233 return 0;
456 "acpi_battery_select() failed")); 234 for (i = 0; i < ARRAY_SIZE(state_readers); ++i) {
457 goto end; 235 result = acpi_smbus_read(battery->sbs->hc,
458 } 236 state_readers[i].mode,
459 237 ACPI_SBS_BATTERY,
460 /* If necessary, enable the alarm */ 238 state_readers[i].command,
461 239 (u8 *)battery +
462 if (alarm > 0) { 240 state_readers[i].offset);
463 result = 241 if (result)
464 acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03,
465 (u8 *)&battery_mode);
466 if (result) {
467 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
468 "acpi_smbus_read() failed"));
469 goto end;
470 }
471
472 battery_mode &= 0xbfff;
473 result =
474 acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
475 (u8 *)&battery_mode, 2);
476 if (result) {
477 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
478 "acpi_smbus_write() failed"));
479 goto end; 242 goto end;
480 }
481 } 243 }
482
483 foo = alarm / (battery->mode ? 10 : 1);
484 result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01,
485 (u8 *)&foo, 2);
486 if (result) {
487 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
488 "acpi_smbus_write() failed"));
489 goto end;
490 }
491
492 end: 244 end:
493 245 battery->update_time = jiffies;
494 return result; 246 return result;
495} 247}
496 248
497static int acpi_battery_set_mode(struct acpi_battery *battery) 249static int acpi_battery_get_alarm(struct acpi_battery *battery)
498{ 250{
499 int result = 0; 251 return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
500 s16 battery_mode; 252 ACPI_SBS_BATTERY, 0x01,
501 253 (u8 *) & battery->alarm_capacity);
502 if (mode == DEF_CAPACITY_UNIT) {
503 goto end;
504 }
505
506 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
507 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode);
508 if (result) {
509 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
510 "acpi_smbus_read() failed"));
511 goto end;
512 }
513
514 if (mode == MAH_CAPACITY_UNIT) {
515 battery_mode &= 0x7fff;
516 } else {
517 battery_mode |= 0x8000;
518 }
519 result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD,
520 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2);
521 if (result) {
522 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
523 "acpi_smbus_write() failed"));
524 goto end;
525 }
526
527 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
528 ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode);
529 if (result) {
530 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
531 "acpi_smbus_read() failed"));
532 goto end;
533 }
534
535 end:
536 return result;
537} 254}
538 255
539static int acpi_battery_init(struct acpi_battery *battery) 256static int acpi_battery_set_alarm(struct acpi_battery *battery)
540{ 257{
541 int result = 0; 258 struct acpi_sbs *sbs = battery->sbs;
542 259 u16 value;
543 result = acpi_battery_select(battery); 260 return 0;
544 if (result) {
545 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
546 "acpi_battery_select() failed"));
547 goto end;
548 }
549
550 result = acpi_battery_set_mode(battery);
551 if (result) {
552 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
553 "acpi_battery_set_mode() failed"));
554 goto end;
555 }
556
557 result = acpi_battery_get_info(battery);
558 if (result) {
559 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
560 "acpi_battery_get_info() failed"));
561 goto end;
562 }
563
564 result = acpi_battery_get_state(battery);
565 if (result) {
566 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
567 "acpi_battery_get_state() failed"));
568 goto end;
569 }
570 261
571 result = acpi_battery_get_alarm(battery); 262 if (sbs->manager_present) {
572 if (result) { 263 acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER,
573 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 264 0x01, (u8 *)&value);
574 "acpi_battery_get_alarm() failed")); 265 value &= 0x0fff;
575 goto end; 266 value |= 1 << (battery->id + 12);
267 acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_MANAGER,
268 0x01, (u8 *)&value, 2);
576 } 269 }
577 270 value = battery->alarm_capacity / (acpi_battery_mode(battery) ? 10 : 1);
578 end: 271 return acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
579 return result; 272 0x01, (u8 *)&value, 2);
580} 273}
581 274
582static int acpi_ac_get_present(struct acpi_sbs *sbs) 275static int acpi_ac_get_present(struct acpi_sbs *sbs)
583{ 276{
584 int result = 0; 277 int result;
585 s16 charger_status; 278 u16 status;
586
587 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBC_SMBUS_ADDR, 0x13,
588 (u8 *)&charger_status);
589
590 if (result) {
591 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
592 "acpi_smbus_read() failed"));
593 goto end;
594 }
595
596 sbs->charger_present = (charger_status & 0x8000) >> 15;
597
598 end:
599 279
280 result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER,
281 0x13, (u8 *) & status);
282 if (!result)
283 sbs->charger_present = (status >> 15) & 0x1;
600 return result; 284 return result;
601} 285}
602 286
@@ -607,7 +291,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs)
607/* Generic Routines */ 291/* Generic Routines */
608 292
609static int 293static int
610acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, 294acpi_sbs_add_fs(struct proc_dir_entry **dir,
611 struct proc_dir_entry *parent_dir, 295 struct proc_dir_entry *parent_dir,
612 char *dir_name, 296 char *dir_name,
613 struct file_operations *info_fops, 297 struct file_operations *info_fops,
@@ -669,7 +353,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir,
669} 353}
670 354
671static void 355static void
672acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, 356acpi_sbs_remove_fs(struct proc_dir_entry **dir,
673 struct proc_dir_entry *parent_dir) 357 struct proc_dir_entry *parent_dir)
674{ 358{
675 359
@@ -687,75 +371,47 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir,
687 371
688static struct proc_dir_entry *acpi_battery_dir = NULL; 372static struct proc_dir_entry *acpi_battery_dir = NULL;
689 373
374static inline char *acpi_battery_units(struct acpi_battery *battery)
375{
376 return acpi_battery_mode(battery) ? " mWh" : " mAh";
377}
378
379
690static int acpi_battery_read_info(struct seq_file *seq, void *offset) 380static int acpi_battery_read_info(struct seq_file *seq, void *offset)
691{ 381{
692 struct acpi_battery *battery = seq->private; 382 struct acpi_battery *battery = seq->private;
693 struct acpi_sbs *sbs = battery->sbs; 383 struct acpi_sbs *sbs = battery->sbs;
694 int cscale;
695 int result = 0; 384 int result = 0;
696 385
697 if (sbs_mutex_lock(sbs)) { 386 mutex_lock(&sbs->lock);
698 return -ENODEV;
699 }
700 387
701 result = acpi_check_update_proc(sbs); 388 seq_printf(seq, "present: %s\n",
702 if (result) 389 (battery->present) ? "yes" : "no");
390 if (!battery->present)
703 goto end; 391 goto end;
704 392
705 if (update_time == 0) {
706 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO);
707 if (result) {
708 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
709 "acpi_sbs_update_run() failed"));
710 }
711 }
712
713 if (battery->present) {
714 seq_printf(seq, "present: yes\n");
715 } else {
716 seq_printf(seq, "present: no\n");
717 goto end;
718 }
719
720 if (battery->mode) {
721 cscale = battery->vscale * battery->ipscale;
722 } else {
723 cscale = battery->ipscale;
724 }
725 seq_printf(seq, "design capacity: %i%s\n", 393 seq_printf(seq, "design capacity: %i%s\n",
726 battery->design_capacity * cscale, 394 battery->design_capacity * acpi_battery_scale(battery),
727 battery->mode ? "0 mWh" : " mAh"); 395 acpi_battery_units(battery));
728
729 seq_printf(seq, "last full capacity: %i%s\n", 396 seq_printf(seq, "last full capacity: %i%s\n",
730 battery->full_charge_capacity * cscale, 397 battery->full_charge_capacity * acpi_battery_scale(battery),
731 battery->mode ? "0 mWh" : " mAh"); 398 acpi_battery_units(battery));
732
733 seq_printf(seq, "battery technology: rechargeable\n"); 399 seq_printf(seq, "battery technology: rechargeable\n");
734
735 seq_printf(seq, "design voltage: %i mV\n", 400 seq_printf(seq, "design voltage: %i mV\n",
736 battery->design_voltage * battery->vscale); 401 battery->design_voltage * acpi_battery_vscale(battery));
737
738 seq_printf(seq, "design capacity warning: unknown\n"); 402 seq_printf(seq, "design capacity warning: unknown\n");
739 seq_printf(seq, "design capacity low: unknown\n"); 403 seq_printf(seq, "design capacity low: unknown\n");
740 seq_printf(seq, "capacity granularity 1: unknown\n"); 404 seq_printf(seq, "capacity granularity 1: unknown\n");
741 seq_printf(seq, "capacity granularity 2: unknown\n"); 405 seq_printf(seq, "capacity granularity 2: unknown\n");
742 406 seq_printf(seq, "model number: %s\n", battery->device_name);
743 seq_printf(seq, "model number: %s\n",
744 battery->device_name);
745
746 seq_printf(seq, "serial number: %i\n", 407 seq_printf(seq, "serial number: %i\n",
747 battery->serial_number); 408 battery->serial_number);
748
749 seq_printf(seq, "battery type: %s\n", 409 seq_printf(seq, "battery type: %s\n",
750 battery->device_chemistry); 410 battery->device_chemistry);
751
752 seq_printf(seq, "OEM info: %s\n", 411 seq_printf(seq, "OEM info: %s\n",
753 battery->manufacturer_name); 412 battery->manufacturer_name);
754
755 end: 413 end:
756 414 mutex_unlock(&sbs->lock);
757 sbs_mutex_unlock(sbs);
758
759 return result; 415 return result;
760} 416}
761 417
@@ -769,73 +425,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
769 struct acpi_battery *battery = seq->private; 425 struct acpi_battery *battery = seq->private;
770 struct acpi_sbs *sbs = battery->sbs; 426 struct acpi_sbs *sbs = battery->sbs;
771 int result = 0; 427 int result = 0;
772 int cscale;
773 int foo;
774
775 if (sbs_mutex_lock(sbs)) {
776 return -ENODEV;
777 }
778
779 result = acpi_check_update_proc(sbs);
780 if (result)
781 goto end;
782
783 if (update_time == 0) {
784 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE);
785 if (result) {
786 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
787 "acpi_sbs_update_run() failed"));
788 }
789 }
790 428
791 if (battery->present) { 429 mutex_lock(&sbs->lock);
792 seq_printf(seq, "present: yes\n"); 430 seq_printf(seq, "present: %s\n",
793 } else { 431 (battery->present) ? "yes" : "no");
794 seq_printf(seq, "present: no\n"); 432 if (!battery->present)
795 goto end; 433 goto end;
796 }
797
798 if (battery->mode) {
799 cscale = battery->vscale * battery->ipscale;
800 } else {
801 cscale = battery->ipscale;
802 }
803
804 if (battery->state & 0x0010) {
805 seq_printf(seq, "capacity state: critical\n");
806 } else {
807 seq_printf(seq, "capacity state: ok\n");
808 }
809
810 foo = (s16) battery->current_now * battery->ipscale;
811 if (battery->mode) {
812 foo = foo * battery->design_voltage / 1000;
813 }
814 if (battery->current_now < 0) {
815 seq_printf(seq, "charging state: discharging\n");
816 seq_printf(seq, "present rate: %d %s\n",
817 -foo, battery->mode ? "mW" : "mA");
818 } else if (battery->current_now > 0) {
819 seq_printf(seq, "charging state: charging\n");
820 seq_printf(seq, "present rate: %d %s\n",
821 foo, battery->mode ? "mW" : "mA");
822 } else {
823 seq_printf(seq, "charging state: charged\n");
824 seq_printf(seq, "present rate: 0 %s\n",
825 battery->mode ? "mW" : "mA");
826 }
827 434
435 acpi_battery_get_state(battery);
436 seq_printf(seq, "capacity state: %s\n",
437 (battery->state & 0x0010) ? "critical" : "ok");
438 seq_printf(seq, "charging state: %s\n",
439 (battery->current_now < 0) ? "discharging" :
440 ((battery->current_now > 0) ? "charging" : "charged"));
441 seq_printf(seq, "present rate: %d mA\n",
442 abs(battery->current_now) * acpi_battery_ipscale(battery));
828 seq_printf(seq, "remaining capacity: %i%s\n", 443 seq_printf(seq, "remaining capacity: %i%s\n",
829 battery->capacity_now * cscale, 444 battery->capacity_now * acpi_battery_scale(battery),
830 battery->mode ? "0 mWh" : " mAh"); 445 acpi_battery_units(battery));
831
832 seq_printf(seq, "present voltage: %i mV\n", 446 seq_printf(seq, "present voltage: %i mV\n",
833 battery->voltage_now * battery->vscale); 447 battery->voltage_now * acpi_battery_vscale(battery));
834 448
835 end: 449 end:
836 450 mutex_unlock(&sbs->lock);
837 sbs_mutex_unlock(sbs);
838
839 return result; 451 return result;
840} 452}
841 453
@@ -849,48 +461,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
849 struct acpi_battery *battery = seq->private; 461 struct acpi_battery *battery = seq->private;
850 struct acpi_sbs *sbs = battery->sbs; 462 struct acpi_sbs *sbs = battery->sbs;
851 int result = 0; 463 int result = 0;
852 int cscale;
853
854 if (sbs_mutex_lock(sbs)) {
855 return -ENODEV;
856 }
857 464
858 result = acpi_check_update_proc(sbs); 465 mutex_lock(&sbs->lock);
859 if (result)
860 goto end;
861
862 if (update_time == 0) {
863 result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM);
864 if (result) {
865 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
866 "acpi_sbs_update_run() failed"));
867 }
868 }
869 466
870 if (!battery->present) { 467 if (!battery->present) {
871 seq_printf(seq, "present: no\n"); 468 seq_printf(seq, "present: no\n");
872 goto end; 469 goto end;
873 } 470 }
874 471
875 if (battery->mode) { 472 acpi_battery_get_alarm(battery);
876 cscale = battery->vscale * battery->ipscale;
877 } else {
878 cscale = battery->ipscale;
879 }
880
881 seq_printf(seq, "alarm: "); 473 seq_printf(seq, "alarm: ");
882 if (battery->alarm_capacity) { 474 if (battery->alarm_capacity)
883 seq_printf(seq, "%i%s\n", 475 seq_printf(seq, "%i%s\n",
884 battery->alarm_capacity * cscale, 476 battery->alarm_capacity *
885 battery->mode ? "0 mWh" : " mAh"); 477 acpi_battery_scale(battery),
886 } else { 478 acpi_battery_units(battery));
479 else
887 seq_printf(seq, "disabled\n"); 480 seq_printf(seq, "disabled\n");
888 }
889
890 end: 481 end:
891 482 mutex_unlock(&sbs->lock);
892 sbs_mutex_unlock(sbs);
893
894 return result; 483 return result;
895} 484}
896 485
@@ -902,59 +491,28 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer,
902 struct acpi_battery *battery = seq->private; 491 struct acpi_battery *battery = seq->private;
903 struct acpi_sbs *sbs = battery->sbs; 492 struct acpi_sbs *sbs = battery->sbs;
904 char alarm_string[12] = { '\0' }; 493 char alarm_string[12] = { '\0' };
905 int result, old_alarm, new_alarm; 494 int result = 0;
906 495 mutex_lock(&sbs->lock);
907 if (sbs_mutex_lock(sbs)) {
908 return -ENODEV;
909 }
910
911 result = acpi_check_update_proc(sbs);
912 if (result)
913 goto end;
914
915 if (!battery->present) { 496 if (!battery->present) {
916 result = -ENODEV; 497 result = -ENODEV;
917 goto end; 498 goto end;
918 } 499 }
919
920 if (count > sizeof(alarm_string) - 1) { 500 if (count > sizeof(alarm_string) - 1) {
921 result = -EINVAL; 501 result = -EINVAL;
922 goto end; 502 goto end;
923 } 503 }
924
925 if (copy_from_user(alarm_string, buffer, count)) { 504 if (copy_from_user(alarm_string, buffer, count)) {
926 result = -EFAULT; 505 result = -EFAULT;
927 goto end; 506 goto end;
928 } 507 }
929
930 alarm_string[count] = 0; 508 alarm_string[count] = 0;
931 509 battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0);
932 old_alarm = battery->alarm_capacity; 510 acpi_battery_set_alarm(battery);
933 new_alarm = simple_strtoul(alarm_string, NULL, 0);
934
935 result = acpi_battery_set_alarm(battery, new_alarm);
936 if (result) {
937 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
938 "acpi_battery_set_alarm() failed"));
939 acpi_battery_set_alarm(battery, old_alarm);
940 goto end;
941 }
942 result = acpi_battery_get_alarm(battery);
943 if (result) {
944 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
945 "acpi_battery_get_alarm() failed"));
946 acpi_battery_set_alarm(battery, old_alarm);
947 goto end;
948 }
949
950 end: 511 end:
951 sbs_mutex_unlock(sbs); 512 mutex_unlock(&sbs->lock);
952 513 if (result)
953 if (result) {
954 return result; 514 return result;
955 } else { 515 return count;
956 return count;
957 }
958} 516}
959 517
960static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 518static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
@@ -993,26 +551,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL;
993 551
994static int acpi_ac_read_state(struct seq_file *seq, void *offset) 552static int acpi_ac_read_state(struct seq_file *seq, void *offset)
995{ 553{
996 struct acpi_sbs *sbs = seq->private;
997 int result;
998 554
999 if (sbs_mutex_lock(sbs)) { 555 struct acpi_sbs *sbs = seq->private;
1000 return -ENODEV;
1001 }
1002 556
1003 if (update_time == 0) { 557 mutex_lock(&sbs->lock);
1004 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE);
1005 if (result) {
1006 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1007 "acpi_sbs_update_run() failed"));
1008 }
1009 }
1010 558
1011 seq_printf(seq, "state: %s\n", 559 seq_printf(seq, "state: %s\n",
1012 sbs->charger_present ? "on-line" : "off-line"); 560 sbs->charger_present ? "on-line" : "off-line");
1013 561
1014 sbs_mutex_unlock(sbs); 562 mutex_unlock(&sbs->lock);
1015
1016 return 0; 563 return 0;
1017} 564}
1018 565
@@ -1035,67 +582,54 @@ static struct file_operations acpi_ac_state_fops = {
1035 582
1036/* Smart Battery */ 583/* Smart Battery */
1037 584
1038static int acpi_battery_add(struct acpi_sbs *sbs, int id) 585static int acpi_battery_read(struct acpi_battery *battery)
1039{ 586{
1040 int is_present; 587 int result = 0, saved_present = battery->present;
1041 int result; 588 u16 state;
1042 char dir_name[32];
1043 struct acpi_battery *battery;
1044 589
1045 battery = &sbs->battery[id]; 590 if (battery->sbs->manager_present) {
591 result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD,
592 ACPI_SBS_MANAGER, 0x01, (u8 *)&state);
593 if (!result)
594 battery->present = state & (1 << battery->id);
595 state &= 0x0fff;
596 state |= 1 << (battery->id + 12);
597 acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD,
598 ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2);
599 } else if (battery->id == 0)
600 battery->present = 1;
601 if (result || !battery->present)
602 return result;
1046 603
1047 battery->alive = 0; 604 if (saved_present != battery->present) {
605 battery->update_time = 0;
606 result = acpi_battery_get_info(battery);
607 if (result)
608 return result;
609 }
610 result = acpi_battery_get_state(battery);
611 return result;
612}
1048 613
1049 battery->init_state = 0; 614static int acpi_battery_add(struct acpi_sbs *sbs, int id)
615{
616 int result;
617 struct acpi_battery *battery = &sbs->battery[id];
1050 battery->id = id; 618 battery->id = id;
1051 battery->sbs = sbs; 619 battery->sbs = sbs;
620 battery->update_time = 0;
621 result = acpi_battery_read(battery);
622 if (result)
623 return result;
1052 624
1053 result = acpi_battery_select(battery); 625 sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
1054 if (result) { 626 acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
1055 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 627 battery->name, &acpi_battery_info_fops,
1056 "acpi_battery_select() failed")); 628 &acpi_battery_state_fops, &acpi_battery_alarm_fops,
1057 goto end; 629 battery);
1058 }
1059
1060 result = acpi_battery_get_present(battery);
1061 if (result) {
1062 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1063 "acpi_battery_get_present() failed"));
1064 goto end;
1065 }
1066
1067 is_present = battery->present;
1068
1069 if (is_present) {
1070 result = acpi_battery_init(battery);
1071 if (result) {
1072 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1073 "acpi_battery_init() failed"));
1074 goto end;
1075 }
1076 battery->init_state = 1;
1077 }
1078
1079 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1080
1081 result = acpi_sbs_generic_add_fs(&battery->proc_entry,
1082 acpi_battery_dir,
1083 dir_name,
1084 &acpi_battery_info_fops,
1085 &acpi_battery_state_fops,
1086 &acpi_battery_alarm_fops, battery);
1087 if (result) {
1088 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1089 "acpi_sbs_generic_add_fs() failed"));
1090 goto end;
1091 }
1092 battery->alive = 1;
1093
1094 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", 630 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
1095 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, 631 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
1096 sbs->battery->present ? "present" : "absent"); 632 battery->name, sbs->battery->present ? "present" : "absent");
1097
1098 end:
1099 return result; 633 return result;
1100} 634}
1101 635
@@ -1103,354 +637,105 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
1103{ 637{
1104 638
1105 if (sbs->battery[id].proc_entry) { 639 if (sbs->battery[id].proc_entry) {
1106 acpi_sbs_generic_remove_fs(&(sbs->battery[id].proc_entry), 640 acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry),
1107 acpi_battery_dir); 641 acpi_battery_dir);
1108 } 642 }
1109} 643}
1110 644
1111static int acpi_ac_add(struct acpi_sbs *sbs) 645static int acpi_charger_add(struct acpi_sbs *sbs)
1112{ 646{
1113 int result; 647 int result;
1114 648
1115 result = acpi_ac_get_present(sbs); 649 result = acpi_ac_get_present(sbs);
1116 if (result) { 650 if (result)
1117 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1118 "acpi_ac_get_present() failed"));
1119 goto end; 651 goto end;
1120 } 652 result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
1121 653 ACPI_AC_DIR_NAME, NULL,
1122 result = acpi_sbs_generic_add_fs(&sbs->ac_entry, 654 &acpi_ac_state_fops, NULL, sbs);
1123 acpi_ac_dir, 655 if (result)
1124 ACPI_AC_DIR_NAME,
1125 NULL, &acpi_ac_state_fops, NULL, sbs);
1126 if (result) {
1127 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1128 "acpi_sbs_generic_add_fs() failed"));
1129 goto end; 656 goto end;
1130 }
1131
1132 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", 657 printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
1133 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), 658 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
1134 ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); 659 ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
1135
1136 end: 660 end:
1137
1138 return result; 661 return result;
1139} 662}
1140 663
1141static void acpi_ac_remove(struct acpi_sbs *sbs) 664static void acpi_charger_remove(struct acpi_sbs *sbs)
1142{ 665{
1143 666
1144 if (sbs->ac_entry) { 667 if (sbs->charger_entry)
1145 acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); 668 acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
1146 }
1147}
1148
1149static void acpi_sbs_update_time_run(unsigned long data)
1150{
1151 acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data);
1152} 669}
1153 670
1154static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) 671void acpi_sbs_callback(void *context)
1155{ 672{
1156 struct acpi_battery *battery; 673 int id;
1157 int result = 0, cnt; 674 struct acpi_sbs *sbs = context;
1158 int old_ac_present = -1; 675 struct acpi_battery *bat;
1159 int old_present = -1; 676 u8 saved_charger_state = sbs->charger_present;
1160 int new_ac_present = -1; 677 u8 saved_battery_state;
1161 int new_present = -1; 678 acpi_ac_get_present(sbs);
1162 int id_min = 0, id_max = MAX_SBS_BAT - 1; 679 if (sbs->charger_present != saved_charger_state) {
1163 char dir_name[32]; 680 acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
1164 int do_battery_init = 0, do_ac_init = 0; 681 ACPI_SBS_NOTIFY_STATUS,
1165 int old_remaining_capacity = 0; 682 sbs->charger_present);
1166 int update_battery = 1;
1167 int up_tm = update_time;
1168
1169 if (sbs_zombie(sbs)) {
1170 goto end;
1171 }
1172
1173 if (id >= 0) {
1174 id_min = id_max = id;
1175 }
1176
1177 if (data_type == DATA_TYPE_COMMON && up_tm > 0) {
1178 cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1179 if (sbs->run_cnt % cnt != 0) {
1180 update_battery = 0;
1181 }
1182 }
1183
1184 sbs->run_cnt++;
1185
1186 if (!update_battery) {
1187 goto end;
1188 }
1189
1190 old_ac_present = sbs->charger_present;
1191
1192 result = acpi_ac_get_present(sbs);
1193 if (result) {
1194 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1195 "acpi_ac_get_present() failed"));
1196 }
1197
1198 new_ac_present = sbs->charger_present;
1199
1200 do_ac_init = (old_ac_present != new_ac_present);
1201 if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) {
1202 do_ac_init = 1;
1203 }
1204
1205 if (do_ac_init) {
1206 result = acpi_bus_generate_proc_event4(ACPI_AC_CLASS,
1207 ACPI_AC_DIR_NAME,
1208 ACPI_SBS_AC_NOTIFY_STATUS,
1209 new_ac_present);
1210 if (result) {
1211 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1212 "acpi_bus_generate_event4() failed"));
1213 }
1214 acpi_bus_generate_netlink_event(ACPI_AC_CLASS, ACPI_AC_DIR_NAME,
1215 ACPI_SBS_AC_NOTIFY_STATUS,
1216 new_ac_present);
1217 }
1218
1219 if (data_type == DATA_TYPE_COMMON) {
1220 if (!do_ac_init && !update_battery) {
1221 goto end;
1222 }
1223 }
1224
1225 if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) {
1226 goto end;
1227 } 683 }
1228 684 if (sbs->manager_present) {
1229 for (id = id_min; id <= id_max; id++) { 685 for (id = 0; id < MAX_SBS_BAT; ++id) {
1230 battery = &sbs->battery[id]; 686 if (!(sbs->batteries_supported & (1 << id)))
1231 if (battery->alive == 0) { 687 continue;
1232 continue; 688 bat = &sbs->battery[id];
1233 } 689 saved_battery_state = bat->present;
1234 690 acpi_battery_read(bat);
1235 old_remaining_capacity = battery->capacity_now; 691 if (saved_battery_state == bat->present)
1236 692 continue;
1237 old_present = battery->present; 693 acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
1238 694 bat->name,
1239 result = acpi_battery_select(battery); 695 ACPI_SBS_NOTIFY_STATUS,
1240 if (result) { 696 bat->present);
1241 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1242 "acpi_battery_select() failed"));
1243 }
1244
1245 result = acpi_battery_get_present(battery);
1246 if (result) {
1247 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1248 "acpi_battery_get_present() failed"));
1249 }
1250
1251 new_present = battery->present;
1252
1253 do_battery_init = ((old_present != new_present)
1254 && new_present);
1255 if (!new_present)
1256 goto event;
1257 if (do_ac_init || do_battery_init) {
1258 result = acpi_battery_init(battery);
1259 if (result) {
1260 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1261 "acpi_battery_init() "
1262 "failed"));
1263 }
1264 }
1265 if (sbs_zombie(sbs)) {
1266 goto end;
1267 }
1268
1269 if ((data_type == DATA_TYPE_COMMON
1270 || data_type == DATA_TYPE_INFO)
1271 && new_present) {
1272 result = acpi_battery_get_info(battery);
1273 if (result) {
1274 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1275 "acpi_battery_get_info() failed"));
1276 }
1277 }
1278 if (data_type == DATA_TYPE_INFO) {
1279 continue;
1280 }
1281 if (sbs_zombie(sbs)) {
1282 goto end;
1283 }
1284
1285 if ((data_type == DATA_TYPE_COMMON
1286 || data_type == DATA_TYPE_STATE)
1287 && new_present) {
1288 result = acpi_battery_get_state(battery);
1289 if (result) {
1290 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1291 "acpi_battery_get_state() failed"));
1292 }
1293 }
1294 if (data_type == DATA_TYPE_STATE) {
1295 goto event;
1296 }
1297 if (sbs_zombie(sbs)) {
1298 goto end;
1299 }
1300
1301 if ((data_type == DATA_TYPE_COMMON
1302 || data_type == DATA_TYPE_ALARM)
1303 && new_present) {
1304 result = acpi_battery_get_alarm(battery);
1305 if (result) {
1306 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1307 "acpi_battery_get_alarm() "
1308 "failed"));
1309 }
1310 }
1311 if (data_type == DATA_TYPE_ALARM) {
1312 continue;
1313 }
1314 if (sbs_zombie(sbs)) {
1315 goto end;
1316 }
1317
1318 event:
1319
1320 if (old_present != new_present || do_ac_init ||
1321 old_remaining_capacity !=
1322 battery->capacity_now) {
1323 sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id);
1324 result = acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS,
1325 dir_name,
1326 ACPI_SBS_BATTERY_NOTIFY_STATUS,
1327 new_present);
1328 acpi_bus_generate_netlink_event(ACPI_BATTERY_CLASS, dir_name,
1329 ACPI_SBS_BATTERY_NOTIFY_STATUS,
1330 new_present);
1331 if (result) {
1332 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1333 "acpi_bus_generate_proc_event4() "
1334 "failed"));
1335 }
1336 } 697 }
1337 } 698 }
1338
1339 end:
1340
1341 return result;
1342} 699}
1343 700
1344static void acpi_sbs_update_time(void *data) 701static int acpi_sbs_remove(struct acpi_device *device, int type);
1345{
1346 struct acpi_sbs *sbs = data;
1347 unsigned long delay = -1;
1348 int result;
1349 unsigned int up_tm = update_time;
1350
1351 if (sbs_mutex_lock(sbs))
1352 return;
1353
1354 result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON);
1355 if (result) {
1356 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1357 "acpi_sbs_update_run() failed"));
1358 }
1359
1360 if (sbs_zombie(sbs)) {
1361 goto end;
1362 }
1363
1364 if (!up_tm) {
1365 if (timer_pending(&sbs->update_timer))
1366 del_timer(&sbs->update_timer);
1367 } else {
1368 delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm);
1369 delay = jiffies + HZ * delay;
1370 if (timer_pending(&sbs->update_timer)) {
1371 mod_timer(&sbs->update_timer, delay);
1372 } else {
1373 sbs->update_timer.data = (unsigned long)data;
1374 sbs->update_timer.function = acpi_sbs_update_time_run;
1375 sbs->update_timer.expires = delay;
1376 add_timer(&sbs->update_timer);
1377 }
1378 }
1379
1380 end:
1381
1382 sbs_mutex_unlock(sbs);
1383}
1384 702
1385static int acpi_sbs_add(struct acpi_device *device) 703static int acpi_sbs_add(struct acpi_device *device)
1386{ 704{
1387 struct acpi_sbs *sbs = NULL; 705 struct acpi_sbs *sbs;
1388 int result = 0, remove_result = 0; 706 int result = 0;
1389 int id; 707 int id;
1390 708
1391 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); 709 sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL);
1392 if (!sbs) { 710 if (!sbs) {
1393 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed"));
1394 result = -ENOMEM; 711 result = -ENOMEM;
1395 goto end; 712 goto end;
1396 } 713 }
1397 714
1398 mutex_init(&sbs->mutex); 715 mutex_init(&sbs->lock);
1399
1400 sbs_mutex_lock(sbs);
1401 716
1402 sbs->device = device;
1403 sbs->hc = acpi_driver_data(device->parent); 717 sbs->hc = acpi_driver_data(device->parent);
1404 718 sbs->device = device;
1405 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); 719 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME);
1406 strcpy(acpi_device_class(device), ACPI_SBS_CLASS); 720 strcpy(acpi_device_class(device), ACPI_SBS_CLASS);
1407 acpi_driver_data(device) = sbs; 721 acpi_driver_data(device) = sbs;
1408 722
1409 result = acpi_ac_add(sbs); 723 result = acpi_charger_add(sbs);
1410 if (result) {
1411 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed"));
1412 goto end;
1413 }
1414
1415 acpi_sbsm_get_info(sbs);
1416
1417 if (!sbs->manager_present) {
1418 result = acpi_battery_add(sbs, 0);
1419 if (result) {
1420 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1421 "acpi_battery_add() failed"));
1422 goto end;
1423 }
1424 } else {
1425 for (id = 0; id < MAX_SBS_BAT; id++) {
1426 if ((sbs->batteries_supported & (1 << id))) {
1427 result = acpi_battery_add(sbs, id);
1428 if (result) {
1429 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1430 "acpi_battery_add() failed"));
1431 goto end;
1432 }
1433 }
1434 }
1435 }
1436
1437 init_timer(&sbs->update_timer);
1438 result = acpi_check_update_proc(sbs);
1439 if (result) 724 if (result)
1440 goto end; 725 goto end;
1441 726
727 result = acpi_manager_get_info(sbs);
728 if (!result) {
729 sbs->manager_present = 1;
730 for (id = 0; id < MAX_SBS_BAT; ++id)
731 if ((sbs->batteries_supported & (1 << id)))
732 acpi_battery_add(sbs, id);
733 } else
734 acpi_battery_add(sbs, 0);
735 acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs);
1442 end: 736 end:
1443 737 if (result)
1444 sbs_mutex_unlock(sbs); 738 acpi_sbs_remove(device, 0);
1445
1446 if (result) {
1447 remove_result = acpi_sbs_remove(device, 0);
1448 if (remove_result) {
1449 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1450 "acpi_sbs_remove() failed"));
1451 }
1452 }
1453
1454 return result; 739 return result;
1455} 740}
1456 741
@@ -1459,34 +744,19 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
1459 struct acpi_sbs *sbs; 744 struct acpi_sbs *sbs;
1460 int id; 745 int id;
1461 746
1462 if (!device) { 747 if (!device)
1463 return -EINVAL; 748 return -EINVAL;
1464 }
1465
1466 sbs = acpi_driver_data(device); 749 sbs = acpi_driver_data(device);
1467 if (!sbs) { 750 if (!sbs)
1468 return -EINVAL; 751 return -EINVAL;
1469 } 752 mutex_lock(&sbs->lock);
1470 753 acpi_smbus_unregister_callback(sbs->hc);
1471 sbs_mutex_lock(sbs); 754 for (id = 0; id < MAX_SBS_BAT; ++id)
1472
1473 sbs->zombie = 1;
1474 del_timer_sync(&sbs->update_timer);
1475 acpi_os_wait_events_complete(NULL);
1476 del_timer_sync(&sbs->update_timer);
1477
1478 for (id = 0; id < MAX_SBS_BAT; id++) {
1479 acpi_battery_remove(sbs, id); 755 acpi_battery_remove(sbs, id);
1480 } 756 acpi_charger_remove(sbs);
1481 757 mutex_unlock(&sbs->lock);
1482 acpi_ac_remove(sbs); 758 mutex_destroy(&sbs->lock);
1483
1484 sbs_mutex_unlock(sbs);
1485
1486 mutex_destroy(&sbs->mutex);
1487
1488 kfree(sbs); 759 kfree(sbs);
1489
1490 return 0; 760 return 0;
1491} 761}
1492 762
@@ -1505,14 +775,10 @@ static void acpi_sbs_rmdirs(void)
1505static int acpi_sbs_resume(struct acpi_device *device) 775static int acpi_sbs_resume(struct acpi_device *device)
1506{ 776{
1507 struct acpi_sbs *sbs; 777 struct acpi_sbs *sbs;
1508
1509 if (!device) 778 if (!device)
1510 return -EINVAL; 779 return -EINVAL;
1511
1512 sbs = device->driver_data; 780 sbs = device->driver_data;
1513 781 acpi_sbs_callback(sbs);
1514 sbs->run_cnt = 0;
1515
1516 return 0; 782 return 0;
1517} 783}
1518 784
@@ -1523,14 +789,6 @@ static int __init acpi_sbs_init(void)
1523 if (acpi_disabled) 789 if (acpi_disabled)
1524 return -ENODEV; 790 return -ENODEV;
1525 791
1526 if (mode != DEF_CAPACITY_UNIT
1527 && mode != MAH_CAPACITY_UNIT
1528 && mode != MWH_CAPACITY_UNIT) {
1529 ACPI_EXCEPTION((AE_INFO, AE_ERROR,
1530 "invalid mode = %d", mode));
1531 return -EINVAL;
1532 }
1533
1534 acpi_ac_dir = acpi_lock_ac_dir(); 792 acpi_ac_dir = acpi_lock_ac_dir();
1535 if (!acpi_ac_dir) { 793 if (!acpi_ac_dir) {
1536 ACPI_EXCEPTION((AE_INFO, AE_ERROR, 794 ACPI_EXCEPTION((AE_INFO, AE_ERROR,