blob: 558fedf8a7a1b315d0a5b0823a729a932a60c4f1 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04003 * battery.c - ACPI Battery Driver (Revision: 2.0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04005 * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de>
6 * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
8 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
Ognjen Galicfa938542018-02-07 15:58:13 +010011#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
Dmitry Rozhkov53dd2002018-07-24 14:27:32 +030013#include <linux/async.h>
14#include <linux/delay.h>
15#include <linux/dmi.h>
16#include <linux/jiffies.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/kernel.h>
Ognjen Galicfa938542018-02-07 15:58:13 +010018#include <linux/list.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/module.h>
Ognjen Galicfa938542018-02-07 15:58:13 +010020#include <linux/mutex.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090021#include <linux/slab.h>
Kyle McMartin25be5822011-03-22 16:19:50 -040022#include <linux/suspend.h>
Dmitry Rozhkov53dd2002018-07-24 14:27:32 +030023#include <linux/types.h>
24
Kamil Iskra4000e6262012-11-16 22:28:58 +010025#include <asm/unaligned.h>
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040026
Lan Tianyu3a670cc2014-05-04 11:07:25 +080027#ifdef CONFIG_ACPI_PROCFS_POWER
28#include <linux/proc_fs.h>
29#include <linux/seq_file.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -080030#include <linux/uaccess.h>
Lan Tianyu3a670cc2014-05-04 11:07:25 +080031#endif
32
Lv Zheng8b484632013-12-03 08:49:16 +080033#include <linux/acpi.h>
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040034#include <linux/power_supply.h>
35
Ognjen Galicfa938542018-02-07 15:58:13 +010036#include <acpi/battery.h>
Alexander Mezinf03be352014-03-12 00:58:46 +070037
Len Browna192a952009-07-28 16:45:54 -040038#define PREFIX "ACPI: "
39
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
41
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#define ACPI_BATTERY_DEVICE_NAME "Battery"
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Lan Tianyuae6f6182011-06-30 11:32:40 +080044/* Battery power unit: 0 means mW, 1 means mA */
45#define ACPI_BATTERY_POWER_UNIT_MA 1
46
Zhang Rui1ac5aaa2014-05-28 15:23:36 +080047#define ACPI_BATTERY_STATE_DISCHARGING 0x1
48#define ACPI_BATTERY_STATE_CHARGING 0x2
49#define ACPI_BATTERY_STATE_CRITICAL 0x4
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#define _COMPONENT ACPI_BATTERY_COMPONENT
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030052
Len Brownf52fd662007-02-12 22:42:12 -050053ACPI_MODULE_NAME("battery");
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Len Brownf52fd662007-02-12 22:42:12 -050055MODULE_AUTHOR("Paul Diefenbaugh");
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +040056MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
Len Brown7cda93e2007-02-12 23:50:02 -050057MODULE_DESCRIPTION("ACPI Battery Driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070058MODULE_LICENSE("GPL");
59
Luis Henriqueseca21d912015-05-11 22:49:05 +010060static async_cookie_t async_cookie;
Hans de Goedebc39fbc2017-04-19 14:02:09 +020061static bool battery_driver_registered;
Lan Tianyua90b4032014-01-06 22:50:37 +080062static int battery_bix_broken_package;
Alexander Mezinf43691c2014-06-04 02:01:23 +070063static int battery_notification_delay_ms;
Hans de Goede1b799c52018-04-12 12:02:00 +020064static int battery_ac_is_broken;
Carlo Caioneec625a32018-04-18 14:04:39 +020065static int battery_check_pmic = 1;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040066static unsigned int cache_time = 1000;
67module_param(cache_time, uint, 0644);
68MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030069
Lan Tianyu3a670cc2014-05-04 11:07:25 +080070#ifdef CONFIG_ACPI_PROCFS_POWER
71extern struct proc_dir_entry *acpi_lock_battery_dir(void);
72extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +080073#endif
74
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040075static const struct acpi_device_id battery_device_ids[] = {
76 {"PNP0C0A", 0},
77 {"", 0},
78};
79
80MODULE_DEVICE_TABLE(acpi, battery_device_ids);
81
Hans de Goededccfae62017-04-19 14:02:10 +020082/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
83static const char * const acpi_battery_blacklist[] = {
84 "INT33F4", /* X-Powers AXP288 PMIC */
85};
86
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +040087enum {
88 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +040089 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +080090 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e6262012-11-16 22:28:58 +010091 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
92 switches between mWh and mAh depending on whether the system
93 is running on battery or not. When mAh is the unit, most
94 reported values are incorrect and need to be adjusted by
95 10000/design_voltage. Verified on x201, t410, t410s, and x220.
96 Pre-2010 and 2012 models appear to always report in mWh and
97 are thus unaffected (tested with t42, t61, t500, x200, x300,
98 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
99 the 2011 models that fixes the issue (tested on x220 with a
100 post-1.29 BIOS), but as of Nov. 2012, no such update is
101 available for the 2010 models. */
102 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Laszlo Totha20136a2018-02-24 10:20:15 +0100103 /* for batteries reporting current capacity with design capacity
104 * on a full charge, but showing degradation in full charge cap.
105 */
106 ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400107};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400108
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400109struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400110 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300111 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100112 struct power_supply *bat;
113 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400114 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400115 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100116 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400117 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200118 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400119 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400120 int capacity_now;
121 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400122 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400123 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400124 int technology;
125 int design_voltage;
126 int design_capacity_warning;
127 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400128 int cycle_count;
129 int measurement_accuracy;
130 int max_sampling_time;
131 int min_sampling_time;
132 int max_averaging_interval;
133 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400134 int capacity_granularity_1;
135 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400136 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400137 char model_number[32];
138 char serial_number[32];
139 char type[32];
140 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400141 int state;
142 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400143 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144};
145
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100146#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400147
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000148static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400149{
150 return battery->device->status.battery_present;
151}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400152
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400153static int acpi_battery_technology(struct acpi_battery *battery)
154{
155 if (!strcasecmp("NiCd", battery->type))
156 return POWER_SUPPLY_TECHNOLOGY_NiCd;
157 if (!strcasecmp("NiMH", battery->type))
158 return POWER_SUPPLY_TECHNOLOGY_NiMH;
159 if (!strcasecmp("LION", battery->type))
160 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300161 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300162 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400163 if (!strcasecmp("LiP", battery->type))
164 return POWER_SUPPLY_TECHNOLOGY_LIPO;
165 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
166}
167
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300168static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400169
Richard Hughes56f382a2009-01-25 15:05:50 +0000170static int acpi_battery_is_charged(struct acpi_battery *battery)
171{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800172 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000173 if (battery->state != 0)
174 return 0;
175
176 /* battery not reporting charge */
177 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
178 battery->capacity_now == 0)
179 return 0;
180
181 /* good batteries update full_charge as the batteries degrade */
182 if (battery->full_charge_capacity == battery->capacity_now)
183 return 1;
184
185 /* fallback to using design values for broken batteries */
186 if (battery->design_capacity == battery->capacity_now)
187 return 1;
188
189 /* we don't do any sort of metric based on percentages */
190 return 0;
191}
192
Laszlo Totha20136a2018-02-24 10:20:15 +0100193static bool acpi_battery_is_degraded(struct acpi_battery *battery)
194{
195 return battery->full_charge_capacity && battery->design_capacity &&
196 battery->full_charge_capacity < battery->design_capacity;
197}
198
Hans de Goede19fffc82018-04-12 12:01:59 +0200199static int acpi_battery_handle_discharging(struct acpi_battery *battery)
200{
201 /*
202 * Some devices wrongly report discharging if the battery's charge level
203 * was above the device's start charging threshold atm the AC adapter
204 * was plugged in and the device thus did not start a new charge cycle.
205 */
Hans de Goede1b799c52018-04-12 12:02:00 +0200206 if ((battery_ac_is_broken || power_supply_is_system_supplied()) &&
207 battery->rate_now == 0)
Hans de Goede19fffc82018-04-12 12:01:59 +0200208 return POWER_SUPPLY_STATUS_NOT_CHARGING;
209
210 return POWER_SUPPLY_STATUS_DISCHARGING;
211}
212
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400213static int acpi_battery_get_property(struct power_supply *psy,
214 enum power_supply_property psp,
215 union power_supply_propval *val)
216{
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200217 int ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400218 struct acpi_battery *battery = to_acpi_battery(psy);
219
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300220 if (acpi_battery_present(battery)) {
221 /* run battery update only if it is present */
222 acpi_battery_get_state(battery);
223 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400224 return -ENODEV;
225 switch (psp) {
226 case POWER_SUPPLY_PROP_STATUS:
Daniel Drake82bf43b2018-03-14 16:42:17 +0800227 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
Hans de Goede19fffc82018-04-12 12:01:59 +0200228 val->intval = acpi_battery_handle_discharging(battery);
Daniel Drake82bf43b2018-03-14 16:42:17 +0800229 else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400230 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000231 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400232 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800233 else
234 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400235 break;
236 case POWER_SUPPLY_PROP_PRESENT:
237 val->intval = acpi_battery_present(battery);
238 break;
239 case POWER_SUPPLY_PROP_TECHNOLOGY:
240 val->intval = acpi_battery_technology(battery);
241 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400242 case POWER_SUPPLY_PROP_CYCLE_COUNT:
243 val->intval = battery->cycle_count;
244 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400245 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200246 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
247 ret = -ENODEV;
248 else
249 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400250 break;
251 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200252 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
253 ret = -ENODEV;
254 else
255 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400256 break;
257 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400258 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200259 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
260 ret = -ENODEV;
261 else
262 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400263 break;
264 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
265 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200266 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
267 ret = -ENODEV;
268 else
269 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400270 break;
271 case POWER_SUPPLY_PROP_CHARGE_FULL:
272 case POWER_SUPPLY_PROP_ENERGY_FULL:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200273 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
274 ret = -ENODEV;
275 else
276 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400277 break;
278 case POWER_SUPPLY_PROP_CHARGE_NOW:
279 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200280 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
281 ret = -ENODEV;
282 else
283 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400284 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700285 case POWER_SUPPLY_PROP_CAPACITY:
286 if (battery->capacity_now && battery->full_charge_capacity)
287 val->intval = battery->capacity_now * 100/
288 battery->full_charge_capacity;
289 else
290 val->intval = 0;
291 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800292 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
293 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
294 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
295 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
296 (battery->capacity_now <= battery->alarm))
297 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
298 else if (acpi_battery_is_charged(battery))
299 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
300 else
301 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
302 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400303 case POWER_SUPPLY_PROP_MODEL_NAME:
304 val->strval = battery->model_number;
305 break;
306 case POWER_SUPPLY_PROP_MANUFACTURER:
307 val->strval = battery->oem_info;
308 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100309 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
310 val->strval = battery->serial_number;
311 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400312 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200313 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400314 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200315 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400316}
317
318static enum power_supply_property charge_battery_props[] = {
319 POWER_SUPPLY_PROP_STATUS,
320 POWER_SUPPLY_PROP_PRESENT,
321 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400322 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400323 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
324 POWER_SUPPLY_PROP_VOLTAGE_NOW,
325 POWER_SUPPLY_PROP_CURRENT_NOW,
326 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
327 POWER_SUPPLY_PROP_CHARGE_FULL,
328 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700329 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800330 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400331 POWER_SUPPLY_PROP_MODEL_NAME,
332 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100333 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400334};
335
336static enum power_supply_property energy_battery_props[] = {
337 POWER_SUPPLY_PROP_STATUS,
338 POWER_SUPPLY_PROP_PRESENT,
339 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400340 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400341 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
342 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400343 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400344 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
345 POWER_SUPPLY_PROP_ENERGY_FULL,
346 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700347 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800348 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400349 POWER_SUPPLY_PROP_MODEL_NAME,
350 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100351 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400352};
353
Hans de Goedeb41901a2018-08-07 09:36:30 +0200354static enum power_supply_property energy_battery_full_cap_broken_props[] = {
355 POWER_SUPPLY_PROP_STATUS,
356 POWER_SUPPLY_PROP_PRESENT,
357 POWER_SUPPLY_PROP_TECHNOLOGY,
358 POWER_SUPPLY_PROP_CYCLE_COUNT,
359 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
360 POWER_SUPPLY_PROP_VOLTAGE_NOW,
361 POWER_SUPPLY_PROP_POWER_NOW,
362 POWER_SUPPLY_PROP_ENERGY_NOW,
363 POWER_SUPPLY_PROP_MODEL_NAME,
364 POWER_SUPPLY_PROP_MANUFACTURER,
365 POWER_SUPPLY_PROP_SERIAL_NUMBER,
366};
367
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368/* --------------------------------------------------------------------------
369 Battery Management
370 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400371struct acpi_offsets {
372 size_t offset; /* offset inside struct acpi_sbs_battery */
373 u8 mode; /* int or string? */
374};
375
Mathias Krausea4658782015-06-13 14:26:53 +0200376static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400377 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400378 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400379 {offsetof(struct acpi_battery, capacity_now), 0},
380 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400381};
382
Mathias Krausea4658782015-06-13 14:26:53 +0200383static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400384 {offsetof(struct acpi_battery, power_unit), 0},
385 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400386 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400387 {offsetof(struct acpi_battery, technology), 0},
388 {offsetof(struct acpi_battery, design_voltage), 0},
389 {offsetof(struct acpi_battery, design_capacity_warning), 0},
390 {offsetof(struct acpi_battery, design_capacity_low), 0},
391 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
392 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
393 {offsetof(struct acpi_battery, model_number), 1},
394 {offsetof(struct acpi_battery, serial_number), 1},
395 {offsetof(struct acpi_battery, type), 1},
396 {offsetof(struct acpi_battery, oem_info), 1},
397};
398
Mathias Krausea4658782015-06-13 14:26:53 +0200399static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200400 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400401 {offsetof(struct acpi_battery, power_unit), 0},
402 {offsetof(struct acpi_battery, design_capacity), 0},
403 {offsetof(struct acpi_battery, full_charge_capacity), 0},
404 {offsetof(struct acpi_battery, technology), 0},
405 {offsetof(struct acpi_battery, design_voltage), 0},
406 {offsetof(struct acpi_battery, design_capacity_warning), 0},
407 {offsetof(struct acpi_battery, design_capacity_low), 0},
408 {offsetof(struct acpi_battery, cycle_count), 0},
409 {offsetof(struct acpi_battery, measurement_accuracy), 0},
410 {offsetof(struct acpi_battery, max_sampling_time), 0},
411 {offsetof(struct acpi_battery, min_sampling_time), 0},
412 {offsetof(struct acpi_battery, max_averaging_interval), 0},
413 {offsetof(struct acpi_battery, min_averaging_interval), 0},
414 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
415 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
416 {offsetof(struct acpi_battery, model_number), 1},
417 {offsetof(struct acpi_battery, serial_number), 1},
418 {offsetof(struct acpi_battery, type), 1},
419 {offsetof(struct acpi_battery, oem_info), 1},
420};
421
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400422static int extract_package(struct acpi_battery *battery,
423 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200424 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300425{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300426 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400427 union acpi_object *element;
428 if (package->type != ACPI_TYPE_PACKAGE)
429 return -EFAULT;
430 for (i = 0; i < num; ++i) {
431 if (package->package.count <= i)
432 return -EFAULT;
433 element = &package->package.elements[i];
434 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300435 u8 *ptr = (u8 *)battery + offsets[i].offset;
436 if (element->type == ACPI_TYPE_STRING ||
437 element->type == ACPI_TYPE_BUFFER)
438 strncpy(ptr, element->string.pointer, 32);
439 else if (element->type == ACPI_TYPE_INTEGER) {
440 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800441 sizeof(u64));
442 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400443 } else
444 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400445 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400446 int *x = (int *)((u8 *)battery + offsets[i].offset);
447 *x = (element->type == ACPI_TYPE_INTEGER) ?
448 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300449 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300450 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300451 return 0;
452}
453
454static int acpi_battery_get_status(struct acpi_battery *battery)
455{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400456 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300457 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
458 return -ENODEV;
459 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400460 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300461}
462
Dave Lambley2d09af42016-11-04 01:05:40 +0000463
464static int extract_battery_info(const int use_bix,
465 struct acpi_battery *battery,
466 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400468 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400469
Dave Lambley2d09af42016-11-04 01:05:40 +0000470 if (use_bix && battery_bix_broken_package)
471 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800472 extended_info_offsets + 1,
473 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000474 else if (use_bix)
475 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400476 extended_info_offsets,
477 ARRAY_SIZE(extended_info_offsets));
478 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000479 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400480 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800481 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
482 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100483 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
484 battery->power_unit && battery->design_voltage) {
485 battery->design_capacity = battery->design_capacity *
486 10000 / battery->design_voltage;
487 battery->full_charge_capacity = battery->full_charge_capacity *
488 10000 / battery->design_voltage;
489 battery->design_capacity_warning =
490 battery->design_capacity_warning *
491 10000 / battery->design_voltage;
492 /* Curiously, design_capacity_low, unlike the rest of them,
493 is correct. */
494 /* capacity_granularity_* equal 1 on the systems tested, so
495 it's impossible to tell if they would need an adjustment
496 or not if their values were higher. */
497 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100498 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
499 battery->capacity_now > battery->full_charge_capacity)
500 battery->capacity_now = battery->full_charge_capacity;
501
Patrick Mocheld550d982006-06-27 00:41:40 -0400502 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503}
504
Dave Lambley2d09af42016-11-04 01:05:40 +0000505static int acpi_battery_get_info(struct acpi_battery *battery)
506{
507 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
508 int use_bix;
509 int result = -ENODEV;
510
511 if (!acpi_battery_present(battery))
512 return 0;
513
514
515 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
516 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
517 acpi_status status = AE_ERROR;
518
519 mutex_lock(&battery->lock);
520 status = acpi_evaluate_object(battery->device->handle,
521 use_bix ? "_BIX":"_BIF",
522 NULL, &buffer);
523 mutex_unlock(&battery->lock);
524
525 if (ACPI_FAILURE(status)) {
526 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
527 use_bix ? "_BIX":"_BIF"));
528 } else {
529 result = extract_battery_info(use_bix,
530 battery,
531 &buffer);
532
533 kfree(buffer.pointer);
534 break;
535 }
536 }
537
538 if (!result && !use_bix && xinfo)
539 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
540
541 return result;
542}
543
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300544static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
Len Brown4be44fc2005-08-05 00:44:28 -0400546 int result = 0;
547 acpi_status status = 0;
548 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300550 if (!acpi_battery_present(battery))
551 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400553 if (battery->update_time &&
554 time_before(jiffies, battery->update_time +
555 msecs_to_jiffies(cache_time)))
556 return 0;
557
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400558 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400559 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400560 NULL, &buffer);
561 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400562
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400564 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400565 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400567
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400568 result = extract_package(battery, buffer.pointer,
569 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400570 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400571 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700572
Lan Tianyu55003b22011-06-30 11:33:12 +0800573 /* For buggy DSDTs that report negative 16-bit values for either
574 * charging or discharging current and/or report 0 as 65536
575 * due to bad math.
576 */
577 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
578 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
579 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700580 battery->rate_now = abs((s16)battery->rate_now);
Dmitry Rozhkovdd1fca92018-07-24 14:27:33 +0300581 pr_warn_once(FW_BUG "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);
Hans de Goedeb41901a2018-08-07 09:36:30 +0200802 } else if (battery->full_charge_capacity == 0) {
803 battery->bat_desc.properties =
804 energy_battery_full_cap_broken_props;
805 battery->bat_desc.num_properties =
806 ARRAY_SIZE(energy_battery_full_cap_broken_props);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300807 } else {
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100808 battery->bat_desc.properties = energy_battery_props;
809 battery->bat_desc.num_properties =
Andrey Borzenkov508df922007-10-28 12:50:09 +0300810 ARRAY_SIZE(energy_battery_props);
811 }
812
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100813 battery->bat_desc.name = acpi_device_bid(battery->device);
814 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
815 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300816
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100817 battery->bat = power_supply_register_no_ws(&battery->device->dev,
818 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800819
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100820 if (IS_ERR(battery->bat)) {
821 int result = PTR_ERR(battery->bat);
822
823 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300824 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100825 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100826 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100827 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300828}
829
830static void sysfs_remove_battery(struct acpi_battery *battery)
831{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300832 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100833 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300834 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300835 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800836 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100837 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100838 device_remove_file(&battery->bat->dev, &alarm_attr);
839 power_supply_unregister(battery->bat);
840 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300841 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700842}
843
Kamil Iskra4000e6262012-11-16 22:28:58 +0100844static void find_battery(const struct dmi_header *dm, void *private)
845{
846 struct acpi_battery *battery = (struct acpi_battery *)private;
847 /* Note: the hardcoded offsets below have been extracted from
848 the source code of dmidecode. */
849 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
850 const u8 *dmi_data = (const u8 *)(dm + 1);
851 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
852 if (dm->length >= 18)
853 dmi_capacity *= dmi_data[17];
854 if (battery->design_capacity * battery->design_voltage / 1000
855 != dmi_capacity &&
856 battery->design_capacity * 10 == dmi_capacity)
857 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
858 &battery->flags);
859 }
860}
861
Zhang Rui557d5862010-10-22 10:02:06 +0800862/*
863 * According to the ACPI spec, some kinds of primary batteries can
864 * report percentage battery remaining capacity directly to OS.
865 * In this case, it reports the Last Full Charged Capacity == 100
866 * and BatteryPresentRate == 0xFFFFFFFF.
867 *
868 * Now we found some battery reports percentage remaining capacity
869 * even if it's rechargeable.
870 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
871 *
872 * Handle this correctly so that they won't break userspace.
873 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800874static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800875{
876 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000877 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800878
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000879 if (battery->full_charge_capacity == 100 &&
880 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
881 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800882 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
883 battery->full_charge_capacity = battery->design_capacity;
884 battery->capacity_now = (battery->capacity_now *
885 battery->full_charge_capacity) / 100;
886 }
Kamil Iskra4000e6262012-11-16 22:28:58 +0100887
888 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000889 return;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100890
891 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
892 const char *s;
893 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200894 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e6262012-11-16 22:28:58 +0100895 dmi_walk(find_battery, battery);
896 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
897 &battery->flags) &&
898 battery->design_voltage) {
899 battery->design_capacity =
900 battery->design_capacity *
901 10000 / battery->design_voltage;
902 battery->full_charge_capacity =
903 battery->full_charge_capacity *
904 10000 / battery->design_voltage;
905 battery->design_capacity_warning =
906 battery->design_capacity_warning *
907 10000 / battery->design_voltage;
908 battery->capacity_now = battery->capacity_now *
909 10000 / battery->design_voltage;
910 }
911 }
912 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100913
914 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
915 return;
916
917 if (acpi_battery_is_degraded(battery) &&
918 battery->capacity_now > battery->full_charge_capacity) {
919 set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
920 battery->capacity_now = battery->full_charge_capacity;
921 }
Zhang Rui557d5862010-10-22 10:02:06 +0800922}
923
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800924static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500925{
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700926 int result = acpi_battery_get_status(battery);
927
Andrey Borzenkov508df922007-10-28 12:50:09 +0300928 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300929 return result;
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700930
Andrey Borzenkov508df922007-10-28 12:50:09 +0300931 if (!acpi_battery_present(battery)) {
932 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500933 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300934 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300935 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800936
937 if (resume)
938 return 0;
939
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700940 if (!battery->update_time) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500941 result = acpi_battery_get_info(battery);
942 if (result)
943 return result;
944 acpi_battery_init_alarm(battery);
945 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200946
947 result = acpi_battery_get_state(battery);
948 if (result)
949 return result;
950 acpi_battery_quirks(battery);
951
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100952 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100953 result = sysfs_add_battery(battery);
954 if (result)
955 return result;
956 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800957
958 /*
959 * Wakeup the system if battery is critical low
960 * or lower than the alarm level
961 */
962 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
963 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
964 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200965 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800966
Zhang Rui557d5862010-10-22 10:02:06 +0800967 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500968}
969
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100970static void acpi_battery_refresh(struct acpi_battery *battery)
971{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100972 int power_unit;
973
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100974 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100975 return;
976
Andy Whitcroftc5971452012-05-03 14:48:26 +0100977 power_unit = battery->power_unit;
978
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100979 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +0100980
981 if (power_unit == battery->power_unit)
982 return;
983
984 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100985 sysfs_remove_battery(battery);
986 sysfs_add_battery(battery);
987}
988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989/* --------------------------------------------------------------------------
Lan Tianyu3a670cc2014-05-04 11:07:25 +0800990 FS Interface (/proc)
991 -------------------------------------------------------------------------- */
992
993#ifdef CONFIG_ACPI_PROCFS_POWER
994static struct proc_dir_entry *acpi_battery_dir;
995
Mathias Krause27059b92015-06-13 14:26:54 +0200996static const char *acpi_battery_units(const struct acpi_battery *battery)
997{
998 return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
999 "mA" : "mW";
1000}
1001
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001002static int acpi_battery_info_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001003{
1004 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001005 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001006
1007 if (result)
1008 goto end;
1009
1010 seq_printf(seq, "present: %s\n",
1011 acpi_battery_present(battery) ? "yes" : "no");
1012 if (!acpi_battery_present(battery))
1013 goto end;
1014 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1015 seq_printf(seq, "design capacity: unknown\n");
1016 else
1017 seq_printf(seq, "design capacity: %d %sh\n",
1018 battery->design_capacity,
1019 acpi_battery_units(battery));
1020
1021 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
1022 seq_printf(seq, "last full capacity: unknown\n");
1023 else
1024 seq_printf(seq, "last full capacity: %d %sh\n",
1025 battery->full_charge_capacity,
1026 acpi_battery_units(battery));
1027
1028 seq_printf(seq, "battery technology: %srechargeable\n",
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001029 battery->technology ? "" : "non-");
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001030
1031 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
1032 seq_printf(seq, "design voltage: unknown\n");
1033 else
1034 seq_printf(seq, "design voltage: %d mV\n",
1035 battery->design_voltage);
1036 seq_printf(seq, "design capacity warning: %d %sh\n",
1037 battery->design_capacity_warning,
1038 acpi_battery_units(battery));
1039 seq_printf(seq, "design capacity low: %d %sh\n",
1040 battery->design_capacity_low,
1041 acpi_battery_units(battery));
1042 seq_printf(seq, "cycle count: %i\n", battery->cycle_count);
1043 seq_printf(seq, "capacity granularity 1: %d %sh\n",
1044 battery->capacity_granularity_1,
1045 acpi_battery_units(battery));
1046 seq_printf(seq, "capacity granularity 2: %d %sh\n",
1047 battery->capacity_granularity_2,
1048 acpi_battery_units(battery));
1049 seq_printf(seq, "model number: %s\n", battery->model_number);
1050 seq_printf(seq, "serial number: %s\n", battery->serial_number);
1051 seq_printf(seq, "battery type: %s\n", battery->type);
1052 seq_printf(seq, "OEM info: %s\n", battery->oem_info);
1053 end:
1054 if (result)
1055 seq_printf(seq, "ERROR: Unable to read battery info\n");
1056 return result;
1057}
1058
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001059static int acpi_battery_state_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001060{
1061 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001062 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001063
1064 if (result)
1065 goto end;
1066
1067 seq_printf(seq, "present: %s\n",
1068 acpi_battery_present(battery) ? "yes" : "no");
1069 if (!acpi_battery_present(battery))
1070 goto end;
1071
1072 seq_printf(seq, "capacity state: %s\n",
1073 (battery->state & 0x04) ? "critical" : "ok");
1074 if ((battery->state & 0x01) && (battery->state & 0x02))
1075 seq_printf(seq,
1076 "charging state: charging/discharging\n");
1077 else if (battery->state & 0x01)
1078 seq_printf(seq, "charging state: discharging\n");
1079 else if (battery->state & 0x02)
1080 seq_printf(seq, "charging state: charging\n");
1081 else
1082 seq_printf(seq, "charging state: charged\n");
1083
1084 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
1085 seq_printf(seq, "present rate: unknown\n");
1086 else
1087 seq_printf(seq, "present rate: %d %s\n",
1088 battery->rate_now, acpi_battery_units(battery));
1089
1090 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
1091 seq_printf(seq, "remaining capacity: unknown\n");
1092 else
1093 seq_printf(seq, "remaining capacity: %d %sh\n",
1094 battery->capacity_now, acpi_battery_units(battery));
1095 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
1096 seq_printf(seq, "present voltage: unknown\n");
1097 else
1098 seq_printf(seq, "present voltage: %d mV\n",
1099 battery->voltage_now);
1100 end:
1101 if (result)
1102 seq_printf(seq, "ERROR: Unable to read battery state\n");
1103
1104 return result;
1105}
1106
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001107static int acpi_battery_alarm_proc_show(struct seq_file *seq, void *offset)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001108{
1109 struct acpi_battery *battery = seq->private;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001110 int result = acpi_battery_update(battery, false);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001111
1112 if (result)
1113 goto end;
1114
1115 if (!acpi_battery_present(battery)) {
1116 seq_printf(seq, "present: no\n");
1117 goto end;
1118 }
1119 seq_printf(seq, "alarm: ");
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001120 if (battery->alarm) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001121 seq_printf(seq, "%u %sh\n", battery->alarm,
1122 acpi_battery_units(battery));
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001123 } else {
1124 seq_printf(seq, "unsupported\n");
1125 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001126 end:
1127 if (result)
1128 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
1129 return result;
1130}
1131
1132static ssize_t acpi_battery_write_alarm(struct file *file,
1133 const char __user * buffer,
1134 size_t count, loff_t * ppos)
1135{
1136 int result = 0;
1137 char alarm_string[12] = { '\0' };
1138 struct seq_file *m = file->private_data;
1139 struct acpi_battery *battery = m->private;
1140
1141 if (!battery || (count > sizeof(alarm_string) - 1))
1142 return -EINVAL;
1143 if (!acpi_battery_present(battery)) {
1144 result = -ENODEV;
1145 goto end;
1146 }
1147 if (copy_from_user(alarm_string, buffer, count)) {
1148 result = -EFAULT;
1149 goto end;
1150 }
1151 alarm_string[count] = '\0';
Christoph Jaeger3d915892014-06-13 21:49:58 +02001152 if (kstrtoint(alarm_string, 0, &battery->alarm)) {
1153 result = -EINVAL;
1154 goto end;
1155 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001156 result = acpi_battery_set_alarm(battery);
1157 end:
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001158 if (result)
1159 return result;
1160 return count;
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001161}
1162
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001163static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001164{
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001165 return single_open(file, acpi_battery_alarm_proc_show, PDE_DATA(inode));
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001166}
1167
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001168static const struct file_operations acpi_battery_alarm_fops = {
1169 .owner = THIS_MODULE,
1170 .open = acpi_battery_alarm_proc_open,
1171 .read = seq_read,
1172 .write = acpi_battery_write_alarm,
1173 .llseek = seq_lseek,
1174 .release = single_release,
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001175};
1176
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001177static int acpi_battery_add_fs(struct acpi_device *device)
1178{
Dmitry Rozhkovdd1fca92018-07-24 14:27:33 +03001179 pr_warning(PREFIX "Deprecated procfs I/F for battery is loaded, please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001180 if (!acpi_device_dir(device)) {
1181 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
1182 acpi_battery_dir);
1183 if (!acpi_device_dir(device))
1184 return -ENODEV;
1185 }
1186
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001187 if (!proc_create_single_data("info", S_IRUGO, acpi_device_dir(device),
1188 acpi_battery_info_proc_show, acpi_driver_data(device)))
1189 return -ENODEV;
1190 if (!proc_create_single_data("state", S_IRUGO, acpi_device_dir(device),
1191 acpi_battery_state_proc_show, acpi_driver_data(device)))
1192 return -ENODEV;
1193 if (!proc_create_data("alarm", S_IFREG | S_IRUGO | S_IWUSR,
1194 acpi_device_dir(device), &acpi_battery_alarm_fops,
1195 acpi_driver_data(device)))
1196 return -ENODEV;
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001197 return 0;
1198}
1199
1200static void acpi_battery_remove_fs(struct acpi_device *device)
1201{
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001202 if (!acpi_device_dir(device))
1203 return;
Christoph Hellwige7b087f2018-04-11 16:27:14 +02001204 remove_proc_subtree(acpi_device_bid(device), acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001205 acpi_device_dir(device) = NULL;
1206}
1207
1208#endif
1209
1210/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 Driver Interface
1212 -------------------------------------------------------------------------- */
1213
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001214static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001216 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001217 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001220 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001221 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001222 /*
1223 * On Acer Aspire V5-573G notifications are sometimes triggered too
1224 * early. For example, when AC is unplugged and notification is
1225 * triggered, battery state is still reported as "Full", and changes to
1226 * "Discharging" only after short delay, without any notification.
1227 */
1228 if (battery_notification_delay_ms > 0)
1229 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001230 if (event == ACPI_BATTERY_NOTIFY_INFO)
1231 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001232 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001233 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001234 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001235 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001236 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001237 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001238 if (old && battery->bat)
1239 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240}
1241
Kyle McMartin25be5822011-03-22 16:19:50 -04001242static int battery_notify(struct notifier_block *nb,
1243 unsigned long mode, void *_unused)
1244{
1245 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1246 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001247 int result;
1248
Kyle McMartin25be5822011-03-22 16:19:50 -04001249 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001250 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001251 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001252 if (!acpi_battery_present(battery))
1253 return 0;
1254
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001255 if (battery->bat) {
1256 acpi_battery_refresh(battery);
1257 } else {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001258 result = acpi_battery_get_info(battery);
1259 if (result)
1260 return result;
1261
1262 result = sysfs_add_battery(battery);
1263 if (result)
1264 return result;
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001265 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001266
1267 acpi_battery_init_alarm(battery);
1268 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001269 break;
1270 }
1271
1272 return 0;
1273}
1274
Mathias Krause048d16d2015-06-13 14:26:55 +02001275static int __init
1276battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001277{
1278 battery_bix_broken_package = 1;
1279 return 0;
1280}
1281
Mathias Krause048d16d2015-06-13 14:26:55 +02001282static int __init
1283battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001284{
1285 battery_notification_delay_ms = 1000;
1286 return 0;
1287}
1288
Hans de Goede1b799c52018-04-12 12:02:00 +02001289static int __init
1290battery_ac_is_broken_quirk(const struct dmi_system_id *d)
1291{
1292 battery_ac_is_broken = 1;
1293 return 0;
1294}
1295
Carlo Caioneec625a32018-04-18 14:04:39 +02001296static int __init
1297battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
1298{
1299 battery_check_pmic = 0;
1300 return 0;
1301}
1302
Mathias Krause048d16d2015-06-13 14:26:55 +02001303static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001304 {
Hans de Goede91afa072018-04-12 12:01:58 +02001305 /* NEC LZ750/LS */
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001306 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001307 .matches = {
1308 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1309 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1310 },
1311 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001312 {
Hans de Goede91afa072018-04-12 12:01:58 +02001313 /* Acer Aspire V5-573G */
Alexander Mezinf43691c2014-06-04 02:01:23 +07001314 .callback = battery_notification_delay_quirk,
Alexander Mezinf43691c2014-06-04 02:01:23 +07001315 .matches = {
1316 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1317 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1318 },
1319 },
Hans de Goede1b799c52018-04-12 12:02:00 +02001320 {
1321 /* Point of View mobii wintab p800w */
1322 .callback = battery_ac_is_broken_quirk,
1323 .matches = {
1324 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1325 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1326 DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
1327 /* Above matches are too generic, add bios-date match */
1328 DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
1329 },
1330 },
Carlo Caioneec625a32018-04-18 14:04:39 +02001331 {
1332 /* ECS EF20EA */
1333 .callback = battery_do_not_check_pmic_quirk,
1334 .matches = {
1335 DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
1336 },
1337 },
1338 {
1339 /* Lenovo Ideapad Miix 320 */
1340 .callback = battery_do_not_check_pmic_quirk,
1341 .matches = {
1342 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1343 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
1344 DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
1345 },
1346 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001347 {},
1348};
1349
Lan Tianyu75646e72014-07-07 15:47:12 +08001350/*
1351 * Some machines'(E,G Lenovo Z480) ECs are not stable
1352 * during boot up and this causes battery driver fails to be
1353 * probed due to failure of getting battery information
1354 * from EC sometimes. After several retries, the operation
1355 * may work. So add retry code here and 20ms sleep between
1356 * every retries.
1357 */
1358static int acpi_battery_update_retry(struct acpi_battery *battery)
1359{
1360 int retry, ret;
1361
1362 for (retry = 5; retry; retry--) {
1363 ret = acpi_battery_update(battery, false);
1364 if (!ret)
1365 break;
1366
1367 msleep(20);
1368 }
1369 return ret;
1370}
1371
Len Brown4be44fc2005-08-05 00:44:28 -04001372static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373{
Len Brown4be44fc2005-08-05 00:44:28 -04001374 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001375 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001378 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001379
1380 if (device->dep_unmet)
1381 return -EPROBE_DEFER;
1382
Burman Yan36bcbec2006-12-19 12:56:11 -08001383 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001385 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001386 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1388 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001389 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001390 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001391 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001392 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001393 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001394
1395 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001396 if (result)
1397 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001398
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001399#ifdef CONFIG_ACPI_PROCFS_POWER
1400 result = acpi_battery_add_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001401 if (result) {
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001402 acpi_battery_remove_fs(device);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001403 goto fail;
1404 }
Bjørn Mork6993ce42017-12-05 18:46:39 +01001405#endif
Kyle McMartin25be5822011-03-22 16:19:50 -04001406
Dmitry Rozhkovdd1fca92018-07-24 14:27:33 +03001407 pr_info(PREFIX "%s Slot [%s] (battery %s)\n",
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001408 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1409 device->status.battery_present ? "present" : "absent");
1410
Kyle McMartin25be5822011-03-22 16:19:50 -04001411 battery->pm_nb.notifier_call = battery_notify;
1412 register_pm_notifier(&battery->pm_nb);
1413
Zhang Ruie0d1f092014-05-28 15:23:38 +08001414 device_init_wakeup(&device->dev, 1);
1415
Patrick Mocheld550d982006-06-27 00:41:40 -04001416 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001417
1418fail:
1419 sysfs_remove_battery(battery);
1420 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001421 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001422 kfree(battery);
1423 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424}
1425
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001426static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
Len Brown4be44fc2005-08-05 00:44:28 -04001428 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001431 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001432 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001433 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001434 unregister_pm_notifier(&battery->pm_nb);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001435#ifdef CONFIG_ACPI_PROCFS_POWER
1436 acpi_battery_remove_fs(device);
1437#endif
Andrey Borzenkov508df922007-10-28 12:50:09 +03001438 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001439 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001440 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001442 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443}
1444
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001445#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001446/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001447static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001448{
1449 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001450
1451 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001452 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001453
1454 battery = acpi_driver_data(to_acpi_device(dev));
1455 if (!battery)
1456 return -EINVAL;
1457
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001458 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001459 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001460 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001461}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001462#else
1463#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001464#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001465
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001466static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1467
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001468static struct acpi_driver acpi_battery_driver = {
1469 .name = "battery",
1470 .class = ACPI_BATTERY_CLASS,
1471 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001472 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001473 .ops = {
1474 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001475 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001476 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001477 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001478 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001479};
1480
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001481static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482{
Hans de Goededccfae62017-04-19 14:02:10 +02001483 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001484 int result;
1485
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001486 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001487
Carlo Caioneec625a32018-04-18 14:04:39 +02001488 if (battery_check_pmic) {
1489 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1490 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1491 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1492 ": found native %s PMIC, not loading\n",
1493 acpi_battery_blacklist[i]);
1494 return;
1495 }
1496 }
1497
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001498#ifdef CONFIG_ACPI_PROCFS_POWER
1499 acpi_battery_dir = acpi_lock_battery_dir();
1500 if (!acpi_battery_dir)
1501 return;
1502#endif
Luis Henriques479faaf2015-05-11 22:48:46 +01001503 result = acpi_bus_register_driver(&acpi_battery_driver);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001504#ifdef CONFIG_ACPI_PROCFS_POWER
Luis Henriques479faaf2015-05-11 22:48:46 +01001505 if (result < 0)
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001506 acpi_unlock_battery_dir(acpi_battery_dir);
1507#endif
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001508 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001509}
1510
1511static int __init acpi_battery_init(void)
1512{
Luis Henriquese234b072015-05-11 22:48:38 +01001513 if (acpi_disabled)
1514 return -ENODEV;
1515
Luis Henriqueseca21d912015-05-11 22:49:05 +01001516 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001517 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518}
1519
Len Brown4be44fc2005-08-05 00:44:28 -04001520static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001522 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001523 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001524 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001525 battery_hook_exit();
1526 }
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001527#ifdef CONFIG_ACPI_PROCFS_POWER
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001528 if (acpi_battery_dir)
1529 acpi_unlock_battery_dir(acpi_battery_dir);
Lan Tianyu3a670cc2014-05-04 11:07:25 +08001530#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531}
1532
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533module_init(acpi_battery_init);
1534module_exit(acpi_battery_exit);