blob: b4580b2e8706f141bbfe9ccae21831916b814e4c [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;
Ognjen Galic91eea702018-02-07 15:59:36 +010077static int battery_quirk_notcharging;
Kai-Heng Fengc68f0672017-11-21 03:33:06 -050078static int battery_full_discharging;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040079static unsigned int cache_time = 1000;
80module_param(cache_time, uint, 0644);
81MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030082
Lan Tianyu3a670cc2014-05-04 11:07:25 +080083#ifdef CONFIG_ACPI_PROCFS_POWER
84extern struct proc_dir_entry *acpi_lock_battery_dir(void);
85extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
86
87enum acpi_battery_files {
88 info_tag = 0,
89 state_tag,
90 alarm_tag,
91 ACPI_BATTERY_NUMFILES,
92};
93
94#endif
95
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040096static const struct acpi_device_id battery_device_ids[] = {
97 {"PNP0C0A", 0},
98 {"", 0},
99};
100
101MODULE_DEVICE_TABLE(acpi, battery_device_ids);
102
Hans de Goededccfae62017-04-19 14:02:10 +0200103/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
104static const char * const acpi_battery_blacklist[] = {
105 "INT33F4", /* X-Powers AXP288 PMIC */
106};
107
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400108enum {
109 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400110 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +0800111 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e622012-11-16 22:28:58 +0100112 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
113 switches between mWh and mAh depending on whether the system
114 is running on battery or not. When mAh is the unit, most
115 reported values are incorrect and need to be adjusted by
116 10000/design_voltage. Verified on x201, t410, t410s, and x220.
117 Pre-2010 and 2012 models appear to always report in mWh and
118 are thus unaffected (tested with t42, t61, t500, x200, x300,
119 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
120 the 2011 models that fixes the issue (tested on x220 with a
121 post-1.29 BIOS), but as of Nov. 2012, no such update is
122 available for the 2010 models. */
123 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400124};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400125
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400126struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400127 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300128 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100129 struct power_supply *bat;
130 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400131 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400132 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100133 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400134 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200135 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400136 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400137 int capacity_now;
138 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400139 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400140 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400141 int technology;
142 int design_voltage;
143 int design_capacity_warning;
144 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400145 int cycle_count;
146 int measurement_accuracy;
147 int max_sampling_time;
148 int min_sampling_time;
149 int max_averaging_interval;
150 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400151 int capacity_granularity_1;
152 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400153 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400154 char model_number[32];
155 char serial_number[32];
156 char type[32];
157 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400158 int state;
159 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400160 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161};
162
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100163#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400164
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000165static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400166{
167 return battery->device->status.battery_present;
168}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400169
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400170static int acpi_battery_technology(struct acpi_battery *battery)
171{
172 if (!strcasecmp("NiCd", battery->type))
173 return POWER_SUPPLY_TECHNOLOGY_NiCd;
174 if (!strcasecmp("NiMH", battery->type))
175 return POWER_SUPPLY_TECHNOLOGY_NiMH;
176 if (!strcasecmp("LION", battery->type))
177 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300178 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300179 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400180 if (!strcasecmp("LiP", battery->type))
181 return POWER_SUPPLY_TECHNOLOGY_LIPO;
182 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
183}
184
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300185static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400186
Richard Hughes56f382a2009-01-25 15:05:50 +0000187static int acpi_battery_is_charged(struct acpi_battery *battery)
188{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800189 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000190 if (battery->state != 0)
191 return 0;
192
193 /* battery not reporting charge */
194 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
195 battery->capacity_now == 0)
196 return 0;
197
198 /* good batteries update full_charge as the batteries degrade */
199 if (battery->full_charge_capacity == battery->capacity_now)
200 return 1;
201
202 /* fallback to using design values for broken batteries */
203 if (battery->design_capacity == battery->capacity_now)
204 return 1;
205
206 /* we don't do any sort of metric based on percentages */
207 return 0;
208}
209
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400210static int acpi_battery_get_property(struct power_supply *psy,
211 enum power_supply_property psp,
212 union power_supply_propval *val)
213{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200214 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400215 struct acpi_battery *battery = to_acpi_battery(psy);
216
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300217 if (acpi_battery_present(battery)) {
218 /* run battery update only if it is present */
219 acpi_battery_get_state(battery);
220 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400221 return -ENODEV;
222 switch (psp) {
223 case POWER_SUPPLY_PROP_STATUS:
Kai-Heng Fengc68f0672017-11-21 03:33:06 -0500224 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) {
225 if (battery_full_discharging && battery->rate_now == 0)
226 val->intval = POWER_SUPPLY_STATUS_FULL;
227 else
228 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
229 } else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400230 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000231 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400232 val->intval = POWER_SUPPLY_STATUS_FULL;
Ognjen Galic91eea702018-02-07 15:59:36 +0100233 else if (battery_quirk_notcharging)
234 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800235 else
236 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400237 break;
238 case POWER_SUPPLY_PROP_PRESENT:
239 val->intval = acpi_battery_present(battery);
240 break;
241 case POWER_SUPPLY_PROP_TECHNOLOGY:
242 val->intval = acpi_battery_technology(battery);
243 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400244 case POWER_SUPPLY_PROP_CYCLE_COUNT:
245 val->intval = battery->cycle_count;
246 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400247 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200248 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
249 ret = -ENODEV;
250 else
251 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400252 break;
253 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200254 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
255 ret = -ENODEV;
256 else
257 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400258 break;
259 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400260 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200261 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
262 ret = -ENODEV;
263 else
264 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400265 break;
266 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
267 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200268 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
269 ret = -ENODEV;
270 else
271 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400272 break;
273 case POWER_SUPPLY_PROP_CHARGE_FULL:
274 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200275 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
276 ret = -ENODEV;
277 else
278 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400279 break;
280 case POWER_SUPPLY_PROP_CHARGE_NOW:
281 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200282 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
283 ret = -ENODEV;
284 else
285 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400286 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700287 case POWER_SUPPLY_PROP_CAPACITY:
288 if (battery->capacity_now && battery->full_charge_capacity)
289 val->intval = battery->capacity_now * 100/
290 battery->full_charge_capacity;
291 else
292 val->intval = 0;
293 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800294 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
295 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
296 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
297 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
298 (battery->capacity_now <= battery->alarm))
299 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
300 else if (acpi_battery_is_charged(battery))
301 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
302 else
303 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
304 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400305 case POWER_SUPPLY_PROP_MODEL_NAME:
306 val->strval = battery->model_number;
307 break;
308 case POWER_SUPPLY_PROP_MANUFACTURER:
309 val->strval = battery->oem_info;
310 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100311 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
312 val->strval = battery->serial_number;
313 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400314 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200315 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400316 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200317 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400318}
319
320static enum power_supply_property charge_battery_props[] = {
321 POWER_SUPPLY_PROP_STATUS,
322 POWER_SUPPLY_PROP_PRESENT,
323 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400324 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400325 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
326 POWER_SUPPLY_PROP_VOLTAGE_NOW,
327 POWER_SUPPLY_PROP_CURRENT_NOW,
328 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
329 POWER_SUPPLY_PROP_CHARGE_FULL,
330 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700331 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800332 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400333 POWER_SUPPLY_PROP_MODEL_NAME,
334 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100335 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400336};
337
338static enum power_supply_property energy_battery_props[] = {
339 POWER_SUPPLY_PROP_STATUS,
340 POWER_SUPPLY_PROP_PRESENT,
341 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400342 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400343 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
344 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400345 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400346 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
347 POWER_SUPPLY_PROP_ENERGY_FULL,
348 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700349 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800350 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400351 POWER_SUPPLY_PROP_MODEL_NAME,
352 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100353 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400354};
355
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356/* --------------------------------------------------------------------------
357 Battery Management
358 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400359struct acpi_offsets {
360 size_t offset; /* offset inside struct acpi_sbs_battery */
361 u8 mode; /* int or string? */
362};
363
Mathias Krausea4658782015-06-13 14:26:53 +0200364static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400365 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400366 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400367 {offsetof(struct acpi_battery, capacity_now), 0},
368 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400369};
370
Mathias Krausea4658782015-06-13 14:26:53 +0200371static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400372 {offsetof(struct acpi_battery, power_unit), 0},
373 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400374 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400375 {offsetof(struct acpi_battery, technology), 0},
376 {offsetof(struct acpi_battery, design_voltage), 0},
377 {offsetof(struct acpi_battery, design_capacity_warning), 0},
378 {offsetof(struct acpi_battery, design_capacity_low), 0},
379 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
380 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
381 {offsetof(struct acpi_battery, model_number), 1},
382 {offsetof(struct acpi_battery, serial_number), 1},
383 {offsetof(struct acpi_battery, type), 1},
384 {offsetof(struct acpi_battery, oem_info), 1},
385};
386
Mathias Krausea4658782015-06-13 14:26:53 +0200387static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200388 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400389 {offsetof(struct acpi_battery, power_unit), 0},
390 {offsetof(struct acpi_battery, design_capacity), 0},
391 {offsetof(struct acpi_battery, full_charge_capacity), 0},
392 {offsetof(struct acpi_battery, technology), 0},
393 {offsetof(struct acpi_battery, design_voltage), 0},
394 {offsetof(struct acpi_battery, design_capacity_warning), 0},
395 {offsetof(struct acpi_battery, design_capacity_low), 0},
396 {offsetof(struct acpi_battery, cycle_count), 0},
397 {offsetof(struct acpi_battery, measurement_accuracy), 0},
398 {offsetof(struct acpi_battery, max_sampling_time), 0},
399 {offsetof(struct acpi_battery, min_sampling_time), 0},
400 {offsetof(struct acpi_battery, max_averaging_interval), 0},
401 {offsetof(struct acpi_battery, min_averaging_interval), 0},
402 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
403 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
404 {offsetof(struct acpi_battery, model_number), 1},
405 {offsetof(struct acpi_battery, serial_number), 1},
406 {offsetof(struct acpi_battery, type), 1},
407 {offsetof(struct acpi_battery, oem_info), 1},
408};
409
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400410static int extract_package(struct acpi_battery *battery,
411 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200412 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300413{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300414 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400415 union acpi_object *element;
416 if (package->type != ACPI_TYPE_PACKAGE)
417 return -EFAULT;
418 for (i = 0; i < num; ++i) {
419 if (package->package.count <= i)
420 return -EFAULT;
421 element = &package->package.elements[i];
422 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300423 u8 *ptr = (u8 *)battery + offsets[i].offset;
424 if (element->type == ACPI_TYPE_STRING ||
425 element->type == ACPI_TYPE_BUFFER)
426 strncpy(ptr, element->string.pointer, 32);
427 else if (element->type == ACPI_TYPE_INTEGER) {
428 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800429 sizeof(u64));
430 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400431 } else
432 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400433 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400434 int *x = (int *)((u8 *)battery + offsets[i].offset);
435 *x = (element->type == ACPI_TYPE_INTEGER) ?
436 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300437 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300438 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300439 return 0;
440}
441
442static int acpi_battery_get_status(struct acpi_battery *battery)
443{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400444 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300445 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
446 return -ENODEV;
447 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400448 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300449}
450
Dave Lambley2d09af42016-11-04 01:05:40 +0000451
452static int extract_battery_info(const int use_bix,
453 struct acpi_battery *battery,
454 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400456 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400457
Dave Lambley2d09af42016-11-04 01:05:40 +0000458 if (use_bix && battery_bix_broken_package)
459 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800460 extended_info_offsets + 1,
461 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000462 else if (use_bix)
463 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400464 extended_info_offsets,
465 ARRAY_SIZE(extended_info_offsets));
466 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000467 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400468 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800469 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
470 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e622012-11-16 22:28:58 +0100471 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
472 battery->power_unit && battery->design_voltage) {
473 battery->design_capacity = battery->design_capacity *
474 10000 / battery->design_voltage;
475 battery->full_charge_capacity = battery->full_charge_capacity *
476 10000 / battery->design_voltage;
477 battery->design_capacity_warning =
478 battery->design_capacity_warning *
479 10000 / battery->design_voltage;
480 /* Curiously, design_capacity_low, unlike the rest of them,
481 is correct. */
482 /* capacity_granularity_* equal 1 on the systems tested, so
483 it's impossible to tell if they would need an adjustment
484 or not if their values were higher. */
485 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400486 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487}
488
Dave Lambley2d09af42016-11-04 01:05:40 +0000489static int acpi_battery_get_info(struct acpi_battery *battery)
490{
491 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
492 int use_bix;
493 int result = -ENODEV;
494
495 if (!acpi_battery_present(battery))
496 return 0;
497
498
499 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
500 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
501 acpi_status status = AE_ERROR;
502
503 mutex_lock(&battery->lock);
504 status = acpi_evaluate_object(battery->device->handle,
505 use_bix ? "_BIX":"_BIF",
506 NULL, &buffer);
507 mutex_unlock(&battery->lock);
508
509 if (ACPI_FAILURE(status)) {
510 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
511 use_bix ? "_BIX":"_BIF"));
512 } else {
513 result = extract_battery_info(use_bix,
514 battery,
515 &buffer);
516
517 kfree(buffer.pointer);
518 break;
519 }
520 }
521
522 if (!result && !use_bix && xinfo)
523 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
524
525 return result;
526}
527
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300528static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529{
Len Brown4be44fc2005-08-05 00:44:28 -0400530 int result = 0;
531 acpi_status status = 0;
532 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300534 if (!acpi_battery_present(battery))
535 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400537 if (battery->update_time &&
538 time_before(jiffies, battery->update_time +
539 msecs_to_jiffies(cache_time)))
540 return 0;
541
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400542 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400543 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400544 NULL, &buffer);
545 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400548 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400549 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400551
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400552 result = extract_package(battery, buffer.pointer,
553 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400554 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400555 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700556
Lan Tianyu55003b22011-06-30 11:33:12 +0800557 /* For buggy DSDTs that report negative 16-bit values for either
558 * charging or discharging current and/or report 0 as 65536
559 * due to bad math.
560 */
561 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
562 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
563 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700564 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100565 printk_once(KERN_WARNING FW_BUG
566 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800567 }
Hector Martinbc76f902009-08-06 15:57:48 -0700568
Zhang Rui557d5862010-10-22 10:02:06 +0800569 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
570 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
571 battery->capacity_now = (battery->capacity_now *
572 battery->full_charge_capacity) / 100;
Kamil Iskra4000e622012-11-16 22:28:58 +0100573 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
574 battery->power_unit && battery->design_voltage) {
575 battery->capacity_now = battery->capacity_now *
576 10000 / battery->design_voltage;
577 }
Patrick Mocheld550d982006-06-27 00:41:40 -0400578 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579}
580
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400581static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
Len Brown4be44fc2005-08-05 00:44:28 -0400583 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400585 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400586 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300587 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400589 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800590 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
591 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400592 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400595 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400597 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400598 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599}
600
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300601static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300603 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800604 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400605 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400606 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400608 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400609 if (!battery->alarm)
610 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400611 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612}
613
Andrey Borzenkov508df922007-10-28 12:50:09 +0300614static ssize_t acpi_battery_alarm_show(struct device *dev,
615 struct device_attribute *attr,
616 char *buf)
617{
618 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
619 return sprintf(buf, "%d\n", battery->alarm * 1000);
620}
621
622static ssize_t acpi_battery_alarm_store(struct device *dev,
623 struct device_attribute *attr,
624 const char *buf, size_t count)
625{
626 unsigned long x;
627 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100628 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300629 battery->alarm = x/1000;
630 if (acpi_battery_present(battery))
631 acpi_battery_set_alarm(battery);
632 return count;
633}
634
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530635static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700636 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300637 .show = acpi_battery_alarm_show,
638 .store = acpi_battery_alarm_store,
639};
640
Ognjen Galicfa938542018-02-07 15:58:13 +0100641/*
642 * The Battery Hooking API
643 *
644 * This API is used inside other drivers that need to expose
645 * platform-specific behaviour within the generic driver in a
646 * generic way.
647 *
648 */
649
650static LIST_HEAD(acpi_battery_list);
651static LIST_HEAD(battery_hook_list);
652static DEFINE_MUTEX(hook_mutex);
653
Colin Ian King514bcc52018-02-23 16:32:55 +0000654static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
Ognjen Galicfa938542018-02-07 15:58:13 +0100655{
656 struct acpi_battery *battery;
657 /*
658 * In order to remove a hook, we first need to
659 * de-register all the batteries that are registered.
660 */
661 if (lock)
662 mutex_lock(&hook_mutex);
663 list_for_each_entry(battery, &acpi_battery_list, list) {
664 hook->remove_battery(battery->bat);
665 }
666 list_del(&hook->list);
667 if (lock)
668 mutex_unlock(&hook_mutex);
669 pr_info("extension unregistered: %s\n", hook->name);
670}
671
672void battery_hook_unregister(struct acpi_battery_hook *hook)
673{
674 __battery_hook_unregister(hook, 1);
675}
676EXPORT_SYMBOL_GPL(battery_hook_unregister);
677
678void battery_hook_register(struct acpi_battery_hook *hook)
679{
680 struct acpi_battery *battery;
681
682 mutex_lock(&hook_mutex);
683 INIT_LIST_HEAD(&hook->list);
684 list_add(&hook->list, &battery_hook_list);
685 /*
686 * Now that the driver is registered, we need
687 * to notify the hook that a battery is available
688 * for each battery, so that the driver may add
689 * its attributes.
690 */
691 list_for_each_entry(battery, &acpi_battery_list, list) {
692 if (hook->add_battery(battery->bat)) {
693 /*
694 * If a add-battery returns non-zero,
695 * the registration of the extension has failed,
696 * and we will not add it to the list of loaded
697 * hooks.
698 */
699 pr_err("extension failed to load: %s", hook->name);
700 __battery_hook_unregister(hook, 0);
701 return;
702 }
703 }
704 pr_info("new extension: %s\n", hook->name);
705 mutex_unlock(&hook_mutex);
706}
707EXPORT_SYMBOL_GPL(battery_hook_register);
708
709/*
710 * This function gets called right after the battery sysfs
711 * attributes have been added, so that the drivers that
712 * define custom sysfs attributes can add their own.
Ognjen Galic91eea702018-02-07 15:59:36 +0100713 */
Ognjen Galicfa938542018-02-07 15:58:13 +0100714static void battery_hook_add_battery(struct acpi_battery *battery)
715{
716 struct acpi_battery_hook *hook_node;
717
718 mutex_lock(&hook_mutex);
719 INIT_LIST_HEAD(&battery->list);
720 list_add(&battery->list, &acpi_battery_list);
721 /*
722 * Since we added a new battery to the list, we need to
723 * iterate over the hooks and call add_battery for each
724 * hook that was registered. This usually happens
725 * when a battery gets hotplugged or initialized
726 * during the battery module initialization.
727 */
728 list_for_each_entry(hook_node, &battery_hook_list, list) {
729 if (hook_node->add_battery(battery->bat)) {
730 /*
731 * The notification of the extensions has failed, to
732 * prevent further errors we will unload the extension.
733 */
734 __battery_hook_unregister(hook_node, 0);
735 pr_err("error in extension, unloading: %s",
736 hook_node->name);
737 }
738 }
739 mutex_unlock(&hook_mutex);
740}
741
742static void battery_hook_remove_battery(struct acpi_battery *battery)
743{
744 struct acpi_battery_hook *hook;
745
746 mutex_lock(&hook_mutex);
747 /*
748 * Before removing the hook, we need to remove all
749 * custom attributes from the battery.
750 */
751 list_for_each_entry(hook, &battery_hook_list, list) {
752 hook->remove_battery(battery->bat);
753 }
754 /* Then, just remove the battery from the list */
755 list_del(&battery->list);
756 mutex_unlock(&hook_mutex);
757}
758
759static void __exit battery_hook_exit(void)
760{
761 struct acpi_battery_hook *hook;
762 struct acpi_battery_hook *ptr;
763 /*
764 * At this point, the acpi_bus_unregister_driver()
765 * has called remove for all batteries. We just
766 * need to remove the hooks.
767 */
768 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
769 __battery_hook_unregister(hook, 1);
770 }
771 mutex_destroy(&hook_mutex);
772}
773
Andrey Borzenkov508df922007-10-28 12:50:09 +0300774static int sysfs_add_battery(struct acpi_battery *battery)
775{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100776 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300777
Lan Tianyuae6f6182011-06-30 11:32:40 +0800778 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100779 battery->bat_desc.properties = charge_battery_props;
780 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300781 ARRAY_SIZE(charge_battery_props);
782 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100783 battery->bat_desc.properties = energy_battery_props;
784 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300785 ARRAY_SIZE(energy_battery_props);
786 }
787
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100788 battery->bat_desc.name = acpi_device_bid(battery->device);
789 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
790 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300791
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100792 battery->bat = power_supply_register_no_ws(&battery->device->dev,
793 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800794
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100795 if (IS_ERR(battery->bat)) {
796 int result = PTR_ERR(battery->bat);
797
798 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300799 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100800 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100801 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100802 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300803}
804
805static void sysfs_remove_battery(struct acpi_battery *battery)
806{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300807 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100808 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300809 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300810 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800811 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100812 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100813 device_remove_file(&battery->bat->dev, &alarm_attr);
814 power_supply_unregister(battery->bat);
815 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300816 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700817}
818
Kamil Iskra4000e622012-11-16 22:28:58 +0100819static void find_battery(const struct dmi_header *dm, void *private)
820{
821 struct acpi_battery *battery = (struct acpi_battery *)private;
822 /* Note: the hardcoded offsets below have been extracted from
823 the source code of dmidecode. */
824 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
825 const u8 *dmi_data = (const u8 *)(dm + 1);
826 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
827 if (dm->length >= 18)
828 dmi_capacity *= dmi_data[17];
829 if (battery->design_capacity * battery->design_voltage / 1000
830 != dmi_capacity &&
831 battery->design_capacity * 10 == dmi_capacity)
832 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
833 &battery->flags);
834 }
835}
836
Zhang Rui557d5862010-10-22 10:02:06 +0800837/*
838 * According to the ACPI spec, some kinds of primary batteries can
839 * report percentage battery remaining capacity directly to OS.
840 * In this case, it reports the Last Full Charged Capacity == 100
841 * and BatteryPresentRate == 0xFFFFFFFF.
842 *
843 * Now we found some battery reports percentage remaining capacity
844 * even if it's rechargeable.
845 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
846 *
847 * Handle this correctly so that they won't break userspace.
848 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800849static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800850{
851 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000852 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800853
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000854 if (battery->full_charge_capacity == 100 &&
855 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
856 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800857 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
858 battery->full_charge_capacity = battery->design_capacity;
859 battery->capacity_now = (battery->capacity_now *
860 battery->full_charge_capacity) / 100;
861 }
Kamil Iskra4000e622012-11-16 22:28:58 +0100862
863 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000864 return;
Kamil Iskra4000e622012-11-16 22:28:58 +0100865
866 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
867 const char *s;
868 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200869 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e622012-11-16 22:28:58 +0100870 dmi_walk(find_battery, battery);
871 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
872 &battery->flags) &&
873 battery->design_voltage) {
874 battery->design_capacity =
875 battery->design_capacity *
876 10000 / battery->design_voltage;
877 battery->full_charge_capacity =
878 battery->full_charge_capacity *
879 10000 / battery->design_voltage;
880 battery->design_capacity_warning =
881 battery->design_capacity_warning *
882 10000 / battery->design_voltage;
883 battery->capacity_now = battery->capacity_now *
884 10000 / battery->design_voltage;
885 }
886 }
887 }
Zhang Rui557d5862010-10-22 10:02:06 +0800888}
889
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800890static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500891{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300892 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500893 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300894 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300895 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300896 if (!acpi_battery_present(battery)) {
897 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500898 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300899 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300900 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800901
902 if (resume)
903 return 0;
904
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300905 if (!battery->update_time ||
906 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500907 result = acpi_battery_get_info(battery);
908 if (result)
909 return result;
910 acpi_battery_init_alarm(battery);
911 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200912
913 result = acpi_battery_get_state(battery);
914 if (result)
915 return result;
916 acpi_battery_quirks(battery);
917
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100918 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100919 result = sysfs_add_battery(battery);
920 if (result)
921 return result;
922 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800923
924 /*
925 * Wakeup the system if battery is critical low
926 * or lower than the alarm level
927 */
928 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
929 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
930 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200931 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800932
Zhang Rui557d5862010-10-22 10:02:06 +0800933 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500934}
935
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100936static void acpi_battery_refresh(struct acpi_battery *battery)
937{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100938 int power_unit;
939
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100940 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100941 return;
942
Andy Whitcroftc5971452012-05-03 14:48:26 +0100943 power_unit = battery->power_unit;
944
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100945 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100946
947 if (power_unit == battery->power_unit)
948 return;
949
950 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100951 sysfs_remove_battery(battery);
952 sysfs_add_battery(battery);
953}
954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800956 FS Interface (/proc)
957 -------------------------------------------------------------------------- */
958
959#ifdef CONFIG_ACPI_PROCFS_POWER
960static struct proc_dir_entry *acpi_battery_dir;
961
Mathias Krause27059b92015-06-13 14:26:54 +0200962static const char *acpi_battery_units(const struct acpi_battery *battery)
963{
964 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
965 "mA" : "mW";
966}
967
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800968static int acpi_battery_print_info(struct seq_file *seq, int result)
969{
970 struct acpi_battery *battery = seq->private;
971
972 if (result)
973 goto end;
974
975 seq_printf(seq, "present: %s\n",
976 acpi_battery_present(battery) ? "yes" : "no");
977 if (!acpi_battery_present(battery))
978 goto end;
979 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
980 seq_printf(seq, "design capacity: unknown\n");
981 else
982 seq_printf(seq, "design capacity: %d %sh\n",
983 battery->design_capacity,
984 acpi_battery_units(battery));
985
986 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
987 seq_printf(seq, "last full capacity: unknown\n");
988 else
989 seq_printf(seq, "last full capacity: %d %sh\n",
990 battery->full_charge_capacity,
991 acpi_battery_units(battery));
992
993 seq_printf(seq, "battery technology: %srechargeable\n",
994 (!battery->technology)?"non-":"");
995
996 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
997 seq_printf(seq, "design voltage: unknown\n");
998 else
999 seq_printf(seq, "design voltage: %d mV\n",
1000 battery->design_voltage);
1001 seq_printf(seq, "design capacity warning: %d %sh\n",
1002 battery->design_capacity_warning,
1003 acpi_battery_units(battery));
1004 seq_printf(seq, "design capacity low: %d %sh\n",
1005 battery->design_capacity_low,
1006 acpi_battery_units(battery));
1007 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1008 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1009 battery->capacity_granularity_1,
1010 acpi_battery_units(battery));
1011 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1012 battery->capacity_granularity_2,
1013 acpi_battery_units(battery));
1014 seq_printf(seq, "model number: %s\n", battery->model_number);
1015 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1016 seq_printf(seq, "battery type: %s\n", battery->type);
1017 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1018 end:
1019 if (result)
1020 seq_printf(seq, "ERROR: Unable to read battery info\n");
1021 return result;
1022}
1023
1024static int acpi_battery_print_state(struct seq_file *seq, int result)
1025{
1026 struct acpi_battery *battery = seq->private;
1027
1028 if (result)
1029 goto end;
1030
1031 seq_printf(seq, "present: %s\n",
1032 acpi_battery_present(battery) ? "yes" : "no");
1033 if (!acpi_battery_present(battery))
1034 goto end;
1035
1036 seq_printf(seq, "capacity state: %s\n",
1037 (battery->state & 0x04) ? "critical" : "ok");
1038 if ((battery->state & 0x01) && (battery->state & 0x02))
1039 seq_printf(seq,
1040 "charging state: charging/discharging\n");
1041 else if (battery->state & 0x01)
1042 seq_printf(seq, "charging state: discharging\n");
1043 else if (battery->state & 0x02)
1044 seq_printf(seq, "charging state: charging\n");
1045 else
1046 seq_printf(seq, "charging state: charged\n");
1047
1048 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1049 seq_printf(seq, "present rate: unknown\n");
1050 else
1051 seq_printf(seq, "present rate: %d %s\n",
1052 battery->rate_now, acpi_battery_units(battery));
1053
1054 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1055 seq_printf(seq, "remaining capacity: unknown\n");
1056 else
1057 seq_printf(seq, "remaining capacity: %d %sh\n",
1058 battery->capacity_now, acpi_battery_units(battery));
1059 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1060 seq_printf(seq, "present voltage: unknown\n");
1061 else
1062 seq_printf(seq, "present voltage: %d mV\n",
1063 battery->voltage_now);
1064 end:
1065 if (result)
1066 seq_printf(seq, "ERROR: Unable to read battery state\n");
1067
1068 return result;
1069}
1070
1071static int acpi_battery_print_alarm(struct seq_file *seq, int result)
1072{
1073 struct acpi_battery *battery = seq->private;
1074
1075 if (result)
1076 goto end;
1077
1078 if (!acpi_battery_present(battery)) {
1079 seq_printf(seq, "present: no\n");
1080 goto end;
1081 }
1082 seq_printf(seq, "alarm: ");
1083 if (!battery->alarm)
1084 seq_printf(seq, "unsupported\n");
1085 else
1086 seq_printf(seq, "%u %sh\n", battery->alarm,
1087 acpi_battery_units(battery));
1088 end:
1089 if (result)
1090 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1091 return result;
1092}
1093
1094static ssize_t acpi_battery_write_alarm(struct file *file,
1095 const char __user * buffer,
1096 size_t count, loff_t * ppos)
1097{
1098 int result = 0;
1099 char alarm_string[12] = { '\0' };
1100 struct seq_file *m = file->private_data;
1101 struct acpi_battery *battery = m->private;
1102
1103 if (!battery || (count > sizeof(alarm_string) - 1))
1104 return -EINVAL;
1105 if (!acpi_battery_present(battery)) {
1106 result = -ENODEV;
1107 goto end;
1108 }
1109 if (copy_from_user(alarm_string, buffer, count)) {
1110 result = -EFAULT;
1111 goto end;
1112 }
1113 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001114 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1115 result = -EINVAL;
1116 goto end;
1117 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001118 result = acpi_battery_set_alarm(battery);
1119 end:
1120 if (!result)
1121 return count;
1122 return result;
1123}
1124
1125typedef int(*print_func)(struct seq_file *seq, int result);
1126
1127static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
1128 acpi_battery_print_info,
1129 acpi_battery_print_state,
1130 acpi_battery_print_alarm,
1131};
1132
1133static int acpi_battery_read(int fid, struct seq_file *seq)
1134{
1135 struct acpi_battery *battery = seq->private;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001136 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001137 return acpi_print_funcs[fid](seq, result);
1138}
1139
1140#define DECLARE_FILE_FUNCTIONS(_name) \
1141static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
1142{ \
1143 return acpi_battery_read(_name##_tag, seq); \
1144} \
1145static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
1146{ \
1147 return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
1148}
1149
1150DECLARE_FILE_FUNCTIONS(info);
1151DECLARE_FILE_FUNCTIONS(state);
1152DECLARE_FILE_FUNCTIONS(alarm);
1153
1154#undef DECLARE_FILE_FUNCTIONS
1155
1156#define FILE_DESCRIPTION_RO(_name) \
1157 { \
1158 .name = __stringify(_name), \
1159 .mode = S_IRUGO, \
1160 .ops = { \
1161 .open = acpi_battery_##_name##_open_fs, \
1162 .read = seq_read, \
1163 .llseek = seq_lseek, \
1164 .release = single_release, \
1165 .owner = THIS_MODULE, \
1166 }, \
1167 }
1168
1169#define FILE_DESCRIPTION_RW(_name) \
1170 { \
1171 .name = __stringify(_name), \
1172 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
1173 .ops = { \
1174 .open = acpi_battery_##_name##_open_fs, \
1175 .read = seq_read, \
1176 .llseek = seq_lseek, \
1177 .write = acpi_battery_write_##_name, \
1178 .release = single_release, \
1179 .owner = THIS_MODULE, \
1180 }, \
1181 }
1182
1183static const struct battery_file {
1184 struct file_operations ops;
1185 umode_t mode;
1186 const char *name;
1187} acpi_battery_file[] = {
1188 FILE_DESCRIPTION_RO(info),
1189 FILE_DESCRIPTION_RO(state),
1190 FILE_DESCRIPTION_RW(alarm),
1191};
1192
1193#undef FILE_DESCRIPTION_RO
1194#undef FILE_DESCRIPTION_RW
1195
1196static int acpi_battery_add_fs(struct acpi_device *device)
1197{
1198 struct proc_dir_entry *entry = NULL;
1199 int i;
1200
1201 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1202 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1203 if (!acpi_device_dir(device)) {
1204 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1205 acpi_battery_dir);
1206 if (!acpi_device_dir(device))
1207 return -ENODEV;
1208 }
1209
1210 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
1211 entry = proc_create_data(acpi_battery_file[i].name,
1212 acpi_battery_file[i].mode,
1213 acpi_device_dir(device),
1214 &acpi_battery_file[i].ops,
1215 acpi_driver_data(device));
1216 if (!entry)
1217 return -ENODEV;
1218 }
1219 return 0;
1220}
1221
1222static void acpi_battery_remove_fs(struct acpi_device *device)
1223{
1224 int i;
1225 if (!acpi_device_dir(device))
1226 return;
1227 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1228 remove_proc_entry(acpi_battery_file[i].name,
1229 acpi_device_dir(device));
1230
1231 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1232 acpi_device_dir(device) = NULL;
1233}
1234
1235#endif
1236
1237/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 Driver Interface
1239 -------------------------------------------------------------------------- */
1240
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001241static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001243 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001244 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001245
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001247 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001248 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001249 /*
1250 * On Acer Aspire V5-573G notifications are sometimes triggered too
1251 * early. For example, when AC is unplugged and notification is
1252 * triggered, battery state is still reported as "Full", and changes to
1253 * "Discharging" only after short delay, without any notification.
1254 */
1255 if (battery_notification_delay_ms > 0)
1256 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001257 if (event == ACPI_BATTERY_NOTIFY_INFO)
1258 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001259 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001260 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001261 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001262 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001263 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001264 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001265 if (old && battery->bat)
1266 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267}
1268
Kyle McMartin25be5822011-03-22 16:19:50 -04001269static int battery_notify(struct notifier_block *nb,
1270 unsigned long mode, void *_unused)
1271{
1272 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1273 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001274 int result;
1275
Kyle McMartin25be5822011-03-22 16:19:50 -04001276 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001277 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001278 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001279 if (!acpi_battery_present(battery))
1280 return 0;
1281
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001282 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001283 result = acpi_battery_get_info(battery);
1284 if (result)
1285 return result;
1286
1287 result = sysfs_add_battery(battery);
1288 if (result)
1289 return result;
1290 } else
1291 acpi_battery_refresh(battery);
1292
1293 acpi_battery_init_alarm(battery);
1294 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001295 break;
1296 }
1297
1298 return 0;
1299}
1300
Mathias Krause048d16d2015-06-13 14:26:55 +02001301static int __init
1302battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001303{
1304 battery_bix_broken_package = 1;
1305 return 0;
1306}
1307
Mathias Krause048d16d2015-06-13 14:26:55 +02001308static int __init
1309battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001310{
1311 battery_notification_delay_ms = 1000;
1312 return 0;
1313}
1314
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001315static int __init battery_full_discharging_quirk(const struct dmi_system_id *d)
1316{
1317 battery_full_discharging = 1;
1318 return 0;
1319}
1320
Ognjen Galic91eea702018-02-07 15:59:36 +01001321static int __init battery_quirk_not_charging(const struct dmi_system_id *d)
1322{
1323 battery_quirk_notcharging = 1;
1324 return 0;
1325}
1326
Mathias Krause048d16d2015-06-13 14:26:55 +02001327static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001328 {
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001329 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001330 .ident = "NEC LZ750/LS",
1331 .matches = {
1332 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1333 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1334 },
1335 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001336 {
1337 .callback = battery_notification_delay_quirk,
1338 .ident = "Acer Aspire V5-573G",
1339 .matches = {
1340 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1341 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1342 },
1343 },
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001344 {
1345 .callback = battery_full_discharging_quirk,
1346 .ident = "ASUS GL502VSK",
1347 .matches = {
1348 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1349 DMI_MATCH(DMI_PRODUCT_NAME, "GL502VSK"),
1350 },
1351 },
1352 {
1353 .callback = battery_full_discharging_quirk,
1354 .ident = "ASUS UX305LA",
1355 .matches = {
1356 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1357 DMI_MATCH(DMI_PRODUCT_NAME, "UX305LA"),
1358 },
1359 },
Kai Heng Feng44468232018-01-29 13:40:36 +08001360 {
1361 .callback = battery_full_discharging_quirk,
1362 .ident = "ASUS UX360UA",
1363 .matches = {
1364 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1365 DMI_MATCH(DMI_PRODUCT_NAME, "UX360UA"),
1366 },
1367 },
1368 {
1369 .callback = battery_full_discharging_quirk,
1370 .ident = "ASUS UX410UAK",
1371 .matches = {
1372 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1373 DMI_MATCH(DMI_PRODUCT_NAME, "UX410UAK"),
1374 },
1375 },
Ognjen Galic91eea702018-02-07 15:59:36 +01001376 {
1377 /*
1378 * On Lenovo ThinkPads the BIOS specification defines
1379 * a state when the bits for charging and discharging
1380 * are both set to 0. That state is "Not Charging".
1381 */
1382 .callback = battery_quirk_not_charging,
1383 .ident = "Lenovo ThinkPad",
1384 .matches = {
1385 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1386 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
1387 },
1388 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001389 {},
1390};
1391
Lan Tianyu75646e72014-07-07 15:47:12 +08001392/*
1393 * Some machines'(E,G Lenovo Z480) ECs are not stable
1394 * during boot up and this causes battery driver fails to be
1395 * probed due to failure of getting battery information
1396 * from EC sometimes. After several retries, the operation
1397 * may work. So add retry code here and 20ms sleep between
1398 * every retries.
1399 */
1400static int acpi_battery_update_retry(struct acpi_battery *battery)
1401{
1402 int retry, ret;
1403
1404 for (retry = 5; retry; retry--) {
1405 ret = acpi_battery_update(battery, false);
1406 if (!ret)
1407 break;
1408
1409 msleep(20);
1410 }
1411 return ret;
1412}
1413
Len Brown4be44fc2005-08-05 00:44:28 -04001414static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415{
Len Brown4be44fc2005-08-05 00:44:28 -04001416 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001417 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001418
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001420 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001421
1422 if (device->dep_unmet)
1423 return -EPROBE_DEFER;
1424
Burman Yan36bcbec2006-12-19 12:56:11 -08001425 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001427 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001428 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1430 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001431 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001432 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001433 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001434 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001435 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001436
1437 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001438 if (result)
1439 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001440
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001441#ifdef CONFIG_ACPI_PROCFS_POWER
1442 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001443 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001444 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001445 goto fail;
1446 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001447#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001448
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001449 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1450 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1451 device->status.battery_present ? "present" : "absent");
1452
Kyle McMartin25be5822011-03-22 16:19:50 -04001453 battery->pm_nb.notifier_call = battery_notify;
1454 register_pm_notifier(&battery->pm_nb);
1455
Zhang Ruie0d1f092014-05-28 15:23:38 +08001456 device_init_wakeup(&device->dev, 1);
1457
Patrick Mocheld550d982006-06-27 00:41:40 -04001458 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001459
1460fail:
1461 sysfs_remove_battery(battery);
1462 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001463 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001464 kfree(battery);
1465 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466}
1467
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001468static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469{
Len Brown4be44fc2005-08-05 00:44:28 -04001470 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001473 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001474 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001475 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001476 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001477#ifdef CONFIG_ACPI_PROCFS_POWER
1478 acpi_battery_remove_fs(device);
1479#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001480 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001481 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001482 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001484 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485}
1486
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001487#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001488/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001489static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001490{
1491 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001492
1493 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001494 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001495
1496 battery = acpi_driver_data(to_acpi_device(dev));
1497 if (!battery)
1498 return -EINVAL;
1499
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001500 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001501 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001502 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001503}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001504#else
1505#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001506#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001507
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001508static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1509
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001510static struct acpi_driver acpi_battery_driver = {
1511 .name = "battery",
1512 .class = ACPI_BATTERY_CLASS,
1513 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001514 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001515 .ops = {
1516 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001517 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001518 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001519 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001520 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001521};
1522
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001523static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524{
Hans de Goededccfae62017-04-19 14:02:10 +02001525 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001526 int result;
1527
Hans de Goededccfae62017-04-19 14:02:10 +02001528 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1529 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1530 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1531 ": found native %s PMIC, not loading\n",
1532 acpi_battery_blacklist[i]);
1533 return;
1534 }
1535
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001536 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001537
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001538#ifdef CONFIG_ACPI_PROCFS_POWER
1539 acpi_battery_dir = acpi_lock_battery_dir();
1540 if (!acpi_battery_dir)
1541 return;
1542#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001543 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001544#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001545 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001546 acpi_unlock_battery_dir(acpi_battery_dir);
1547#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001548 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001549}
1550
1551static int __init acpi_battery_init(void)
1552{
Luis Henriquese234b072015-05-11 22:48:38 +01001553 if (acpi_disabled)
1554 return -ENODEV;
1555
Luis Henriqueseca21d912015-05-11 22:49:05 +01001556 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001557 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558}
1559
Len Brown4be44fc2005-08-05 00:44:28 -04001560static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001562 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001563 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001564 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001565 battery_hook_exit();
1566 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001567#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001568 if (acpi_battery_dir)
1569 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001570#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571}
1572
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573module_init(acpi_battery_init);
1574module_exit(acpi_battery_exit);