blob: 63d43677f644bcc4c9d3aab0079167f35e7fdda8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04002 * battery.c - ACPI Battery Driver (Revision: 2.0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04004 * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
5 * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
7 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
8 *
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or (at
14 * your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 *
25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 */
27
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/types.h>
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040032#include <linux/jiffies.h>
Arjan van de Ven0f66af52009-01-10 14:19:05 -050033#include <linux/async.h>
Hector Martinbc76f902009-08-06 15:57:48 -070034#include <linux/dmi.h>
Alexander Mezinf43691c2014-06-04 02:01:23 +070035#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090036#include <linux/slab.h>
Kyle McMartin25be5822011-03-22 16:19:50 -040037#include <linux/suspend.h>
Kamil Iskra4000e622012-11-16 22:28:58 +010038#include <asm/unaligned.h>
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040039
Lan Tianyu3a670cc2014-05-04 11:07:25 +080040#ifdef CONFIG_ACPI_PROCFS_POWER
41#include <linux/proc_fs.h>
42#include <linux/seq_file.h>
43#include <asm/uaccess.h>
44#endif
45
Lv Zheng8b484632013-12-03 08:49:16 +080046#include <linux/acpi.h>
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040047#include <linux/power_supply.h>
48
Alexander Mezinf03be352014-03-12 00:58:46 +070049#include "battery.h"
50
Len Browna192a952009-07-28 16:45:54 -040051#define PREFIX "ACPI: "
52
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055#define ACPI_BATTERY_DEVICE_NAME "Battery"
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
Lan Tianyuae6f6182011-06-30 11:32:40 +080057/* Battery power unit: 0 means mW, 1 means mA */
58#define ACPI_BATTERY_POWER_UNIT_MA 1
59
Zhang Rui1ac5aaa2014-05-28 15:23:36 +080060#define ACPI_BATTERY_STATE_DISCHARGING 0x1
61#define ACPI_BATTERY_STATE_CHARGING 0x2
62#define ACPI_BATTERY_STATE_CRITICAL 0x4
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064#define _COMPONENT ACPI_BATTERY_COMPONENT
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030065
Len Brownf52fd662007-02-12 22:42:12 -050066ACPI_MODULE_NAME("battery");
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
Len Brownf52fd662007-02-12 22:42:12 -050068MODULE_AUTHOR("Paul Diefenbaugh");
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +040069MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
Len Brown7cda93e2007-02-12 23:50:02 -050070MODULE_DESCRIPTION("ACPI Battery Driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070071MODULE_LICENSE("GPL");
72
Lan Tianyua90b4032014-01-06 22:50:37 +080073static int battery_bix_broken_package;
Alexander Mezinf43691c2014-06-04 02:01:23 +070074static int battery_notification_delay_ms;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040075static unsigned int cache_time = 1000;
76module_param(cache_time, uint, 0644);
77MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030078
Lan Tianyu3a670cc2014-05-04 11:07:25 +080079#ifdef CONFIG_ACPI_PROCFS_POWER
80extern struct proc_dir_entry *acpi_lock_battery_dir(void);
81extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
82
83enum acpi_battery_files {
84 info_tag = 0,
85 state_tag,
86 alarm_tag,
87 ACPI_BATTERY_NUMFILES,
88};
89
90#endif
91
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040092static const struct acpi_device_id battery_device_ids[] = {
93 {"PNP0C0A", 0},
94 {"", 0},
95};
96
97MODULE_DEVICE_TABLE(acpi, battery_device_ids);
98
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +040099enum {
100 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400101 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +0800102 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e622012-11-16 22:28:58 +0100103 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
104 switches between mWh and mAh depending on whether the system
105 is running on battery or not. When mAh is the unit, most
106 reported values are incorrect and need to be adjusted by
107 10000/design_voltage. Verified on x201, t410, t410s, and x220.
108 Pre-2010 and 2012 models appear to always report in mWh and
109 are thus unaffected (tested with t42, t61, t500, x200, x300,
110 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
111 the 2011 models that fixes the issue (tested on x220 with a
112 post-1.29 BIOS), but as of Nov. 2012, no such update is
113 available for the 2010 models. */
114 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400115};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400116
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400117struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400118 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300119 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100120 struct power_supply *bat;
121 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400122 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400123 struct notifier_block pm_nb;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400124 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200125 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400126 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400127 int capacity_now;
128 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400129 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400130 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400131 int technology;
132 int design_voltage;
133 int design_capacity_warning;
134 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400135 int cycle_count;
136 int measurement_accuracy;
137 int max_sampling_time;
138 int min_sampling_time;
139 int max_averaging_interval;
140 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400141 int capacity_granularity_1;
142 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400143 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400144 char model_number[32];
145 char serial_number[32];
146 char type[32];
147 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400148 int state;
149 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400150 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151};
152
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100153#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400154
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000155static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400156{
157 return battery->device->status.battery_present;
158}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400159
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400160static int acpi_battery_technology(struct acpi_battery *battery)
161{
162 if (!strcasecmp("NiCd", battery->type))
163 return POWER_SUPPLY_TECHNOLOGY_NiCd;
164 if (!strcasecmp("NiMH", battery->type))
165 return POWER_SUPPLY_TECHNOLOGY_NiMH;
166 if (!strcasecmp("LION", battery->type))
167 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300168 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300169 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400170 if (!strcasecmp("LiP", battery->type))
171 return POWER_SUPPLY_TECHNOLOGY_LIPO;
172 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
173}
174
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300175static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400176
Richard Hughes56f382a2009-01-25 15:05:50 +0000177static int acpi_battery_is_charged(struct acpi_battery *battery)
178{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800179 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000180 if (battery->state != 0)
181 return 0;
182
183 /* battery not reporting charge */
184 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
185 battery->capacity_now == 0)
186 return 0;
187
188 /* good batteries update full_charge as the batteries degrade */
189 if (battery->full_charge_capacity == battery->capacity_now)
190 return 1;
191
192 /* fallback to using design values for broken batteries */
193 if (battery->design_capacity == battery->capacity_now)
194 return 1;
195
196 /* we don't do any sort of metric based on percentages */
197 return 0;
198}
199
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400200static int acpi_battery_get_property(struct power_supply *psy,
201 enum power_supply_property psp,
202 union power_supply_propval *val)
203{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200204 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400205 struct acpi_battery *battery = to_acpi_battery(psy);
206
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300207 if (acpi_battery_present(battery)) {
208 /* run battery update only if it is present */
209 acpi_battery_get_state(battery);
210 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400211 return -ENODEV;
212 switch (psp) {
213 case POWER_SUPPLY_PROP_STATUS:
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800214 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400215 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800216 else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400217 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000218 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400219 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800220 else
221 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400222 break;
223 case POWER_SUPPLY_PROP_PRESENT:
224 val->intval = acpi_battery_present(battery);
225 break;
226 case POWER_SUPPLY_PROP_TECHNOLOGY:
227 val->intval = acpi_battery_technology(battery);
228 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400229 case POWER_SUPPLY_PROP_CYCLE_COUNT:
230 val->intval = battery->cycle_count;
231 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400232 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200233 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
234 ret = -ENODEV;
235 else
236 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400237 break;
238 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200239 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
240 ret = -ENODEV;
241 else
242 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400243 break;
244 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400245 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200246 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
247 ret = -ENODEV;
248 else
249 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400250 break;
251 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
252 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200253 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
254 ret = -ENODEV;
255 else
256 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400257 break;
258 case POWER_SUPPLY_PROP_CHARGE_FULL:
259 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200260 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
261 ret = -ENODEV;
262 else
263 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400264 break;
265 case POWER_SUPPLY_PROP_CHARGE_NOW:
266 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200267 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
268 ret = -ENODEV;
269 else
270 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400271 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700272 case POWER_SUPPLY_PROP_CAPACITY:
273 if (battery->capacity_now && battery->full_charge_capacity)
274 val->intval = battery->capacity_now * 100/
275 battery->full_charge_capacity;
276 else
277 val->intval = 0;
278 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800279 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
280 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
281 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
282 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
283 (battery->capacity_now <= battery->alarm))
284 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
285 else if (acpi_battery_is_charged(battery))
286 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
287 else
288 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
289 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400290 case POWER_SUPPLY_PROP_MODEL_NAME:
291 val->strval = battery->model_number;
292 break;
293 case POWER_SUPPLY_PROP_MANUFACTURER:
294 val->strval = battery->oem_info;
295 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100296 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
297 val->strval = battery->serial_number;
298 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400299 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200300 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400301 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200302 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400303}
304
305static enum power_supply_property charge_battery_props[] = {
306 POWER_SUPPLY_PROP_STATUS,
307 POWER_SUPPLY_PROP_PRESENT,
308 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400309 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400310 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
311 POWER_SUPPLY_PROP_VOLTAGE_NOW,
312 POWER_SUPPLY_PROP_CURRENT_NOW,
313 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
314 POWER_SUPPLY_PROP_CHARGE_FULL,
315 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700316 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800317 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400318 POWER_SUPPLY_PROP_MODEL_NAME,
319 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100320 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400321};
322
323static enum power_supply_property energy_battery_props[] = {
324 POWER_SUPPLY_PROP_STATUS,
325 POWER_SUPPLY_PROP_PRESENT,
326 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400327 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400328 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
329 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400330 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400331 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
332 POWER_SUPPLY_PROP_ENERGY_FULL,
333 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700334 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800335 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400336 POWER_SUPPLY_PROP_MODEL_NAME,
337 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100338 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400339};
340
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800341#ifdef CONFIG_ACPI_PROCFS_POWER
342inline char *acpi_battery_units(struct acpi_battery *battery)
343{
344 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
345 "mA" : "mW";
346}
347#endif
348
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349/* --------------------------------------------------------------------------
350 Battery Management
351 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400352struct acpi_offsets {
353 size_t offset; /* offset inside struct acpi_sbs_battery */
354 u8 mode; /* int or string? */
355};
356
357static struct acpi_offsets state_offsets[] = {
358 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400359 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400360 {offsetof(struct acpi_battery, capacity_now), 0},
361 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400362};
363
364static struct acpi_offsets info_offsets[] = {
365 {offsetof(struct acpi_battery, power_unit), 0},
366 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400367 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400368 {offsetof(struct acpi_battery, technology), 0},
369 {offsetof(struct acpi_battery, design_voltage), 0},
370 {offsetof(struct acpi_battery, design_capacity_warning), 0},
371 {offsetof(struct acpi_battery, design_capacity_low), 0},
372 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
373 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
374 {offsetof(struct acpi_battery, model_number), 1},
375 {offsetof(struct acpi_battery, serial_number), 1},
376 {offsetof(struct acpi_battery, type), 1},
377 {offsetof(struct acpi_battery, oem_info), 1},
378};
379
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400380static struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200381 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400382 {offsetof(struct acpi_battery, power_unit), 0},
383 {offsetof(struct acpi_battery, design_capacity), 0},
384 {offsetof(struct acpi_battery, full_charge_capacity), 0},
385 {offsetof(struct acpi_battery, technology), 0},
386 {offsetof(struct acpi_battery, design_voltage), 0},
387 {offsetof(struct acpi_battery, design_capacity_warning), 0},
388 {offsetof(struct acpi_battery, design_capacity_low), 0},
389 {offsetof(struct acpi_battery, cycle_count), 0},
390 {offsetof(struct acpi_battery, measurement_accuracy), 0},
391 {offsetof(struct acpi_battery, max_sampling_time), 0},
392 {offsetof(struct acpi_battery, min_sampling_time), 0},
393 {offsetof(struct acpi_battery, max_averaging_interval), 0},
394 {offsetof(struct acpi_battery, min_averaging_interval), 0},
395 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
396 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
397 {offsetof(struct acpi_battery, model_number), 1},
398 {offsetof(struct acpi_battery, serial_number), 1},
399 {offsetof(struct acpi_battery, type), 1},
400 {offsetof(struct acpi_battery, oem_info), 1},
401};
402
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400403static int extract_package(struct acpi_battery *battery,
404 union acpi_object *package,
405 struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300406{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300407 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400408 union acpi_object *element;
409 if (package->type != ACPI_TYPE_PACKAGE)
410 return -EFAULT;
411 for (i = 0; i < num; ++i) {
412 if (package->package.count <= i)
413 return -EFAULT;
414 element = &package->package.elements[i];
415 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300416 u8 *ptr = (u8 *)battery + offsets[i].offset;
417 if (element->type == ACPI_TYPE_STRING ||
418 element->type == ACPI_TYPE_BUFFER)
419 strncpy(ptr, element->string.pointer, 32);
420 else if (element->type == ACPI_TYPE_INTEGER) {
421 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800422 sizeof(u64));
423 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400424 } else
425 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400426 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400427 int *x = (int *)((u8 *)battery + offsets[i].offset);
428 *x = (element->type == ACPI_TYPE_INTEGER) ?
429 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300430 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300431 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300432 return 0;
433}
434
435static int acpi_battery_get_status(struct acpi_battery *battery)
436{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400437 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300438 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
439 return -ENODEV;
440 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400441 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300442}
443
444static int acpi_battery_get_info(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400446 int result = -EFAULT;
Len Brown4be44fc2005-08-05 00:44:28 -0400447 acpi_status status = 0;
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000448 char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400449 "_BIX" : "_BIF";
450
Len Brown4be44fc2005-08-05 00:44:28 -0400451 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300453 if (!acpi_battery_present(battery))
454 return 0;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400455 mutex_lock(&battery->lock);
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400456 status = acpi_evaluate_object(battery->device->handle, name,
457 NULL, &buffer);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400458 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400459
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 if (ACPI_FAILURE(status)) {
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400461 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
Patrick Mocheld550d982006-06-27 00:41:40 -0400462 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 }
Lan Tianyua90b4032014-01-06 22:50:37 +0800464
465 if (battery_bix_broken_package)
466 result = extract_package(battery, buffer.pointer,
467 extended_info_offsets + 1,
468 ARRAY_SIZE(extended_info_offsets) - 1);
469 else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400470 result = extract_package(battery, buffer.pointer,
471 extended_info_offsets,
472 ARRAY_SIZE(extended_info_offsets));
473 else
474 result = extract_package(battery, buffer.pointer,
475 info_offsets, ARRAY_SIZE(info_offsets));
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400476 kfree(buffer.pointer);
Zhang Rui557d5862010-10-22 10:02:06 +0800477 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
478 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e622012-11-16 22:28:58 +0100479 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
480 battery->power_unit && battery->design_voltage) {
481 battery->design_capacity = battery->design_capacity *
482 10000 / battery->design_voltage;
483 battery->full_charge_capacity = battery->full_charge_capacity *
484 10000 / battery->design_voltage;
485 battery->design_capacity_warning =
486 battery->design_capacity_warning *
487 10000 / battery->design_voltage;
488 /* Curiously, design_capacity_low, unlike the rest of them,
489 is correct. */
490 /* capacity_granularity_* equal 1 on the systems tested, so
491 it's impossible to tell if they would need an adjustment
492 or not if their values were higher. */
493 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400494 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495}
496
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300497static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
Len Brown4be44fc2005-08-05 00:44:28 -0400499 int result = 0;
500 acpi_status status = 0;
501 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300503 if (!acpi_battery_present(battery))
504 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400506 if (battery->update_time &&
507 time_before(jiffies, battery->update_time +
508 msecs_to_jiffies(cache_time)))
509 return 0;
510
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400511 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400512 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400513 NULL, &buffer);
514 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400517 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400518 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400520
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400521 result = extract_package(battery, buffer.pointer,
522 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400523 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400524 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700525
Lan Tianyu55003b22011-06-30 11:33:12 +0800526 /* For buggy DSDTs that report negative 16-bit values for either
527 * charging or discharging current and/or report 0 as 65536
528 * due to bad math.
529 */
530 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
531 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
532 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700533 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100534 printk_once(KERN_WARNING FW_BUG
535 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800536 }
Hector Martinbc76f902009-08-06 15:57:48 -0700537
Zhang Rui557d5862010-10-22 10:02:06 +0800538 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
539 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
540 battery->capacity_now = (battery->capacity_now *
541 battery->full_charge_capacity) / 100;
Kamil Iskra4000e622012-11-16 22:28:58 +0100542 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
543 battery->power_unit && battery->design_voltage) {
544 battery->capacity_now = battery->capacity_now *
545 10000 / battery->design_voltage;
546 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400547 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548}
549
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400550static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551{
Len Brown4be44fc2005-08-05 00:44:28 -0400552 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400554 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400555 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300556 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400558 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800559 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
560 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400561 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400564 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400566 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400567 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568}
569
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300570static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300572 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800573 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400574 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400575 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400577 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400578 if (!battery->alarm)
579 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400580 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581}
582
Andrey Borzenkov508df922007-10-28 12:50:09 +0300583static ssize_t acpi_battery_alarm_show(struct device *dev,
584 struct device_attribute *attr,
585 char *buf)
586{
587 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
588 return sprintf(buf, "%d\n", battery->alarm * 1000);
589}
590
591static ssize_t acpi_battery_alarm_store(struct device *dev,
592 struct device_attribute *attr,
593 const char *buf, size_t count)
594{
595 unsigned long x;
596 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100597 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300598 battery->alarm = x/1000;
599 if (acpi_battery_present(battery))
600 acpi_battery_set_alarm(battery);
601 return count;
602}
603
604static struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700605 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300606 .show = acpi_battery_alarm_show,
607 .store = acpi_battery_alarm_store,
608};
609
610static int sysfs_add_battery(struct acpi_battery *battery)
611{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100612 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300613
Lan Tianyuae6f6182011-06-30 11:32:40 +0800614 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100615 battery->bat_desc.properties = charge_battery_props;
616 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300617 ARRAY_SIZE(charge_battery_props);
618 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100619 battery->bat_desc.properties = energy_battery_props;
620 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300621 ARRAY_SIZE(energy_battery_props);
622 }
623
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100624 battery->bat_desc.name = acpi_device_bid(battery->device);
625 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
626 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300627
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100628 battery->bat = power_supply_register_no_ws(&battery->device->dev,
629 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800630
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100631 if (IS_ERR(battery->bat)) {
632 int result = PTR_ERR(battery->bat);
633
634 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300635 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100636 }
637 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300638}
639
640static void sysfs_remove_battery(struct acpi_battery *battery)
641{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300642 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100643 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300644 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300645 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800646 }
647
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100648 device_remove_file(&battery->bat->dev, &alarm_attr);
649 power_supply_unregister(battery->bat);
650 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300651 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700652}
653
Kamil Iskra4000e622012-11-16 22:28:58 +0100654static void find_battery(const struct dmi_header *dm, void *private)
655{
656 struct acpi_battery *battery = (struct acpi_battery *)private;
657 /* Note: the hardcoded offsets below have been extracted from
658 the source code of dmidecode. */
659 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
660 const u8 *dmi_data = (const u8 *)(dm + 1);
661 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
662 if (dm->length >= 18)
663 dmi_capacity *= dmi_data[17];
664 if (battery->design_capacity * battery->design_voltage / 1000
665 != dmi_capacity &&
666 battery->design_capacity * 10 == dmi_capacity)
667 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
668 &battery->flags);
669 }
670}
671
Zhang Rui557d5862010-10-22 10:02:06 +0800672/*
673 * According to the ACPI spec, some kinds of primary batteries can
674 * report percentage battery remaining capacity directly to OS.
675 * In this case, it reports the Last Full Charged Capacity == 100
676 * and BatteryPresentRate == 0xFFFFFFFF.
677 *
678 * Now we found some battery reports percentage remaining capacity
679 * even if it's rechargeable.
680 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
681 *
682 * Handle this correctly so that they won't break userspace.
683 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800684static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800685{
686 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000687 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800688
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000689 if (battery->full_charge_capacity == 100 &&
690 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
691 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800692 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
693 battery->full_charge_capacity = battery->design_capacity;
694 battery->capacity_now = (battery->capacity_now *
695 battery->full_charge_capacity) / 100;
696 }
Kamil Iskra4000e622012-11-16 22:28:58 +0100697
698 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000699 return;
Kamil Iskra4000e622012-11-16 22:28:58 +0100700
701 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
702 const char *s;
703 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200704 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e622012-11-16 22:28:58 +0100705 dmi_walk(find_battery, battery);
706 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
707 &battery->flags) &&
708 battery->design_voltage) {
709 battery->design_capacity =
710 battery->design_capacity *
711 10000 / battery->design_voltage;
712 battery->full_charge_capacity =
713 battery->full_charge_capacity *
714 10000 / battery->design_voltage;
715 battery->design_capacity_warning =
716 battery->design_capacity_warning *
717 10000 / battery->design_voltage;
718 battery->capacity_now = battery->capacity_now *
719 10000 / battery->design_voltage;
720 }
721 }
722 }
Zhang Rui557d5862010-10-22 10:02:06 +0800723}
724
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800725static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500726{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300727 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500728 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300729 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300730 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300731 if (!acpi_battery_present(battery)) {
732 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500733 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300734 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300735 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800736
737 if (resume)
738 return 0;
739
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300740 if (!battery->update_time ||
741 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500742 result = acpi_battery_get_info(battery);
743 if (result)
744 return result;
745 acpi_battery_init_alarm(battery);
746 }
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100747 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100748 result = sysfs_add_battery(battery);
749 if (result)
750 return result;
751 }
Zhang Rui557d5862010-10-22 10:02:06 +0800752 result = acpi_battery_get_state(battery);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800753 if (result)
754 return result;
Lan Tianyu7b786222011-06-30 11:33:27 +0800755 acpi_battery_quirks(battery);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800756
757 /*
758 * Wakeup the system if battery is critical low
759 * or lower than the alarm level
760 */
761 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
762 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
763 (battery->capacity_now <= battery->alarm)))
764 pm_wakeup_event(&battery->device->dev, 0);
765
Zhang Rui557d5862010-10-22 10:02:06 +0800766 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500767}
768
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100769static void acpi_battery_refresh(struct acpi_battery *battery)
770{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100771 int power_unit;
772
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100773 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100774 return;
775
Andy Whitcroftc5971452012-05-03 14:48:26 +0100776 power_unit = battery->power_unit;
777
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100778 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100779
780 if (power_unit == battery->power_unit)
781 return;
782
783 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100784 sysfs_remove_battery(battery);
785 sysfs_add_battery(battery);
786}
787
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800789 FS Interface (/proc)
790 -------------------------------------------------------------------------- */
791
792#ifdef CONFIG_ACPI_PROCFS_POWER
793static struct proc_dir_entry *acpi_battery_dir;
794
795static int acpi_battery_print_info(struct seq_file *seq, int result)
796{
797 struct acpi_battery *battery = seq->private;
798
799 if (result)
800 goto end;
801
802 seq_printf(seq, "present: %s\n",
803 acpi_battery_present(battery) ? "yes" : "no");
804 if (!acpi_battery_present(battery))
805 goto end;
806 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
807 seq_printf(seq, "design capacity: unknown\n");
808 else
809 seq_printf(seq, "design capacity: %d %sh\n",
810 battery->design_capacity,
811 acpi_battery_units(battery));
812
813 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
814 seq_printf(seq, "last full capacity: unknown\n");
815 else
816 seq_printf(seq, "last full capacity: %d %sh\n",
817 battery->full_charge_capacity,
818 acpi_battery_units(battery));
819
820 seq_printf(seq, "battery technology: %srechargeable\n",
821 (!battery->technology)?"non-":"");
822
823 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
824 seq_printf(seq, "design voltage: unknown\n");
825 else
826 seq_printf(seq, "design voltage: %d mV\n",
827 battery->design_voltage);
828 seq_printf(seq, "design capacity warning: %d %sh\n",
829 battery->design_capacity_warning,
830 acpi_battery_units(battery));
831 seq_printf(seq, "design capacity low: %d %sh\n",
832 battery->design_capacity_low,
833 acpi_battery_units(battery));
834 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
835 seq_printf(seq, "capacity granularity 1: %d %sh\n",
836 battery->capacity_granularity_1,
837 acpi_battery_units(battery));
838 seq_printf(seq, "capacity granularity 2: %d %sh\n",
839 battery->capacity_granularity_2,
840 acpi_battery_units(battery));
841 seq_printf(seq, "model number: %s\n", battery->model_number);
842 seq_printf(seq, "serial number: %s\n", battery->serial_number);
843 seq_printf(seq, "battery type: %s\n", battery->type);
844 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
845 end:
846 if (result)
847 seq_printf(seq, "ERROR: Unable to read battery info\n");
848 return result;
849}
850
851static int acpi_battery_print_state(struct seq_file *seq, int result)
852{
853 struct acpi_battery *battery = seq->private;
854
855 if (result)
856 goto end;
857
858 seq_printf(seq, "present: %s\n",
859 acpi_battery_present(battery) ? "yes" : "no");
860 if (!acpi_battery_present(battery))
861 goto end;
862
863 seq_printf(seq, "capacity state: %s\n",
864 (battery->state & 0x04) ? "critical" : "ok");
865 if ((battery->state & 0x01) && (battery->state & 0x02))
866 seq_printf(seq,
867 "charging state: charging/discharging\n");
868 else if (battery->state & 0x01)
869 seq_printf(seq, "charging state: discharging\n");
870 else if (battery->state & 0x02)
871 seq_printf(seq, "charging state: charging\n");
872 else
873 seq_printf(seq, "charging state: charged\n");
874
875 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
876 seq_printf(seq, "present rate: unknown\n");
877 else
878 seq_printf(seq, "present rate: %d %s\n",
879 battery->rate_now, acpi_battery_units(battery));
880
881 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
882 seq_printf(seq, "remaining capacity: unknown\n");
883 else
884 seq_printf(seq, "remaining capacity: %d %sh\n",
885 battery->capacity_now, acpi_battery_units(battery));
886 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
887 seq_printf(seq, "present voltage: unknown\n");
888 else
889 seq_printf(seq, "present voltage: %d mV\n",
890 battery->voltage_now);
891 end:
892 if (result)
893 seq_printf(seq, "ERROR: Unable to read battery state\n");
894
895 return result;
896}
897
898static int acpi_battery_print_alarm(struct seq_file *seq, int result)
899{
900 struct acpi_battery *battery = seq->private;
901
902 if (result)
903 goto end;
904
905 if (!acpi_battery_present(battery)) {
906 seq_printf(seq, "present: no\n");
907 goto end;
908 }
909 seq_printf(seq, "alarm: ");
910 if (!battery->alarm)
911 seq_printf(seq, "unsupported\n");
912 else
913 seq_printf(seq, "%u %sh\n", battery->alarm,
914 acpi_battery_units(battery));
915 end:
916 if (result)
917 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
918 return result;
919}
920
921static ssize_t acpi_battery_write_alarm(struct file *file,
922 const char __user * buffer,
923 size_t count, loff_t * ppos)
924{
925 int result = 0;
926 char alarm_string[12] = { '\0' };
927 struct seq_file *m = file->private_data;
928 struct acpi_battery *battery = m->private;
929
930 if (!battery || (count > sizeof(alarm_string) - 1))
931 return -EINVAL;
932 if (!acpi_battery_present(battery)) {
933 result = -ENODEV;
934 goto end;
935 }
936 if (copy_from_user(alarm_string, buffer, count)) {
937 result = -EFAULT;
938 goto end;
939 }
940 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +0200941 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
942 result = -EINVAL;
943 goto end;
944 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800945 result = acpi_battery_set_alarm(battery);
946 end:
947 if (!result)
948 return count;
949 return result;
950}
951
952typedef int(*print_func)(struct seq_file *seq, int result);
953
954static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
955 acpi_battery_print_info,
956 acpi_battery_print_state,
957 acpi_battery_print_alarm,
958};
959
960static int acpi_battery_read(int fid, struct seq_file *seq)
961{
962 struct acpi_battery *battery = seq->private;
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800963 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800964 return acpi_print_funcs[fid](seq, result);
965}
966
967#define DECLARE_FILE_FUNCTIONS(_name) \
968static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
969{ \
970 return acpi_battery_read(_name##_tag, seq); \
971} \
972static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
973{ \
974 return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
975}
976
977DECLARE_FILE_FUNCTIONS(info);
978DECLARE_FILE_FUNCTIONS(state);
979DECLARE_FILE_FUNCTIONS(alarm);
980
981#undef DECLARE_FILE_FUNCTIONS
982
983#define FILE_DESCRIPTION_RO(_name) \
984 { \
985 .name = __stringify(_name), \
986 .mode = S_IRUGO, \
987 .ops = { \
988 .open = acpi_battery_##_name##_open_fs, \
989 .read = seq_read, \
990 .llseek = seq_lseek, \
991 .release = single_release, \
992 .owner = THIS_MODULE, \
993 }, \
994 }
995
996#define FILE_DESCRIPTION_RW(_name) \
997 { \
998 .name = __stringify(_name), \
999 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
1000 .ops = { \
1001 .open = acpi_battery_##_name##_open_fs, \
1002 .read = seq_read, \
1003 .llseek = seq_lseek, \
1004 .write = acpi_battery_write_##_name, \
1005 .release = single_release, \
1006 .owner = THIS_MODULE, \
1007 }, \
1008 }
1009
1010static const struct battery_file {
1011 struct file_operations ops;
1012 umode_t mode;
1013 const char *name;
1014} acpi_battery_file[] = {
1015 FILE_DESCRIPTION_RO(info),
1016 FILE_DESCRIPTION_RO(state),
1017 FILE_DESCRIPTION_RW(alarm),
1018};
1019
1020#undef FILE_DESCRIPTION_RO
1021#undef FILE_DESCRIPTION_RW
1022
1023static int acpi_battery_add_fs(struct acpi_device *device)
1024{
1025 struct proc_dir_entry *entry = NULL;
1026 int i;
1027
1028 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1029 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1030 if (!acpi_device_dir(device)) {
1031 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1032 acpi_battery_dir);
1033 if (!acpi_device_dir(device))
1034 return -ENODEV;
1035 }
1036
1037 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
1038 entry = proc_create_data(acpi_battery_file[i].name,
1039 acpi_battery_file[i].mode,
1040 acpi_device_dir(device),
1041 &acpi_battery_file[i].ops,
1042 acpi_driver_data(device));
1043 if (!entry)
1044 return -ENODEV;
1045 }
1046 return 0;
1047}
1048
1049static void acpi_battery_remove_fs(struct acpi_device *device)
1050{
1051 int i;
1052 if (!acpi_device_dir(device))
1053 return;
1054 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1055 remove_proc_entry(acpi_battery_file[i].name,
1056 acpi_device_dir(device));
1057
1058 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1059 acpi_device_dir(device) = NULL;
1060}
1061
1062#endif
1063
1064/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 Driver Interface
1066 -------------------------------------------------------------------------- */
1067
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001068static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001070 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001071 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001072
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001074 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001075 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001076 /*
1077 * On Acer Aspire V5-573G notifications are sometimes triggered too
1078 * early. For example, when AC is unplugged and notification is
1079 * triggered, battery state is still reported as "Full", and changes to
1080 * "Discharging" only after short delay, without any notification.
1081 */
1082 if (battery_notification_delay_ms > 0)
1083 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001084 if (event == ACPI_BATTERY_NOTIFY_INFO)
1085 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001086 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001087 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001088 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001089 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001090 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001091 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001092 if (old && battery->bat)
1093 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
Kyle McMartin25be5822011-03-22 16:19:50 -04001096static int battery_notify(struct notifier_block *nb,
1097 unsigned long mode, void *_unused)
1098{
1099 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1100 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001101 int result;
1102
Kyle McMartin25be5822011-03-22 16:19:50 -04001103 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001104 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001105 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001106 if (!acpi_battery_present(battery))
1107 return 0;
1108
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001109 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001110 result = acpi_battery_get_info(battery);
1111 if (result)
1112 return result;
1113
1114 result = sysfs_add_battery(battery);
1115 if (result)
1116 return result;
1117 } else
1118 acpi_battery_refresh(battery);
1119
1120 acpi_battery_init_alarm(battery);
1121 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001122 break;
1123 }
1124
1125 return 0;
1126}
1127
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001128static int battery_bix_broken_package_quirk(const struct dmi_system_id *d)
1129{
1130 battery_bix_broken_package = 1;
1131 return 0;
1132}
1133
Alexander Mezinf43691c2014-06-04 02:01:23 +07001134static int battery_notification_delay_quirk(const struct dmi_system_id *d)
1135{
1136 battery_notification_delay_ms = 1000;
1137 return 0;
1138}
1139
Lan Tianyua90b4032014-01-06 22:50:37 +08001140static struct dmi_system_id bat_dmi_table[] = {
1141 {
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001142 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001143 .ident = "NEC LZ750/LS",
1144 .matches = {
1145 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1146 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1147 },
1148 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001149 {
1150 .callback = battery_notification_delay_quirk,
1151 .ident = "Acer Aspire V5-573G",
1152 .matches = {
1153 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1154 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1155 },
1156 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001157 {},
1158};
1159
Lan Tianyu75646e72014-07-07 15:47:12 +08001160/*
1161 * Some machines'(E,G Lenovo Z480) ECs are not stable
1162 * during boot up and this causes battery driver fails to be
1163 * probed due to failure of getting battery information
1164 * from EC sometimes. After several retries, the operation
1165 * may work. So add retry code here and 20ms sleep between
1166 * every retries.
1167 */
1168static int acpi_battery_update_retry(struct acpi_battery *battery)
1169{
1170 int retry, ret;
1171
1172 for (retry = 5; retry; retry--) {
1173 ret = acpi_battery_update(battery, false);
1174 if (!ret)
1175 break;
1176
1177 msleep(20);
1178 }
1179 return ret;
1180}
1181
Len Brown4be44fc2005-08-05 00:44:28 -04001182static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183{
Len Brown4be44fc2005-08-05 00:44:28 -04001184 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001185 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001186
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001188 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001189
1190 if (device->dep_unmet)
1191 return -EPROBE_DEFER;
1192
Burman Yan36bcbec2006-12-19 12:56:11 -08001193 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001195 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001196 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1198 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001199 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001200 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001201 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001202 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001203 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001204
1205 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001206 if (result)
1207 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001208
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001209#ifdef CONFIG_ACPI_PROCFS_POWER
1210 result = acpi_battery_add_fs(device);
1211#endif
1212 if (result) {
1213#ifdef CONFIG_ACPI_PROCFS_POWER
1214 acpi_battery_remove_fs(device);
1215#endif
1216 goto fail;
1217 }
Kyle McMartin25be5822011-03-22 16:19:50 -04001218
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001219 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1220 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1221 device->status.battery_present ? "present" : "absent");
1222
Kyle McMartin25be5822011-03-22 16:19:50 -04001223 battery->pm_nb.notifier_call = battery_notify;
1224 register_pm_notifier(&battery->pm_nb);
1225
Zhang Ruie0d1f092014-05-28 15:23:38 +08001226 device_init_wakeup(&device->dev, 1);
1227
Patrick Mocheld550d982006-06-27 00:41:40 -04001228 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001229
1230fail:
1231 sysfs_remove_battery(battery);
1232 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001233 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001234 kfree(battery);
1235 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236}
1237
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001238static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239{
Len Brown4be44fc2005-08-05 00:44:28 -04001240 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001243 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001244 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001245 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001246 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001247#ifdef CONFIG_ACPI_PROCFS_POWER
1248 acpi_battery_remove_fs(device);
1249#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001250 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001251 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001252 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001254 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255}
1256
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001257#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001258/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001259static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001260{
1261 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001262
1263 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001264 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001265
1266 battery = acpi_driver_data(to_acpi_device(dev));
1267 if (!battery)
1268 return -EINVAL;
1269
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001270 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001271 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001272 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001273}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001274#else
1275#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001276#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001277
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001278static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1279
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001280static struct acpi_driver acpi_battery_driver = {
1281 .name = "battery",
1282 .class = ACPI_BATTERY_CLASS,
1283 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001284 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001285 .ops = {
1286 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001287 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001288 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001289 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001290 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001291};
1292
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001293static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294{
Pavel Machek4d8316d2006-08-14 22:37:22 -07001295 if (acpi_disabled)
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001296 return;
Lan Tianyua90b4032014-01-06 22:50:37 +08001297
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001298 dmi_check_system(bat_dmi_table);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001299
1300#ifdef CONFIG_ACPI_PROCFS_POWER
1301 acpi_battery_dir = acpi_lock_battery_dir();
1302 if (!acpi_battery_dir)
1303 return;
1304#endif
1305 if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
1306#ifdef CONFIG_ACPI_PROCFS_POWER
1307 acpi_unlock_battery_dir(acpi_battery_dir);
1308#endif
1309 return;
1310 }
1311 return;
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001312}
1313
1314static int __init acpi_battery_init(void)
1315{
1316 async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001317 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318}
1319
Len Brown4be44fc2005-08-05 00:44:28 -04001320static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 acpi_bus_unregister_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001323#ifdef CONFIG_ACPI_PROCFS_POWER
1324 acpi_unlock_battery_dir(acpi_battery_dir);
1325#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326}
1327
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328module_init(acpi_battery_init);
1329module_exit(acpi_battery_exit);