blob: bdb24d636d9acc9c1a0dedbb2f30c6e2ed381593 [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 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 */
23
Ognjen Galicfa938542018-02-07 15:58:13 +010024#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/kernel.h>
Ognjen Galicfa938542018-02-07 15:58:13 +010027#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/module.h>
Ognjen Galicfa938542018-02-07 15:58:13 +010029#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#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>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080043#include <linux/uaccess.h>
Lan Tianyu3a670cc2014-05-04 11:07:25 +080044#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
Ognjen Galicfa938542018-02-07 15:58:13 +010049#include <acpi/battery.h>
Alexander Mezinf03be352014-03-12 00:58:46 +070050
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
Luis Henriqueseca21d912015-05-11 22:49:05 +010073static async_cookie_t async_cookie;
Hans de Goedebc39fbc2017-04-19 14:02:09 +020074static bool battery_driver_registered;
Lan Tianyua90b4032014-01-06 22:50:37 +080075static int battery_bix_broken_package;
Alexander Mezinf43691c2014-06-04 02:01:23 +070076static int battery_notification_delay_ms;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040077static unsigned int cache_time = 1000;
78module_param(cache_time, uint, 0644);
79MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030080
Lan Tianyu3a670cc2014-05-04 11:07:25 +080081#ifdef CONFIG_ACPI_PROCFS_POWER
82extern struct proc_dir_entry *acpi_lock_battery_dir(void);
83extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
84
85enum acpi_battery_files {
86 info_tag = 0,
87 state_tag,
88 alarm_tag,
89 ACPI_BATTERY_NUMFILES,
90};
91
92#endif
93
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040094static const struct acpi_device_id battery_device_ids[] = {
95 {"PNP0C0A", 0},
96 {"", 0},
97};
98
99MODULE_DEVICE_TABLE(acpi, battery_device_ids);
100
Hans de Goededccfae62017-04-19 14:02:10 +0200101/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
102static const char * const acpi_battery_blacklist[] = {
103 "INT33F4", /* X-Powers AXP288 PMIC */
104};
105
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400106enum {
107 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400108 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +0800109 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e622012-11-16 22:28:58 +0100110 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
111 switches between mWh and mAh depending on whether the system
112 is running on battery or not. When mAh is the unit, most
113 reported values are incorrect and need to be adjusted by
114 10000/design_voltage. Verified on x201, t410, t410s, and x220.
115 Pre-2010 and 2012 models appear to always report in mWh and
116 are thus unaffected (tested with t42, t61, t500, x200, x300,
117 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
118 the 2011 models that fixes the issue (tested on x220 with a
119 post-1.29 BIOS), but as of Nov. 2012, no such update is
120 available for the 2010 models. */
121 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Laszlo Totha20136a2018-02-24 10:20:15 +0100122 /* for batteries reporting current capacity with design capacity
123 * on a full charge, but showing degradation in full charge cap.
124 */
125 ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400126};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400127
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400128struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400129 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300130 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100131 struct power_supply *bat;
132 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400133 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400134 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100135 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400136 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200137 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400138 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400139 int capacity_now;
140 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400141 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400142 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400143 int technology;
144 int design_voltage;
145 int design_capacity_warning;
146 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400147 int cycle_count;
148 int measurement_accuracy;
149 int max_sampling_time;
150 int min_sampling_time;
151 int max_averaging_interval;
152 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400153 int capacity_granularity_1;
154 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400155 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400156 char model_number[32];
157 char serial_number[32];
158 char type[32];
159 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400160 int state;
161 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400162 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163};
164
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100165#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400166
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000167static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400168{
169 return battery->device->status.battery_present;
170}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400171
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400172static int acpi_battery_technology(struct acpi_battery *battery)
173{
174 if (!strcasecmp("NiCd", battery->type))
175 return POWER_SUPPLY_TECHNOLOGY_NiCd;
176 if (!strcasecmp("NiMH", battery->type))
177 return POWER_SUPPLY_TECHNOLOGY_NiMH;
178 if (!strcasecmp("LION", battery->type))
179 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300180 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300181 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400182 if (!strcasecmp("LiP", battery->type))
183 return POWER_SUPPLY_TECHNOLOGY_LIPO;
184 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
185}
186
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300187static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400188
Richard Hughes56f382a2009-01-25 15:05:50 +0000189static int acpi_battery_is_charged(struct acpi_battery *battery)
190{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800191 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000192 if (battery->state != 0)
193 return 0;
194
195 /* battery not reporting charge */
196 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
197 battery->capacity_now == 0)
198 return 0;
199
200 /* good batteries update full_charge as the batteries degrade */
201 if (battery->full_charge_capacity == battery->capacity_now)
202 return 1;
203
204 /* fallback to using design values for broken batteries */
205 if (battery->design_capacity == battery->capacity_now)
206 return 1;
207
208 /* we don't do any sort of metric based on percentages */
209 return 0;
210}
211
Laszlo Totha20136a2018-02-24 10:20:15 +0100212static bool acpi_battery_is_degraded(struct acpi_battery *battery)
213{
214 return battery->full_charge_capacity && battery->design_capacity &&
215 battery->full_charge_capacity < battery->design_capacity;
216}
217
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400218static int acpi_battery_get_property(struct power_supply *psy,
219 enum power_supply_property psp,
220 union power_supply_propval *val)
221{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200222 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400223 struct acpi_battery *battery = to_acpi_battery(psy);
224
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300225 if (acpi_battery_present(battery)) {
226 /* run battery update only if it is present */
227 acpi_battery_get_state(battery);
228 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400229 return -ENODEV;
230 switch (psp) {
231 case POWER_SUPPLY_PROP_STATUS:
Daniel Drake82bf43b2018-03-14 16:42:17 +0800232 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
233 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
234 else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400235 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000236 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400237 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800238 else
239 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400240 break;
241 case POWER_SUPPLY_PROP_PRESENT:
242 val->intval = acpi_battery_present(battery);
243 break;
244 case POWER_SUPPLY_PROP_TECHNOLOGY:
245 val->intval = acpi_battery_technology(battery);
246 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400247 case POWER_SUPPLY_PROP_CYCLE_COUNT:
248 val->intval = battery->cycle_count;
249 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400250 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200251 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
252 ret = -ENODEV;
253 else
254 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400255 break;
256 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200257 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
258 ret = -ENODEV;
259 else
260 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400261 break;
262 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400263 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200264 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
265 ret = -ENODEV;
266 else
267 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400268 break;
269 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
270 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200271 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
272 ret = -ENODEV;
273 else
274 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400275 break;
276 case POWER_SUPPLY_PROP_CHARGE_FULL:
277 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200278 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
279 ret = -ENODEV;
280 else
281 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400282 break;
283 case POWER_SUPPLY_PROP_CHARGE_NOW:
284 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200285 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
286 ret = -ENODEV;
287 else
288 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400289 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700290 case POWER_SUPPLY_PROP_CAPACITY:
291 if (battery->capacity_now && battery->full_charge_capacity)
292 val->intval = battery->capacity_now * 100/
293 battery->full_charge_capacity;
294 else
295 val->intval = 0;
296 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800297 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
298 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
299 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
300 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
301 (battery->capacity_now <= battery->alarm))
302 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
303 else if (acpi_battery_is_charged(battery))
304 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
305 else
306 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
307 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400308 case POWER_SUPPLY_PROP_MODEL_NAME:
309 val->strval = battery->model_number;
310 break;
311 case POWER_SUPPLY_PROP_MANUFACTURER:
312 val->strval = battery->oem_info;
313 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100314 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
315 val->strval = battery->serial_number;
316 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400317 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200318 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400319 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200320 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400321}
322
323static enum power_supply_property charge_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,
330 POWER_SUPPLY_PROP_CURRENT_NOW,
331 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
332 POWER_SUPPLY_PROP_CHARGE_FULL,
333 POWER_SUPPLY_PROP_CHARGE_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
341static enum power_supply_property energy_battery_props[] = {
342 POWER_SUPPLY_PROP_STATUS,
343 POWER_SUPPLY_PROP_PRESENT,
344 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400345 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400346 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
347 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400348 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400349 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
350 POWER_SUPPLY_PROP_ENERGY_FULL,
351 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700352 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800353 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400354 POWER_SUPPLY_PROP_MODEL_NAME,
355 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100356 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400357};
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359/* --------------------------------------------------------------------------
360 Battery Management
361 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400362struct acpi_offsets {
363 size_t offset; /* offset inside struct acpi_sbs_battery */
364 u8 mode; /* int or string? */
365};
366
Mathias Krausea4658782015-06-13 14:26:53 +0200367static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400368 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400369 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400370 {offsetof(struct acpi_battery, capacity_now), 0},
371 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400372};
373
Mathias Krausea4658782015-06-13 14:26:53 +0200374static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400375 {offsetof(struct acpi_battery, power_unit), 0},
376 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400377 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400378 {offsetof(struct acpi_battery, technology), 0},
379 {offsetof(struct acpi_battery, design_voltage), 0},
380 {offsetof(struct acpi_battery, design_capacity_warning), 0},
381 {offsetof(struct acpi_battery, design_capacity_low), 0},
382 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
383 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
384 {offsetof(struct acpi_battery, model_number), 1},
385 {offsetof(struct acpi_battery, serial_number), 1},
386 {offsetof(struct acpi_battery, type), 1},
387 {offsetof(struct acpi_battery, oem_info), 1},
388};
389
Mathias Krausea4658782015-06-13 14:26:53 +0200390static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200391 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400392 {offsetof(struct acpi_battery, power_unit), 0},
393 {offsetof(struct acpi_battery, design_capacity), 0},
394 {offsetof(struct acpi_battery, full_charge_capacity), 0},
395 {offsetof(struct acpi_battery, technology), 0},
396 {offsetof(struct acpi_battery, design_voltage), 0},
397 {offsetof(struct acpi_battery, design_capacity_warning), 0},
398 {offsetof(struct acpi_battery, design_capacity_low), 0},
399 {offsetof(struct acpi_battery, cycle_count), 0},
400 {offsetof(struct acpi_battery, measurement_accuracy), 0},
401 {offsetof(struct acpi_battery, max_sampling_time), 0},
402 {offsetof(struct acpi_battery, min_sampling_time), 0},
403 {offsetof(struct acpi_battery, max_averaging_interval), 0},
404 {offsetof(struct acpi_battery, min_averaging_interval), 0},
405 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
406 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
407 {offsetof(struct acpi_battery, model_number), 1},
408 {offsetof(struct acpi_battery, serial_number), 1},
409 {offsetof(struct acpi_battery, type), 1},
410 {offsetof(struct acpi_battery, oem_info), 1},
411};
412
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400413static int extract_package(struct acpi_battery *battery,
414 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200415 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300416{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300417 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400418 union acpi_object *element;
419 if (package->type != ACPI_TYPE_PACKAGE)
420 return -EFAULT;
421 for (i = 0; i < num; ++i) {
422 if (package->package.count <= i)
423 return -EFAULT;
424 element = &package->package.elements[i];
425 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300426 u8 *ptr = (u8 *)battery + offsets[i].offset;
427 if (element->type == ACPI_TYPE_STRING ||
428 element->type == ACPI_TYPE_BUFFER)
429 strncpy(ptr, element->string.pointer, 32);
430 else if (element->type == ACPI_TYPE_INTEGER) {
431 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800432 sizeof(u64));
433 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400434 } else
435 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400436 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400437 int *x = (int *)((u8 *)battery + offsets[i].offset);
438 *x = (element->type == ACPI_TYPE_INTEGER) ?
439 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300440 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300441 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300442 return 0;
443}
444
445static int acpi_battery_get_status(struct acpi_battery *battery)
446{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400447 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300448 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
449 return -ENODEV;
450 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400451 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300452}
453
Dave Lambley2d09af42016-11-04 01:05:40 +0000454
455static int extract_battery_info(const int use_bix,
456 struct acpi_battery *battery,
457 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400459 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400460
Dave Lambley2d09af42016-11-04 01:05:40 +0000461 if (use_bix && battery_bix_broken_package)
462 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800463 extended_info_offsets + 1,
464 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000465 else if (use_bix)
466 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400467 extended_info_offsets,
468 ARRAY_SIZE(extended_info_offsets));
469 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000470 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400471 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800472 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
473 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e622012-11-16 22:28:58 +0100474 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
475 battery->power_unit && battery->design_voltage) {
476 battery->design_capacity = battery->design_capacity *
477 10000 / battery->design_voltage;
478 battery->full_charge_capacity = battery->full_charge_capacity *
479 10000 / battery->design_voltage;
480 battery->design_capacity_warning =
481 battery->design_capacity_warning *
482 10000 / battery->design_voltage;
483 /* Curiously, design_capacity_low, unlike the rest of them,
484 is correct. */
485 /* capacity_granularity_* equal 1 on the systems tested, so
486 it's impossible to tell if they would need an adjustment
487 or not if their values were higher. */
488 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100489 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
490 battery->capacity_now > battery->full_charge_capacity)
491 battery->capacity_now = battery->full_charge_capacity;
492
Patrick Mocheld550d982006-06-27 00:41:40 -0400493 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
Dave Lambley2d09af42016-11-04 01:05:40 +0000496static int acpi_battery_get_info(struct acpi_battery *battery)
497{
498 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
499 int use_bix;
500 int result = -ENODEV;
501
502 if (!acpi_battery_present(battery))
503 return 0;
504
505
506 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
507 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
508 acpi_status status = AE_ERROR;
509
510 mutex_lock(&battery->lock);
511 status = acpi_evaluate_object(battery->device->handle,
512 use_bix ? "_BIX":"_BIF",
513 NULL, &buffer);
514 mutex_unlock(&battery->lock);
515
516 if (ACPI_FAILURE(status)) {
517 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
518 use_bix ? "_BIX":"_BIF"));
519 } else {
520 result = extract_battery_info(use_bix,
521 battery,
522 &buffer);
523
524 kfree(buffer.pointer);
525 break;
526 }
527 }
528
529 if (!result && !use_bix && xinfo)
530 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
531
532 return result;
533}
534
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300535static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
Len Brown4be44fc2005-08-05 00:44:28 -0400537 int result = 0;
538 acpi_status status = 0;
539 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300541 if (!acpi_battery_present(battery))
542 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400544 if (battery->update_time &&
545 time_before(jiffies, battery->update_time +
546 msecs_to_jiffies(cache_time)))
547 return 0;
548
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400549 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400550 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400551 NULL, &buffer);
552 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400553
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400555 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400556 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400558
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400559 result = extract_package(battery, buffer.pointer,
560 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400561 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400562 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700563
Lan Tianyu55003b22011-06-30 11:33:12 +0800564 /* For buggy DSDTs that report negative 16-bit values for either
565 * charging or discharging current and/or report 0 as 65536
566 * due to bad math.
567 */
568 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
569 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
570 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700571 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100572 printk_once(KERN_WARNING FW_BUG
573 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800574 }
Hector Martinbc76f902009-08-06 15:57:48 -0700575
Zhang Rui557d5862010-10-22 10:02:06 +0800576 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
577 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
578 battery->capacity_now = (battery->capacity_now *
579 battery->full_charge_capacity) / 100;
Kamil Iskra4000e622012-11-16 22:28:58 +0100580 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
581 battery->power_unit && battery->design_voltage) {
582 battery->capacity_now = battery->capacity_now *
583 10000 / battery->design_voltage;
584 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100585 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
586 battery->capacity_now > battery->full_charge_capacity)
587 battery->capacity_now = battery->full_charge_capacity;
588
Patrick Mocheld550d982006-06-27 00:41:40 -0400589 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590}
591
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400592static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
Len Brown4be44fc2005-08-05 00:44:28 -0400594 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400596 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400597 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300598 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400600 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800601 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
602 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400603 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400606 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400608 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400609 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300612static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300614 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800615 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400616 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400617 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400619 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400620 if (!battery->alarm)
621 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400622 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623}
624
Andrey Borzenkov508df922007-10-28 12:50:09 +0300625static ssize_t acpi_battery_alarm_show(struct device *dev,
626 struct device_attribute *attr,
627 char *buf)
628{
629 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
630 return sprintf(buf, "%d\n", battery->alarm * 1000);
631}
632
633static ssize_t acpi_battery_alarm_store(struct device *dev,
634 struct device_attribute *attr,
635 const char *buf, size_t count)
636{
637 unsigned long x;
638 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100639 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300640 battery->alarm = x/1000;
641 if (acpi_battery_present(battery))
642 acpi_battery_set_alarm(battery);
643 return count;
644}
645
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530646static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700647 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300648 .show = acpi_battery_alarm_show,
649 .store = acpi_battery_alarm_store,
650};
651
Ognjen Galicfa938542018-02-07 15:58:13 +0100652/*
653 * The Battery Hooking API
654 *
655 * This API is used inside other drivers that need to expose
656 * platform-specific behaviour within the generic driver in a
657 * generic way.
658 *
659 */
660
661static LIST_HEAD(acpi_battery_list);
662static LIST_HEAD(battery_hook_list);
663static DEFINE_MUTEX(hook_mutex);
664
Colin Ian King514bcc52018-02-23 16:32:55 +0000665static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
Ognjen Galicfa938542018-02-07 15:58:13 +0100666{
667 struct acpi_battery *battery;
668 /*
669 * In order to remove a hook, we first need to
670 * de-register all the batteries that are registered.
671 */
672 if (lock)
673 mutex_lock(&hook_mutex);
674 list_for_each_entry(battery, &acpi_battery_list, list) {
675 hook->remove_battery(battery->bat);
676 }
677 list_del(&hook->list);
678 if (lock)
679 mutex_unlock(&hook_mutex);
680 pr_info("extension unregistered: %s\n", hook->name);
681}
682
683void battery_hook_unregister(struct acpi_battery_hook *hook)
684{
685 __battery_hook_unregister(hook, 1);
686}
687EXPORT_SYMBOL_GPL(battery_hook_unregister);
688
689void battery_hook_register(struct acpi_battery_hook *hook)
690{
691 struct acpi_battery *battery;
692
693 mutex_lock(&hook_mutex);
694 INIT_LIST_HEAD(&hook->list);
695 list_add(&hook->list, &battery_hook_list);
696 /*
697 * Now that the driver is registered, we need
698 * to notify the hook that a battery is available
699 * for each battery, so that the driver may add
700 * its attributes.
701 */
702 list_for_each_entry(battery, &acpi_battery_list, list) {
703 if (hook->add_battery(battery->bat)) {
704 /*
705 * If a add-battery returns non-zero,
706 * the registration of the extension has failed,
707 * and we will not add it to the list of loaded
708 * hooks.
709 */
710 pr_err("extension failed to load: %s", hook->name);
711 __battery_hook_unregister(hook, 0);
712 return;
713 }
714 }
715 pr_info("new extension: %s\n", hook->name);
716 mutex_unlock(&hook_mutex);
717}
718EXPORT_SYMBOL_GPL(battery_hook_register);
719
720/*
721 * This function gets called right after the battery sysfs
722 * attributes have been added, so that the drivers that
723 * define custom sysfs attributes can add their own.
Rafael J. Wysocki7a4ea102018-03-13 10:07:49 +0100724*/
Ognjen Galicfa938542018-02-07 15:58:13 +0100725static void battery_hook_add_battery(struct acpi_battery *battery)
726{
727 struct acpi_battery_hook *hook_node;
728
729 mutex_lock(&hook_mutex);
730 INIT_LIST_HEAD(&battery->list);
731 list_add(&battery->list, &acpi_battery_list);
732 /*
733 * Since we added a new battery to the list, we need to
734 * iterate over the hooks and call add_battery for each
735 * hook that was registered. This usually happens
736 * when a battery gets hotplugged or initialized
737 * during the battery module initialization.
738 */
739 list_for_each_entry(hook_node, &battery_hook_list, list) {
740 if (hook_node->add_battery(battery->bat)) {
741 /*
742 * The notification of the extensions has failed, to
743 * prevent further errors we will unload the extension.
744 */
745 __battery_hook_unregister(hook_node, 0);
746 pr_err("error in extension, unloading: %s",
747 hook_node->name);
748 }
749 }
750 mutex_unlock(&hook_mutex);
751}
752
753static void battery_hook_remove_battery(struct acpi_battery *battery)
754{
755 struct acpi_battery_hook *hook;
756
757 mutex_lock(&hook_mutex);
758 /*
759 * Before removing the hook, we need to remove all
760 * custom attributes from the battery.
761 */
762 list_for_each_entry(hook, &battery_hook_list, list) {
763 hook->remove_battery(battery->bat);
764 }
765 /* Then, just remove the battery from the list */
766 list_del(&battery->list);
767 mutex_unlock(&hook_mutex);
768}
769
770static void __exit battery_hook_exit(void)
771{
772 struct acpi_battery_hook *hook;
773 struct acpi_battery_hook *ptr;
774 /*
775 * At this point, the acpi_bus_unregister_driver()
776 * has called remove for all batteries. We just
777 * need to remove the hooks.
778 */
779 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
780 __battery_hook_unregister(hook, 1);
781 }
782 mutex_destroy(&hook_mutex);
783}
784
Andrey Borzenkov508df922007-10-28 12:50:09 +0300785static int sysfs_add_battery(struct acpi_battery *battery)
786{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100787 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300788
Lan Tianyuae6f6182011-06-30 11:32:40 +0800789 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100790 battery->bat_desc.properties = charge_battery_props;
791 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300792 ARRAY_SIZE(charge_battery_props);
793 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100794 battery->bat_desc.properties = energy_battery_props;
795 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300796 ARRAY_SIZE(energy_battery_props);
797 }
798
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100799 battery->bat_desc.name = acpi_device_bid(battery->device);
800 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
801 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300802
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100803 battery->bat = power_supply_register_no_ws(&battery->device->dev,
804 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800805
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100806 if (IS_ERR(battery->bat)) {
807 int result = PTR_ERR(battery->bat);
808
809 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300810 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100811 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100812 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100813 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300814}
815
816static void sysfs_remove_battery(struct acpi_battery *battery)
817{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300818 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100819 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300820 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300821 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800822 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100823 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100824 device_remove_file(&battery->bat->dev, &alarm_attr);
825 power_supply_unregister(battery->bat);
826 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300827 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700828}
829
Kamil Iskra4000e622012-11-16 22:28:58 +0100830static void find_battery(const struct dmi_header *dm, void *private)
831{
832 struct acpi_battery *battery = (struct acpi_battery *)private;
833 /* Note: the hardcoded offsets below have been extracted from
834 the source code of dmidecode. */
835 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
836 const u8 *dmi_data = (const u8 *)(dm + 1);
837 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
838 if (dm->length >= 18)
839 dmi_capacity *= dmi_data[17];
840 if (battery->design_capacity * battery->design_voltage / 1000
841 != dmi_capacity &&
842 battery->design_capacity * 10 == dmi_capacity)
843 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
844 &battery->flags);
845 }
846}
847
Zhang Rui557d5862010-10-22 10:02:06 +0800848/*
849 * According to the ACPI spec, some kinds of primary batteries can
850 * report percentage battery remaining capacity directly to OS.
851 * In this case, it reports the Last Full Charged Capacity == 100
852 * and BatteryPresentRate == 0xFFFFFFFF.
853 *
854 * Now we found some battery reports percentage remaining capacity
855 * even if it's rechargeable.
856 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
857 *
858 * Handle this correctly so that they won't break userspace.
859 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800860static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800861{
862 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000863 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800864
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000865 if (battery->full_charge_capacity == 100 &&
866 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
867 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800868 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
869 battery->full_charge_capacity = battery->design_capacity;
870 battery->capacity_now = (battery->capacity_now *
871 battery->full_charge_capacity) / 100;
872 }
Kamil Iskra4000e622012-11-16 22:28:58 +0100873
874 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000875 return;
Kamil Iskra4000e622012-11-16 22:28:58 +0100876
877 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
878 const char *s;
879 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200880 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e622012-11-16 22:28:58 +0100881 dmi_walk(find_battery, battery);
882 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
883 &battery->flags) &&
884 battery->design_voltage) {
885 battery->design_capacity =
886 battery->design_capacity *
887 10000 / battery->design_voltage;
888 battery->full_charge_capacity =
889 battery->full_charge_capacity *
890 10000 / battery->design_voltage;
891 battery->design_capacity_warning =
892 battery->design_capacity_warning *
893 10000 / battery->design_voltage;
894 battery->capacity_now = battery->capacity_now *
895 10000 / battery->design_voltage;
896 }
897 }
898 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100899
900 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
901 return;
902
903 if (acpi_battery_is_degraded(battery) &&
904 battery->capacity_now > battery->full_charge_capacity) {
905 set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
906 battery->capacity_now = battery->full_charge_capacity;
907 }
Zhang Rui557d5862010-10-22 10:02:06 +0800908}
909
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800910static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500911{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300912 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500913 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300914 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300915 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300916 if (!acpi_battery_present(battery)) {
917 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500918 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300919 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300920 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800921
922 if (resume)
923 return 0;
924
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300925 if (!battery->update_time ||
926 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500927 result = acpi_battery_get_info(battery);
928 if (result)
929 return result;
930 acpi_battery_init_alarm(battery);
931 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200932
933 result = acpi_battery_get_state(battery);
934 if (result)
935 return result;
936 acpi_battery_quirks(battery);
937
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100938 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100939 result = sysfs_add_battery(battery);
940 if (result)
941 return result;
942 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800943
944 /*
945 * Wakeup the system if battery is critical low
946 * or lower than the alarm level
947 */
948 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
949 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
950 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200951 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800952
Zhang Rui557d5862010-10-22 10:02:06 +0800953 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500954}
955
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100956static void acpi_battery_refresh(struct acpi_battery *battery)
957{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100958 int power_unit;
959
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100960 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100961 return;
962
Andy Whitcroftc5971452012-05-03 14:48:26 +0100963 power_unit = battery->power_unit;
964
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100965 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100966
967 if (power_unit == battery->power_unit)
968 return;
969
970 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100971 sysfs_remove_battery(battery);
972 sysfs_add_battery(battery);
973}
974
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800976 FS Interface (/proc)
977 -------------------------------------------------------------------------- */
978
979#ifdef CONFIG_ACPI_PROCFS_POWER
980static struct proc_dir_entry *acpi_battery_dir;
981
Mathias Krause27059b92015-06-13 14:26:54 +0200982static const char *acpi_battery_units(const struct acpi_battery *battery)
983{
984 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
985 "mA" : "mW";
986}
987
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800988static int acpi_battery_print_info(struct seq_file *seq, int result)
989{
990 struct acpi_battery *battery = seq->private;
991
992 if (result)
993 goto end;
994
995 seq_printf(seq, "present: %s\n",
996 acpi_battery_present(battery) ? "yes" : "no");
997 if (!acpi_battery_present(battery))
998 goto end;
999 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1000 seq_printf(seq, "design capacity: unknown\n");
1001 else
1002 seq_printf(seq, "design capacity: %d %sh\n",
1003 battery->design_capacity,
1004 acpi_battery_units(battery));
1005
1006 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1007 seq_printf(seq, "last full capacity: unknown\n");
1008 else
1009 seq_printf(seq, "last full capacity: %d %sh\n",
1010 battery->full_charge_capacity,
1011 acpi_battery_units(battery));
1012
1013 seq_printf(seq, "battery technology: %srechargeable\n",
1014 (!battery->technology)?"non-":"");
1015
1016 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1017 seq_printf(seq, "design voltage: unknown\n");
1018 else
1019 seq_printf(seq, "design voltage: %d mV\n",
1020 battery->design_voltage);
1021 seq_printf(seq, "design capacity warning: %d %sh\n",
1022 battery->design_capacity_warning,
1023 acpi_battery_units(battery));
1024 seq_printf(seq, "design capacity low: %d %sh\n",
1025 battery->design_capacity_low,
1026 acpi_battery_units(battery));
1027 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1028 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1029 battery->capacity_granularity_1,
1030 acpi_battery_units(battery));
1031 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1032 battery->capacity_granularity_2,
1033 acpi_battery_units(battery));
1034 seq_printf(seq, "model number: %s\n", battery->model_number);
1035 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1036 seq_printf(seq, "battery type: %s\n", battery->type);
1037 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1038 end:
1039 if (result)
1040 seq_printf(seq, "ERROR: Unable to read battery info\n");
1041 return result;
1042}
1043
1044static int acpi_battery_print_state(struct seq_file *seq, int result)
1045{
1046 struct acpi_battery *battery = seq->private;
1047
1048 if (result)
1049 goto end;
1050
1051 seq_printf(seq, "present: %s\n",
1052 acpi_battery_present(battery) ? "yes" : "no");
1053 if (!acpi_battery_present(battery))
1054 goto end;
1055
1056 seq_printf(seq, "capacity state: %s\n",
1057 (battery->state & 0x04) ? "critical" : "ok");
1058 if ((battery->state & 0x01) && (battery->state & 0x02))
1059 seq_printf(seq,
1060 "charging state: charging/discharging\n");
1061 else if (battery->state & 0x01)
1062 seq_printf(seq, "charging state: discharging\n");
1063 else if (battery->state & 0x02)
1064 seq_printf(seq, "charging state: charging\n");
1065 else
1066 seq_printf(seq, "charging state: charged\n");
1067
1068 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1069 seq_printf(seq, "present rate: unknown\n");
1070 else
1071 seq_printf(seq, "present rate: %d %s\n",
1072 battery->rate_now, acpi_battery_units(battery));
1073
1074 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1075 seq_printf(seq, "remaining capacity: unknown\n");
1076 else
1077 seq_printf(seq, "remaining capacity: %d %sh\n",
1078 battery->capacity_now, acpi_battery_units(battery));
1079 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1080 seq_printf(seq, "present voltage: unknown\n");
1081 else
1082 seq_printf(seq, "present voltage: %d mV\n",
1083 battery->voltage_now);
1084 end:
1085 if (result)
1086 seq_printf(seq, "ERROR: Unable to read battery state\n");
1087
1088 return result;
1089}
1090
1091static int acpi_battery_print_alarm(struct seq_file *seq, int result)
1092{
1093 struct acpi_battery *battery = seq->private;
1094
1095 if (result)
1096 goto end;
1097
1098 if (!acpi_battery_present(battery)) {
1099 seq_printf(seq, "present: no\n");
1100 goto end;
1101 }
1102 seq_printf(seq, "alarm: ");
1103 if (!battery->alarm)
1104 seq_printf(seq, "unsupported\n");
1105 else
1106 seq_printf(seq, "%u %sh\n", battery->alarm,
1107 acpi_battery_units(battery));
1108 end:
1109 if (result)
1110 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1111 return result;
1112}
1113
1114static ssize_t acpi_battery_write_alarm(struct file *file,
1115 const char __user * buffer,
1116 size_t count, loff_t * ppos)
1117{
1118 int result = 0;
1119 char alarm_string[12] = { '\0' };
1120 struct seq_file *m = file->private_data;
1121 struct acpi_battery *battery = m->private;
1122
1123 if (!battery || (count > sizeof(alarm_string) - 1))
1124 return -EINVAL;
1125 if (!acpi_battery_present(battery)) {
1126 result = -ENODEV;
1127 goto end;
1128 }
1129 if (copy_from_user(alarm_string, buffer, count)) {
1130 result = -EFAULT;
1131 goto end;
1132 }
1133 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001134 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1135 result = -EINVAL;
1136 goto end;
1137 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001138 result = acpi_battery_set_alarm(battery);
1139 end:
1140 if (!result)
1141 return count;
1142 return result;
1143}
1144
1145typedef int(*print_func)(struct seq_file *seq, int result);
1146
1147static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
1148 acpi_battery_print_info,
1149 acpi_battery_print_state,
1150 acpi_battery_print_alarm,
1151};
1152
1153static int acpi_battery_read(int fid, struct seq_file *seq)
1154{
1155 struct acpi_battery *battery = seq->private;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001156 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001157 return acpi_print_funcs[fid](seq, result);
1158}
1159
1160#define DECLARE_FILE_FUNCTIONS(_name) \
1161static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
1162{ \
1163 return acpi_battery_read(_name##_tag, seq); \
1164} \
1165static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
1166{ \
1167 return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
1168}
1169
1170DECLARE_FILE_FUNCTIONS(info);
1171DECLARE_FILE_FUNCTIONS(state);
1172DECLARE_FILE_FUNCTIONS(alarm);
1173
1174#undef DECLARE_FILE_FUNCTIONS
1175
1176#define FILE_DESCRIPTION_RO(_name) \
1177 { \
1178 .name = __stringify(_name), \
1179 .mode = S_IRUGO, \
1180 .ops = { \
1181 .open = acpi_battery_##_name##_open_fs, \
1182 .read = seq_read, \
1183 .llseek = seq_lseek, \
1184 .release = single_release, \
1185 .owner = THIS_MODULE, \
1186 }, \
1187 }
1188
1189#define FILE_DESCRIPTION_RW(_name) \
1190 { \
1191 .name = __stringify(_name), \
1192 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
1193 .ops = { \
1194 .open = acpi_battery_##_name##_open_fs, \
1195 .read = seq_read, \
1196 .llseek = seq_lseek, \
1197 .write = acpi_battery_write_##_name, \
1198 .release = single_release, \
1199 .owner = THIS_MODULE, \
1200 }, \
1201 }
1202
1203static const struct battery_file {
1204 struct file_operations ops;
1205 umode_t mode;
1206 const char *name;
1207} acpi_battery_file[] = {
1208 FILE_DESCRIPTION_RO(info),
1209 FILE_DESCRIPTION_RO(state),
1210 FILE_DESCRIPTION_RW(alarm),
1211};
1212
1213#undef FILE_DESCRIPTION_RO
1214#undef FILE_DESCRIPTION_RW
1215
1216static int acpi_battery_add_fs(struct acpi_device *device)
1217{
1218 struct proc_dir_entry *entry = NULL;
1219 int i;
1220
1221 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1222 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1223 if (!acpi_device_dir(device)) {
1224 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1225 acpi_battery_dir);
1226 if (!acpi_device_dir(device))
1227 return -ENODEV;
1228 }
1229
1230 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
1231 entry = proc_create_data(acpi_battery_file[i].name,
1232 acpi_battery_file[i].mode,
1233 acpi_device_dir(device),
1234 &acpi_battery_file[i].ops,
1235 acpi_driver_data(device));
1236 if (!entry)
1237 return -ENODEV;
1238 }
1239 return 0;
1240}
1241
1242static void acpi_battery_remove_fs(struct acpi_device *device)
1243{
1244 int i;
1245 if (!acpi_device_dir(device))
1246 return;
1247 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1248 remove_proc_entry(acpi_battery_file[i].name,
1249 acpi_device_dir(device));
1250
1251 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1252 acpi_device_dir(device) = NULL;
1253}
1254
1255#endif
1256
1257/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 Driver Interface
1259 -------------------------------------------------------------------------- */
1260
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001261static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001263 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001264 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001265
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001267 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001268 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001269 /*
1270 * On Acer Aspire V5-573G notifications are sometimes triggered too
1271 * early. For example, when AC is unplugged and notification is
1272 * triggered, battery state is still reported as "Full", and changes to
1273 * "Discharging" only after short delay, without any notification.
1274 */
1275 if (battery_notification_delay_ms > 0)
1276 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001277 if (event == ACPI_BATTERY_NOTIFY_INFO)
1278 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001279 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001280 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001281 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001282 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001283 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001284 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001285 if (old && battery->bat)
1286 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287}
1288
Kyle McMartin25be5822011-03-22 16:19:50 -04001289static int battery_notify(struct notifier_block *nb,
1290 unsigned long mode, void *_unused)
1291{
1292 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1293 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001294 int result;
1295
Kyle McMartin25be5822011-03-22 16:19:50 -04001296 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001297 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001298 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001299 if (!acpi_battery_present(battery))
1300 return 0;
1301
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001302 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001303 result = acpi_battery_get_info(battery);
1304 if (result)
1305 return result;
1306
1307 result = sysfs_add_battery(battery);
1308 if (result)
1309 return result;
1310 } else
1311 acpi_battery_refresh(battery);
1312
1313 acpi_battery_init_alarm(battery);
1314 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001315 break;
1316 }
1317
1318 return 0;
1319}
1320
Mathias Krause048d16d2015-06-13 14:26:55 +02001321static int __init
1322battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001323{
1324 battery_bix_broken_package = 1;
1325 return 0;
1326}
1327
Mathias Krause048d16d2015-06-13 14:26:55 +02001328static int __init
1329battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001330{
1331 battery_notification_delay_ms = 1000;
1332 return 0;
1333}
1334
Mathias Krause048d16d2015-06-13 14:26:55 +02001335static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001336 {
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001337 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001338 .ident = "NEC LZ750/LS",
1339 .matches = {
1340 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1341 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1342 },
1343 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001344 {
1345 .callback = battery_notification_delay_quirk,
1346 .ident = "Acer Aspire V5-573G",
1347 .matches = {
1348 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1349 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1350 },
1351 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001352 {},
1353};
1354
Lan Tianyu75646e72014-07-07 15:47:12 +08001355/*
1356 * Some machines'(E,G Lenovo Z480) ECs are not stable
1357 * during boot up and this causes battery driver fails to be
1358 * probed due to failure of getting battery information
1359 * from EC sometimes. After several retries, the operation
1360 * may work. So add retry code here and 20ms sleep between
1361 * every retries.
1362 */
1363static int acpi_battery_update_retry(struct acpi_battery *battery)
1364{
1365 int retry, ret;
1366
1367 for (retry = 5; retry; retry--) {
1368 ret = acpi_battery_update(battery, false);
1369 if (!ret)
1370 break;
1371
1372 msleep(20);
1373 }
1374 return ret;
1375}
1376
Len Brown4be44fc2005-08-05 00:44:28 -04001377static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378{
Len Brown4be44fc2005-08-05 00:44:28 -04001379 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001380 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001383 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001384
1385 if (device->dep_unmet)
1386 return -EPROBE_DEFER;
1387
Burman Yan36bcbec2006-12-19 12:56:11 -08001388 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001390 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001391 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1393 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001394 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001395 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001396 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001397 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001398 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001399
1400 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001401 if (result)
1402 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001403
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001404#ifdef CONFIG_ACPI_PROCFS_POWER
1405 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001406 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001407 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001408 goto fail;
1409 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001410#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001411
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001412 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1413 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1414 device->status.battery_present ? "present" : "absent");
1415
Kyle McMartin25be5822011-03-22 16:19:50 -04001416 battery->pm_nb.notifier_call = battery_notify;
1417 register_pm_notifier(&battery->pm_nb);
1418
Zhang Ruie0d1f092014-05-28 15:23:38 +08001419 device_init_wakeup(&device->dev, 1);
1420
Patrick Mocheld550d982006-06-27 00:41:40 -04001421 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001422
1423fail:
1424 sysfs_remove_battery(battery);
1425 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001426 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001427 kfree(battery);
1428 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429}
1430
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001431static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Len Brown4be44fc2005-08-05 00:44:28 -04001433 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001436 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001437 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001438 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001439 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001440#ifdef CONFIG_ACPI_PROCFS_POWER
1441 acpi_battery_remove_fs(device);
1442#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001443 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001444 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001445 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001447 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448}
1449
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001450#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001451/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001452static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001453{
1454 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001455
1456 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001457 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001458
1459 battery = acpi_driver_data(to_acpi_device(dev));
1460 if (!battery)
1461 return -EINVAL;
1462
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001463 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001464 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001465 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001466}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001467#else
1468#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001469#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001470
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001471static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1472
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001473static struct acpi_driver acpi_battery_driver = {
1474 .name = "battery",
1475 .class = ACPI_BATTERY_CLASS,
1476 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001477 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001478 .ops = {
1479 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001480 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001481 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001482 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001483 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001484};
1485
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001486static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487{
Hans de Goededccfae62017-04-19 14:02:10 +02001488 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001489 int result;
1490
Hans de Goededccfae62017-04-19 14:02:10 +02001491 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1492 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1493 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1494 ": found native %s PMIC, not loading\n",
1495 acpi_battery_blacklist[i]);
1496 return;
1497 }
1498
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001499 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001500
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001501#ifdef CONFIG_ACPI_PROCFS_POWER
1502 acpi_battery_dir = acpi_lock_battery_dir();
1503 if (!acpi_battery_dir)
1504 return;
1505#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001506 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001507#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001508 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001509 acpi_unlock_battery_dir(acpi_battery_dir);
1510#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001511 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001512}
1513
1514static int __init acpi_battery_init(void)
1515{
Luis Henriquese234b072015-05-11 22:48:38 +01001516 if (acpi_disabled)
1517 return -ENODEV;
1518
Luis Henriqueseca21d912015-05-11 22:49:05 +01001519 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001520 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521}
1522
Len Brown4be44fc2005-08-05 00:44:28 -04001523static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001525 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001526 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001527 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001528 battery_hook_exit();
1529 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001530#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001531 if (acpi_battery_dir)
1532 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001533#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534}
1535
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536module_init(acpi_battery_init);
1537module_exit(acpi_battery_exit);