Blame view
drivers/acpi/sbs.c
19.4 KB
c942fddf8 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
3f86b8324 ACPI: add support... |
2 |
/* |
db1c291af ACPI: SBS: Make S... |
3 |
* sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $) |
3f86b8324 ACPI: add support... |
4 |
* |
db1c291af ACPI: SBS: Make S... |
5 6 |
* Copyright (c) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> * Copyright (c) 2005-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> |
3f86b8324 ACPI: add support... |
7 |
* Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> |
3f86b8324 ACPI: add support... |
8 9 10 |
*/ #include <linux/init.h> |
5a0e3ad6a include cleanup: ... |
11 |
#include <linux/slab.h> |
3f86b8324 ACPI: add support... |
12 13 14 |
#include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> |
94f6c0860 ACPI: SBS: Add su... |
15 |
|
3f86b8324 ACPI: add support... |
16 |
#include <linux/acpi.h> |
6d15702cc ACPI: sbs: use EC... |
17 |
#include <linux/timer.h> |
722062334 ACPI: sbs: Common... |
18 |
#include <linux/jiffies.h> |
3f86b8324 ACPI: add support... |
19 |
#include <linux/delay.h> |
94f6c0860 ACPI: SBS: Add su... |
20 |
#include <linux/power_supply.h> |
630b3aff8 treewide: Consoli... |
21 |
#include <linux/platform_data/x86/apple.h> |
fa93854f7 battery: Add the ... |
22 |
#include <acpi/battery.h> |
94f6c0860 ACPI: SBS: Add su... |
23 |
|
91087dfa5 ACPI: SBS: Split ... |
24 |
#include "sbshc.h" |
a192a9580 ACPI: Move defini... |
25 |
#define PREFIX "ACPI: " |
3f86b8324 ACPI: add support... |
26 27 |
#define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" |
3f86b8324 ACPI: add support... |
28 |
#define ACPI_SBS_DEVICE_NAME "Smart Battery System" |
3f86b8324 ACPI: add support... |
29 30 |
#define ACPI_BATTERY_DIR_NAME "BAT%i" #define ACPI_AC_DIR_NAME "AC0" |
3f86b8324 ACPI: add support... |
31 |
|
db1c291af ACPI: SBS: Make S... |
32 33 |
#define ACPI_SBS_NOTIFY_STATUS 0x80 #define ACPI_SBS_NOTIFY_INFO 0x81 |
3f86b8324 ACPI: add support... |
34 |
|
db1c291af ACPI: SBS: Make S... |
35 |
MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>"); |
3f86b8324 ACPI: add support... |
36 37 |
MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); MODULE_LICENSE("GPL"); |
db1c291af ACPI: SBS: Make S... |
38 39 40 |
static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
6d15702cc ACPI: sbs: use EC... |
41 |
|
db1c291af ACPI: SBS: Make S... |
42 |
#define MAX_SBS_BAT 4 |
6d15702cc ACPI: sbs: use EC... |
43 |
#define ACPI_SBS_BLOCK_MAX 32 |
1ba90e3a8 ACPI: autoload mo... |
44 |
static const struct acpi_device_id sbs_device_ids[] = { |
91087dfa5 ACPI: SBS: Split ... |
45 |
{"ACPI0002", 0}, |
1ba90e3a8 ACPI: autoload mo... |
46 47 48 |
{"", 0}, }; MODULE_DEVICE_TABLE(acpi, sbs_device_ids); |
3f86b8324 ACPI: add support... |
49 |
struct acpi_battery { |
297d716f6 power_supply: Cha... |
50 51 |
struct power_supply *bat; struct power_supply_desc bat_desc; |
3f86b8324 ACPI: add support... |
52 |
struct acpi_sbs *sbs; |
db1c291af ACPI: SBS: Make S... |
53 54 |
unsigned long update_time; char name[8]; |
89862e3be ACPI: SBS: Simpli... |
55 56 57 |
char manufacturer_name[ACPI_SBS_BLOCK_MAX]; char device_name[ACPI_SBS_BLOCK_MAX]; char device_chemistry[ACPI_SBS_BLOCK_MAX]; |
94f6c0860 ACPI: SBS: Add su... |
58 |
u16 alarm_capacity; |
89862e3be ACPI: SBS: Simpli... |
59 60 61 62 |
u16 full_charge_capacity; u16 design_capacity; u16 design_voltage; u16 serial_number; |
db1c291af ACPI: SBS: Make S... |
63 64 |
u16 cycle_count; u16 temp_now; |
89862e3be ACPI: SBS: Simpli... |
65 |
u16 voltage_now; |
7faa144a5 ACPI: battery: ad... |
66 67 |
s16 rate_now; s16 rate_avg; |
89862e3be ACPI: SBS: Simpli... |
68 |
u16 capacity_now; |
db1c291af ACPI: SBS: Make S... |
69 |
u16 state_of_charge; |
89862e3be ACPI: SBS: Simpli... |
70 |
u16 state; |
89862e3be ACPI: SBS: Simpli... |
71 |
u16 mode; |
db1c291af ACPI: SBS: Make S... |
72 |
u16 spec; |
89862e3be ACPI: SBS: Simpli... |
73 |
u8 id; |
89862e3be ACPI: SBS: Simpli... |
74 |
u8 present:1; |
037cbc63f ACPI: SBS: Fix re... |
75 |
u8 have_sysfs_alarm:1; |
3f86b8324 ACPI: add support... |
76 |
}; |
297d716f6 power_supply: Cha... |
77 |
#define to_acpi_battery(x) power_supply_get_drvdata(x) |
94f6c0860 ACPI: SBS: Add su... |
78 |
|
3f86b8324 ACPI: add support... |
79 |
struct acpi_sbs { |
297d716f6 power_supply: Cha... |
80 |
struct power_supply *charger; |
3f86b8324 ACPI: add support... |
81 |
struct acpi_device *device; |
91087dfa5 ACPI: SBS: Split ... |
82 |
struct acpi_smb_hc *hc; |
db1c291af ACPI: SBS: Make S... |
83 |
struct mutex lock; |
3f86b8324 ACPI: add support... |
84 |
struct acpi_battery battery[MAX_SBS_BAT]; |
db1c291af ACPI: SBS: Make S... |
85 |
u8 batteries_supported:4; |
89862e3be ACPI: SBS: Simpli... |
86 87 |
u8 manager_present:1; u8 charger_present:1; |
3031cddea ACPI / SBS: Don't... |
88 |
u8 charger_exists:1; |
3f86b8324 ACPI: add support... |
89 |
}; |
297d716f6 power_supply: Cha... |
90 |
#define to_acpi_sbs(x) power_supply_get_drvdata(x) |
94f6c0860 ACPI: SBS: Add su... |
91 |
|
51fac8388 ACPI: Remove usel... |
92 |
static int acpi_sbs_remove(struct acpi_device *device); |
1dd5c715e ACPI / SBS: Add g... |
93 |
static int acpi_battery_get_state(struct acpi_battery *battery); |
db1c291af ACPI: SBS: Make S... |
94 |
static inline int battery_scale(int log) |
722062334 ACPI: sbs: Common... |
95 |
{ |
db1c291af ACPI: SBS: Make S... |
96 97 98 99 |
int scale = 1; while (log--) scale *= 10; return scale; |
722062334 ACPI: sbs: Common... |
100 |
} |
db1c291af ACPI: SBS: Make S... |
101 |
static inline int acpi_battery_vscale(struct acpi_battery *battery) |
722062334 ACPI: sbs: Common... |
102 |
{ |
db1c291af ACPI: SBS: Make S... |
103 |
return battery_scale((battery->spec & 0x0f00) >> 8); |
722062334 ACPI: sbs: Common... |
104 |
} |
db1c291af ACPI: SBS: Make S... |
105 |
static inline int acpi_battery_ipscale(struct acpi_battery *battery) |
722062334 ACPI: sbs: Common... |
106 |
{ |
db1c291af ACPI: SBS: Make S... |
107 |
return battery_scale((battery->spec & 0xf000) >> 12); |
722062334 ACPI: sbs: Common... |
108 |
} |
db1c291af ACPI: SBS: Make S... |
109 |
static inline int acpi_battery_mode(struct acpi_battery *battery) |
722062334 ACPI: sbs: Common... |
110 |
{ |
db1c291af ACPI: SBS: Make S... |
111 |
return (battery->mode & 0x8000); |
722062334 ACPI: sbs: Common... |
112 |
} |
3f86b8324 ACPI: add support... |
113 |
|
db1c291af ACPI: SBS: Make S... |
114 |
static inline int acpi_battery_scale(struct acpi_battery *battery) |
3f86b8324 ACPI: add support... |
115 |
{ |
db1c291af ACPI: SBS: Make S... |
116 117 |
return (acpi_battery_mode(battery) ? 10 : 1) * acpi_battery_ipscale(battery); |
3f86b8324 ACPI: add support... |
118 |
} |
94f6c0860 ACPI: SBS: Add su... |
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
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 ACPI / SBS: Add g... |
155 156 |
acpi_battery_get_state(battery); |
94f6c0860 ACPI: SBS: Add su... |
157 158 |
switch (psp) { case POWER_SUPPLY_PROP_STATUS: |
7faa144a5 ACPI: battery: ad... |
159 |
if (battery->rate_now < 0) |
94f6c0860 ACPI: SBS: Add su... |
160 |
val->intval = POWER_SUPPLY_STATUS_DISCHARGING; |
7faa144a5 ACPI: battery: ad... |
161 |
else if (battery->rate_now > 0) |
94f6c0860 ACPI: SBS: Add su... |
162 163 164 165 166 167 168 169 170 171 |
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 ACPI: SBS: Export... |
172 173 174 |
case POWER_SUPPLY_PROP_CYCLE_COUNT: val->intval = battery->cycle_count; break; |
94f6c0860 ACPI: SBS: Add su... |
175 176 177 178 179 180 181 182 183 |
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 ACPI: battery: ad... |
184 185 |
case POWER_SUPPLY_PROP_POWER_NOW: val->intval = abs(battery->rate_now) * |
94f6c0860 ACPI: SBS: Add su... |
186 |
acpi_battery_ipscale(battery) * 1000; |
e4108292c ACPI / SBS: Corre... |
187 188 189 |
val->intval *= (acpi_battery_mode(battery)) ? (battery->voltage_now * acpi_battery_vscale(battery) / 1000) : 1; |
94f6c0860 ACPI: SBS: Add su... |
190 191 |
break; case POWER_SUPPLY_PROP_CURRENT_AVG: |
7faa144a5 ACPI: battery: ad... |
192 193 |
case POWER_SUPPLY_PROP_POWER_AVG: val->intval = abs(battery->rate_avg) * |
94f6c0860 ACPI: SBS: Add su... |
194 |
acpi_battery_ipscale(battery) * 1000; |
e4108292c ACPI / SBS: Corre... |
195 196 197 |
val->intval *= (acpi_battery_mode(battery)) ? (battery->voltage_now * acpi_battery_vscale(battery) / 1000) : 1; |
94f6c0860 ACPI: SBS: Add su... |
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
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 ACPI: SBS: Export... |
240 |
POWER_SUPPLY_PROP_CYCLE_COUNT, |
94f6c0860 ACPI: SBS: Add su... |
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
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 ACPI: battery: ad... |
262 263 |
POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_POWER_AVG, |
94f6c0860 ACPI: SBS: Add su... |
264 265 266 267 268 269 270 271 |
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 ACPI: battery: ad... |
272 |
|
297d716f6 power_supply: Cha... |
273 274 275 276 277 278 279 |
static const struct power_supply_desc acpi_sbs_charger_desc = { .name = "sbs-charger", .type = POWER_SUPPLY_TYPE_MAINS, .properties = sbs_ac_props, .num_properties = ARRAY_SIZE(sbs_ac_props), .get_property = sbs_get_ac_property, }; |
94f6c0860 ACPI: SBS: Add su... |
280 |
|
db1c291af ACPI: SBS: Make S... |
281 282 283 |
/* -------------------------------------------------------------------------- Smart Battery System Management -------------------------------------------------------------------------- */ |
3f86b8324 ACPI: add support... |
284 |
|
db1c291af ACPI: SBS: Make S... |
285 286 287 288 289 |
struct acpi_battery_reader { u8 command; /* command for battery */ u8 mode; /* word or block? */ size_t offset; /* offset inside struct acpi_sbs_battery */ }; |
3f86b8324 ACPI: add support... |
290 |
|
db1c291af ACPI: SBS: Make S... |
291 292 293 294 295 296 297 298 299 300 301 302 303 |
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 ACPI: add support... |
304 |
|
db1c291af ACPI: SBS: Make S... |
305 306 307 |
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 ACPI: battery: ad... |
308 309 |
{0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)}, {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)}, |
db1c291af ACPI: SBS: Make S... |
310 311 312 313 |
{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 ACPI: add support... |
314 |
|
db1c291af ACPI: SBS: Make S... |
315 |
static int acpi_manager_get_info(struct acpi_sbs *sbs) |
3f86b8324 ACPI: add support... |
316 |
{ |
3f86b8324 ACPI: add support... |
317 |
int result = 0; |
db1c291af ACPI: SBS: Make S... |
318 |
u16 battery_system_info; |
3f86b8324 ACPI: add support... |
319 |
|
db1c291af ACPI: SBS: Make S... |
320 |
result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, |
94f6c0860 ACPI: SBS: Add su... |
321 |
0x04, (u8 *)&battery_system_info); |
db1c291af ACPI: SBS: Make S... |
322 323 |
if (!result) sbs->batteries_supported = battery_system_info & 0x000f; |
635227ee8 ACPI: remove func... |
324 |
return result; |
3f86b8324 ACPI: add support... |
325 326 327 328 |
} static int acpi_battery_get_info(struct acpi_battery *battery) { |
db1c291af ACPI: SBS: Make S... |
329 |
int i, result = 0; |
3f86b8324 ACPI: add support... |
330 |
|
db1c291af ACPI: SBS: Make S... |
331 |
for (i = 0; i < ARRAY_SIZE(info_readers); ++i) { |
94f6c0860 ACPI: SBS: Add su... |
332 333 334 335 336 337 |
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 ACPI: SBS: Make S... |
338 339 |
if (result) break; |
3f86b8324 ACPI: add support... |
340 |
} |
635227ee8 ACPI: remove func... |
341 |
return result; |
3f86b8324 ACPI: add support... |
342 |
} |
3f86b8324 ACPI: add support... |
343 344 |
static int acpi_battery_get_state(struct acpi_battery *battery) { |
db1c291af ACPI: SBS: Make S... |
345 |
int i, result = 0; |
3f86b8324 ACPI: add support... |
346 |
|
94f6c0860 ACPI: SBS: Add su... |
347 348 |
if (battery->update_time && time_before(jiffies, battery->update_time + |
db1c291af ACPI: SBS: Make S... |
349 350 351 352 353 354 355 |
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, |
c6237b210 ACPI: Fix whitesp... |
356 |
(u8 *)battery + |
db1c291af ACPI: SBS: Make S... |
357 358 |
state_readers[i].offset); if (result) |
3f86b8324 ACPI: add support... |
359 |
goto end; |
3f86b8324 ACPI: add support... |
360 |
} |
3f86b8324 ACPI: add support... |
361 |
end: |
db1c291af ACPI: SBS: Make S... |
362 |
battery->update_time = jiffies; |
635227ee8 ACPI: remove func... |
363 |
return result; |
3f86b8324 ACPI: add support... |
364 |
} |
db1c291af ACPI: SBS: Make S... |
365 |
static int acpi_battery_get_alarm(struct acpi_battery *battery) |
3f86b8324 ACPI: add support... |
366 |
{ |
db1c291af ACPI: SBS: Make S... |
367 368 |
return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x01, |
94f6c0860 ACPI: SBS: Add su... |
369 |
(u8 *)&battery->alarm_capacity); |
3f86b8324 ACPI: add support... |
370 |
} |
db1c291af ACPI: SBS: Make S... |
371 |
static int acpi_battery_set_alarm(struct acpi_battery *battery) |
3f86b8324 ACPI: add support... |
372 |
{ |
db1c291af ACPI: SBS: Make S... |
373 |
struct acpi_sbs *sbs = battery->sbs; |
94f6c0860 ACPI: SBS: Add su... |
374 375 376 |
u16 value, sel = 1 << (battery->id + 12); int ret; |
3f86b8324 ACPI: add support... |
377 |
|
db1c291af ACPI: SBS: Make S... |
378 |
if (sbs->manager_present) { |
94f6c0860 ACPI: SBS: Add su... |
379 |
ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, |
db1c291af ACPI: SBS: Make S... |
380 |
0x01, (u8 *)&value); |
94f6c0860 ACPI: SBS: Add su... |
381 382 383 384 385 |
if (ret) goto end; if ((value & 0xf000) != sel) { value &= 0x0fff; value |= sel; |
a84bc8cfb ACPI / SBS: fix i... |
386 |
ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, |
94f6c0860 ACPI: SBS: Add su... |
387 388 |
ACPI_SBS_MANAGER, 0x01, (u8 *)&value, 2); |
a84bc8cfb ACPI / SBS: fix i... |
389 390 |
if (ret) goto end; |
94f6c0860 ACPI: SBS: Add su... |
391 |
} |
3f86b8324 ACPI: add support... |
392 |
} |
94f6c0860 ACPI: SBS: Add su... |
393 394 395 396 |
ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x01, (u8 *)&battery->alarm_capacity, 2); end: return ret; |
3f86b8324 ACPI: add support... |
397 398 399 400 |
} static int acpi_ac_get_present(struct acpi_sbs *sbs) { |
db1c291af ACPI: SBS: Make S... |
401 402 |
int result; u16 status; |
3f86b8324 ACPI: add support... |
403 |
|
db1c291af ACPI: SBS: Make S... |
404 405 |
result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, 0x13, (u8 *) & status); |
3031cddea ACPI / SBS: Don't... |
406 407 408 409 410 411 |
if (result) return result; /* * The spec requires that bit 4 always be 1. If it's not set, assume |
ca1721c5b ACPI / SBS: Fix G... |
412 413 414 415 416 |
* that the implementation doesn't support an SBS charger. * * And on some MacBooks a status of 0xffff is always returned, no * matter whether the charger is plugged in or not, which is also * wrong, so ignore the SBS charger for those too. |
3031cddea ACPI / SBS: Don't... |
417 |
*/ |
ca1721c5b ACPI / SBS: Fix G... |
418 |
if (!((status >> 4) & 0x1) || status == 0xffff) |
3031cddea ACPI / SBS: Don't... |
419 420 421 422 |
return -ENODEV; sbs->charger_present = (status >> 15) & 0x1; return 0; |
3f86b8324 ACPI: add support... |
423 |
} |
8bd955320 ACPI: SBS: Add sy... |
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 |
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)); |
32a905120 ACPI / SBS: Fix i... |
441 442 |
if (sscanf(buf, "%lu ", &x) == 1) |
8bd955320 ACPI: SBS: Add sy... |
443 444 445 446 447 448 |
battery->alarm_capacity = x / (1000 * acpi_battery_scale(battery)); if (battery->present) acpi_battery_set_alarm(battery); return count; } |
82d2b6105 ACPI: make device... |
449 |
static const struct device_attribute alarm_attr = { |
01e8ef11b x86: sysfs: kill ... |
450 |
.attr = {.name = "alarm", .mode = 0644}, |
8bd955320 ACPI: SBS: Add sy... |
451 452 453 |
.show = acpi_battery_alarm_show, .store = acpi_battery_alarm_store, }; |
3f86b8324 ACPI: add support... |
454 |
/* -------------------------------------------------------------------------- |
3f86b8324 ACPI: add support... |
455 456 |
Driver Interface -------------------------------------------------------------------------- */ |
db1c291af ACPI: SBS: Make S... |
457 |
static int acpi_battery_read(struct acpi_battery *battery) |
3f86b8324 ACPI: add support... |
458 |
{ |
db1c291af ACPI: SBS: Make S... |
459 460 |
int result = 0, saved_present = battery->present; u16 state; |
3f86b8324 ACPI: add support... |
461 |
|
db1c291af ACPI: SBS: Make S... |
462 463 464 465 466 467 468 469 470 471 472 |
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; |
9faf6136f ACPI / SBS: Disab... |
473 |
|
db1c291af ACPI: SBS: Make S... |
474 475 |
if (result || !battery->present) return result; |
3f86b8324 ACPI: add support... |
476 |
|
db1c291af ACPI: SBS: Make S... |
477 478 479 |
if (saved_present != battery->present) { battery->update_time = 0; result = acpi_battery_get_info(battery); |
9faf6136f ACPI / SBS: Disab... |
480 481 |
if (result) { battery->present = 0; |
db1c291af ACPI: SBS: Make S... |
482 |
return result; |
9faf6136f ACPI / SBS: Disab... |
483 |
} |
db1c291af ACPI: SBS: Make S... |
484 485 |
} result = acpi_battery_get_state(battery); |
9faf6136f ACPI / SBS: Disab... |
486 487 |
if (result) battery->present = 0; |
db1c291af ACPI: SBS: Make S... |
488 489 |
return result; } |
3f86b8324 ACPI: add support... |
490 |
|
94f6c0860 ACPI: SBS: Add su... |
491 |
/* Smart Battery */ |
db1c291af ACPI: SBS: Make S... |
492 493 |
static int acpi_battery_add(struct acpi_sbs *sbs, int id) { |
db1c291af ACPI: SBS: Make S... |
494 |
struct acpi_battery *battery = &sbs->battery[id]; |
297d716f6 power_supply: Cha... |
495 |
struct power_supply_config psy_cfg = { .drv_data = battery, }; |
94f6c0860 ACPI: SBS: Add su... |
496 |
int result; |
3f86b8324 ACPI: add support... |
497 498 |
battery->id = id; battery->sbs = sbs; |
db1c291af ACPI: SBS: Make S... |
499 500 501 |
result = acpi_battery_read(battery); if (result) return result; |
3f86b8324 ACPI: add support... |
502 |
|
db1c291af ACPI: SBS: Make S... |
503 |
sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); |
297d716f6 power_supply: Cha... |
504 505 |
battery->bat_desc.name = battery->name; battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY; |
94f6c0860 ACPI: SBS: Add su... |
506 |
if (!acpi_battery_mode(battery)) { |
297d716f6 power_supply: Cha... |
507 508 |
battery->bat_desc.properties = sbs_charge_battery_props; battery->bat_desc.num_properties = |
94f6c0860 ACPI: SBS: Add su... |
509 510 |
ARRAY_SIZE(sbs_charge_battery_props); } else { |
297d716f6 power_supply: Cha... |
511 512 |
battery->bat_desc.properties = sbs_energy_battery_props; battery->bat_desc.num_properties = |
94f6c0860 ACPI: SBS: Add su... |
513 514 |
ARRAY_SIZE(sbs_energy_battery_props); } |
297d716f6 power_supply: Cha... |
515 516 517 518 519 520 |
battery->bat_desc.get_property = acpi_sbs_battery_get_property; battery->bat = power_supply_register(&sbs->device->dev, &battery->bat_desc, &psy_cfg); if (IS_ERR(battery->bat)) { result = PTR_ERR(battery->bat); battery->bat = NULL; |
037cbc63f ACPI: SBS: Fix re... |
521 |
goto end; |
297d716f6 power_supply: Cha... |
522 |
} |
9faf6136f ACPI / SBS: Disab... |
523 |
|
297d716f6 power_supply: Cha... |
524 |
result = device_create_file(&battery->bat->dev, &alarm_attr); |
037cbc63f ACPI: SBS: Fix re... |
525 526 527 528 |
if (result) goto end; battery->have_sysfs_alarm = 1; end: |
722062334 ACPI: sbs: Common... |
529 530 |
printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s) ", |
db1c291af ACPI: SBS: Make S... |
531 |
ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
bbafbecb2 ACPI: SBS: Host c... |
532 |
battery->name, battery->present ? "present" : "absent"); |
635227ee8 ACPI: remove func... |
533 |
return result; |
3f86b8324 ACPI: add support... |
534 535 536 537 |
} static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { |
037cbc63f ACPI: SBS: Fix re... |
538 |
struct acpi_battery *battery = &sbs->battery[id]; |
c19bdb612 ACPI: Fix unused ... |
539 |
|
297d716f6 power_supply: Cha... |
540 |
if (battery->bat) { |
037cbc63f ACPI: SBS: Fix re... |
541 |
if (battery->have_sysfs_alarm) |
297d716f6 power_supply: Cha... |
542 543 |
device_remove_file(&battery->bat->dev, &alarm_attr); power_supply_unregister(battery->bat); |
3f86b8324 ACPI: add support... |
544 545 |
} } |
db1c291af ACPI: SBS: Make S... |
546 |
static int acpi_charger_add(struct acpi_sbs *sbs) |
3f86b8324 ACPI: add support... |
547 548 |
{ int result; |
297d716f6 power_supply: Cha... |
549 |
struct power_supply_config psy_cfg = { .drv_data = sbs, }; |
3f86b8324 ACPI: add support... |
550 |
|
3f86b8324 ACPI: add support... |
551 |
result = acpi_ac_get_present(sbs); |
db1c291af ACPI: SBS: Make S... |
552 |
if (result) |
3f86b8324 ACPI: add support... |
553 |
goto end; |
2a68b995c ACPI / SBS: Remov... |
554 |
|
3031cddea ACPI / SBS: Don't... |
555 |
sbs->charger_exists = 1; |
297d716f6 power_supply: Cha... |
556 557 558 559 560 561 |
sbs->charger = power_supply_register(&sbs->device->dev, &acpi_sbs_charger_desc, &psy_cfg); if (IS_ERR(sbs->charger)) { result = PTR_ERR(sbs->charger); sbs->charger = NULL; } |
722062334 ACPI: sbs: Common... |
562 563 564 |
printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s) ", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), |
89862e3be ACPI: SBS: Simpli... |
565 |
ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); |
3f86b8324 ACPI: add support... |
566 |
end: |
635227ee8 ACPI: remove func... |
567 |
return result; |
3f86b8324 ACPI: add support... |
568 |
} |
db1c291af ACPI: SBS: Make S... |
569 |
static void acpi_charger_remove(struct acpi_sbs *sbs) |
3f86b8324 ACPI: add support... |
570 |
{ |
297d716f6 power_supply: Cha... |
571 572 |
if (sbs->charger) power_supply_unregister(sbs->charger); |
3f86b8324 ACPI: add support... |
573 |
} |
e5685b9d3 ACPI: misc cleanups |
574 |
static void acpi_sbs_callback(void *context) |
3f86b8324 ACPI: add support... |
575 |
{ |
db1c291af ACPI: SBS: Make S... |
576 577 578 579 580 |
int id; struct acpi_sbs *sbs = context; struct acpi_battery *bat; u8 saved_charger_state = sbs->charger_present; u8 saved_battery_state; |
3031cddea ACPI / SBS: Don't... |
581 582 583 584 |
if (sbs->charger_exists) { acpi_ac_get_present(sbs); if (sbs->charger_present != saved_charger_state) |
297d716f6 power_supply: Cha... |
585 |
kobject_uevent(&sbs->charger->dev.kobj, KOBJ_CHANGE); |
3031cddea ACPI / SBS: Don't... |
586 |
} |
1696d9dc5 ACPI: Remove the ... |
587 |
|
db1c291af ACPI: SBS: Make S... |
588 589 590 591 592 593 594 595 596 |
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; |
297d716f6 power_supply: Cha... |
597 |
kobject_uevent(&bat->bat->dev.kobj, KOBJ_CHANGE); |
3f86b8324 ACPI: add support... |
598 |
} |
3f86b8324 ACPI: add support... |
599 |
} |
3f86b8324 ACPI: add support... |
600 |
} |
3f86b8324 ACPI: add support... |
601 602 |
static int acpi_sbs_add(struct acpi_device *device) { |
db1c291af ACPI: SBS: Make S... |
603 604 |
struct acpi_sbs *sbs; int result = 0; |
6d15702cc ACPI: sbs: use EC... |
605 |
int id; |
3f86b8324 ACPI: add support... |
606 |
|
36bcbec7c ACPI: replace kma... |
607 |
sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); |
3f86b8324 ACPI: add support... |
608 |
if (!sbs) { |
722062334 ACPI: sbs: Common... |
609 610 |
result = -ENOMEM; goto end; |
3f86b8324 ACPI: add support... |
611 |
} |
3f86b8324 ACPI: add support... |
612 |
|
db1c291af ACPI: SBS: Make S... |
613 |
mutex_init(&sbs->lock); |
722062334 ACPI: sbs: Common... |
614 |
|
91087dfa5 ACPI: SBS: Split ... |
615 |
sbs->hc = acpi_driver_data(device->parent); |
db1c291af ACPI: SBS: Make S... |
616 |
sbs->device = device; |
3f86b8324 ACPI: add support... |
617 618 |
strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); |
db89b4f0d ACPI: catch calls... |
619 |
device->driver_data = sbs; |
3f86b8324 ACPI: add support... |
620 |
|
db1c291af ACPI: SBS: Make S... |
621 |
result = acpi_charger_add(sbs); |
3031cddea ACPI / SBS: Don't... |
622 |
if (result && result != -ENODEV) |
722062334 ACPI: sbs: Common... |
623 |
goto end; |
3f86b8324 ACPI: add support... |
624 |
|
9faf6136f ACPI / SBS: Disab... |
625 |
result = 0; |
630b3aff8 treewide: Consoli... |
626 |
if (!x86_apple_machine) { |
9faf6136f ACPI / SBS: Disab... |
627 628 |
result = acpi_manager_get_info(sbs); if (!result) { |
61f8ff693 ACPI / SBS: Enabl... |
629 |
sbs->manager_present = 1; |
9faf6136f ACPI / SBS: Disab... |
630 631 632 633 634 635 636 |
for (id = 0; id < MAX_SBS_BAT; ++id) if ((sbs->batteries_supported & (1 << id))) acpi_battery_add(sbs, id); } } if (!sbs->manager_present) |
db1c291af ACPI: SBS: Make S... |
637 |
acpi_battery_add(sbs, 0); |
9faf6136f ACPI / SBS: Disab... |
638 |
|
db1c291af ACPI: SBS: Make S... |
639 |
acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); |
3f86b8324 ACPI: add support... |
640 |
end: |
db1c291af ACPI: SBS: Make S... |
641 |
if (result) |
51fac8388 ACPI: Remove usel... |
642 |
acpi_sbs_remove(device); |
635227ee8 ACPI: remove func... |
643 |
return result; |
3f86b8324 ACPI: add support... |
644 |
} |
51fac8388 ACPI: Remove usel... |
645 |
static int acpi_sbs_remove(struct acpi_device *device) |
3f86b8324 ACPI: add support... |
646 |
{ |
cece90148 Pull style into t... |
647 |
struct acpi_sbs *sbs; |
3f86b8324 ACPI: add support... |
648 |
int id; |
db1c291af ACPI: SBS: Make S... |
649 |
if (!device) |
963497c12 ACPI: sbs: check ... |
650 |
return -EINVAL; |
722062334 ACPI: sbs: Common... |
651 |
sbs = acpi_driver_data(device); |
db1c291af ACPI: SBS: Make S... |
652 |
if (!sbs) |
635227ee8 ACPI: remove func... |
653 |
return -EINVAL; |
db1c291af ACPI: SBS: Make S... |
654 655 656 |
mutex_lock(&sbs->lock); acpi_smbus_unregister_callback(sbs->hc); for (id = 0; id < MAX_SBS_BAT; ++id) |
3f86b8324 ACPI: add support... |
657 |
acpi_battery_remove(sbs, id); |
db1c291af ACPI: SBS: Make S... |
658 659 660 |
acpi_charger_remove(sbs); mutex_unlock(&sbs->lock); mutex_destroy(&sbs->lock); |
3f86b8324 ACPI: add support... |
661 |
kfree(sbs); |
635227ee8 ACPI: remove func... |
662 |
return 0; |
3f86b8324 ACPI: add support... |
663 |
} |
906924048 ACPI / PM: Fix un... |
664 |
#ifdef CONFIG_PM_SLEEP |
d202f77d2 ACPI: Use struct ... |
665 |
static int acpi_sbs_resume(struct device *dev) |
722062334 ACPI: sbs: Common... |
666 667 |
{ struct acpi_sbs *sbs; |
d202f77d2 ACPI: Use struct ... |
668 |
if (!dev) |
722062334 ACPI: sbs: Common... |
669 |
return -EINVAL; |
d202f77d2 ACPI: Use struct ... |
670 |
sbs = to_acpi_device(dev)->driver_data; |
db1c291af ACPI: SBS: Make S... |
671 |
acpi_sbs_callback(sbs); |
722062334 ACPI: sbs: Common... |
672 673 |
return 0; } |
15029dd79 ACPI / SBS: fix S... |
674 675 |
#else #define acpi_sbs_resume NULL |
906924048 ACPI / PM: Fix un... |
676 |
#endif |
722062334 ACPI: sbs: Common... |
677 |
|
d202f77d2 ACPI: Use struct ... |
678 |
static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume); |
94f6c0860 ACPI: SBS: Add su... |
679 680 681 682 683 684 685 |
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, |
94f6c0860 ACPI: SBS: Add su... |
686 |
}, |
d202f77d2 ACPI: Use struct ... |
687 |
.drv.pm = &acpi_sbs_pm, |
94f6c0860 ACPI: SBS: Add su... |
688 |
}; |
3f86b8324 ACPI: add support... |
689 690 691 |
static int __init acpi_sbs_init(void) { int result = 0; |
b20d2aeb0 ACPI: skip smart ... |
692 693 |
if (acpi_disabled) return -ENODEV; |
2a68b995c ACPI / SBS: Remov... |
694 |
|
3f86b8324 ACPI: add support... |
695 |
result = acpi_bus_register_driver(&acpi_sbs_driver); |
2a68b995c ACPI / SBS: Remov... |
696 |
if (result < 0) |
635227ee8 ACPI: remove func... |
697 |
return -ENODEV; |
2a68b995c ACPI / SBS: Remov... |
698 |
|
635227ee8 ACPI: remove func... |
699 |
return 0; |
3f86b8324 ACPI: add support... |
700 701 702 703 |
} static void __exit acpi_sbs_exit(void) { |
3f86b8324 ACPI: add support... |
704 |
acpi_bus_unregister_driver(&acpi_sbs_driver); |
635227ee8 ACPI: remove func... |
705 |
return; |
3f86b8324 ACPI: add support... |
706 707 708 709 |
} module_init(acpi_sbs_init); module_exit(acpi_sbs_exit); |