blob: 96ed134bacf8470fa12229d2a57c026d1a91bced [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,
Laszlo Totha20136a2018-02-24 10:20:15 +0100124 /* for batteries reporting current capacity with design capacity
125 * on a full charge, but showing degradation in full charge cap.
126 */
127 ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400128};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400129
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400130struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400131 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300132 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100133 struct power_supply *bat;
134 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400135 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400136 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100137 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400138 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200139 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400140 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400141 int capacity_now;
142 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400143 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400144 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400145 int technology;
146 int design_voltage;
147 int design_capacity_warning;
148 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400149 int cycle_count;
150 int measurement_accuracy;
151 int max_sampling_time;
152 int min_sampling_time;
153 int max_averaging_interval;
154 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400155 int capacity_granularity_1;
156 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400157 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400158 char model_number[32];
159 char serial_number[32];
160 char type[32];
161 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400162 int state;
163 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400164 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165};
166
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100167#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400168
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000169static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400170{
171 return battery->device->status.battery_present;
172}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400173
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400174static int acpi_battery_technology(struct acpi_battery *battery)
175{
176 if (!strcasecmp("NiCd", battery->type))
177 return POWER_SUPPLY_TECHNOLOGY_NiCd;
178 if (!strcasecmp("NiMH", battery->type))
179 return POWER_SUPPLY_TECHNOLOGY_NiMH;
180 if (!strcasecmp("LION", battery->type))
181 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300182 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300183 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400184 if (!strcasecmp("LiP", battery->type))
185 return POWER_SUPPLY_TECHNOLOGY_LIPO;
186 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
187}
188
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300189static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400190
Richard Hughes56f382a2009-01-25 15:05:50 +0000191static int acpi_battery_is_charged(struct acpi_battery *battery)
192{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800193 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000194 if (battery->state != 0)
195 return 0;
196
197 /* battery not reporting charge */
198 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
199 battery->capacity_now == 0)
200 return 0;
201
202 /* good batteries update full_charge as the batteries degrade */
203 if (battery->full_charge_capacity == battery->capacity_now)
204 return 1;
205
206 /* fallback to using design values for broken batteries */
207 if (battery->design_capacity == battery->capacity_now)
208 return 1;
209
210 /* we don't do any sort of metric based on percentages */
211 return 0;
212}
213
Laszlo Totha20136a2018-02-24 10:20:15 +0100214static bool acpi_battery_is_degraded(struct acpi_battery *battery)
215{
216 return battery->full_charge_capacity && battery->design_capacity &&
217 battery->full_charge_capacity < battery->design_capacity;
218}
219
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400220static int acpi_battery_get_property(struct power_supply *psy,
221 enum power_supply_property psp,
222 union power_supply_propval *val)
223{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200224 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400225 struct acpi_battery *battery = to_acpi_battery(psy);
226
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300227 if (acpi_battery_present(battery)) {
228 /* run battery update only if it is present */
229 acpi_battery_get_state(battery);
230 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400231 return -ENODEV;
232 switch (psp) {
233 case POWER_SUPPLY_PROP_STATUS:
Kai-Heng Fengc68f0672017-11-21 03:33:06 -0500234 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) {
235 if (battery_full_discharging && battery->rate_now == 0)
236 val->intval = POWER_SUPPLY_STATUS_FULL;
237 else
238 val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
239 } else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400240 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000241 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400242 val->intval = POWER_SUPPLY_STATUS_FULL;
Ognjen Galic91eea702018-02-07 15:59:36 +0100243 else if (battery_quirk_notcharging)
244 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800245 else
246 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400247 break;
248 case POWER_SUPPLY_PROP_PRESENT:
249 val->intval = acpi_battery_present(battery);
250 break;
251 case POWER_SUPPLY_PROP_TECHNOLOGY:
252 val->intval = acpi_battery_technology(battery);
253 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400254 case POWER_SUPPLY_PROP_CYCLE_COUNT:
255 val->intval = battery->cycle_count;
256 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400257 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200258 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
259 ret = -ENODEV;
260 else
261 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400262 break;
263 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200264 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
265 ret = -ENODEV;
266 else
267 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400268 break;
269 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400270 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200271 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
272 ret = -ENODEV;
273 else
274 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400275 break;
276 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
277 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200278 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
279 ret = -ENODEV;
280 else
281 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400282 break;
283 case POWER_SUPPLY_PROP_CHARGE_FULL:
284 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200285 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
286 ret = -ENODEV;
287 else
288 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400289 break;
290 case POWER_SUPPLY_PROP_CHARGE_NOW:
291 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200292 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
293 ret = -ENODEV;
294 else
295 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400296 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700297 case POWER_SUPPLY_PROP_CAPACITY:
298 if (battery->capacity_now && battery->full_charge_capacity)
299 val->intval = battery->capacity_now * 100/
300 battery->full_charge_capacity;
301 else
302 val->intval = 0;
303 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800304 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
305 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
306 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
307 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
308 (battery->capacity_now <= battery->alarm))
309 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
310 else if (acpi_battery_is_charged(battery))
311 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
312 else
313 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
314 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400315 case POWER_SUPPLY_PROP_MODEL_NAME:
316 val->strval = battery->model_number;
317 break;
318 case POWER_SUPPLY_PROP_MANUFACTURER:
319 val->strval = battery->oem_info;
320 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100321 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
322 val->strval = battery->serial_number;
323 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400324 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200325 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400326 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200327 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400328}
329
330static enum power_supply_property charge_battery_props[] = {
331 POWER_SUPPLY_PROP_STATUS,
332 POWER_SUPPLY_PROP_PRESENT,
333 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400334 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400335 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
336 POWER_SUPPLY_PROP_VOLTAGE_NOW,
337 POWER_SUPPLY_PROP_CURRENT_NOW,
338 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
339 POWER_SUPPLY_PROP_CHARGE_FULL,
340 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700341 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800342 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400343 POWER_SUPPLY_PROP_MODEL_NAME,
344 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100345 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400346};
347
348static enum power_supply_property energy_battery_props[] = {
349 POWER_SUPPLY_PROP_STATUS,
350 POWER_SUPPLY_PROP_PRESENT,
351 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400352 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400353 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
354 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400355 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400356 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
357 POWER_SUPPLY_PROP_ENERGY_FULL,
358 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700359 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800360 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400361 POWER_SUPPLY_PROP_MODEL_NAME,
362 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100363 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400364};
365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366/* --------------------------------------------------------------------------
367 Battery Management
368 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400369struct acpi_offsets {
370 size_t offset; /* offset inside struct acpi_sbs_battery */
371 u8 mode; /* int or string? */
372};
373
Mathias Krausea4658782015-06-13 14:26:53 +0200374static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400375 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400376 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400377 {offsetof(struct acpi_battery, capacity_now), 0},
378 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400379};
380
Mathias Krausea4658782015-06-13 14:26:53 +0200381static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400382 {offsetof(struct acpi_battery, power_unit), 0},
383 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400384 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400385 {offsetof(struct acpi_battery, technology), 0},
386 {offsetof(struct acpi_battery, design_voltage), 0},
387 {offsetof(struct acpi_battery, design_capacity_warning), 0},
388 {offsetof(struct acpi_battery, design_capacity_low), 0},
389 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
390 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
391 {offsetof(struct acpi_battery, model_number), 1},
392 {offsetof(struct acpi_battery, serial_number), 1},
393 {offsetof(struct acpi_battery, type), 1},
394 {offsetof(struct acpi_battery, oem_info), 1},
395};
396
Mathias Krausea4658782015-06-13 14:26:53 +0200397static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200398 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400399 {offsetof(struct acpi_battery, power_unit), 0},
400 {offsetof(struct acpi_battery, design_capacity), 0},
401 {offsetof(struct acpi_battery, full_charge_capacity), 0},
402 {offsetof(struct acpi_battery, technology), 0},
403 {offsetof(struct acpi_battery, design_voltage), 0},
404 {offsetof(struct acpi_battery, design_capacity_warning), 0},
405 {offsetof(struct acpi_battery, design_capacity_low), 0},
406 {offsetof(struct acpi_battery, cycle_count), 0},
407 {offsetof(struct acpi_battery, measurement_accuracy), 0},
408 {offsetof(struct acpi_battery, max_sampling_time), 0},
409 {offsetof(struct acpi_battery, min_sampling_time), 0},
410 {offsetof(struct acpi_battery, max_averaging_interval), 0},
411 {offsetof(struct acpi_battery, min_averaging_interval), 0},
412 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
413 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
414 {offsetof(struct acpi_battery, model_number), 1},
415 {offsetof(struct acpi_battery, serial_number), 1},
416 {offsetof(struct acpi_battery, type), 1},
417 {offsetof(struct acpi_battery, oem_info), 1},
418};
419
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400420static int extract_package(struct acpi_battery *battery,
421 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200422 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300423{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300424 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400425 union acpi_object *element;
426 if (package->type != ACPI_TYPE_PACKAGE)
427 return -EFAULT;
428 for (i = 0; i < num; ++i) {
429 if (package->package.count <= i)
430 return -EFAULT;
431 element = &package->package.elements[i];
432 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300433 u8 *ptr = (u8 *)battery + offsets[i].offset;
434 if (element->type == ACPI_TYPE_STRING ||
435 element->type == ACPI_TYPE_BUFFER)
436 strncpy(ptr, element->string.pointer, 32);
437 else if (element->type == ACPI_TYPE_INTEGER) {
438 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800439 sizeof(u64));
440 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400441 } else
442 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400443 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400444 int *x = (int *)((u8 *)battery + offsets[i].offset);
445 *x = (element->type == ACPI_TYPE_INTEGER) ?
446 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300447 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300448 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300449 return 0;
450}
451
452static int acpi_battery_get_status(struct acpi_battery *battery)
453{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400454 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300455 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
456 return -ENODEV;
457 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400458 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300459}
460
Dave Lambley2d09af42016-11-04 01:05:40 +0000461
462static int extract_battery_info(const int use_bix,
463 struct acpi_battery *battery,
464 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400466 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400467
Dave Lambley2d09af42016-11-04 01:05:40 +0000468 if (use_bix && battery_bix_broken_package)
469 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800470 extended_info_offsets + 1,
471 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000472 else if (use_bix)
473 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400474 extended_info_offsets,
475 ARRAY_SIZE(extended_info_offsets));
476 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000477 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400478 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800479 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
480 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e622012-11-16 22:28:58 +0100481 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
482 battery->power_unit && battery->design_voltage) {
483 battery->design_capacity = battery->design_capacity *
484 10000 / battery->design_voltage;
485 battery->full_charge_capacity = battery->full_charge_capacity *
486 10000 / battery->design_voltage;
487 battery->design_capacity_warning =
488 battery->design_capacity_warning *
489 10000 / battery->design_voltage;
490 /* Curiously, design_capacity_low, unlike the rest of them,
491 is correct. */
492 /* capacity_granularity_* equal 1 on the systems tested, so
493 it's impossible to tell if they would need an adjustment
494 or not if their values were higher. */
495 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100496 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
497 battery->capacity_now > battery->full_charge_capacity)
498 battery->capacity_now = battery->full_charge_capacity;
499
Patrick Mocheld550d982006-06-27 00:41:40 -0400500 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501}
502
Dave Lambley2d09af42016-11-04 01:05:40 +0000503static int acpi_battery_get_info(struct acpi_battery *battery)
504{
505 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
506 int use_bix;
507 int result = -ENODEV;
508
509 if (!acpi_battery_present(battery))
510 return 0;
511
512
513 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
514 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
515 acpi_status status = AE_ERROR;
516
517 mutex_lock(&battery->lock);
518 status = acpi_evaluate_object(battery->device->handle,
519 use_bix ? "_BIX":"_BIF",
520 NULL, &buffer);
521 mutex_unlock(&battery->lock);
522
523 if (ACPI_FAILURE(status)) {
524 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
525 use_bix ? "_BIX":"_BIF"));
526 } else {
527 result = extract_battery_info(use_bix,
528 battery,
529 &buffer);
530
531 kfree(buffer.pointer);
532 break;
533 }
534 }
535
536 if (!result && !use_bix && xinfo)
537 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
538
539 return result;
540}
541
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300542static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543{
Len Brown4be44fc2005-08-05 00:44:28 -0400544 int result = 0;
545 acpi_status status = 0;
546 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300548 if (!acpi_battery_present(battery))
549 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400551 if (battery->update_time &&
552 time_before(jiffies, battery->update_time +
553 msecs_to_jiffies(cache_time)))
554 return 0;
555
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400556 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400557 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400558 NULL, &buffer);
559 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400560
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400562 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400563 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400565
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400566 result = extract_package(battery, buffer.pointer,
567 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400568 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400569 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700570
Lan Tianyu55003b22011-06-30 11:33:12 +0800571 /* For buggy DSDTs that report negative 16-bit values for either
572 * charging or discharging current and/or report 0 as 65536
573 * due to bad math.
574 */
575 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
576 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
577 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700578 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100579 printk_once(KERN_WARNING FW_BUG
580 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800581 }
Hector Martinbc76f902009-08-06 15:57:48 -0700582
Zhang Rui557d5862010-10-22 10:02:06 +0800583 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
584 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
585 battery->capacity_now = (battery->capacity_now *
586 battery->full_charge_capacity) / 100;
Kamil Iskra4000e622012-11-16 22:28:58 +0100587 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
588 battery->power_unit && battery->design_voltage) {
589 battery->capacity_now = battery->capacity_now *
590 10000 / battery->design_voltage;
591 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100592 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
593 battery->capacity_now > battery->full_charge_capacity)
594 battery->capacity_now = battery->full_charge_capacity;
595
Patrick Mocheld550d982006-06-27 00:41:40 -0400596 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400599static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600{
Len Brown4be44fc2005-08-05 00:44:28 -0400601 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400603 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400604 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300605 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400607 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800608 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
609 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400610 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400611
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400613 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400615 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400616 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617}
618
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300619static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300621 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800622 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400623 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400624 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400626 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400627 if (!battery->alarm)
628 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400629 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630}
631
Andrey Borzenkov508df922007-10-28 12:50:09 +0300632static ssize_t acpi_battery_alarm_show(struct device *dev,
633 struct device_attribute *attr,
634 char *buf)
635{
636 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
637 return sprintf(buf, "%d\n", battery->alarm * 1000);
638}
639
640static ssize_t acpi_battery_alarm_store(struct device *dev,
641 struct device_attribute *attr,
642 const char *buf, size_t count)
643{
644 unsigned long x;
645 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100646 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300647 battery->alarm = x/1000;
648 if (acpi_battery_present(battery))
649 acpi_battery_set_alarm(battery);
650 return count;
651}
652
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530653static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700654 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300655 .show = acpi_battery_alarm_show,
656 .store = acpi_battery_alarm_store,
657};
658
Ognjen Galicfa938542018-02-07 15:58:13 +0100659/*
660 * The Battery Hooking API
661 *
662 * This API is used inside other drivers that need to expose
663 * platform-specific behaviour within the generic driver in a
664 * generic way.
665 *
666 */
667
668static LIST_HEAD(acpi_battery_list);
669static LIST_HEAD(battery_hook_list);
670static DEFINE_MUTEX(hook_mutex);
671
Colin Ian King514bcc52018-02-23 16:32:55 +0000672static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
Ognjen Galicfa938542018-02-07 15:58:13 +0100673{
674 struct acpi_battery *battery;
675 /*
676 * In order to remove a hook, we first need to
677 * de-register all the batteries that are registered.
678 */
679 if (lock)
680 mutex_lock(&hook_mutex);
681 list_for_each_entry(battery, &acpi_battery_list, list) {
682 hook->remove_battery(battery->bat);
683 }
684 list_del(&hook->list);
685 if (lock)
686 mutex_unlock(&hook_mutex);
687 pr_info("extension unregistered: %s\n", hook->name);
688}
689
690void battery_hook_unregister(struct acpi_battery_hook *hook)
691{
692 __battery_hook_unregister(hook, 1);
693}
694EXPORT_SYMBOL_GPL(battery_hook_unregister);
695
696void battery_hook_register(struct acpi_battery_hook *hook)
697{
698 struct acpi_battery *battery;
699
700 mutex_lock(&hook_mutex);
701 INIT_LIST_HEAD(&hook->list);
702 list_add(&hook->list, &battery_hook_list);
703 /*
704 * Now that the driver is registered, we need
705 * to notify the hook that a battery is available
706 * for each battery, so that the driver may add
707 * its attributes.
708 */
709 list_for_each_entry(battery, &acpi_battery_list, list) {
710 if (hook->add_battery(battery->bat)) {
711 /*
712 * If a add-battery returns non-zero,
713 * the registration of the extension has failed,
714 * and we will not add it to the list of loaded
715 * hooks.
716 */
717 pr_err("extension failed to load: %s", hook->name);
718 __battery_hook_unregister(hook, 0);
719 return;
720 }
721 }
722 pr_info("new extension: %s\n", hook->name);
723 mutex_unlock(&hook_mutex);
724}
725EXPORT_SYMBOL_GPL(battery_hook_register);
726
727/*
728 * This function gets called right after the battery sysfs
729 * attributes have been added, so that the drivers that
730 * define custom sysfs attributes can add their own.
Ognjen Galic91eea702018-02-07 15:59:36 +0100731 */
Ognjen Galicfa938542018-02-07 15:58:13 +0100732static void battery_hook_add_battery(struct acpi_battery *battery)
733{
734 struct acpi_battery_hook *hook_node;
735
736 mutex_lock(&hook_mutex);
737 INIT_LIST_HEAD(&battery->list);
738 list_add(&battery->list, &acpi_battery_list);
739 /*
740 * Since we added a new battery to the list, we need to
741 * iterate over the hooks and call add_battery for each
742 * hook that was registered. This usually happens
743 * when a battery gets hotplugged or initialized
744 * during the battery module initialization.
745 */
746 list_for_each_entry(hook_node, &battery_hook_list, list) {
747 if (hook_node->add_battery(battery->bat)) {
748 /*
749 * The notification of the extensions has failed, to
750 * prevent further errors we will unload the extension.
751 */
752 __battery_hook_unregister(hook_node, 0);
753 pr_err("error in extension, unloading: %s",
754 hook_node->name);
755 }
756 }
757 mutex_unlock(&hook_mutex);
758}
759
760static void battery_hook_remove_battery(struct acpi_battery *battery)
761{
762 struct acpi_battery_hook *hook;
763
764 mutex_lock(&hook_mutex);
765 /*
766 * Before removing the hook, we need to remove all
767 * custom attributes from the battery.
768 */
769 list_for_each_entry(hook, &battery_hook_list, list) {
770 hook->remove_battery(battery->bat);
771 }
772 /* Then, just remove the battery from the list */
773 list_del(&battery->list);
774 mutex_unlock(&hook_mutex);
775}
776
777static void __exit battery_hook_exit(void)
778{
779 struct acpi_battery_hook *hook;
780 struct acpi_battery_hook *ptr;
781 /*
782 * At this point, the acpi_bus_unregister_driver()
783 * has called remove for all batteries. We just
784 * need to remove the hooks.
785 */
786 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
787 __battery_hook_unregister(hook, 1);
788 }
789 mutex_destroy(&hook_mutex);
790}
791
Andrey Borzenkov508df922007-10-28 12:50:09 +0300792static int sysfs_add_battery(struct acpi_battery *battery)
793{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100794 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300795
Lan Tianyuae6f6182011-06-30 11:32:40 +0800796 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100797 battery->bat_desc.properties = charge_battery_props;
798 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300799 ARRAY_SIZE(charge_battery_props);
800 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100801 battery->bat_desc.properties = energy_battery_props;
802 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300803 ARRAY_SIZE(energy_battery_props);
804 }
805
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100806 battery->bat_desc.name = acpi_device_bid(battery->device);
807 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
808 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300809
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100810 battery->bat = power_supply_register_no_ws(&battery->device->dev,
811 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800812
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100813 if (IS_ERR(battery->bat)) {
814 int result = PTR_ERR(battery->bat);
815
816 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300817 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100818 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100819 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100820 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300821}
822
823static void sysfs_remove_battery(struct acpi_battery *battery)
824{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300825 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100826 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300827 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300828 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800829 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100830 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100831 device_remove_file(&battery->bat->dev, &alarm_attr);
832 power_supply_unregister(battery->bat);
833 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300834 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700835}
836
Kamil Iskra4000e622012-11-16 22:28:58 +0100837static void find_battery(const struct dmi_header *dm, void *private)
838{
839 struct acpi_battery *battery = (struct acpi_battery *)private;
840 /* Note: the hardcoded offsets below have been extracted from
841 the source code of dmidecode. */
842 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
843 const u8 *dmi_data = (const u8 *)(dm + 1);
844 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
845 if (dm->length >= 18)
846 dmi_capacity *= dmi_data[17];
847 if (battery->design_capacity * battery->design_voltage / 1000
848 != dmi_capacity &&
849 battery->design_capacity * 10 == dmi_capacity)
850 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
851 &battery->flags);
852 }
853}
854
Zhang Rui557d5862010-10-22 10:02:06 +0800855/*
856 * According to the ACPI spec, some kinds of primary batteries can
857 * report percentage battery remaining capacity directly to OS.
858 * In this case, it reports the Last Full Charged Capacity == 100
859 * and BatteryPresentRate == 0xFFFFFFFF.
860 *
861 * Now we found some battery reports percentage remaining capacity
862 * even if it's rechargeable.
863 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
864 *
865 * Handle this correctly so that they won't break userspace.
866 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800867static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800868{
869 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000870 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800871
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000872 if (battery->full_charge_capacity == 100 &&
873 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
874 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800875 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
876 battery->full_charge_capacity = battery->design_capacity;
877 battery->capacity_now = (battery->capacity_now *
878 battery->full_charge_capacity) / 100;
879 }
Kamil Iskra4000e622012-11-16 22:28:58 +0100880
881 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000882 return;
Kamil Iskra4000e622012-11-16 22:28:58 +0100883
884 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
885 const char *s;
886 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200887 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e622012-11-16 22:28:58 +0100888 dmi_walk(find_battery, battery);
889 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
890 &battery->flags) &&
891 battery->design_voltage) {
892 battery->design_capacity =
893 battery->design_capacity *
894 10000 / battery->design_voltage;
895 battery->full_charge_capacity =
896 battery->full_charge_capacity *
897 10000 / battery->design_voltage;
898 battery->design_capacity_warning =
899 battery->design_capacity_warning *
900 10000 / battery->design_voltage;
901 battery->capacity_now = battery->capacity_now *
902 10000 / battery->design_voltage;
903 }
904 }
905 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100906
907 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
908 return;
909
910 if (acpi_battery_is_degraded(battery) &&
911 battery->capacity_now > battery->full_charge_capacity) {
912 set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
913 battery->capacity_now = battery->full_charge_capacity;
914 }
Zhang Rui557d5862010-10-22 10:02:06 +0800915}
916
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800917static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500918{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300919 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500920 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300921 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300922 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300923 if (!acpi_battery_present(battery)) {
924 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500925 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300926 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300927 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800928
929 if (resume)
930 return 0;
931
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300932 if (!battery->update_time ||
933 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500934 result = acpi_battery_get_info(battery);
935 if (result)
936 return result;
937 acpi_battery_init_alarm(battery);
938 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200939
940 result = acpi_battery_get_state(battery);
941 if (result)
942 return result;
943 acpi_battery_quirks(battery);
944
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100945 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100946 result = sysfs_add_battery(battery);
947 if (result)
948 return result;
949 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800950
951 /*
952 * Wakeup the system if battery is critical low
953 * or lower than the alarm level
954 */
955 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
956 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
957 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200958 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800959
Zhang Rui557d5862010-10-22 10:02:06 +0800960 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500961}
962
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100963static void acpi_battery_refresh(struct acpi_battery *battery)
964{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100965 int power_unit;
966
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100967 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100968 return;
969
Andy Whitcroftc5971452012-05-03 14:48:26 +0100970 power_unit = battery->power_unit;
971
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100972 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100973
974 if (power_unit == battery->power_unit)
975 return;
976
977 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100978 sysfs_remove_battery(battery);
979 sysfs_add_battery(battery);
980}
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800983 FS Interface (/proc)
984 -------------------------------------------------------------------------- */
985
986#ifdef CONFIG_ACPI_PROCFS_POWER
987static struct proc_dir_entry *acpi_battery_dir;
988
Mathias Krause27059b92015-06-13 14:26:54 +0200989static const char *acpi_battery_units(const struct acpi_battery *battery)
990{
991 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
992 "mA" : "mW";
993}
994
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800995static int acpi_battery_print_info(struct seq_file *seq, int result)
996{
997 struct acpi_battery *battery = seq->private;
998
999 if (result)
1000 goto end;
1001
1002 seq_printf(seq, "present: %s\n",
1003 acpi_battery_present(battery) ? "yes" : "no");
1004 if (!acpi_battery_present(battery))
1005 goto end;
1006 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1007 seq_printf(seq, "design capacity: unknown\n");
1008 else
1009 seq_printf(seq, "design capacity: %d %sh\n",
1010 battery->design_capacity,
1011 acpi_battery_units(battery));
1012
1013 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1014 seq_printf(seq, "last full capacity: unknown\n");
1015 else
1016 seq_printf(seq, "last full capacity: %d %sh\n",
1017 battery->full_charge_capacity,
1018 acpi_battery_units(battery));
1019
1020 seq_printf(seq, "battery technology: %srechargeable\n",
1021 (!battery->technology)?"non-":"");
1022
1023 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1024 seq_printf(seq, "design voltage: unknown\n");
1025 else
1026 seq_printf(seq, "design voltage: %d mV\n",
1027 battery->design_voltage);
1028 seq_printf(seq, "design capacity warning: %d %sh\n",
1029 battery->design_capacity_warning,
1030 acpi_battery_units(battery));
1031 seq_printf(seq, "design capacity low: %d %sh\n",
1032 battery->design_capacity_low,
1033 acpi_battery_units(battery));
1034 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1035 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1036 battery->capacity_granularity_1,
1037 acpi_battery_units(battery));
1038 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1039 battery->capacity_granularity_2,
1040 acpi_battery_units(battery));
1041 seq_printf(seq, "model number: %s\n", battery->model_number);
1042 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1043 seq_printf(seq, "battery type: %s\n", battery->type);
1044 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1045 end:
1046 if (result)
1047 seq_printf(seq, "ERROR: Unable to read battery info\n");
1048 return result;
1049}
1050
1051static int acpi_battery_print_state(struct seq_file *seq, int result)
1052{
1053 struct acpi_battery *battery = seq->private;
1054
1055 if (result)
1056 goto end;
1057
1058 seq_printf(seq, "present: %s\n",
1059 acpi_battery_present(battery) ? "yes" : "no");
1060 if (!acpi_battery_present(battery))
1061 goto end;
1062
1063 seq_printf(seq, "capacity state: %s\n",
1064 (battery->state & 0x04) ? "critical" : "ok");
1065 if ((battery->state & 0x01) && (battery->state & 0x02))
1066 seq_printf(seq,
1067 "charging state: charging/discharging\n");
1068 else if (battery->state & 0x01)
1069 seq_printf(seq, "charging state: discharging\n");
1070 else if (battery->state & 0x02)
1071 seq_printf(seq, "charging state: charging\n");
1072 else
1073 seq_printf(seq, "charging state: charged\n");
1074
1075 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1076 seq_printf(seq, "present rate: unknown\n");
1077 else
1078 seq_printf(seq, "present rate: %d %s\n",
1079 battery->rate_now, acpi_battery_units(battery));
1080
1081 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1082 seq_printf(seq, "remaining capacity: unknown\n");
1083 else
1084 seq_printf(seq, "remaining capacity: %d %sh\n",
1085 battery->capacity_now, acpi_battery_units(battery));
1086 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1087 seq_printf(seq, "present voltage: unknown\n");
1088 else
1089 seq_printf(seq, "present voltage: %d mV\n",
1090 battery->voltage_now);
1091 end:
1092 if (result)
1093 seq_printf(seq, "ERROR: Unable to read battery state\n");
1094
1095 return result;
1096}
1097
1098static int acpi_battery_print_alarm(struct seq_file *seq, int result)
1099{
1100 struct acpi_battery *battery = seq->private;
1101
1102 if (result)
1103 goto end;
1104
1105 if (!acpi_battery_present(battery)) {
1106 seq_printf(seq, "present: no\n");
1107 goto end;
1108 }
1109 seq_printf(seq, "alarm: ");
1110 if (!battery->alarm)
1111 seq_printf(seq, "unsupported\n");
1112 else
1113 seq_printf(seq, "%u %sh\n", battery->alarm,
1114 acpi_battery_units(battery));
1115 end:
1116 if (result)
1117 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1118 return result;
1119}
1120
1121static ssize_t acpi_battery_write_alarm(struct file *file,
1122 const char __user * buffer,
1123 size_t count, loff_t * ppos)
1124{
1125 int result = 0;
1126 char alarm_string[12] = { '\0' };
1127 struct seq_file *m = file->private_data;
1128 struct acpi_battery *battery = m->private;
1129
1130 if (!battery || (count > sizeof(alarm_string) - 1))
1131 return -EINVAL;
1132 if (!acpi_battery_present(battery)) {
1133 result = -ENODEV;
1134 goto end;
1135 }
1136 if (copy_from_user(alarm_string, buffer, count)) {
1137 result = -EFAULT;
1138 goto end;
1139 }
1140 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001141 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1142 result = -EINVAL;
1143 goto end;
1144 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001145 result = acpi_battery_set_alarm(battery);
1146 end:
1147 if (!result)
1148 return count;
1149 return result;
1150}
1151
1152typedef int(*print_func)(struct seq_file *seq, int result);
1153
1154static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
1155 acpi_battery_print_info,
1156 acpi_battery_print_state,
1157 acpi_battery_print_alarm,
1158};
1159
1160static int acpi_battery_read(int fid, struct seq_file *seq)
1161{
1162 struct acpi_battery *battery = seq->private;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001163 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001164 return acpi_print_funcs[fid](seq, result);
1165}
1166
1167#define DECLARE_FILE_FUNCTIONS(_name) \
1168static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
1169{ \
1170 return acpi_battery_read(_name##_tag, seq); \
1171} \
1172static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
1173{ \
1174 return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
1175}
1176
1177DECLARE_FILE_FUNCTIONS(info);
1178DECLARE_FILE_FUNCTIONS(state);
1179DECLARE_FILE_FUNCTIONS(alarm);
1180
1181#undef DECLARE_FILE_FUNCTIONS
1182
1183#define FILE_DESCRIPTION_RO(_name) \
1184 { \
1185 .name = __stringify(_name), \
1186 .mode = S_IRUGO, \
1187 .ops = { \
1188 .open = acpi_battery_##_name##_open_fs, \
1189 .read = seq_read, \
1190 .llseek = seq_lseek, \
1191 .release = single_release, \
1192 .owner = THIS_MODULE, \
1193 }, \
1194 }
1195
1196#define FILE_DESCRIPTION_RW(_name) \
1197 { \
1198 .name = __stringify(_name), \
1199 .mode = S_IFREG | S_IRUGO | S_IWUSR, \
1200 .ops = { \
1201 .open = acpi_battery_##_name##_open_fs, \
1202 .read = seq_read, \
1203 .llseek = seq_lseek, \
1204 .write = acpi_battery_write_##_name, \
1205 .release = single_release, \
1206 .owner = THIS_MODULE, \
1207 }, \
1208 }
1209
1210static const struct battery_file {
1211 struct file_operations ops;
1212 umode_t mode;
1213 const char *name;
1214} acpi_battery_file[] = {
1215 FILE_DESCRIPTION_RO(info),
1216 FILE_DESCRIPTION_RO(state),
1217 FILE_DESCRIPTION_RW(alarm),
1218};
1219
1220#undef FILE_DESCRIPTION_RO
1221#undef FILE_DESCRIPTION_RW
1222
1223static int acpi_battery_add_fs(struct acpi_device *device)
1224{
1225 struct proc_dir_entry *entry = NULL;
1226 int i;
1227
1228 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1229 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1230 if (!acpi_device_dir(device)) {
1231 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1232 acpi_battery_dir);
1233 if (!acpi_device_dir(device))
1234 return -ENODEV;
1235 }
1236
1237 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
1238 entry = proc_create_data(acpi_battery_file[i].name,
1239 acpi_battery_file[i].mode,
1240 acpi_device_dir(device),
1241 &acpi_battery_file[i].ops,
1242 acpi_driver_data(device));
1243 if (!entry)
1244 return -ENODEV;
1245 }
1246 return 0;
1247}
1248
1249static void acpi_battery_remove_fs(struct acpi_device *device)
1250{
1251 int i;
1252 if (!acpi_device_dir(device))
1253 return;
1254 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
1255 remove_proc_entry(acpi_battery_file[i].name,
1256 acpi_device_dir(device));
1257
1258 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
1259 acpi_device_dir(device) = NULL;
1260}
1261
1262#endif
1263
1264/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 Driver Interface
1266 -------------------------------------------------------------------------- */
1267
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001268static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001270 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001271 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001274 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001275 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001276 /*
1277 * On Acer Aspire V5-573G notifications are sometimes triggered too
1278 * early. For example, when AC is unplugged and notification is
1279 * triggered, battery state is still reported as "Full", and changes to
1280 * "Discharging" only after short delay, without any notification.
1281 */
1282 if (battery_notification_delay_ms > 0)
1283 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001284 if (event == ACPI_BATTERY_NOTIFY_INFO)
1285 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001286 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001287 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001288 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001289 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001290 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001291 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001292 if (old && battery->bat)
1293 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294}
1295
Kyle McMartin25be5822011-03-22 16:19:50 -04001296static int battery_notify(struct notifier_block *nb,
1297 unsigned long mode, void *_unused)
1298{
1299 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1300 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001301 int result;
1302
Kyle McMartin25be5822011-03-22 16:19:50 -04001303 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001304 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001305 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001306 if (!acpi_battery_present(battery))
1307 return 0;
1308
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001309 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001310 result = acpi_battery_get_info(battery);
1311 if (result)
1312 return result;
1313
1314 result = sysfs_add_battery(battery);
1315 if (result)
1316 return result;
1317 } else
1318 acpi_battery_refresh(battery);
1319
1320 acpi_battery_init_alarm(battery);
1321 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001322 break;
1323 }
1324
1325 return 0;
1326}
1327
Mathias Krause048d16d2015-06-13 14:26:55 +02001328static int __init
1329battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001330{
1331 battery_bix_broken_package = 1;
1332 return 0;
1333}
1334
Mathias Krause048d16d2015-06-13 14:26:55 +02001335static int __init
1336battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001337{
1338 battery_notification_delay_ms = 1000;
1339 return 0;
1340}
1341
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001342static int __init battery_full_discharging_quirk(const struct dmi_system_id *d)
1343{
1344 battery_full_discharging = 1;
1345 return 0;
1346}
1347
Ognjen Galic91eea702018-02-07 15:59:36 +01001348static int __init battery_quirk_not_charging(const struct dmi_system_id *d)
1349{
1350 battery_quirk_notcharging = 1;
1351 return 0;
1352}
1353
Mathias Krause048d16d2015-06-13 14:26:55 +02001354static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001355 {
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001356 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001357 .ident = "NEC LZ750/LS",
1358 .matches = {
1359 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1360 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1361 },
1362 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001363 {
1364 .callback = battery_notification_delay_quirk,
1365 .ident = "Acer Aspire V5-573G",
1366 .matches = {
1367 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1368 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1369 },
1370 },
Kai-Heng Fengc68f0672017-11-21 03:33:06 -05001371 {
1372 .callback = battery_full_discharging_quirk,
1373 .ident = "ASUS GL502VSK",
1374 .matches = {
1375 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1376 DMI_MATCH(DMI_PRODUCT_NAME, "GL502VSK"),
1377 },
1378 },
1379 {
1380 .callback = battery_full_discharging_quirk,
1381 .ident = "ASUS UX305LA",
1382 .matches = {
1383 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1384 DMI_MATCH(DMI_PRODUCT_NAME, "UX305LA"),
1385 },
1386 },
Kai Heng Feng44468232018-01-29 13:40:36 +08001387 {
1388 .callback = battery_full_discharging_quirk,
1389 .ident = "ASUS UX360UA",
1390 .matches = {
1391 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1392 DMI_MATCH(DMI_PRODUCT_NAME, "UX360UA"),
1393 },
1394 },
1395 {
1396 .callback = battery_full_discharging_quirk,
1397 .ident = "ASUS UX410UAK",
1398 .matches = {
1399 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1400 DMI_MATCH(DMI_PRODUCT_NAME, "UX410UAK"),
1401 },
1402 },
Ognjen Galic91eea702018-02-07 15:59:36 +01001403 {
1404 /*
1405 * On Lenovo ThinkPads the BIOS specification defines
1406 * a state when the bits for charging and discharging
1407 * are both set to 0. That state is "Not Charging".
1408 */
1409 .callback = battery_quirk_not_charging,
1410 .ident = "Lenovo ThinkPad",
1411 .matches = {
1412 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1413 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
1414 },
1415 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001416 {},
1417};
1418
Lan Tianyu75646e72014-07-07 15:47:12 +08001419/*
1420 * Some machines'(E,G Lenovo Z480) ECs are not stable
1421 * during boot up and this causes battery driver fails to be
1422 * probed due to failure of getting battery information
1423 * from EC sometimes. After several retries, the operation
1424 * may work. So add retry code here and 20ms sleep between
1425 * every retries.
1426 */
1427static int acpi_battery_update_retry(struct acpi_battery *battery)
1428{
1429 int retry, ret;
1430
1431 for (retry = 5; retry; retry--) {
1432 ret = acpi_battery_update(battery, false);
1433 if (!ret)
1434 break;
1435
1436 msleep(20);
1437 }
1438 return ret;
1439}
1440
Len Brown4be44fc2005-08-05 00:44:28 -04001441static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442{
Len Brown4be44fc2005-08-05 00:44:28 -04001443 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001444 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001445
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001447 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001448
1449 if (device->dep_unmet)
1450 return -EPROBE_DEFER;
1451
Burman Yan36bcbec2006-12-19 12:56:11 -08001452 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001454 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001455 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1457 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001458 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001459 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001460 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001461 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001462 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001463
1464 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001465 if (result)
1466 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001467
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001468#ifdef CONFIG_ACPI_PROCFS_POWER
1469 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001470 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001471 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001472 goto fail;
1473 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001474#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001475
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001476 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1477 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1478 device->status.battery_present ? "present" : "absent");
1479
Kyle McMartin25be5822011-03-22 16:19:50 -04001480 battery->pm_nb.notifier_call = battery_notify;
1481 register_pm_notifier(&battery->pm_nb);
1482
Zhang Ruie0d1f092014-05-28 15:23:38 +08001483 device_init_wakeup(&device->dev, 1);
1484
Patrick Mocheld550d982006-06-27 00:41:40 -04001485 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001486
1487fail:
1488 sysfs_remove_battery(battery);
1489 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001490 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001491 kfree(battery);
1492 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493}
1494
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001495static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496{
Len Brown4be44fc2005-08-05 00:44:28 -04001497 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001500 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001501 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001502 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001503 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001504#ifdef CONFIG_ACPI_PROCFS_POWER
1505 acpi_battery_remove_fs(device);
1506#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001507 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001508 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001509 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001511 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001514#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001515/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001516static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001517{
1518 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001519
1520 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001521 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001522
1523 battery = acpi_driver_data(to_acpi_device(dev));
1524 if (!battery)
1525 return -EINVAL;
1526
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001527 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001528 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001529 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001530}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001531#else
1532#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001533#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001534
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001535static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1536
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001537static struct acpi_driver acpi_battery_driver = {
1538 .name = "battery",
1539 .class = ACPI_BATTERY_CLASS,
1540 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001541 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001542 .ops = {
1543 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001544 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001545 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001546 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001547 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001548};
1549
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001550static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
Hans de Goededccfae62017-04-19 14:02:10 +02001552 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001553 int result;
1554
Hans de Goededccfae62017-04-19 14:02:10 +02001555 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1556 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1557 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1558 ": found native %s PMIC, not loading\n",
1559 acpi_battery_blacklist[i]);
1560 return;
1561 }
1562
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001563 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001564
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001565#ifdef CONFIG_ACPI_PROCFS_POWER
1566 acpi_battery_dir = acpi_lock_battery_dir();
1567 if (!acpi_battery_dir)
1568 return;
1569#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001570 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001571#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001572 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001573 acpi_unlock_battery_dir(acpi_battery_dir);
1574#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001575 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001576}
1577
1578static int __init acpi_battery_init(void)
1579{
Luis Henriquese234b072015-05-11 22:48:38 +01001580 if (acpi_disabled)
1581 return -ENODEV;
1582
Luis Henriqueseca21d912015-05-11 22:49:05 +01001583 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001584 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585}
1586
Len Brown4be44fc2005-08-05 00:44:28 -04001587static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001589 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001590 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001591 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001592 battery_hook_exit();
1593 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001594#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001595 if (acpi_battery_dir)
1596 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001597#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
1599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600module_init(acpi_battery_init);
1601module_exit(acpi_battery_exit);