blob: d79ad844c78fcee1e51cfa7cde066363e45f51ef [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 Iskra4000e6262012-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;
Hans de Goede1b799c52018-04-12 12:02:00 +020077static int battery_ac_is_broken;
Carlo Caioneec625a32018-04-18 14:04:39 +020078static int battery_check_pmic = 1;
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);
Lan Tianyu3a670cc2014-05-04 11:07:25 +080086#endif
87
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040088static const struct acpi_device_id battery_device_ids[] = {
89 {"PNP0C0A", 0},
90 {"", 0},
91};
92
93MODULE_DEVICE_TABLE(acpi, battery_device_ids);
94
Hans de Goededccfae62017-04-19 14:02:10 +020095/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
96static const char * const acpi_battery_blacklist[] = {
97 "INT33F4", /* X-Powers AXP288 PMIC */
98};
99
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400100enum {
101 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400102 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +0800103 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e6262012-11-16 22:28:58 +0100104 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
105 switches between mWh and mAh depending on whether the system
106 is running on battery or not. When mAh is the unit, most
107 reported values are incorrect and need to be adjusted by
108 10000/design_voltage. Verified on x201, t410, t410s, and x220.
109 Pre-2010 and 2012 models appear to always report in mWh and
110 are thus unaffected (tested with t42, t61, t500, x200, x300,
111 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
112 the 2011 models that fixes the issue (tested on x220 with a
113 post-1.29 BIOS), but as of Nov. 2012, no such update is
114 available for the 2010 models. */
115 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Laszlo Totha20136a2018-02-24 10:20:15 +0100116 /* for batteries reporting current capacity with design capacity
117 * on a full charge, but showing degradation in full charge cap.
118 */
119 ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400120};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400121
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400122struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400123 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300124 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100125 struct power_supply *bat;
126 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400127 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400128 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100129 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400130 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200131 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400132 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400133 int capacity_now;
134 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400135 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400136 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400137 int technology;
138 int design_voltage;
139 int design_capacity_warning;
140 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400141 int cycle_count;
142 int measurement_accuracy;
143 int max_sampling_time;
144 int min_sampling_time;
145 int max_averaging_interval;
146 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400147 int capacity_granularity_1;
148 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400149 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400150 char model_number[32];
151 char serial_number[32];
152 char type[32];
153 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400154 int state;
155 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400156 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157};
158
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100159#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400160
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000161static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400162{
163 return battery->device->status.battery_present;
164}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400165
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400166static int acpi_battery_technology(struct acpi_battery *battery)
167{
168 if (!strcasecmp("NiCd", battery->type))
169 return POWER_SUPPLY_TECHNOLOGY_NiCd;
170 if (!strcasecmp("NiMH", battery->type))
171 return POWER_SUPPLY_TECHNOLOGY_NiMH;
172 if (!strcasecmp("LION", battery->type))
173 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300174 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300175 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400176 if (!strcasecmp("LiP", battery->type))
177 return POWER_SUPPLY_TECHNOLOGY_LIPO;
178 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
179}
180
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300181static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400182
Richard Hughes56f382a2009-01-25 15:05:50 +0000183static int acpi_battery_is_charged(struct acpi_battery *battery)
184{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800185 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000186 if (battery->state != 0)
187 return 0;
188
189 /* battery not reporting charge */
190 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
191 battery->capacity_now == 0)
192 return 0;
193
194 /* good batteries update full_charge as the batteries degrade */
195 if (battery->full_charge_capacity == battery->capacity_now)
196 return 1;
197
198 /* fallback to using design values for broken batteries */
199 if (battery->design_capacity == battery->capacity_now)
200 return 1;
201
202 /* we don't do any sort of metric based on percentages */
203 return 0;
204}
205
Laszlo Totha20136a2018-02-24 10:20:15 +0100206static bool acpi_battery_is_degraded(struct acpi_battery *battery)
207{
208 return battery->full_charge_capacity && battery->design_capacity &&
209 battery->full_charge_capacity < battery->design_capacity;
210}
211
Hans de Goede19fffc82018-04-12 12:01:59 +0200212static int acpi_battery_handle_discharging(struct acpi_battery *battery)
213{
214 /*
215 * Some devices wrongly report discharging if the battery's charge level
216 * was above the device's start charging threshold atm the AC adapter
217 * was plugged in and the device thus did not start a new charge cycle.
218 */
Hans de Goede1b799c52018-04-12 12:02:00 +0200219 if ((battery_ac_is_broken || power_supply_is_system_supplied()) &&
220 battery->rate_now == 0)
Hans de Goede19fffc82018-04-12 12:01:59 +0200221 return POWER_SUPPLY_STATUS_NOT_CHARGING;
222
223 return POWER_SUPPLY_STATUS_DISCHARGING;
224}
225
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400226static int acpi_battery_get_property(struct power_supply *psy,
227 enum power_supply_property psp,
228 union power_supply_propval *val)
229{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200230 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400231 struct acpi_battery *battery = to_acpi_battery(psy);
232
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300233 if (acpi_battery_present(battery)) {
234 /* run battery update only if it is present */
235 acpi_battery_get_state(battery);
236 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400237 return -ENODEV;
238 switch (psp) {
239 case POWER_SUPPLY_PROP_STATUS:
Daniel Drake82bf43b2018-03-14 16:42:17 +0800240 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
Hans de Goede19fffc82018-04-12 12:01:59 +0200241 val->intval = acpi_battery_handle_discharging(battery);
Daniel Drake82bf43b2018-03-14 16:42:17 +0800242 else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400243 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000244 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400245 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800246 else
247 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400248 break;
249 case POWER_SUPPLY_PROP_PRESENT:
250 val->intval = acpi_battery_present(battery);
251 break;
252 case POWER_SUPPLY_PROP_TECHNOLOGY:
253 val->intval = acpi_battery_technology(battery);
254 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400255 case POWER_SUPPLY_PROP_CYCLE_COUNT:
256 val->intval = battery->cycle_count;
257 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400258 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200259 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
260 ret = -ENODEV;
261 else
262 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400263 break;
264 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200265 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
266 ret = -ENODEV;
267 else
268 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400269 break;
270 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400271 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200272 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
273 ret = -ENODEV;
274 else
275 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400276 break;
277 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
278 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200279 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
280 ret = -ENODEV;
281 else
282 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400283 break;
284 case POWER_SUPPLY_PROP_CHARGE_FULL:
285 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200286 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
287 ret = -ENODEV;
288 else
289 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400290 break;
291 case POWER_SUPPLY_PROP_CHARGE_NOW:
292 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200293 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
294 ret = -ENODEV;
295 else
296 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400297 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700298 case POWER_SUPPLY_PROP_CAPACITY:
299 if (battery->capacity_now && battery->full_charge_capacity)
300 val->intval = battery->capacity_now * 100/
301 battery->full_charge_capacity;
302 else
303 val->intval = 0;
304 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800305 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
306 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
307 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
308 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
309 (battery->capacity_now <= battery->alarm))
310 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
311 else if (acpi_battery_is_charged(battery))
312 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
313 else
314 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
315 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400316 case POWER_SUPPLY_PROP_MODEL_NAME:
317 val->strval = battery->model_number;
318 break;
319 case POWER_SUPPLY_PROP_MANUFACTURER:
320 val->strval = battery->oem_info;
321 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100322 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
323 val->strval = battery->serial_number;
324 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400325 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200326 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400327 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200328 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400329}
330
331static enum power_supply_property charge_battery_props[] = {
332 POWER_SUPPLY_PROP_STATUS,
333 POWER_SUPPLY_PROP_PRESENT,
334 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400335 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400336 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
337 POWER_SUPPLY_PROP_VOLTAGE_NOW,
338 POWER_SUPPLY_PROP_CURRENT_NOW,
339 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
340 POWER_SUPPLY_PROP_CHARGE_FULL,
341 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700342 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800343 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400344 POWER_SUPPLY_PROP_MODEL_NAME,
345 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100346 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400347};
348
349static enum power_supply_property energy_battery_props[] = {
350 POWER_SUPPLY_PROP_STATUS,
351 POWER_SUPPLY_PROP_PRESENT,
352 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400353 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400354 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
355 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400356 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400357 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
358 POWER_SUPPLY_PROP_ENERGY_FULL,
359 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700360 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800361 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400362 POWER_SUPPLY_PROP_MODEL_NAME,
363 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100364 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400365};
366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367/* --------------------------------------------------------------------------
368 Battery Management
369 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400370struct acpi_offsets {
371 size_t offset; /* offset inside struct acpi_sbs_battery */
372 u8 mode; /* int or string? */
373};
374
Mathias Krausea4658782015-06-13 14:26:53 +0200375static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400376 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400377 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400378 {offsetof(struct acpi_battery, capacity_now), 0},
379 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400380};
381
Mathias Krausea4658782015-06-13 14:26:53 +0200382static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400383 {offsetof(struct acpi_battery, power_unit), 0},
384 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400385 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400386 {offsetof(struct acpi_battery, technology), 0},
387 {offsetof(struct acpi_battery, design_voltage), 0},
388 {offsetof(struct acpi_battery, design_capacity_warning), 0},
389 {offsetof(struct acpi_battery, design_capacity_low), 0},
390 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
391 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
392 {offsetof(struct acpi_battery, model_number), 1},
393 {offsetof(struct acpi_battery, serial_number), 1},
394 {offsetof(struct acpi_battery, type), 1},
395 {offsetof(struct acpi_battery, oem_info), 1},
396};
397
Mathias Krausea4658782015-06-13 14:26:53 +0200398static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200399 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400400 {offsetof(struct acpi_battery, power_unit), 0},
401 {offsetof(struct acpi_battery, design_capacity), 0},
402 {offsetof(struct acpi_battery, full_charge_capacity), 0},
403 {offsetof(struct acpi_battery, technology), 0},
404 {offsetof(struct acpi_battery, design_voltage), 0},
405 {offsetof(struct acpi_battery, design_capacity_warning), 0},
406 {offsetof(struct acpi_battery, design_capacity_low), 0},
407 {offsetof(struct acpi_battery, cycle_count), 0},
408 {offsetof(struct acpi_battery, measurement_accuracy), 0},
409 {offsetof(struct acpi_battery, max_sampling_time), 0},
410 {offsetof(struct acpi_battery, min_sampling_time), 0},
411 {offsetof(struct acpi_battery, max_averaging_interval), 0},
412 {offsetof(struct acpi_battery, min_averaging_interval), 0},
413 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
414 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
415 {offsetof(struct acpi_battery, model_number), 1},
416 {offsetof(struct acpi_battery, serial_number), 1},
417 {offsetof(struct acpi_battery, type), 1},
418 {offsetof(struct acpi_battery, oem_info), 1},
419};
420
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400421static int extract_package(struct acpi_battery *battery,
422 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200423 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300424{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300425 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400426 union acpi_object *element;
427 if (package->type != ACPI_TYPE_PACKAGE)
428 return -EFAULT;
429 for (i = 0; i < num; ++i) {
430 if (package->package.count <= i)
431 return -EFAULT;
432 element = &package->package.elements[i];
433 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300434 u8 *ptr = (u8 *)battery + offsets[i].offset;
435 if (element->type == ACPI_TYPE_STRING ||
436 element->type == ACPI_TYPE_BUFFER)
437 strncpy(ptr, element->string.pointer, 32);
438 else if (element->type == ACPI_TYPE_INTEGER) {
439 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800440 sizeof(u64));
441 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400442 } else
443 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400444 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400445 int *x = (int *)((u8 *)battery + offsets[i].offset);
446 *x = (element->type == ACPI_TYPE_INTEGER) ?
447 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300448 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300449 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300450 return 0;
451}
452
453static int acpi_battery_get_status(struct acpi_battery *battery)
454{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400455 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300456 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
457 return -ENODEV;
458 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400459 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300460}
461
Dave Lambley2d09af42016-11-04 01:05:40 +0000462
463static int extract_battery_info(const int use_bix,
464 struct acpi_battery *battery,
465 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400467 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400468
Dave Lambley2d09af42016-11-04 01:05:40 +0000469 if (use_bix && battery_bix_broken_package)
470 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800471 extended_info_offsets + 1,
472 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000473 else if (use_bix)
474 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400475 extended_info_offsets,
476 ARRAY_SIZE(extended_info_offsets));
477 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000478 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400479 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800480 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
481 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100482 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
483 battery->power_unit && battery->design_voltage) {
484 battery->design_capacity = battery->design_capacity *
485 10000 / battery->design_voltage;
486 battery->full_charge_capacity = battery->full_charge_capacity *
487 10000 / battery->design_voltage;
488 battery->design_capacity_warning =
489 battery->design_capacity_warning *
490 10000 / battery->design_voltage;
491 /* Curiously, design_capacity_low, unlike the rest of them,
492 is correct. */
493 /* capacity_granularity_* equal 1 on the systems tested, so
494 it's impossible to tell if they would need an adjustment
495 or not if their values were higher. */
496 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100497 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
498 battery->capacity_now > battery->full_charge_capacity)
499 battery->capacity_now = battery->full_charge_capacity;
500
Patrick Mocheld550d982006-06-27 00:41:40 -0400501 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
Dave Lambley2d09af42016-11-04 01:05:40 +0000504static int acpi_battery_get_info(struct acpi_battery *battery)
505{
506 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
507 int use_bix;
508 int result = -ENODEV;
509
510 if (!acpi_battery_present(battery))
511 return 0;
512
513
514 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
515 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
516 acpi_status status = AE_ERROR;
517
518 mutex_lock(&battery->lock);
519 status = acpi_evaluate_object(battery->device->handle,
520 use_bix ? "_BIX":"_BIF",
521 NULL, &buffer);
522 mutex_unlock(&battery->lock);
523
524 if (ACPI_FAILURE(status)) {
525 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
526 use_bix ? "_BIX":"_BIF"));
527 } else {
528 result = extract_battery_info(use_bix,
529 battery,
530 &buffer);
531
532 kfree(buffer.pointer);
533 break;
534 }
535 }
536
537 if (!result && !use_bix && xinfo)
538 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
539
540 return result;
541}
542
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300543static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544{
Len Brown4be44fc2005-08-05 00:44:28 -0400545 int result = 0;
546 acpi_status status = 0;
547 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300549 if (!acpi_battery_present(battery))
550 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400552 if (battery->update_time &&
553 time_before(jiffies, battery->update_time +
554 msecs_to_jiffies(cache_time)))
555 return 0;
556
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400557 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400558 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400559 NULL, &buffer);
560 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400563 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400564 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400566
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400567 result = extract_package(battery, buffer.pointer,
568 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400569 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400570 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700571
Lan Tianyu55003b22011-06-30 11:33:12 +0800572 /* For buggy DSDTs that report negative 16-bit values for either
573 * charging or discharging current and/or report 0 as 65536
574 * due to bad math.
575 */
576 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
577 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
578 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700579 battery->rate_now = abs((s16)battery->rate_now);
Martin Kepplinger92375162015-03-13 00:48:17 +0100580 printk_once(KERN_WARNING FW_BUG
581 "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800582 }
Hector Martinbc76f902009-08-06 15:57:48 -0700583
Zhang Rui557d5862010-10-22 10:02:06 +0800584 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
585 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
586 battery->capacity_now = (battery->capacity_now *
587 battery->full_charge_capacity) / 100;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100588 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
589 battery->power_unit && battery->design_voltage) {
590 battery->capacity_now = battery->capacity_now *
591 10000 / battery->design_voltage;
592 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100593 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
594 battery->capacity_now > battery->full_charge_capacity)
595 battery->capacity_now = battery->full_charge_capacity;
596
Patrick Mocheld550d982006-06-27 00:41:40 -0400597 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400600static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601{
Len Brown4be44fc2005-08-05 00:44:28 -0400602 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400604 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400605 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300606 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400608 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800609 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
610 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400611 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400614 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400616 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400617 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618}
619
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300620static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300622 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800623 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400624 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400625 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400627 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400628 if (!battery->alarm)
629 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400630 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631}
632
Andrey Borzenkov508df922007-10-28 12:50:09 +0300633static ssize_t acpi_battery_alarm_show(struct device *dev,
634 struct device_attribute *attr,
635 char *buf)
636{
637 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
638 return sprintf(buf, "%d\n", battery->alarm * 1000);
639}
640
641static ssize_t acpi_battery_alarm_store(struct device *dev,
642 struct device_attribute *attr,
643 const char *buf, size_t count)
644{
645 unsigned long x;
646 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100647 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300648 battery->alarm = x/1000;
649 if (acpi_battery_present(battery))
650 acpi_battery_set_alarm(battery);
651 return count;
652}
653
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530654static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700655 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300656 .show = acpi_battery_alarm_show,
657 .store = acpi_battery_alarm_store,
658};
659
Ognjen Galicfa938542018-02-07 15:58:13 +0100660/*
661 * The Battery Hooking API
662 *
663 * This API is used inside other drivers that need to expose
664 * platform-specific behaviour within the generic driver in a
665 * generic way.
666 *
667 */
668
669static LIST_HEAD(acpi_battery_list);
670static LIST_HEAD(battery_hook_list);
671static DEFINE_MUTEX(hook_mutex);
672
Colin Ian King514bcc52018-02-23 16:32:55 +0000673static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
Ognjen Galicfa938542018-02-07 15:58:13 +0100674{
675 struct acpi_battery *battery;
676 /*
677 * In order to remove a hook, we first need to
678 * de-register all the batteries that are registered.
679 */
680 if (lock)
681 mutex_lock(&hook_mutex);
682 list_for_each_entry(battery, &acpi_battery_list, list) {
683 hook->remove_battery(battery->bat);
684 }
685 list_del(&hook->list);
686 if (lock)
687 mutex_unlock(&hook_mutex);
688 pr_info("extension unregistered: %s\n", hook->name);
689}
690
691void battery_hook_unregister(struct acpi_battery_hook *hook)
692{
693 __battery_hook_unregister(hook, 1);
694}
695EXPORT_SYMBOL_GPL(battery_hook_unregister);
696
697void battery_hook_register(struct acpi_battery_hook *hook)
698{
699 struct acpi_battery *battery;
700
701 mutex_lock(&hook_mutex);
702 INIT_LIST_HEAD(&hook->list);
703 list_add(&hook->list, &battery_hook_list);
704 /*
705 * Now that the driver is registered, we need
706 * to notify the hook that a battery is available
707 * for each battery, so that the driver may add
708 * its attributes.
709 */
710 list_for_each_entry(battery, &acpi_battery_list, list) {
711 if (hook->add_battery(battery->bat)) {
712 /*
713 * If a add-battery returns non-zero,
714 * the registration of the extension has failed,
715 * and we will not add it to the list of loaded
716 * hooks.
717 */
718 pr_err("extension failed to load: %s", hook->name);
719 __battery_hook_unregister(hook, 0);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200720 goto end;
Ognjen Galicfa938542018-02-07 15:58:13 +0100721 }
722 }
723 pr_info("new extension: %s\n", hook->name);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200724end:
Ognjen Galicfa938542018-02-07 15:58:13 +0100725 mutex_unlock(&hook_mutex);
726}
727EXPORT_SYMBOL_GPL(battery_hook_register);
728
729/*
730 * This function gets called right after the battery sysfs
731 * attributes have been added, so that the drivers that
732 * define custom sysfs attributes can add their own.
Rafael J. Wysocki7a4ea102018-03-13 10:07:49 +0100733*/
Ognjen Galicfa938542018-02-07 15:58:13 +0100734static void battery_hook_add_battery(struct acpi_battery *battery)
735{
Jouke Witteveen673b4272018-07-04 12:27:15 +0200736 struct acpi_battery_hook *hook_node, *tmp;
Ognjen Galicfa938542018-02-07 15:58:13 +0100737
738 mutex_lock(&hook_mutex);
739 INIT_LIST_HEAD(&battery->list);
740 list_add(&battery->list, &acpi_battery_list);
741 /*
742 * Since we added a new battery to the list, we need to
743 * iterate over the hooks and call add_battery for each
744 * hook that was registered. This usually happens
745 * when a battery gets hotplugged or initialized
746 * during the battery module initialization.
747 */
Jouke Witteveen673b4272018-07-04 12:27:15 +0200748 list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) {
Ognjen Galicfa938542018-02-07 15:58:13 +0100749 if (hook_node->add_battery(battery->bat)) {
750 /*
751 * The notification of the extensions has failed, to
752 * prevent further errors we will unload the extension.
753 */
Ognjen Galicfa938542018-02-07 15:58:13 +0100754 pr_err("error in extension, unloading: %s",
755 hook_node->name);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200756 __battery_hook_unregister(hook_node, 0);
Ognjen Galicfa938542018-02-07 15:58:13 +0100757 }
758 }
759 mutex_unlock(&hook_mutex);
760}
761
762static void battery_hook_remove_battery(struct acpi_battery *battery)
763{
764 struct acpi_battery_hook *hook;
765
766 mutex_lock(&hook_mutex);
767 /*
768 * Before removing the hook, we need to remove all
769 * custom attributes from the battery.
770 */
771 list_for_each_entry(hook, &battery_hook_list, list) {
772 hook->remove_battery(battery->bat);
773 }
774 /* Then, just remove the battery from the list */
775 list_del(&battery->list);
776 mutex_unlock(&hook_mutex);
777}
778
779static void __exit battery_hook_exit(void)
780{
781 struct acpi_battery_hook *hook;
782 struct acpi_battery_hook *ptr;
783 /*
784 * At this point, the acpi_bus_unregister_driver()
785 * has called remove for all batteries. We just
786 * need to remove the hooks.
787 */
788 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
789 __battery_hook_unregister(hook, 1);
790 }
791 mutex_destroy(&hook_mutex);
792}
793
Andrey Borzenkov508df922007-10-28 12:50:09 +0300794static int sysfs_add_battery(struct acpi_battery *battery)
795{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100796 struct power_supply_config psy_cfg = { .drv_data = battery, };
Andrey Borzenkov508df922007-10-28 12:50:09 +0300797
Lan Tianyuae6f6182011-06-30 11:32:40 +0800798 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100799 battery->bat_desc.properties = charge_battery_props;
800 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300801 ARRAY_SIZE(charge_battery_props);
802 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100803 battery->bat_desc.properties = energy_battery_props;
804 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300805 ARRAY_SIZE(energy_battery_props);
806 }
807
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100808 battery->bat_desc.name = acpi_device_bid(battery->device);
809 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
810 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300811
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100812 battery->bat = power_supply_register_no_ws(&battery->device->dev,
813 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800814
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100815 if (IS_ERR(battery->bat)) {
816 int result = PTR_ERR(battery->bat);
817
818 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300819 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100820 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100821 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100822 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300823}
824
825static void sysfs_remove_battery(struct acpi_battery *battery)
826{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300827 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100828 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300829 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300830 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800831 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100832 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100833 device_remove_file(&battery->bat->dev, &alarm_attr);
834 power_supply_unregister(battery->bat);
835 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300836 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700837}
838
Kamil Iskra4000e6262012-11-16 22:28:58 +0100839static void find_battery(const struct dmi_header *dm, void *private)
840{
841 struct acpi_battery *battery = (struct acpi_battery *)private;
842 /* Note: the hardcoded offsets below have been extracted from
843 the source code of dmidecode. */
844 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
845 const u8 *dmi_data = (const u8 *)(dm + 1);
846 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
847 if (dm->length >= 18)
848 dmi_capacity *= dmi_data[17];
849 if (battery->design_capacity * battery->design_voltage / 1000
850 != dmi_capacity &&
851 battery->design_capacity * 10 == dmi_capacity)
852 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
853 &battery->flags);
854 }
855}
856
Zhang Rui557d5862010-10-22 10:02:06 +0800857/*
858 * According to the ACPI spec, some kinds of primary batteries can
859 * report percentage battery remaining capacity directly to OS.
860 * In this case, it reports the Last Full Charged Capacity == 100
861 * and BatteryPresentRate == 0xFFFFFFFF.
862 *
863 * Now we found some battery reports percentage remaining capacity
864 * even if it's rechargeable.
865 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
866 *
867 * Handle this correctly so that they won't break userspace.
868 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800869static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800870{
871 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000872 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800873
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000874 if (battery->full_charge_capacity == 100 &&
875 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
876 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800877 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
878 battery->full_charge_capacity = battery->design_capacity;
879 battery->capacity_now = (battery->capacity_now *
880 battery->full_charge_capacity) / 100;
881 }
Kamil Iskra4000e6262012-11-16 22:28:58 +0100882
883 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000884 return;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100885
886 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
887 const char *s;
888 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200889 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e6262012-11-16 22:28:58 +0100890 dmi_walk(find_battery, battery);
891 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
892 &battery->flags) &&
893 battery->design_voltage) {
894 battery->design_capacity =
895 battery->design_capacity *
896 10000 / battery->design_voltage;
897 battery->full_charge_capacity =
898 battery->full_charge_capacity *
899 10000 / battery->design_voltage;
900 battery->design_capacity_warning =
901 battery->design_capacity_warning *
902 10000 / battery->design_voltage;
903 battery->capacity_now = battery->capacity_now *
904 10000 / battery->design_voltage;
905 }
906 }
907 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100908
909 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
910 return;
911
912 if (acpi_battery_is_degraded(battery) &&
913 battery->capacity_now > battery->full_charge_capacity) {
914 set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
915 battery->capacity_now = battery->full_charge_capacity;
916 }
Zhang Rui557d5862010-10-22 10:02:06 +0800917}
918
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800919static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500920{
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300921 int result, old_present = acpi_battery_present(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500922 result = acpi_battery_get_status(battery);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300923 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300924 return result;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300925 if (!acpi_battery_present(battery)) {
926 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500927 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300928 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300929 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800930
931 if (resume)
932 return 0;
933
Alexey Starikovskiy50b17852008-12-23 02:44:54 +0300934 if (!battery->update_time ||
935 old_present != acpi_battery_present(battery)) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500936 result = acpi_battery_get_info(battery);
937 if (result)
938 return result;
939 acpi_battery_init_alarm(battery);
940 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200941
942 result = acpi_battery_get_state(battery);
943 if (result)
944 return result;
945 acpi_battery_quirks(battery);
946
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100947 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100948 result = sysfs_add_battery(battery);
949 if (result)
950 return result;
951 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800952
953 /*
954 * Wakeup the system if battery is critical low
955 * or lower than the alarm level
956 */
957 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
958 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
959 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200960 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800961
Zhang Rui557d5862010-10-22 10:02:06 +0800962 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500963}
964
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100965static void acpi_battery_refresh(struct acpi_battery *battery)
966{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100967 int power_unit;
968
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100969 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100970 return;
971
Andy Whitcroftc5971452012-05-03 14:48:26 +0100972 power_unit = battery->power_unit;
973
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100974 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100975
976 if (power_unit == battery->power_unit)
977 return;
978
979 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100980 sysfs_remove_battery(battery);
981 sysfs_add_battery(battery);
982}
983
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800985 FS Interface (/proc)
986 -------------------------------------------------------------------------- */
987
988#ifdef CONFIG_ACPI_PROCFS_POWER
989static struct proc_dir_entry *acpi_battery_dir;
990
Mathias Krause27059b92015-06-13 14:26:54 +0200991static const char *acpi_battery_units(const struct acpi_battery *battery)
992{
993 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
994 "mA" : "mW";
995}
996
Christoph Hellwige7b087f2018-04-11 16:27:14 +0200997static int acpi_battery_info_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800998{
999 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001000 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001001
1002 if (result)
1003 goto end;
1004
1005 seq_printf(seq, "present: %s\n",
1006 acpi_battery_present(battery) ? "yes" : "no");
1007 if (!acpi_battery_present(battery))
1008 goto end;
1009 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1010 seq_printf(seq, "design capacity: unknown\n");
1011 else
1012 seq_printf(seq, "design capacity: %d %sh\n",
1013 battery->design_capacity,
1014 acpi_battery_units(battery));
1015
1016 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1017 seq_printf(seq, "last full capacity: unknown\n");
1018 else
1019 seq_printf(seq, "last full capacity: %d %sh\n",
1020 battery->full_charge_capacity,
1021 acpi_battery_units(battery));
1022
1023 seq_printf(seq, "battery technology: %srechargeable\n",
1024 (!battery->technology)?"non-":"");
1025
1026 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1027 seq_printf(seq, "design voltage: unknown\n");
1028 else
1029 seq_printf(seq, "design voltage: %d mV\n",
1030 battery->design_voltage);
1031 seq_printf(seq, "design capacity warning: %d %sh\n",
1032 battery->design_capacity_warning,
1033 acpi_battery_units(battery));
1034 seq_printf(seq, "design capacity low: %d %sh\n",
1035 battery->design_capacity_low,
1036 acpi_battery_units(battery));
1037 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1038 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1039 battery->capacity_granularity_1,
1040 acpi_battery_units(battery));
1041 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1042 battery->capacity_granularity_2,
1043 acpi_battery_units(battery));
1044 seq_printf(seq, "model number: %s\n", battery->model_number);
1045 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1046 seq_printf(seq, "battery type: %s\n", battery->type);
1047 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1048 end:
1049 if (result)
1050 seq_printf(seq, "ERROR: Unable to read battery info\n");
1051 return result;
1052}
1053
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001054static int acpi_battery_state_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001055{
1056 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001057 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001058
1059 if (result)
1060 goto end;
1061
1062 seq_printf(seq, "present: %s\n",
1063 acpi_battery_present(battery) ? "yes" : "no");
1064 if (!acpi_battery_present(battery))
1065 goto end;
1066
1067 seq_printf(seq, "capacity state: %s\n",
1068 (battery->state & 0x04) ? "critical" : "ok");
1069 if ((battery->state & 0x01) && (battery->state & 0x02))
1070 seq_printf(seq,
1071 "charging state: charging/discharging\n");
1072 else if (battery->state & 0x01)
1073 seq_printf(seq, "charging state: discharging\n");
1074 else if (battery->state & 0x02)
1075 seq_printf(seq, "charging state: charging\n");
1076 else
1077 seq_printf(seq, "charging state: charged\n");
1078
1079 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1080 seq_printf(seq, "present rate: unknown\n");
1081 else
1082 seq_printf(seq, "present rate: %d %s\n",
1083 battery->rate_now, acpi_battery_units(battery));
1084
1085 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1086 seq_printf(seq, "remaining capacity: unknown\n");
1087 else
1088 seq_printf(seq, "remaining capacity: %d %sh\n",
1089 battery->capacity_now, acpi_battery_units(battery));
1090 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1091 seq_printf(seq, "present voltage: unknown\n");
1092 else
1093 seq_printf(seq, "present voltage: %d mV\n",
1094 battery->voltage_now);
1095 end:
1096 if (result)
1097 seq_printf(seq, "ERROR: Unable to read battery state\n");
1098
1099 return result;
1100}
1101
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001102static int acpi_battery_alarm_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001103{
1104 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001105 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001106
1107 if (result)
1108 goto end;
1109
1110 if (!acpi_battery_present(battery)) {
1111 seq_printf(seq, "present: no\n");
1112 goto end;
1113 }
1114 seq_printf(seq, "alarm: ");
1115 if (!battery->alarm)
1116 seq_printf(seq, "unsupported\n");
1117 else
1118 seq_printf(seq, "%u %sh\n", battery->alarm,
1119 acpi_battery_units(battery));
1120 end:
1121 if (result)
1122 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1123 return result;
1124}
1125
1126static ssize_t acpi_battery_write_alarm(struct file *file,
1127 const char __user * buffer,
1128 size_t count, loff_t * ppos)
1129{
1130 int result = 0;
1131 char alarm_string[12] = { '\0' };
1132 struct seq_file *m = file->private_data;
1133 struct acpi_battery *battery = m->private;
1134
1135 if (!battery || (count > sizeof(alarm_string) - 1))
1136 return -EINVAL;
1137 if (!acpi_battery_present(battery)) {
1138 result = -ENODEV;
1139 goto end;
1140 }
1141 if (copy_from_user(alarm_string, buffer, count)) {
1142 result = -EFAULT;
1143 goto end;
1144 }
1145 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001146 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1147 result = -EINVAL;
1148 goto end;
1149 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001150 result = acpi_battery_set_alarm(battery);
1151 end:
1152 if (!result)
1153 return count;
1154 return result;
1155}
1156
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001157static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001158{
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001159 return single_open(file, acpi_battery_alarm_proc_show, PDE_DATA(inode));
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001160}
1161
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001162static const struct file_operations acpi_battery_alarm_fops = {
1163 .owner = THIS_MODULE,
1164 .open = acpi_battery_alarm_proc_open,
1165 .read = seq_read,
1166 .write = acpi_battery_write_alarm,
1167 .llseek = seq_lseek,
1168 .release = single_release,
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001169};
1170
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001171static int acpi_battery_add_fs(struct acpi_device *device)
1172{
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001173 printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
1174 " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
1175 if (!acpi_device_dir(device)) {
1176 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1177 acpi_battery_dir);
1178 if (!acpi_device_dir(device))
1179 return -ENODEV;
1180 }
1181
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001182 if (!proc_create_single_data("info", S_IRUGO, acpi_device_dir(device),
1183 acpi_battery_info_proc_show, acpi_driver_data(device)))
1184 return -ENODEV;
1185 if (!proc_create_single_data("state", S_IRUGO, acpi_device_dir(device),
1186 acpi_battery_state_proc_show, acpi_driver_data(device)))
1187 return -ENODEV;
1188 if (!proc_create_data("alarm", S_IFREG | S_IRUGO | S_IWUSR,
1189 acpi_device_dir(device), &acpi_battery_alarm_fops,
1190 acpi_driver_data(device)))
1191 return -ENODEV;
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001192 return 0;
1193}
1194
1195static void acpi_battery_remove_fs(struct acpi_device *device)
1196{
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001197 if (!acpi_device_dir(device))
1198 return;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001199 remove_proc_subtree(acpi_device_bid(device), acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001200 acpi_device_dir(device) = NULL;
1201}
1202
1203#endif
1204
1205/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 Driver Interface
1207 -------------------------------------------------------------------------- */
1208
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001209static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001211 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001212 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001215 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001216 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001217 /*
1218 * On Acer Aspire V5-573G notifications are sometimes triggered too
1219 * early. For example, when AC is unplugged and notification is
1220 * triggered, battery state is still reported as "Full", and changes to
1221 * "Discharging" only after short delay, without any notification.
1222 */
1223 if (battery_notification_delay_ms > 0)
1224 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001225 if (event == ACPI_BATTERY_NOTIFY_INFO)
1226 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001227 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001228 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001229 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001230 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001231 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001232 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001233 if (old && battery->bat)
1234 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235}
1236
Kyle McMartin25be5822011-03-22 16:19:50 -04001237static int battery_notify(struct notifier_block *nb,
1238 unsigned long mode, void *_unused)
1239{
1240 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1241 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001242 int result;
1243
Kyle McMartin25be5822011-03-22 16:19:50 -04001244 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001245 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001246 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001247 if (!acpi_battery_present(battery))
1248 return 0;
1249
Krzysztof Kozlowski31f7dc72015-04-14 22:24:13 +09001250 if (!battery->bat) {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001251 result = acpi_battery_get_info(battery);
1252 if (result)
1253 return result;
1254
1255 result = sysfs_add_battery(battery);
1256 if (result)
1257 return result;
1258 } else
1259 acpi_battery_refresh(battery);
1260
1261 acpi_battery_init_alarm(battery);
1262 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001263 break;
1264 }
1265
1266 return 0;
1267}
1268
Mathias Krause048d16d2015-06-13 14:26:55 +02001269static int __init
1270battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001271{
1272 battery_bix_broken_package = 1;
1273 return 0;
1274}
1275
Mathias Krause048d16d2015-06-13 14:26:55 +02001276static int __init
1277battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001278{
1279 battery_notification_delay_ms = 1000;
1280 return 0;
1281}
1282
Hans de Goede1b799c52018-04-12 12:02:00 +02001283static int __init
1284battery_ac_is_broken_quirk(const struct dmi_system_id *d)
1285{
1286 battery_ac_is_broken = 1;
1287 return 0;
1288}
1289
Carlo Caioneec625a32018-04-18 14:04:39 +02001290static int __init
1291battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
1292{
1293 battery_check_pmic = 0;
1294 return 0;
1295}
1296
Mathias Krause048d16d2015-06-13 14:26:55 +02001297static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001298 {
Hans de Goede91afa072018-04-12 12:01:58 +02001299 /* NEC LZ750/LS */
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001300 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001301 .matches = {
1302 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1303 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1304 },
1305 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001306 {
Hans de Goede91afa072018-04-12 12:01:58 +02001307 /* Acer Aspire V5-573G */
Alexander Mezinf43691c2014-06-04 02:01:23 +07001308 .callback = battery_notification_delay_quirk,
Alexander Mezinf43691c2014-06-04 02:01:23 +07001309 .matches = {
1310 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1311 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1312 },
1313 },
Hans de Goede1b799c52018-04-12 12:02:00 +02001314 {
1315 /* Point of View mobii wintab p800w */
1316 .callback = battery_ac_is_broken_quirk,
1317 .matches = {
1318 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1319 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1320 DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
1321 /* Above matches are too generic, add bios-date match */
1322 DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
1323 },
1324 },
Carlo Caioneec625a32018-04-18 14:04:39 +02001325 {
1326 /* ECS EF20EA */
1327 .callback = battery_do_not_check_pmic_quirk,
1328 .matches = {
1329 DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
1330 },
1331 },
1332 {
1333 /* Lenovo Ideapad Miix 320 */
1334 .callback = battery_do_not_check_pmic_quirk,
1335 .matches = {
1336 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1337 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
1338 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
1339 },
1340 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001341 {},
1342};
1343
Lan Tianyu75646e72014-07-07 15:47:12 +08001344/*
1345 * Some machines'(E,G Lenovo Z480) ECs are not stable
1346 * during boot up and this causes battery driver fails to be
1347 * probed due to failure of getting battery information
1348 * from EC sometimes. After several retries, the operation
1349 * may work. So add retry code here and 20ms sleep between
1350 * every retries.
1351 */
1352static int acpi_battery_update_retry(struct acpi_battery *battery)
1353{
1354 int retry, ret;
1355
1356 for (retry = 5; retry; retry--) {
1357 ret = acpi_battery_update(battery, false);
1358 if (!ret)
1359 break;
1360
1361 msleep(20);
1362 }
1363 return ret;
1364}
1365
Len Brown4be44fc2005-08-05 00:44:28 -04001366static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Len Brown4be44fc2005-08-05 00:44:28 -04001368 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001369 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001372 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001373
1374 if (device->dep_unmet)
1375 return -EPROBE_DEFER;
1376
Burman Yan36bcbec2006-12-19 12:56:11 -08001377 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001379 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001380 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1382 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001383 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001384 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001385 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001386 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001387 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001388
1389 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001390 if (result)
1391 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001392
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001393#ifdef CONFIG_ACPI_PROCFS_POWER
1394 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001395 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001396 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001397 goto fail;
1398 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001399#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001400
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001401 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
1402 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1403 device->status.battery_present ? "present" : "absent");
1404
Kyle McMartin25be5822011-03-22 16:19:50 -04001405 battery->pm_nb.notifier_call = battery_notify;
1406 register_pm_notifier(&battery->pm_nb);
1407
Zhang Ruie0d1f092014-05-28 15:23:38 +08001408 device_init_wakeup(&device->dev, 1);
1409
Patrick Mocheld550d982006-06-27 00:41:40 -04001410 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001411
1412fail:
1413 sysfs_remove_battery(battery);
1414 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001415 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001416 kfree(battery);
1417 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418}
1419
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001420static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421{
Len Brown4be44fc2005-08-05 00:44:28 -04001422 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001425 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001426 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001427 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001428 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001429#ifdef CONFIG_ACPI_PROCFS_POWER
1430 acpi_battery_remove_fs(device);
1431#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001432 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001433 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001434 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001436 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437}
1438
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001439#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001440/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001441static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001442{
1443 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001444
1445 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001446 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001447
1448 battery = acpi_driver_data(to_acpi_device(dev));
1449 if (!battery)
1450 return -EINVAL;
1451
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001452 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001453 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001454 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001455}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001456#else
1457#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001458#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001459
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001460static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1461
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001462static struct acpi_driver acpi_battery_driver = {
1463 .name = "battery",
1464 .class = ACPI_BATTERY_CLASS,
1465 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001466 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001467 .ops = {
1468 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001469 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001470 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001471 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001472 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001473};
1474
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001475static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
Hans de Goededccfae62017-04-19 14:02:10 +02001477 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001478 int result;
1479
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001480 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001481
Carlo Caioneec625a32018-04-18 14:04:39 +02001482 if (battery_check_pmic) {
1483 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1484 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1485 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1486 ": found native %s PMIC, not loading\n",
1487 acpi_battery_blacklist[i]);
1488 return;
1489 }
1490 }
1491
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001492#ifdef CONFIG_ACPI_PROCFS_POWER
1493 acpi_battery_dir = acpi_lock_battery_dir();
1494 if (!acpi_battery_dir)
1495 return;
1496#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001497 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001498#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001499 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001500 acpi_unlock_battery_dir(acpi_battery_dir);
1501#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001502 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001503}
1504
1505static int __init acpi_battery_init(void)
1506{
Luis Henriquese234b072015-05-11 22:48:38 +01001507 if (acpi_disabled)
1508 return -ENODEV;
1509
Luis Henriqueseca21d912015-05-11 22:49:05 +01001510 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001511 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
Len Brown4be44fc2005-08-05 00:44:28 -04001514static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001516 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001517 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001518 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001519 battery_hook_exit();
1520 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001521#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001522 if (acpi_battery_dir)
1523 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001524#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
1526
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527module_init(acpi_battery_init);
1528module_exit(acpi_battery_exit);