blob: f14a2bb1f7cdebfa8fd9f3ec5bf0e0d594ca0815 [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;
Kai-Heng Fengc68f0672017-11-21 03:33:06 -050077static int battery_full_discharging;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040078static unsigned int cache_time = 1000;
79module_param(cache_time, uint, 0644);
80MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030081
Lan Tianyu3a670cc2014-05-04 11:07:25 +080082#ifdef CONFIG_ACPI_PROCFS_POWER
83extern struct proc_dir_entry *acpi_lock_battery_dir(void);
84extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
85
86enum acpi_battery_files {
87 info_tag = 0,
88 state_tag,
89 alarm_tag,
90 ACPI_BATTERY_NUMFILES,
91};
92
93#endif
94
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040095static const struct acpi_device_id battery_device_ids[] = {
96 {"PNP0C0A", 0},
97 {"", 0},
98};
99
100MODULE_DEVICE_TABLE(acpi, battery_device_ids);
101
Hans de Goededccfae62017-04-19 14:02:10 +0200102/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
103static const char * const acpi_battery_blacklist[] = {
104 "INT33F4", /* X-Powers AXP288 PMIC */
105};
106
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400107enum {
108 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400109 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +0800110 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e622012-11-16 22:28:58 +0100111 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
112 switches between mWh and mAh depending on whether the system
113 is running on battery or not. When mAh is the unit, most
114 reported values are incorrect and need to be adjusted by
115 10000/design_voltage. Verified on x201, t410, t410s, and x220.
116 Pre-2010 and 2012 models appear to always report in mWh and
117 are thus unaffected (tested with t42, t61, t500, x200, x300,
118 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
119 the 2011 models that fixes the issue (tested on x220 with a
120 post-1.29 BIOS), but as of Nov. 2012, no such update is
121 available for the 2010 models. */
122 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400123};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400124
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400125struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400126 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300127 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100128 struct power_supply *bat;
129 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400130 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400131 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100132 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400133 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200134 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400135 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400136 int capacity_now;
137 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400138 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400139 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400140 int technology;
141 int design_voltage;
142 int design_capacity_warning;
143 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400144 int cycle_count;
145 int measurement_accuracy;
146 int max_sampling_time;
147 int min_sampling_time;
148 int max_averaging_interval;
149 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400150 int capacity_granularity_1;
151 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400152 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400153 char model_number[32];
154 char serial_number[32];
155 char type[32];
156 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400157 int state;
158 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400159 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160};
161
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100162#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400163
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000164static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400165{
166 return battery->device->status.battery_present;
167}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400168
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400169static int acpi_battery_technology(struct acpi_battery *battery)
170{
171 if (!strcasecmp("NiCd", battery->type))
172 return POWER_SUPPLY_TECHNOLOGY_NiCd;
173 if (!strcasecmp("NiMH", battery->type))
174 return POWER_SUPPLY_TECHNOLOGY_NiMH;
175 if (!strcasecmp("LION", battery->type))
176 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300177 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300178 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400179 if (!strcasecmp("LiP", battery->type))
180 return POWER_SUPPLY_TECHNOLOGY_LIPO;
181 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
182}
183
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300184static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400185
Richard Hughes56f382a2009-01-25 15:05:50 +0000186static int acpi_battery_is_charged(struct acpi_battery *battery)
187{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800188 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000189 if (battery->state != 0)
190 return 0;
191
192 /* battery not reporting charge */
193 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
194 battery->capacity_now == 0)
195 return 0;
196
197 /* good batteries update full_charge as the batteries degrade */
198 if (battery->full_charge_capacity == battery->capacity_now)
199 return 1;
200
201 /* fallback to using design values for broken batteries */
202 if (battery->design_capacity == battery->capacity_now)
203 return 1;
204
205 /* we don't do any sort of metric based on percentages */
206 return 0;
207}
208
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400209static int acpi_battery_get_property(struct power_supply *psy,
210 enum power_supply_property psp,
211 union power_supply_propval *val)
212{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200213 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400214 struct acpi_battery *battery = to_acpi_battery(psy);
215
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300216 if (acpi_battery_present(battery)) {
217 /* run battery update only if it is present */
218 acpi_battery_get_state(battery);
219 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400220 return -ENODEV;
221 switch (psp) {
222 case POWER_SUPPLY_PROP_STATUS:
Kai-Heng Fengc68f0672017-11-21 03:33:06 -0500223 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) {
224 if (battery_full_discharging && battery->rate_now == 0)
225 val->intval = POWER_SUPPLY_STATUS_FULL;
226 else
227 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
228 } else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400229 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000230 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400231 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800232 else
233 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400234 break;
235 case POWER_SUPPLY_PROP_PRESENT:
236 val->intval = acpi_battery_present(battery);
237 break;
238 case POWER_SUPPLY_PROP_TECHNOLOGY:
239 val->intval = acpi_battery_technology(battery);
240 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400241 case POWER_SUPPLY_PROP_CYCLE_COUNT:
242 val->intval = battery->cycle_count;
243 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400244 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200245 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
246 ret = -ENODEV;
247 else
248 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400249 break;
250 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200251 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
252 ret = -ENODEV;
253 else
254 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400255 break;
256 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400257 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200258 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
259 ret = -ENODEV;
260 else
261 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400262 break;
263 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
264 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200265 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
266 ret = -ENODEV;
267 else
268 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400269 break;
270 case POWER_SUPPLY_PROP_CHARGE_FULL:
271 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200272 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
273 ret = -ENODEV;
274 else
275 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400276 break;
277 case POWER_SUPPLY_PROP_CHARGE_NOW:
278 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200279 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
280 ret = -ENODEV;
281 else
282 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400283 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700284 case POWER_SUPPLY_PROP_CAPACITY:
285 if (battery->capacity_now && battery->full_charge_capacity)
286 val->intval = battery->capacity_now * 100/
287 battery->full_charge_capacity;
288 else
289 val->intval = 0;
290 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800291 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
292 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
293 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
294 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
295 (battery->capacity_now <= battery->alarm))
296 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
297 else if (acpi_battery_is_charged(battery))
298 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
299 else
300 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
301 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400302 case POWER_SUPPLY_PROP_MODEL_NAME:
303 val->strval = battery->model_number;
304 break;
305 case POWER_SUPPLY_PROP_MANUFACTURER:
306 val->strval = battery->oem_info;
307 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100308 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
309 val->strval = battery->serial_number;
310 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400311 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200312 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400313 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200314 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400315}
316
317static enum power_supply_property charge_battery_props[] = {
318 POWER_SUPPLY_PROP_STATUS,
319 POWER_SUPPLY_PROP_PRESENT,
320 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400321 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400322 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
323 POWER_SUPPLY_PROP_VOLTAGE_NOW,
324 POWER_SUPPLY_PROP_CURRENT_NOW,
325 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
326 POWER_SUPPLY_PROP_CHARGE_FULL,
327 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700328 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800329 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400330 POWER_SUPPLY_PROP_MODEL_NAME,
331 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100332 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400333};
334
335static enum power_supply_property energy_battery_props[] = {
336 POWER_SUPPLY_PROP_STATUS,
337 POWER_SUPPLY_PROP_PRESENT,
338 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400339 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400340 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
341 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400342 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400343 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
344 POWER_SUPPLY_PROP_ENERGY_FULL,
345 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700346 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800347 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400348 POWER_SUPPLY_PROP_MODEL_NAME,
349 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100350 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400351};
352
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353/* --------------------------------------------------------------------------
354 Battery Management
355 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400356struct acpi_offsets {
357 size_t offset; /* offset inside struct acpi_sbs_battery */
358 u8 mode; /* int or string? */
359};
360
Mathias Krausea4658782015-06-13 14:26:53 +0200361static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400362 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400363 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400364 {offsetof(struct acpi_battery, capacity_now), 0},
365 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400366};
367
Mathias Krausea4658782015-06-13 14:26:53 +0200368static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400369 {offsetof(struct acpi_battery, power_unit), 0},
370 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400371 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400372 {offsetof(struct acpi_battery, technology), 0},
373 {offsetof(struct acpi_battery, design_voltage), 0},
374 {offsetof(struct acpi_battery, design_capacity_warning), 0},
375 {offsetof(struct acpi_battery, design_capacity_low), 0},
376 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
377 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
378 {offsetof(struct acpi_battery, model_number), 1},
379 {offsetof(struct acpi_battery, serial_number), 1},
380 {offsetof(struct acpi_battery, type), 1},
381 {offsetof(struct acpi_battery, oem_info), 1},
382};
383
Mathias Krausea4658782015-06-13 14:26:53 +0200384static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200385 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400386 {offsetof(struct acpi_battery, power_unit), 0},
387 {offsetof(struct acpi_battery, design_capacity), 0},
388 {offsetof(struct acpi_battery, full_charge_capacity), 0},
389 {offsetof(struct acpi_battery, technology), 0},
390 {offsetof(struct acpi_battery, design_voltage), 0},
391 {offsetof(struct acpi_battery, design_capacity_warning), 0},
392 {offsetof(struct acpi_battery, design_capacity_low), 0},
393 {offsetof(struct acpi_battery, cycle_count), 0},
394 {offsetof(struct acpi_battery, measurement_accuracy), 0},
395 {offsetof(struct acpi_battery, max_sampling_time), 0},
396 {offsetof(struct acpi_battery, min_sampling_time), 0},
397 {offsetof(struct acpi_battery, max_averaging_interval), 0},
398 {offsetof(struct acpi_battery, min_averaging_interval), 0},
399 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
400 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
401 {offsetof(struct acpi_battery, model_number), 1},
402 {offsetof(struct acpi_battery, serial_number), 1},
403 {offsetof(struct acpi_battery, type), 1},
404 {offsetof(struct acpi_battery, oem_info), 1},
405};
406
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400407static int extract_package(struct acpi_battery *battery,
408 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200409 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300410{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300411 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400412 union acpi_object *element;
413 if (package->type != ACPI_TYPE_PACKAGE)
414 return -EFAULT;
415 for (i = 0; i < num; ++i) {
416 if (package->package.count <= i)
417 return -EFAULT;
418 element = &package->package.elements[i];
419 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300420 u8 *ptr = (u8 *)battery + offsets[i].offset;
421 if (element->type == ACPI_TYPE_STRING ||
422 element->type == ACPI_TYPE_BUFFER)
423 strncpy(ptr, element->string.pointer, 32);
424 else if (element->type == ACPI_TYPE_INTEGER) {
425 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800426 sizeof(u64));
427 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400428 } else
429 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400430 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400431 int *x = (int *)((u8 *)battery + offsets[i].offset);
432 *x = (element->type == ACPI_TYPE_INTEGER) ?
433 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300434 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300435 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300436 return 0;
437}
438
439static int acpi_battery_get_status(struct acpi_battery *battery)
440{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400441 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300442 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
443 return -ENODEV;
444 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400445 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300446}
447
Dave Lambley2d09af42016-11-04 01:05:40 +0000448
449static int extract_battery_info(const int use_bix,
450 struct acpi_battery *battery,
451 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400453 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400454
Dave Lambley2d09af42016-11-04 01:05:40 +0000455 if (use_bix && battery_bix_broken_package)
456 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800457 extended_info_offsets + 1,
458 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000459 else if (use_bix)
460 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400461 extended_info_offsets,
462 ARRAY_SIZE(extended_info_offsets));
463 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000464 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400465 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800466 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
467 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e622012-11-16 22:28:58 +0100468 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
469 battery->power_unit && battery->design_voltage) {
470 battery->design_capacity = battery->design_capacity *
471 10000 / battery->design_voltage;
472 battery->full_charge_capacity = battery->full_charge_capacity *
473 10000 / battery->design_voltage;
474 battery->design_capacity_warning =
475 battery->design_capacity_warning *
476 10000 / battery->design_voltage;
477 /* Curiously, design_capacity_low, unlike the rest of them,
478 is correct. */
479 /* capacity_granularity_* equal 1 on the systems tested, so
480 it's impossible to tell if they would need an adjustment
481 or not if their values were higher. */
482 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400483 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484}
485
Dave Lambley2d09af42016-11-04 01:05:40 +0000486static int acpi_battery_get_info(struct acpi_battery *battery)
487{
488 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
489 int use_bix;
490 int result = -ENODEV;
491
492 if (!acpi_battery_present(battery))
493 return 0;
494
495
496 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
497 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
498 acpi_status status = AE_ERROR;
499
500 mutex_lock(&battery->lock);
501 status = acpi_evaluate_object(battery->device->handle,
502 use_bix ? "_BIX":"_BIF",
503 NULL, &buffer);
504 mutex_unlock(&battery->lock);
505
506 if (ACPI_FAILURE(status)) {
507 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
508 use_bix ? "_BIX":"_BIF"));
509 } else {
510 result = extract_battery_info(use_bix,
511 battery,
512 &buffer);
513
514 kfree(buffer.pointer);
515 break;
516 }
517 }
518
519 if (!result && !use_bix && xinfo)
520 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
521
522 return result;
523}
524
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300525static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
Len Brown4be44fc2005-08-05 00:44:28 -0400527 int result = 0;
528 acpi_status status = 0;
529 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300531 if (!acpi_battery_present(battery))
532 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400534 if (battery->update_time &&
535 time_before(jiffies, battery->update_time +
536 msecs_to_jiffies(cache_time)))
537 return 0;
538
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400539 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400540 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400541 NULL, &buffer);
542 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400543
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400545 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400546 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400548
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400549 result = extract_package(battery, buffer.pointer,
550 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400551 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400552 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700553
Lan Tianyu55003b22011-06-30 11:33:12 +0800554 /* For buggy DSDTs that report negative 16-bit values for either
555 * charging or discharging current and/or report 0 as 65536
556 * due to bad math.
557 */
558 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
559 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
560 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700561 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100562 printk_once(KERN_WARNING FW_BUG
563 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800564 }
Hector Martinbc76f902009-08-06 15:57:48 -0700565
Zhang Rui557d5862010-10-22 10:02:06 +0800566 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
567 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
568 battery->capacity_now = (battery->capacity_now *
569 battery->full_charge_capacity) / 100;
Kamil Iskra4000e622012-11-16 22:28:58 +0100570 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
571 battery->power_unit && battery->design_voltage) {
572 battery->capacity_now = battery->capacity_now *
573 10000 / battery->design_voltage;
574 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400575 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576}
577
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400578static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
Len Brown4be44fc2005-08-05 00:44:28 -0400580 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400582 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400583 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300584 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400586 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800587 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
588 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400589 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400590
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400592 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400594 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400595 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596}
597
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300598static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300600 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800601 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400602 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400603 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400605 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400606 if (!battery->alarm)
607 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400608 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609}
610
Andrey Borzenkov508df922007-10-28 12:50:09 +0300611static ssize_t acpi_battery_alarm_show(struct device *dev,
612 struct device_attribute *attr,
613 char *buf)
614{
615 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
616 return sprintf(buf, "%d\n", battery->alarm * 1000);
617}
618
619static ssize_t acpi_battery_alarm_store(struct device *dev,
620 struct device_attribute *attr,
621 const char *buf, size_t count)
622{
623 unsigned long x;
624 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100625 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300626 battery->alarm = x/1000;
627 if (acpi_battery_present(battery))
628 acpi_battery_set_alarm(battery);
629 return count;
630}
631
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530632static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700633 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300634 .show = acpi_battery_alarm_show,
635 .store = acpi_battery_alarm_store,
636};
637
Ognjen Galicfa938542018-02-07 15:58:13 +0100638/*
639 * The Battery Hooking API
640 *
641 * This API is used inside other drivers that need to expose
642 * platform-specific behaviour within the generic driver in a
643 * generic way.
644 *
645 */
646
647static LIST_HEAD(acpi_battery_list);
648static LIST_HEAD(battery_hook_list);
649static DEFINE_MUTEX(hook_mutex);
650
651void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
652{
653 struct acpi_battery *battery;
654 /*
655 * In order to remove a hook, we first need to
656 * de-register all the batteries that are registered.
657 */
658 if (lock)
659 mutex_lock(&hook_mutex);
660 list_for_each_entry(battery, &acpi_battery_list, list) {
661 hook->remove_battery(battery->bat);
662 }
663 list_del(&hook->list);
664 if (lock)
665 mutex_unlock(&hook_mutex);
666 pr_info("extension unregistered: %s\n", hook->name);
667}
668
669void battery_hook_unregister(struct acpi_battery_hook *hook)
670{
671 __battery_hook_unregister(hook, 1);
672}
673EXPORT_SYMBOL_GPL(battery_hook_unregister);
674
675void battery_hook_register(struct acpi_battery_hook *hook)
676{
677 struct acpi_battery *battery;
678
679 mutex_lock(&hook_mutex);
680 INIT_LIST_HEAD(&hook->list);
681 list_add(&hook->list, &battery_hook_list);
682 /*
683 * Now that the driver is registered, we need
684 * to notify the hook that a battery is available
685 * for each battery, so that the driver may add
686 * its attributes.
687 */
688 list_for_each_entry(battery, &acpi_battery_list, list) {
689 if (hook->add_battery(battery->bat)) {
690 /*
691 * If a add-battery returns non-zero,
692 * the registration of the extension has failed,
693 * and we will not add it to the list of loaded
694 * hooks.
695 */
696 pr_err("extension failed to load: %s", hook->name);
697 __battery_hook_unregister(hook, 0);
698 return;
699 }
700 }
701 pr_info("new extension: %s\n", hook->name);
702 mutex_unlock(&hook_mutex);
703}
704EXPORT_SYMBOL_GPL(battery_hook_register);
705
706/*
707 * This function gets called right after the battery sysfs
708 * attributes have been added, so that the drivers that
709 * define custom sysfs attributes can add their own.
710*/
711static void battery_hook_add_battery(struct acpi_battery *battery)
712{
713 struct acpi_battery_hook *hook_node;
714
715 mutex_lock(&hook_mutex);
716 INIT_LIST_HEAD(&battery->list);
717 list_add(&battery->list, &acpi_battery_list);
718 /*
719 * Since we added a new battery to the list, we need to
720 * iterate over the hooks and call add_battery for each
721 * hook that was registered. This usually happens
722 * when a battery gets hotplugged or initialized
723 * during the battery module initialization.
724 */
725 list_for_each_entry(hook_node, &battery_hook_list, list) {
726 if (hook_node->add_battery(battery->bat)) {
727 /*
728 * The notification of the extensions has failed, to
729 * prevent further errors we will unload the extension.
730 */
731 __battery_hook_unregister(hook_node, 0);
732 pr_err("error in extension, unloading: %s",
733 hook_node->name);
734 }
735 }
736 mutex_unlock(&hook_mutex);
737}
738
739static void battery_hook_remove_battery(struct acpi_battery *battery)
740{
741 struct acpi_battery_hook *hook;
742
743 mutex_lock(&hook_mutex);
744 /*
745 * Before removing the hook, we need to remove all
746 * custom attributes from the battery.
747 */
748 list_for_each_entry(hook, &battery_hook_list, list) {
749 hook->remove_battery(battery->bat);
750 }
751 /* Then, just remove the battery from the list */
752 list_del(&battery->list);
753 mutex_unlock(&hook_mutex);
754}
755
756static void __exit battery_hook_exit(void)
757{
758 struct acpi_battery_hook *hook;
759 struct acpi_battery_hook *ptr;
760 /*
761 * At this point, the acpi_bus_unregister_driver()
762 * has called remove for all batteries. We just
763 * need to remove the hooks.
764 */
765 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
766 __battery_hook_unregister(hook, 1);
767 }
768 mutex_destroy(&hook_mutex);
769}
770
Andrey Borzenkov508df922007-10-28 12:50:09 +0300771static int sysfs_add_battery(struct acpi_battery *battery)
772{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100773 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300774
Lan Tianyuae6f6182011-06-30 11:32:40 +0800775 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100776 battery->bat_desc.properties = charge_battery_props;
777 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300778 ARRAY_SIZE(charge_battery_props);
779 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100780 battery->bat_desc.properties = energy_battery_props;
781 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300782 ARRAY_SIZE(energy_battery_props);
783 }
784
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100785 battery->bat_desc.name = acpi_device_bid(battery->device);
786 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
787 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300788
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100789 battery->bat = power_supply_register_no_ws(&battery->device->dev,
790 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800791
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100792 if (IS_ERR(battery->bat)) {
793 int result = PTR_ERR(battery->bat);
794
795 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300796 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100797 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100798 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100799 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300800}
801
802static void sysfs_remove_battery(struct acpi_battery *battery)
803{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300804 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100805 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300806 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300807 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800808 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100809 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100810 device_remove_file(&battery->bat->dev, &alarm_attr);
811 power_supply_unregister(battery->bat);
812 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300813 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700814}
815
Kamil Iskra4000e622012-11-16 22:28:58 +0100816static void find_battery(const struct dmi_header *dm, void *private)
817{
818 struct acpi_battery *battery = (struct acpi_battery *)private;
819 /* Note: the hardcoded offsets below have been extracted from
820 the source code of dmidecode. */
821 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
822 const u8 *dmi_data = (const u8 *)(dm + 1);
823 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
824 if (dm->length >= 18)
825 dmi_capacity *= dmi_data[17];
826 if (battery->design_capacity * battery->design_voltage / 1000
827 != dmi_capacity &&
828 battery->design_capacity * 10 == dmi_capacity)
829 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
830 &battery->flags);
831 }
832}
833
Zhang Rui557d5862010-10-22 10:02:06 +0800834/*
835 * According to the ACPI spec, some kinds of primary batteries can
836 * report percentage battery remaining capacity directly to OS.
837 * In this case, it reports the Last Full Charged Capacity == 100
838 * and BatteryPresentRate == 0xFFFFFFFF.
839 *
840 * Now we found some battery reports percentage remaining capacity
841 * even if it's rechargeable.
842 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
843 *
844 * Handle this correctly so that they won't break userspace.
845 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800846static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800847{
848 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000849 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800850
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000851 if (battery->full_charge_capacity == 100 &&
852 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
853 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800854 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
855 battery->full_charge_capacity = battery->design_capacity;
856 battery->capacity_now = (battery->capacity_now *
857 battery->full_charge_capacity) / 100;
858 }
Kamil Iskra4000e622012-11-16 22:28:58 +0100859
860 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000861 return;
Kamil Iskra4000e622012-11-16 22:28:58 +0100862
863 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
864 const char *s;
865 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200866 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e622012-11-16 22:28:58 +0100867 dmi_walk(find_battery, battery);
868 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
869 &battery->flags) &&
870 battery->design_voltage) {
871 battery->design_capacity =
872 battery->design_capacity *
873 10000 / battery->design_voltage;
874 battery->full_charge_capacity =
875 battery->full_charge_capacity *
876 10000 / battery->design_voltage;
877 battery->design_capacity_warning =
878 battery->design_capacity_warning *
879 10000 / battery->design_voltage;
880 battery->capacity_now = battery->capacity_now *
881 10000 / battery->design_voltage;
882 }
883 }
884 }
Zhang Rui557d5862010-10-22 10:02:06 +0800885}
886
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800887static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500888{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300889 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500890 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300891 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300892 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300893 if (!acpi_battery_present(battery)) {
894 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500895 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300896 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300897 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800898
899 if (resume)
900 return 0;
901
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300902 if (!battery->update_time ||
903 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500904 result = acpi_battery_get_info(battery);
905 if (result)
906 return result;
907 acpi_battery_init_alarm(battery);
908 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200909
910 result = acpi_battery_get_state(battery);
911 if (result)
912 return result;
913 acpi_battery_quirks(battery);
914
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100915 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100916 result = sysfs_add_battery(battery);
917 if (result)
918 return result;
919 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800920
921 /*
922 * Wakeup the system if battery is critical low
923 * or lower than the alarm level
924 */
925 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
926 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
927 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200928 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800929
Zhang Rui557d5862010-10-22 10:02:06 +0800930 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500931}
932
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100933static void acpi_battery_refresh(struct acpi_battery *battery)
934{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100935 int power_unit;
936
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100937 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100938 return;
939
Andy Whitcroftc5971452012-05-03 14:48:26 +0100940 power_unit = battery->power_unit;
941
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100942 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100943
944 if (power_unit == battery->power_unit)
945 return;
946
947 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100948 sysfs_remove_battery(battery);
949 sysfs_add_battery(battery);
950}
951
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800953 FS Interface (/proc)
954 -------------------------------------------------------------------------- */
955
956#ifdef CONFIG_ACPI_PROCFS_POWER
957static struct proc_dir_entry *acpi_battery_dir;
958
Mathias Krause27059b92015-06-13 14:26:54 +0200959static const char *acpi_battery_units(const struct acpi_battery *battery)
960{
961 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
962 "mA" : "mW";
963}
964
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800965static int acpi_battery_print_info(struct seq_file *seq, int result)
966{
967 struct acpi_battery *battery = seq->private;
968
969 if (result)
970 goto end;
971
972 seq_printf(seq, "present: %s\n",
973 acpi_battery_present(battery) ? "yes" : "no");
974 if (!acpi_battery_present(battery))
975 goto end;
976 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
977 seq_printf(seq, "design capacity: unknown\n");
978 else
979 seq_printf(seq, "design capacity: %d %sh\n",
980 battery->design_capacity,
981 acpi_battery_units(battery));
982
983 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
984 seq_printf(seq, "last full capacity: unknown\n");
985 else
986 seq_printf(seq, "last full capacity: %d %sh\n",
987 battery->full_charge_capacity,
988 acpi_battery_units(battery));
989
990 seq_printf(seq, "battery technology: %srechargeable\n",
991 (!battery->technology)?"non-":"");
992
993 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
994 seq_printf(seq, "design voltage: unknown\n");
995 else
996 seq_printf(seq, "design voltage: %d mV\n",
997 battery->design_voltage);
998 seq_printf(seq, "design capacity warning: %d %sh\n",
999 battery->design_capacity_warning,
1000 acpi_battery_units(battery));
1001 seq_printf(seq, "design capacity low: %d %sh\n",
1002 battery->design_capacity_low,
1003 acpi_battery_units(battery));
1004 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1005 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1006 battery->capacity_granularity_1,
1007 acpi_battery_units(battery));
1008 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1009 battery->capacity_granularity_2,
1010 acpi_battery_units(battery));
1011 seq_printf(seq, "model number: %s\n", battery->model_number);
1012 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1013 seq_printf(seq, "battery type: %s\n", battery->type);
1014 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1015 end:
1016 if (result)
1017 seq_printf(seq, "ERROR: Unable to read battery info\n");
1018 return result;
1019}
1020
1021static int acpi_battery_print_state(struct seq_file *seq, int result)
1022{
1023 struct acpi_battery *battery = seq->private;
1024
1025 if (result)
1026 goto end;
1027
1028 seq_printf(seq, "present: %s\n",
1029 acpi_battery_present(battery) ? "yes" : "no");
1030 if (!acpi_battery_present(battery))
1031 goto end;
1032
1033 seq_printf(seq, "capacity state: %s\n",
1034 (battery->state & 0x04) ? "critical" : "ok");
1035 if ((battery->state & 0x01) && (battery->state & 0x02))
1036 seq_printf(seq,
1037 "charging state: charging/discharging\n");
1038 else if (battery->state & 0x01)
1039 seq_printf(seq, "charging state: discharging\n");
1040 else if (battery->state & 0x02)
1041 seq_printf(seq, "charging state: charging\n");
1042 else
1043 seq_printf(seq, "charging state: charged\n");
1044
1045 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1046 seq_printf(seq, "present rate: unknown\n");
1047 else
1048 seq_printf(seq, "present rate: %d %s\n",
1049 battery->rate_now, acpi_battery_units(battery));
1050
1051 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1052 seq_printf(seq, "remaining capacity: unknown\n");
1053 else
1054 seq_printf(seq, "remaining capacity: %d %sh\n",
1055 battery->capacity_now, acpi_battery_units(battery));
1056 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1057 seq_printf(seq, "present voltage: unknown\n");
1058 else
1059 seq_printf(seq, "present voltage: %d mV\n",
1060 battery->voltage_now);
1061 end:
1062 if (result)
1063 seq_printf(seq, "ERROR: Unable to read battery state\n");
1064
1065 return result;
1066}
1067
1068static int acpi_battery_print_alarm(struct seq_file *seq, int result)
1069{
1070 struct acpi_battery *battery = seq->private;
1071
1072 if (result)
1073 goto end;
1074
1075 if (!acpi_battery_present(battery)) {
1076 seq_printf(seq, "present: no\n");
1077 goto end;
1078 }
1079 seq_printf(seq, "alarm: ");
1080 if (!battery->alarm)
1081 seq_printf(seq, "unsupported\n");
1082 else
1083 seq_printf(seq, "%u %sh\n", battery->alarm,
1084 acpi_battery_units(battery));
1085 end:
1086 if (result)
1087 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1088 return result;
1089}
1090
1091static ssize_t acpi_battery_write_alarm(struct file *file,
1092 const char __user * buffer,
1093 size_t count, loff_t * ppos)
1094{
1095 int result = 0;
1096 char alarm_string[12] = { '\0' };
1097 struct seq_file *m = file->private_data;
1098 struct acpi_battery *battery = m->private;
1099
1100 if (!battery || (count > sizeof(alarm_string) - 1))
1101 return -EINVAL;
1102 if (!acpi_battery_present(battery)) {
1103 result = -ENODEV;
1104 goto end;
1105 }
1106 if (copy_from_user(alarm_string, buffer, count)) {
1107 result = -EFAULT;
1108 goto end;
1109 }
1110 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001111 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1112 result = -EINVAL;
1113 goto end;
1114 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001115 result = acpi_battery_set_alarm(battery);
1116 end:
1117 if (!result)
1118 return count;
1119 return result;
1120}
1121
1122typedef int(*print_func)(struct seq_file *seq, int result);
1123
1124static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
1125 acpi_battery_print_info,
1126 acpi_battery_print_state,
1127 acpi_battery_print_alarm,
1128};
1129
1130static int acpi_battery_read(int fid, struct seq_file *seq)
1131{
1132 struct acpi_battery *battery = seq->private;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001133 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001134 return acpi_print_funcs[fid](seq, result);
1135}
1136
1137#define DECLARE_FILE_FUNCTIONS(_name) \
1138static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
1139{ \
1140 return acpi_battery_read(_name##_tag, seq); \
1141} \
1142static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
1143{ \
1144 return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
1145}
1146
1147DECLARE_FILE_FUNCTIONS(info);
1148DECLARE_FILE_FUNCTIONS(state);
1149DECLARE_FILE_FUNCTIONS(alarm);
1150
1151#undef DECLARE_FILE_FUNCTIONS
1152
1153#define FILE_DESCRIPTION_RO(_name) \
1154 { \
1155 .name = __stringify(_name), \
1156 .mode = S_IRUGO, \
1157 .ops = { \
1158 .open = acpi_battery_##_name##_open_fs, \
1159 .read = seq_read, \
1160 .llseek = seq_lseek, \
1161 .release = single_release, \
1162 .owner = THIS_MODULE, \
1163 }, \
1164 }
1165
1166#define FILE_DESCRIPTION_RW(_name) \
1167 { \
1168 .name = __stringify(_name), \
1169 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
1170 .ops = { \
1171 .open = acpi_battery_##_name##_open_fs, \
1172 .read = seq_read, \
1173 .llseek = seq_lseek, \
1174 .write = acpi_battery_write_##_name, \
1175 .release = single_release, \
1176 .owner = THIS_MODULE, \
1177 }, \
1178 }
1179
1180static const struct battery_file {
1181 struct file_operations ops;
1182 umode_t mode;
1183 const char *name;
1184} acpi_battery_file[] = {
1185 FILE_DESCRIPTION_RO(info),
1186 FILE_DESCRIPTION_RO(state),
1187 FILE_DESCRIPTION_RW(alarm),
1188};
1189
1190#undef FILE_DESCRIPTION_RO
1191#undef FILE_DESCRIPTION_RW
1192
1193static int acpi_battery_add_fs(struct acpi_device *device)
1194{
1195 struct proc_dir_entry *entry = NULL;
1196 int i;
1197
1198 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1199 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1200 if (!acpi_device_dir(device)) {
1201 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1202 acpi_battery_dir);
1203 if (!acpi_device_dir(device))
1204 return -ENODEV;
1205 }
1206
1207 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
1208 entry = proc_create_data(acpi_battery_file[i].name,
1209 acpi_battery_file[i].mode,
1210 acpi_device_dir(device),
1211 &acpi_battery_file[i].ops,
1212 acpi_driver_data(device));
1213 if (!entry)
1214 return -ENODEV;
1215 }
1216 return 0;
1217}
1218
1219static void acpi_battery_remove_fs(struct acpi_device *device)
1220{
1221 int i;
1222 if (!acpi_device_dir(device))
1223 return;
1224 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1225 remove_proc_entry(acpi_battery_file[i].name,
1226 acpi_device_dir(device));
1227
1228 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1229 acpi_device_dir(device) = NULL;
1230}
1231
1232#endif
1233
1234/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 Driver Interface
1236 -------------------------------------------------------------------------- */
1237
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001238static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001240 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001241 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001242
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001244 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001245 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001246 /*
1247 * On Acer Aspire V5-573G notifications are sometimes triggered too
1248 * early. For example, when AC is unplugged and notification is
1249 * triggered, battery state is still reported as "Full", and changes to
1250 * "Discharging" only after short delay, without any notification.
1251 */
1252 if (battery_notification_delay_ms > 0)
1253 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001254 if (event == ACPI_BATTERY_NOTIFY_INFO)
1255 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001256 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001257 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001258 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001259 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001260 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001261 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001262 if (old && battery->bat)
1263 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264}
1265
Kyle McMartin25be5822011-03-22 16:19:50 -04001266static int battery_notify(struct notifier_block *nb,
1267 unsigned long mode, void *_unused)
1268{
1269 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1270 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001271 int result;
1272
Kyle McMartin25be5822011-03-22 16:19:50 -04001273 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001274 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001275 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001276 if (!acpi_battery_present(battery))
1277 return 0;
1278
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001279 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001280 result = acpi_battery_get_info(battery);
1281 if (result)
1282 return result;
1283
1284 result = sysfs_add_battery(battery);
1285 if (result)
1286 return result;
1287 } else
1288 acpi_battery_refresh(battery);
1289
1290 acpi_battery_init_alarm(battery);
1291 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001292 break;
1293 }
1294
1295 return 0;
1296}
1297
Mathias Krause048d16d2015-06-13 14:26:55 +02001298static int __init
1299battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001300{
1301 battery_bix_broken_package = 1;
1302 return 0;
1303}
1304
Mathias Krause048d16d2015-06-13 14:26:55 +02001305static int __init
1306battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001307{
1308 battery_notification_delay_ms = 1000;
1309 return 0;
1310}
1311
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001312static int __init battery_full_discharging_quirk(const struct dmi_system_id *d)
1313{
1314 battery_full_discharging = 1;
1315 return 0;
1316}
1317
Mathias Krause048d16d2015-06-13 14:26:55 +02001318static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001319 {
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001320 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001321 .ident = "NEC LZ750/LS",
1322 .matches = {
1323 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1324 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1325 },
1326 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001327 {
1328 .callback = battery_notification_delay_quirk,
1329 .ident = "Acer Aspire V5-573G",
1330 .matches = {
1331 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1332 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1333 },
1334 },
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001335 {
1336 .callback = battery_full_discharging_quirk,
1337 .ident = "ASUS GL502VSK",
1338 .matches = {
1339 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1340 DMI_MATCH(DMI_PRODUCT_NAME, "GL502VSK"),
1341 },
1342 },
1343 {
1344 .callback = battery_full_discharging_quirk,
1345 .ident = "ASUS UX305LA",
1346 .matches = {
1347 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1348 DMI_MATCH(DMI_PRODUCT_NAME, "UX305LA"),
1349 },
1350 },
Kai Heng Feng44468232018-01-29 13:40:36 +08001351 {
1352 .callback = battery_full_discharging_quirk,
1353 .ident = "ASUS UX360UA",
1354 .matches = {
1355 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1356 DMI_MATCH(DMI_PRODUCT_NAME, "UX360UA"),
1357 },
1358 },
1359 {
1360 .callback = battery_full_discharging_quirk,
1361 .ident = "ASUS UX410UAK",
1362 .matches = {
1363 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1364 DMI_MATCH(DMI_PRODUCT_NAME, "UX410UAK"),
1365 },
1366 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001367 {},
1368};
1369
Lan Tianyu75646e72014-07-07 15:47:12 +08001370/*
1371 * Some machines'(E,G Lenovo Z480) ECs are not stable
1372 * during boot up and this causes battery driver fails to be
1373 * probed due to failure of getting battery information
1374 * from EC sometimes. After several retries, the operation
1375 * may work. So add retry code here and 20ms sleep between
1376 * every retries.
1377 */
1378static int acpi_battery_update_retry(struct acpi_battery *battery)
1379{
1380 int retry, ret;
1381
1382 for (retry = 5; retry; retry--) {
1383 ret = acpi_battery_update(battery, false);
1384 if (!ret)
1385 break;
1386
1387 msleep(20);
1388 }
1389 return ret;
1390}
1391
Len Brown4be44fc2005-08-05 00:44:28 -04001392static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
Len Brown4be44fc2005-08-05 00:44:28 -04001394 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001395 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001398 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001399
1400 if (device->dep_unmet)
1401 return -EPROBE_DEFER;
1402
Burman Yan36bcbec2006-12-19 12:56:11 -08001403 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001405 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001406 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1408 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001409 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001410 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001411 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001412 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001413 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001414
1415 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001416 if (result)
1417 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001418
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001419#ifdef CONFIG_ACPI_PROCFS_POWER
1420 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001421 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001422 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001423 goto fail;
1424 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001425#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001426
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001427 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1428 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1429 device->status.battery_present ? "present" : "absent");
1430
Kyle McMartin25be5822011-03-22 16:19:50 -04001431 battery->pm_nb.notifier_call = battery_notify;
1432 register_pm_notifier(&battery->pm_nb);
1433
Zhang Ruie0d1f092014-05-28 15:23:38 +08001434 device_init_wakeup(&device->dev, 1);
1435
Patrick Mocheld550d982006-06-27 00:41:40 -04001436 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001437
1438fail:
1439 sysfs_remove_battery(battery);
1440 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001441 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001442 kfree(battery);
1443 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444}
1445
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001446static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447{
Len Brown4be44fc2005-08-05 00:44:28 -04001448 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001451 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001452 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001453 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001454 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001455#ifdef CONFIG_ACPI_PROCFS_POWER
1456 acpi_battery_remove_fs(device);
1457#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001458 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001459 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001460 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001462 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001465#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001466/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001467static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001468{
1469 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001470
1471 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001472 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001473
1474 battery = acpi_driver_data(to_acpi_device(dev));
1475 if (!battery)
1476 return -EINVAL;
1477
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001478 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001479 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001480 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001481}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001482#else
1483#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001484#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001485
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001486static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1487
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001488static struct acpi_driver acpi_battery_driver = {
1489 .name = "battery",
1490 .class = ACPI_BATTERY_CLASS,
1491 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001492 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001493 .ops = {
1494 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001495 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001496 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001497 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001498 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001499};
1500
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001501static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
Hans de Goededccfae62017-04-19 14:02:10 +02001503 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001504 int result;
1505
Hans de Goededccfae62017-04-19 14:02:10 +02001506 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1507 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1508 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1509 ": found native %s PMIC, not loading\n",
1510 acpi_battery_blacklist[i]);
1511 return;
1512 }
1513
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001514 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001515
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001516#ifdef CONFIG_ACPI_PROCFS_POWER
1517 acpi_battery_dir = acpi_lock_battery_dir();
1518 if (!acpi_battery_dir)
1519 return;
1520#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001521 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001522#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001523 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001524 acpi_unlock_battery_dir(acpi_battery_dir);
1525#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001526 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001527}
1528
1529static int __init acpi_battery_init(void)
1530{
Luis Henriquese234b072015-05-11 22:48:38 +01001531 if (acpi_disabled)
1532 return -ENODEV;
1533
Luis Henriqueseca21d912015-05-11 22:49:05 +01001534 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001535 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536}
1537
Len Brown4be44fc2005-08-05 00:44:28 -04001538static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001540 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001541 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001542 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001543 battery_hook_exit();
1544 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001545#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001546 if (acpi_battery_dir)
1547 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001548#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549}
1550
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551module_init(acpi_battery_init);
1552module_exit(acpi_battery_exit);