blob: 08ee1c7b12e00004b05f01c5cd9a7fbf64cfb1f1 [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
Lv Zheng8b484632013-12-03 08:49:16 +080027#include <linux/acpi.h>
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040028#include <linux/power_supply.h>
29
Ognjen Galicfa938542018-02-07 15:58:13 +010030#include <acpi/battery.h>
Alexander Mezinf03be352014-03-12 00:58:46 +070031
Len Browna192a952009-07-28 16:45:54 -040032#define PREFIX "ACPI: "
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
Hans de Goedecc99f0a2019-12-10 10:57:50 +010035#define ACPI_BATTERY_CAPACITY_VALID(capacity) \
36 ((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#define ACPI_BATTERY_DEVICE_NAME "Battery"
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Lan Tianyuae6f6182011-06-30 11:32:40 +080040/* Battery power unit: 0 means mW, 1 means mA */
41#define ACPI_BATTERY_POWER_UNIT_MA 1
42
Zhang Rui1ac5aaa2014-05-28 15:23:36 +080043#define ACPI_BATTERY_STATE_DISCHARGING 0x1
44#define ACPI_BATTERY_STATE_CHARGING 0x2
45#define ACPI_BATTERY_STATE_CRITICAL 0x4
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define _COMPONENT ACPI_BATTERY_COMPONENT
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030048
Len Brownf52fd662007-02-12 22:42:12 -050049ACPI_MODULE_NAME("battery");
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Len Brownf52fd662007-02-12 22:42:12 -050051MODULE_AUTHOR("Paul Diefenbaugh");
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +040052MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>");
Len Brown7cda93e2007-02-12 23:50:02 -050053MODULE_DESCRIPTION("ACPI Battery Driver");
Linus Torvalds1da177e2005-04-16 15:20:36 -070054MODULE_LICENSE("GPL");
55
Luis Henriqueseca21d912015-05-11 22:49:05 +010056static async_cookie_t async_cookie;
Hans de Goedebc39fbc2017-04-19 14:02:09 +020057static bool battery_driver_registered;
Lan Tianyua90b4032014-01-06 22:50:37 +080058static int battery_bix_broken_package;
Alexander Mezinf43691c2014-06-04 02:01:23 +070059static int battery_notification_delay_ms;
Hans de Goede1b799c52018-04-12 12:02:00 +020060static int battery_ac_is_broken;
Carlo Caioneec625a32018-04-18 14:04:39 +020061static int battery_check_pmic = 1;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +040062static unsigned int cache_time = 1000;
63module_param(cache_time, uint, 0644);
64MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +030065
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040066static const struct acpi_device_id battery_device_ids[] = {
67 {"PNP0C0A", 0},
68 {"", 0},
69};
70
71MODULE_DEVICE_TABLE(acpi, battery_device_ids);
72
Hans de Goededccfae62017-04-19 14:02:10 +020073/* Lists of PMIC ACPI HIDs with an (often better) native battery driver */
74static const char * const acpi_battery_blacklist[] = {
75 "INT33F4", /* X-Powers AXP288 PMIC */
76};
77
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +040078enum {
79 ACPI_BATTERY_ALARM_PRESENT,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +040080 ACPI_BATTERY_XINFO_PRESENT,
Zhang Rui557d5862010-10-22 10:02:06 +080081 ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
Kamil Iskra4000e6262012-11-16 22:28:58 +010082 /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
83 switches between mWh and mAh depending on whether the system
84 is running on battery or not. When mAh is the unit, most
85 reported values are incorrect and need to be adjusted by
86 10000/design_voltage. Verified on x201, t410, t410s, and x220.
87 Pre-2010 and 2012 models appear to always report in mWh and
88 are thus unaffected (tested with t42, t61, t500, x200, x300,
89 and x230). Also, in mid-2012 Lenovo issued a BIOS update for
90 the 2011 models that fixes the issue (tested on x220 with a
91 post-1.29 BIOS), but as of Nov. 2012, no such update is
92 available for the 2010 models. */
93 ACPI_BATTERY_QUIRK_THINKPAD_MAH,
Laszlo Totha20136a2018-02-24 10:20:15 +010094 /* for batteries reporting current capacity with design capacity
95 * on a full charge, but showing degradation in full charge cap.
96 */
97 ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE,
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +040098};
Alexey Starikovskiyd7380962007-09-26 19:43:04 +040099
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400100struct acpi_battery {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400101 struct mutex lock;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300102 struct mutex sysfs_lock;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100103 struct power_supply *bat;
104 struct power_supply_desc bat_desc;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400105 struct acpi_device *device;
Kyle McMartin25be5822011-03-22 16:19:50 -0400106 struct notifier_block pm_nb;
Ognjen Galicfa938542018-02-07 15:58:13 +0100107 struct list_head list;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400108 unsigned long update_time;
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200109 int revision;
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400110 int rate_now;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400111 int capacity_now;
112 int voltage_now;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400113 int design_capacity;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400114 int full_charge_capacity;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400115 int technology;
116 int design_voltage;
117 int design_capacity_warning;
118 int design_capacity_low;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400119 int cycle_count;
120 int measurement_accuracy;
121 int max_sampling_time;
122 int min_sampling_time;
123 int max_averaging_interval;
124 int min_averaging_interval;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400125 int capacity_granularity_1;
126 int capacity_granularity_2;
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400127 int alarm;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400128 char model_number[32];
129 char serial_number[32];
130 char type[32];
131 char oem_info[32];
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400132 int state;
133 int power_unit;
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400134 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135};
136
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100137#define to_acpi_battery(x) power_supply_get_drvdata(x)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400138
Andy Shevchenkoefd941f2013-03-11 09:17:06 +0000139static inline int acpi_battery_present(struct acpi_battery *battery)
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400140{
141 return battery->device->status.battery_present;
142}
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400143
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400144static int acpi_battery_technology(struct acpi_battery *battery)
145{
146 if (!strcasecmp("NiCd", battery->type))
147 return POWER_SUPPLY_TECHNOLOGY_NiCd;
148 if (!strcasecmp("NiMH", battery->type))
149 return POWER_SUPPLY_TECHNOLOGY_NiMH;
150 if (!strcasecmp("LION", battery->type))
151 return POWER_SUPPLY_TECHNOLOGY_LION;
Andrey Borzenkovad40e682007-11-10 20:02:49 +0300152 if (!strncasecmp("LI-ION", battery->type, 6))
Alexey Starikovskiy0bde7ee2007-10-28 15:33:10 +0300153 return POWER_SUPPLY_TECHNOLOGY_LION;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400154 if (!strcasecmp("LiP", battery->type))
155 return POWER_SUPPLY_TECHNOLOGY_LIPO;
156 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
157}
158
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300159static int acpi_battery_get_state(struct acpi_battery *battery);
Alexey Starikovskiyb19073a2007-10-25 17:10:47 -0400160
Richard Hughes56f382a2009-01-25 15:05:50 +0000161static int acpi_battery_is_charged(struct acpi_battery *battery)
162{
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800163 /* charging, discharging or critical low */
Richard Hughes56f382a2009-01-25 15:05:50 +0000164 if (battery->state != 0)
165 return 0;
166
167 /* battery not reporting charge */
168 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
169 battery->capacity_now == 0)
170 return 0;
171
172 /* good batteries update full_charge as the batteries degrade */
173 if (battery->full_charge_capacity == battery->capacity_now)
174 return 1;
175
176 /* fallback to using design values for broken batteries */
177 if (battery->design_capacity == battery->capacity_now)
178 return 1;
179
180 /* we don't do any sort of metric based on percentages */
181 return 0;
182}
183
Laszlo Totha20136a2018-02-24 10:20:15 +0100184static bool acpi_battery_is_degraded(struct acpi_battery *battery)
185{
Hans de Goedecc99f0a2019-12-10 10:57:50 +0100186 return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
187 ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) &&
Laszlo Totha20136a2018-02-24 10:20:15 +0100188 battery->full_charge_capacity < battery->design_capacity;
189}
190
Hans de Goede19fffc82018-04-12 12:01:59 +0200191static int acpi_battery_handle_discharging(struct acpi_battery *battery)
192{
193 /*
194 * Some devices wrongly report discharging if the battery's charge level
195 * was above the device's start charging threshold atm the AC adapter
196 * was plugged in and the device thus did not start a new charge cycle.
197 */
Hans de Goede1b799c52018-04-12 12:02:00 +0200198 if ((battery_ac_is_broken || power_supply_is_system_supplied()) &&
199 battery->rate_now == 0)
Hans de Goede19fffc82018-04-12 12:01:59 +0200200 return POWER_SUPPLY_STATUS_NOT_CHARGING;
201
202 return POWER_SUPPLY_STATUS_DISCHARGING;
203}
204
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400205static int acpi_battery_get_property(struct power_supply *psy,
206 enum power_supply_property psp,
207 union power_supply_propval *val)
208{
Hans de Goede5b74d1d2019-12-10 10:57:51 +0100209 int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400210 struct acpi_battery *battery = to_acpi_battery(psy);
211
Alexey Starikovskiy91044762007-11-13 12:23:06 +0300212 if (acpi_battery_present(battery)) {
213 /* run battery update only if it is present */
214 acpi_battery_get_state(battery);
215 } else if (psp != POWER_SUPPLY_PROP_PRESENT)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400216 return -ENODEV;
217 switch (psp) {
218 case POWER_SUPPLY_PROP_STATUS:
Daniel Drake82bf43b2018-03-14 16:42:17 +0800219 if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
Hans de Goede19fffc82018-04-12 12:01:59 +0200220 val->intval = acpi_battery_handle_discharging(battery);
Daniel Drake82bf43b2018-03-14 16:42:17 +0800221 else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400222 val->intval = POWER_SUPPLY_STATUS_CHARGING;
Richard Hughes56f382a2009-01-25 15:05:50 +0000223 else if (acpi_battery_is_charged(battery))
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400224 val->intval = POWER_SUPPLY_STATUS_FULL;
Roland Dreier4c41d3a2007-11-07 15:09:09 -0800225 else
226 val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400227 break;
228 case POWER_SUPPLY_PROP_PRESENT:
229 val->intval = acpi_battery_present(battery);
230 break;
231 case POWER_SUPPLY_PROP_TECHNOLOGY:
232 val->intval = acpi_battery_technology(battery);
233 break;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400234 case POWER_SUPPLY_PROP_CYCLE_COUNT:
235 val->intval = battery->cycle_count;
236 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400237 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200238 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
239 ret = -ENODEV;
240 else
241 val->intval = battery->design_voltage * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400242 break;
243 case POWER_SUPPLY_PROP_VOLTAGE_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200244 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
245 ret = -ENODEV;
246 else
247 val->intval = battery->voltage_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400248 break;
249 case POWER_SUPPLY_PROP_CURRENT_NOW:
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400250 case POWER_SUPPLY_PROP_POWER_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200251 if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
252 ret = -ENODEV;
253 else
254 val->intval = battery->rate_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400255 break;
256 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
257 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
Hans de Goedecc99f0a2019-12-10 10:57:50 +0100258 if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200259 ret = -ENODEV;
260 else
261 val->intval = battery->design_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400262 break;
263 case POWER_SUPPLY_PROP_CHARGE_FULL:
264 case POWER_SUPPLY_PROP_ENERGY_FULL:
Hans de Goedecc99f0a2019-12-10 10:57:50 +0100265 if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200266 ret = -ENODEV;
267 else
268 val->intval = battery->full_charge_capacity * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400269 break;
270 case POWER_SUPPLY_PROP_CHARGE_NOW:
271 case POWER_SUPPLY_PROP_ENERGY_NOW:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200272 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
273 ret = -ENODEV;
274 else
275 val->intval = battery->capacity_now * 1000;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400276 break;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700277 case POWER_SUPPLY_PROP_CAPACITY:
Hans de Goede5b74d1d2019-12-10 10:57:51 +0100278 if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
279 full_capacity = battery->full_charge_capacity;
280 else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
281 full_capacity = battery->design_capacity;
282
Hans de Goedecc99f0a2019-12-10 10:57:50 +0100283 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
Hans de Goede5b74d1d2019-12-10 10:57:51 +0100284 full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
Hans de Goedecc99f0a2019-12-10 10:57:50 +0100285 ret = -ENODEV;
286 else
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700287 val->intval = battery->capacity_now * 100/
Hans de Goede5b74d1d2019-12-10 10:57:51 +0100288 full_capacity;
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700289 break;
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800290 case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
291 if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
292 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
293 else if (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
294 (battery->capacity_now <= battery->alarm))
295 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
296 else if (acpi_battery_is_charged(battery))
297 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
298 else
299 val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
300 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400301 case POWER_SUPPLY_PROP_MODEL_NAME:
302 val->strval = battery->model_number;
303 break;
304 case POWER_SUPPLY_PROP_MANUFACTURER:
305 val->strval = battery->oem_info;
306 break;
maximilian attems7c2670b2008-01-22 18:46:50 +0100307 case POWER_SUPPLY_PROP_SERIAL_NUMBER:
308 val->strval = battery->serial_number;
309 break;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400310 default:
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200311 ret = -EINVAL;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400312 }
Rafael J. Wysockia1b4bd62010-10-23 19:35:15 +0200313 return ret;
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400314}
315
316static enum power_supply_property charge_battery_props[] = {
317 POWER_SUPPLY_PROP_STATUS,
318 POWER_SUPPLY_PROP_PRESENT,
319 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400320 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400321 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
322 POWER_SUPPLY_PROP_VOLTAGE_NOW,
323 POWER_SUPPLY_PROP_CURRENT_NOW,
324 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
325 POWER_SUPPLY_PROP_CHARGE_FULL,
326 POWER_SUPPLY_PROP_CHARGE_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700327 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800328 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400329 POWER_SUPPLY_PROP_MODEL_NAME,
330 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100331 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400332};
333
Hans de Goedeff3154d2019-12-10 10:57:52 +0100334static enum power_supply_property charge_battery_full_cap_broken_props[] = {
335 POWER_SUPPLY_PROP_STATUS,
336 POWER_SUPPLY_PROP_PRESENT,
337 POWER_SUPPLY_PROP_TECHNOLOGY,
338 POWER_SUPPLY_PROP_CYCLE_COUNT,
339 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
340 POWER_SUPPLY_PROP_VOLTAGE_NOW,
341 POWER_SUPPLY_PROP_CURRENT_NOW,
342 POWER_SUPPLY_PROP_CHARGE_NOW,
343 POWER_SUPPLY_PROP_MODEL_NAME,
344 POWER_SUPPLY_PROP_MANUFACTURER,
345 POWER_SUPPLY_PROP_SERIAL_NUMBER,
346};
347
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400348static enum power_supply_property energy_battery_props[] = {
349 POWER_SUPPLY_PROP_STATUS,
350 POWER_SUPPLY_PROP_PRESENT,
351 POWER_SUPPLY_PROP_TECHNOLOGY,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400352 POWER_SUPPLY_PROP_CYCLE_COUNT,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400353 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
354 POWER_SUPPLY_PROP_VOLTAGE_NOW,
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400355 POWER_SUPPLY_PROP_POWER_NOW,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400356 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
357 POWER_SUPPLY_PROP_ENERGY_FULL,
358 POWER_SUPPLY_PROP_ENERGY_NOW,
srinivas pandruvadaa58e1152012-04-05 17:38:54 -0700359 POWER_SUPPLY_PROP_CAPACITY,
Zhang Rui1ac5aaa2014-05-28 15:23:36 +0800360 POWER_SUPPLY_PROP_CAPACITY_LEVEL,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400361 POWER_SUPPLY_PROP_MODEL_NAME,
362 POWER_SUPPLY_PROP_MANUFACTURER,
maximilian attems7c2670b2008-01-22 18:46:50 +0100363 POWER_SUPPLY_PROP_SERIAL_NUMBER,
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400364};
365
Hans de Goedeb41901a2018-08-07 09:36:30 +0200366static enum power_supply_property energy_battery_full_cap_broken_props[] = {
367 POWER_SUPPLY_PROP_STATUS,
368 POWER_SUPPLY_PROP_PRESENT,
369 POWER_SUPPLY_PROP_TECHNOLOGY,
370 POWER_SUPPLY_PROP_CYCLE_COUNT,
371 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
372 POWER_SUPPLY_PROP_VOLTAGE_NOW,
373 POWER_SUPPLY_PROP_POWER_NOW,
374 POWER_SUPPLY_PROP_ENERGY_NOW,
375 POWER_SUPPLY_PROP_MODEL_NAME,
376 POWER_SUPPLY_PROP_MANUFACTURER,
377 POWER_SUPPLY_PROP_SERIAL_NUMBER,
378};
379
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380/* --------------------------------------------------------------------------
381 Battery Management
382 -------------------------------------------------------------------------- */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400383struct acpi_offsets {
384 size_t offset; /* offset inside struct acpi_sbs_battery */
385 u8 mode; /* int or string? */
386};
387
Mathias Krausea4658782015-06-13 14:26:53 +0200388static const struct acpi_offsets state_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400389 {offsetof(struct acpi_battery, state), 0},
Alexey Starikovskiy7faa1442009-03-27 22:23:52 -0400390 {offsetof(struct acpi_battery, rate_now), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400391 {offsetof(struct acpi_battery, capacity_now), 0},
392 {offsetof(struct acpi_battery, voltage_now), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400393};
394
Mathias Krausea4658782015-06-13 14:26:53 +0200395static const struct acpi_offsets info_offsets[] = {
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400396 {offsetof(struct acpi_battery, power_unit), 0},
397 {offsetof(struct acpi_battery, design_capacity), 0},
Alexey Starikovskiyd7380962007-09-26 19:43:04 +0400398 {offsetof(struct acpi_battery, full_charge_capacity), 0},
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400399 {offsetof(struct acpi_battery, technology), 0},
400 {offsetof(struct acpi_battery, design_voltage), 0},
401 {offsetof(struct acpi_battery, design_capacity_warning), 0},
402 {offsetof(struct acpi_battery, design_capacity_low), 0},
403 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
404 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
405 {offsetof(struct acpi_battery, model_number), 1},
406 {offsetof(struct acpi_battery, serial_number), 1},
407 {offsetof(struct acpi_battery, type), 1},
408 {offsetof(struct acpi_battery, oem_info), 1},
409};
410
Mathias Krausea4658782015-06-13 14:26:53 +0200411static const struct acpi_offsets extended_info_offsets[] = {
Lan Tianyu016d5ba2013-07-30 14:00:42 +0200412 {offsetof(struct acpi_battery, revision), 0},
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400413 {offsetof(struct acpi_battery, power_unit), 0},
414 {offsetof(struct acpi_battery, design_capacity), 0},
415 {offsetof(struct acpi_battery, full_charge_capacity), 0},
416 {offsetof(struct acpi_battery, technology), 0},
417 {offsetof(struct acpi_battery, design_voltage), 0},
418 {offsetof(struct acpi_battery, design_capacity_warning), 0},
419 {offsetof(struct acpi_battery, design_capacity_low), 0},
420 {offsetof(struct acpi_battery, cycle_count), 0},
421 {offsetof(struct acpi_battery, measurement_accuracy), 0},
422 {offsetof(struct acpi_battery, max_sampling_time), 0},
423 {offsetof(struct acpi_battery, min_sampling_time), 0},
424 {offsetof(struct acpi_battery, max_averaging_interval), 0},
425 {offsetof(struct acpi_battery, min_averaging_interval), 0},
426 {offsetof(struct acpi_battery, capacity_granularity_1), 0},
427 {offsetof(struct acpi_battery, capacity_granularity_2), 0},
428 {offsetof(struct acpi_battery, model_number), 1},
429 {offsetof(struct acpi_battery, serial_number), 1},
430 {offsetof(struct acpi_battery, type), 1},
431 {offsetof(struct acpi_battery, oem_info), 1},
432};
433
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400434static int extract_package(struct acpi_battery *battery,
435 union acpi_object *package,
Mathias Krausea4658782015-06-13 14:26:53 +0200436 const struct acpi_offsets *offsets, int num)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300437{
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300438 int i;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400439 union acpi_object *element;
440 if (package->type != ACPI_TYPE_PACKAGE)
441 return -EFAULT;
442 for (i = 0; i < num; ++i) {
443 if (package->package.count <= i)
444 return -EFAULT;
445 element = &package->package.elements[i];
446 if (offsets[i].mode) {
Alexey Starikovskiy106449e2007-10-29 23:29:40 +0300447 u8 *ptr = (u8 *)battery + offsets[i].offset;
448 if (element->type == ACPI_TYPE_STRING ||
449 element->type == ACPI_TYPE_BUFFER)
450 strncpy(ptr, element->string.pointer, 32);
451 else if (element->type == ACPI_TYPE_INTEGER) {
452 strncpy(ptr, (u8 *)&element->integer.value,
Lin Ming439913f2010-01-28 10:53:19 +0800453 sizeof(u64));
454 ptr[sizeof(u64)] = 0;
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400455 } else
456 *ptr = 0; /* don't have value */
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400457 } else {
Alexey Starikovskiyb8a1bdb2008-03-17 22:37:42 -0400458 int *x = (int *)((u8 *)battery + offsets[i].offset);
459 *x = (element->type == ACPI_TYPE_INTEGER) ?
460 element->integer.value : -1;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300461 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300462 }
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300463 return 0;
464}
465
466static int acpi_battery_get_status(struct acpi_battery *battery)
467{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400468 if (acpi_bus_get_status(battery->device)) {
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300469 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
470 return -ENODEV;
471 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400472 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300473}
474
Dave Lambley2d09af42016-11-04 01:05:40 +0000475
476static int extract_battery_info(const int use_bix,
477 struct acpi_battery *battery,
478 const struct acpi_buffer *buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400480 int result = -EFAULT;
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400481
Dave Lambley2d09af42016-11-04 01:05:40 +0000482 if (use_bix && battery_bix_broken_package)
483 result = extract_package(battery, buffer->pointer,
Lan Tianyua90b4032014-01-06 22:50:37 +0800484 extended_info_offsets + 1,
485 ARRAY_SIZE(extended_info_offsets) - 1);
Dave Lambley2d09af42016-11-04 01:05:40 +0000486 else if (use_bix)
487 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400488 extended_info_offsets,
489 ARRAY_SIZE(extended_info_offsets));
490 else
Dave Lambley2d09af42016-11-04 01:05:40 +0000491 result = extract_package(battery, buffer->pointer,
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400492 info_offsets, ARRAY_SIZE(info_offsets));
Zhang Rui557d5862010-10-22 10:02:06 +0800493 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
494 battery->full_charge_capacity = battery->design_capacity;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100495 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
496 battery->power_unit && battery->design_voltage) {
497 battery->design_capacity = battery->design_capacity *
498 10000 / battery->design_voltage;
499 battery->full_charge_capacity = battery->full_charge_capacity *
500 10000 / battery->design_voltage;
501 battery->design_capacity_warning =
502 battery->design_capacity_warning *
503 10000 / battery->design_voltage;
504 /* Curiously, design_capacity_low, unlike the rest of them,
505 is correct. */
506 /* capacity_granularity_* equal 1 on the systems tested, so
507 it's impossible to tell if they would need an adjustment
508 or not if their values were higher. */
509 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100510 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
511 battery->capacity_now > battery->full_charge_capacity)
512 battery->capacity_now = battery->full_charge_capacity;
513
Patrick Mocheld550d982006-06-27 00:41:40 -0400514 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515}
516
Dave Lambley2d09af42016-11-04 01:05:40 +0000517static int acpi_battery_get_info(struct acpi_battery *battery)
518{
519 const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
520 int use_bix;
521 int result = -ENODEV;
522
523 if (!acpi_battery_present(battery))
524 return 0;
525
526
527 for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
528 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
529 acpi_status status = AE_ERROR;
530
531 mutex_lock(&battery->lock);
532 status = acpi_evaluate_object(battery->device->handle,
533 use_bix ? "_BIX":"_BIF",
534 NULL, &buffer);
535 mutex_unlock(&battery->lock);
536
537 if (ACPI_FAILURE(status)) {
538 ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
539 use_bix ? "_BIX":"_BIF"));
540 } else {
541 result = extract_battery_info(use_bix,
542 battery,
543 &buffer);
544
545 kfree(buffer.pointer);
546 break;
547 }
548 }
549
550 if (!result && !use_bix && xinfo)
551 pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
552
553 return result;
554}
555
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300556static int acpi_battery_get_state(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557{
Len Brown4be44fc2005-08-05 00:44:28 -0400558 int result = 0;
559 acpi_status status = 0;
560 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300562 if (!acpi_battery_present(battery))
563 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400565 if (battery->update_time &&
566 time_before(jiffies, battery->update_time +
567 msecs_to_jiffies(cache_time)))
568 return 0;
569
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400570 mutex_lock(&battery->lock);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400571 status = acpi_evaluate_object(battery->device->handle, "_BST",
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400572 NULL, &buffer);
573 mutex_unlock(&battery->lock);
Len Brown5b31d892007-08-15 00:19:26 -0400574
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 if (ACPI_FAILURE(status)) {
Thomas Renningera6fc6722006-06-26 23:58:43 -0400576 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
Patrick Mocheld550d982006-06-27 00:41:40 -0400577 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 }
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400579
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400580 result = extract_package(battery, buffer.pointer,
581 state_offsets, ARRAY_SIZE(state_offsets));
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400582 battery->update_time = jiffies;
Alexey Starikovskiy78490d82007-05-11 13:18:55 -0400583 kfree(buffer.pointer);
Hector Martinbc76f902009-08-06 15:57:48 -0700584
Lan Tianyu55003b22011-06-30 11:33:12 +0800585 /* For buggy DSDTs that report negative 16-bit values for either
586 * charging or discharging current and/or report 0 as 65536
587 * due to bad math.
588 */
589 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA &&
590 battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN &&
591 (s16)(battery->rate_now) < 0) {
Hector Martinbc76f902009-08-06 15:57:48 -0700592 battery->rate_now = abs((s16)battery->rate_now);
Dmitry Rozhkovdd1fca92018-07-24 14:27:33 +0300593 pr_warn_once(FW_BUG "battery: (dis)charge rate invalid.\n");
Lan Tianyu55003b22011-06-30 11:33:12 +0800594 }
Hector Martinbc76f902009-08-06 15:57:48 -0700595
Zhang Rui557d5862010-10-22 10:02:06 +0800596 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
597 && battery->capacity_now >= 0 && battery->capacity_now <= 100)
598 battery->capacity_now = (battery->capacity_now *
599 battery->full_charge_capacity) / 100;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100600 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
601 battery->power_unit && battery->design_voltage) {
602 battery->capacity_now = battery->capacity_now *
603 10000 / battery->design_voltage;
604 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100605 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags) &&
606 battery->capacity_now > battery->full_charge_capacity)
607 battery->capacity_now = battery->full_charge_capacity;
608
Patrick Mocheld550d982006-06-27 00:41:40 -0400609 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610}
611
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400612static int acpi_battery_set_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613{
Len Brown4be44fc2005-08-05 00:44:28 -0400614 acpi_status status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +0400616 if (!acpi_battery_present(battery) ||
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400617 !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags))
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300618 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400620 mutex_lock(&battery->lock);
Jiang Liu0db98202013-06-29 00:24:39 +0800621 status = acpi_execute_simple_method(battery->device->handle, "_BTP",
622 battery->alarm);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +0400623 mutex_unlock(&battery->lock);
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400624
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 if (ACPI_FAILURE(status))
Patrick Mocheld550d982006-06-27 00:41:40 -0400626 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400628 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm));
Patrick Mocheld550d982006-06-27 00:41:40 -0400629 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630}
631
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300632static int acpi_battery_init_alarm(struct acpi_battery *battery)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300634 /* See if alarms are supported, and if so, set default */
Jiang Liu952c63e2013-06-29 00:24:38 +0800635 if (!acpi_has_method(battery->device->handle, "_BTP")) {
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400636 clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400637 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 }
Alexey Starikovskiy7b3bcc42009-10-15 14:31:24 +0400639 set_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +0400640 if (!battery->alarm)
641 battery->alarm = battery->design_capacity_warning;
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +0400642 return acpi_battery_set_alarm(battery);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643}
644
Andrey Borzenkov508df922007-10-28 12:50:09 +0300645static ssize_t acpi_battery_alarm_show(struct device *dev,
646 struct device_attribute *attr,
647 char *buf)
648{
649 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
650 return sprintf(buf, "%d\n", battery->alarm * 1000);
651}
652
653static ssize_t acpi_battery_alarm_store(struct device *dev,
654 struct device_attribute *attr,
655 const char *buf, size_t count)
656{
657 unsigned long x;
658 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
Luis G.F47a08c82014-01-21 15:40:43 +0100659 if (sscanf(buf, "%lu\n", &x) == 1)
Andrey Borzenkov508df922007-10-28 12:50:09 +0300660 battery->alarm = x/1000;
661 if (acpi_battery_present(battery))
662 acpi_battery_set_alarm(battery);
663 return count;
664}
665
Bhumika Goyal82d2b612017-08-21 17:13:07 +0530666static const struct device_attribute alarm_attr = {
Parag Warudkar01e8ef12008-10-18 20:28:50 -0700667 .attr = {.name = "alarm", .mode = 0644},
Andrey Borzenkov508df922007-10-28 12:50:09 +0300668 .show = acpi_battery_alarm_show,
669 .store = acpi_battery_alarm_store,
670};
671
Ognjen Galicfa938542018-02-07 15:58:13 +0100672/*
673 * The Battery Hooking API
674 *
675 * This API is used inside other drivers that need to expose
676 * platform-specific behaviour within the generic driver in a
677 * generic way.
678 *
679 */
680
681static LIST_HEAD(acpi_battery_list);
682static LIST_HEAD(battery_hook_list);
683static DEFINE_MUTEX(hook_mutex);
684
Colin Ian King514bcc52018-02-23 16:32:55 +0000685static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
Ognjen Galicfa938542018-02-07 15:58:13 +0100686{
687 struct acpi_battery *battery;
688 /*
689 * In order to remove a hook, we first need to
690 * de-register all the batteries that are registered.
691 */
692 if (lock)
693 mutex_lock(&hook_mutex);
694 list_for_each_entry(battery, &acpi_battery_list, list) {
695 hook->remove_battery(battery->bat);
696 }
697 list_del(&hook->list);
698 if (lock)
699 mutex_unlock(&hook_mutex);
700 pr_info("extension unregistered: %s\n", hook->name);
701}
702
703void battery_hook_unregister(struct acpi_battery_hook *hook)
704{
705 __battery_hook_unregister(hook, 1);
706}
707EXPORT_SYMBOL_GPL(battery_hook_unregister);
708
709void battery_hook_register(struct acpi_battery_hook *hook)
710{
711 struct acpi_battery *battery;
712
713 mutex_lock(&hook_mutex);
714 INIT_LIST_HEAD(&hook->list);
715 list_add(&hook->list, &battery_hook_list);
716 /*
717 * Now that the driver is registered, we need
718 * to notify the hook that a battery is available
719 * for each battery, so that the driver may add
720 * its attributes.
721 */
722 list_for_each_entry(battery, &acpi_battery_list, list) {
723 if (hook->add_battery(battery->bat)) {
724 /*
725 * If a add-battery returns non-zero,
726 * the registration of the extension has failed,
727 * and we will not add it to the list of loaded
728 * hooks.
729 */
730 pr_err("extension failed to load: %s", hook->name);
731 __battery_hook_unregister(hook, 0);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200732 goto end;
Ognjen Galicfa938542018-02-07 15:58:13 +0100733 }
734 }
735 pr_info("new extension: %s\n", hook->name);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200736end:
Ognjen Galicfa938542018-02-07 15:58:13 +0100737 mutex_unlock(&hook_mutex);
738}
739EXPORT_SYMBOL_GPL(battery_hook_register);
740
741/*
742 * This function gets called right after the battery sysfs
743 * attributes have been added, so that the drivers that
744 * define custom sysfs attributes can add their own.
Rafael J. Wysocki7a4ea102018-03-13 10:07:49 +0100745*/
Ognjen Galicfa938542018-02-07 15:58:13 +0100746static void battery_hook_add_battery(struct acpi_battery *battery)
747{
Jouke Witteveen673b4272018-07-04 12:27:15 +0200748 struct acpi_battery_hook *hook_node, *tmp;
Ognjen Galicfa938542018-02-07 15:58:13 +0100749
750 mutex_lock(&hook_mutex);
751 INIT_LIST_HEAD(&battery->list);
752 list_add(&battery->list, &acpi_battery_list);
753 /*
754 * Since we added a new battery to the list, we need to
755 * iterate over the hooks and call add_battery for each
756 * hook that was registered. This usually happens
757 * when a battery gets hotplugged or initialized
758 * during the battery module initialization.
759 */
Jouke Witteveen673b4272018-07-04 12:27:15 +0200760 list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) {
Ognjen Galicfa938542018-02-07 15:58:13 +0100761 if (hook_node->add_battery(battery->bat)) {
762 /*
763 * The notification of the extensions has failed, to
764 * prevent further errors we will unload the extension.
765 */
Ognjen Galicfa938542018-02-07 15:58:13 +0100766 pr_err("error in extension, unloading: %s",
767 hook_node->name);
Jouke Witteveen673b4272018-07-04 12:27:15 +0200768 __battery_hook_unregister(hook_node, 0);
Ognjen Galicfa938542018-02-07 15:58:13 +0100769 }
770 }
771 mutex_unlock(&hook_mutex);
772}
773
774static void battery_hook_remove_battery(struct acpi_battery *battery)
775{
776 struct acpi_battery_hook *hook;
777
778 mutex_lock(&hook_mutex);
779 /*
780 * Before removing the hook, we need to remove all
781 * custom attributes from the battery.
782 */
783 list_for_each_entry(hook, &battery_hook_list, list) {
784 hook->remove_battery(battery->bat);
785 }
786 /* Then, just remove the battery from the list */
787 list_del(&battery->list);
788 mutex_unlock(&hook_mutex);
789}
790
791static void __exit battery_hook_exit(void)
792{
793 struct acpi_battery_hook *hook;
794 struct acpi_battery_hook *ptr;
795 /*
796 * At this point, the acpi_bus_unregister_driver()
797 * has called remove for all batteries. We just
798 * need to remove the hooks.
799 */
800 list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
801 __battery_hook_unregister(hook, 1);
802 }
803 mutex_destroy(&hook_mutex);
804}
805
Andrey Borzenkov508df922007-10-28 12:50:09 +0300806static int sysfs_add_battery(struct acpi_battery *battery)
807{
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100808 struct power_supply_config psy_cfg = { .drv_data = battery, };
Hans de Goedeff3154d2019-12-10 10:57:52 +0100809 bool full_cap_broken = false;
810
811 if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
812 !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
813 full_cap_broken = true;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300814
Lan Tianyuae6f6182011-06-30 11:32:40 +0800815 if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
Hans de Goedeff3154d2019-12-10 10:57:52 +0100816 if (full_cap_broken) {
817 battery->bat_desc.properties =
818 charge_battery_full_cap_broken_props;
819 battery->bat_desc.num_properties =
820 ARRAY_SIZE(charge_battery_full_cap_broken_props);
821 } else {
822 battery->bat_desc.properties = charge_battery_props;
823 battery->bat_desc.num_properties =
824 ARRAY_SIZE(charge_battery_props);
825 }
Andrey Borzenkov508df922007-10-28 12:50:09 +0300826 } else {
Hans de Goedeff3154d2019-12-10 10:57:52 +0100827 if (full_cap_broken) {
828 battery->bat_desc.properties =
829 energy_battery_full_cap_broken_props;
830 battery->bat_desc.num_properties =
831 ARRAY_SIZE(energy_battery_full_cap_broken_props);
832 } else {
833 battery->bat_desc.properties = energy_battery_props;
834 battery->bat_desc.num_properties =
835 ARRAY_SIZE(energy_battery_props);
836 }
Andrey Borzenkov508df922007-10-28 12:50:09 +0300837 }
838
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100839 battery->bat_desc.name = acpi_device_bid(battery->device);
840 battery->bat_desc.type = POWER_SUPPLY_TYPE_BATTERY;
841 battery->bat_desc.get_property = acpi_battery_get_property;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300842
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100843 battery->bat = power_supply_register_no_ws(&battery->device->dev,
844 &battery->bat_desc, &psy_cfg);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800845
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100846 if (IS_ERR(battery->bat)) {
847 int result = PTR_ERR(battery->bat);
848
849 battery->bat = NULL;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300850 return result;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100851 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100852 battery_hook_add_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100853 return device_create_file(&battery->bat->dev, &alarm_attr);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300854}
855
856static void sysfs_remove_battery(struct acpi_battery *battery)
857{
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300858 mutex_lock(&battery->sysfs_lock);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100859 if (!battery->bat) {
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300860 mutex_unlock(&battery->sysfs_lock);
Andrey Borzenkov508df922007-10-28 12:50:09 +0300861 return;
Lan Tianyu9c921c222011-06-30 11:34:12 +0800862 }
Ognjen Galicfa938542018-02-07 15:58:13 +0100863 battery_hook_remove_battery(battery);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100864 device_remove_file(&battery->bat->dev, &alarm_attr);
865 power_supply_unregister(battery->bat);
866 battery->bat = NULL;
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +0300867 mutex_unlock(&battery->sysfs_lock);
Hector Martinbc76f902009-08-06 15:57:48 -0700868}
869
Kamil Iskra4000e6262012-11-16 22:28:58 +0100870static void find_battery(const struct dmi_header *dm, void *private)
871{
872 struct acpi_battery *battery = (struct acpi_battery *)private;
873 /* Note: the hardcoded offsets below have been extracted from
874 the source code of dmidecode. */
875 if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
876 const u8 *dmi_data = (const u8 *)(dm + 1);
877 int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
878 if (dm->length >= 18)
879 dmi_capacity *= dmi_data[17];
880 if (battery->design_capacity * battery->design_voltage / 1000
881 != dmi_capacity &&
882 battery->design_capacity * 10 == dmi_capacity)
883 set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
884 &battery->flags);
885 }
886}
887
Zhang Rui557d5862010-10-22 10:02:06 +0800888/*
889 * According to the ACPI spec, some kinds of primary batteries can
890 * report percentage battery remaining capacity directly to OS.
891 * In this case, it reports the Last Full Charged Capacity == 100
892 * and BatteryPresentRate == 0xFFFFFFFF.
893 *
894 * Now we found some battery reports percentage remaining capacity
895 * even if it's rechargeable.
896 * https://bugzilla.kernel.org/show_bug.cgi?id=15979
897 *
898 * Handle this correctly so that they won't break userspace.
899 */
Lan Tianyu7b786222011-06-30 11:33:27 +0800900static void acpi_battery_quirks(struct acpi_battery *battery)
Zhang Rui557d5862010-10-22 10:02:06 +0800901{
902 if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000903 return;
Zhang Rui557d5862010-10-22 10:02:06 +0800904
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000905 if (battery->full_charge_capacity == 100 &&
906 battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
907 battery->capacity_now >= 0 && battery->capacity_now <= 100) {
Zhang Rui557d5862010-10-22 10:02:06 +0800908 set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
909 battery->full_charge_capacity = battery->design_capacity;
910 battery->capacity_now = (battery->capacity_now *
911 battery->full_charge_capacity) / 100;
912 }
Kamil Iskra4000e6262012-11-16 22:28:58 +0100913
914 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
Nicholas Mazzuca0f4c6542013-05-08 23:11:15 +0000915 return;
Kamil Iskra4000e6262012-11-16 22:28:58 +0100916
917 if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
918 const char *s;
919 s = dmi_get_system_info(DMI_PRODUCT_VERSION);
Rasmus Villemoesffd8a732014-09-16 22:51:24 +0200920 if (s && !strncasecmp(s, "ThinkPad", 8)) {
Kamil Iskra4000e6262012-11-16 22:28:58 +0100921 dmi_walk(find_battery, battery);
922 if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
923 &battery->flags) &&
924 battery->design_voltage) {
925 battery->design_capacity =
926 battery->design_capacity *
927 10000 / battery->design_voltage;
928 battery->full_charge_capacity =
929 battery->full_charge_capacity *
930 10000 / battery->design_voltage;
931 battery->design_capacity_warning =
932 battery->design_capacity_warning *
933 10000 / battery->design_voltage;
934 battery->capacity_now = battery->capacity_now *
935 10000 / battery->design_voltage;
936 }
937 }
938 }
Laszlo Totha20136a2018-02-24 10:20:15 +0100939
940 if (test_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags))
941 return;
942
943 if (acpi_battery_is_degraded(battery) &&
944 battery->capacity_now > battery->full_charge_capacity) {
945 set_bit(ACPI_BATTERY_QUIRK_DEGRADED_FULL_CHARGE, &battery->flags);
946 battery->capacity_now = battery->full_charge_capacity;
947 }
Zhang Rui557d5862010-10-22 10:02:06 +0800948}
949
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800950static int acpi_battery_update(struct acpi_battery *battery, bool resume)
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500951{
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700952 int result = acpi_battery_get_status(battery);
953
Andrey Borzenkov508df922007-10-28 12:50:09 +0300954 if (result)
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300955 return result;
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700956
Andrey Borzenkov508df922007-10-28 12:50:09 +0300957 if (!acpi_battery_present(battery)) {
958 sysfs_remove_battery(battery);
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500959 battery->update_time = 0;
Andrey Borzenkov508df922007-10-28 12:50:09 +0300960 return 0;
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +0300961 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +0800962
963 if (resume)
964 return 0;
965
Lucas Rangit Magasweran82f2d302018-07-14 15:40:18 -0700966 if (!battery->update_time) {
Alexey Starikovskiy97749cd2008-01-01 14:27:24 -0500967 result = acpi_battery_get_info(battery);
968 if (result)
969 return result;
970 acpi_battery_init_alarm(battery);
971 }
Carlos Garnacho12c78ca2016-08-10 17:24:15 +0200972
973 result = acpi_battery_get_state(battery);
974 if (result)
975 return result;
976 acpi_battery_quirks(battery);
977
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +0100978 if (!battery->bat) {
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +0100979 result = sysfs_add_battery(battery);
980 if (result)
981 return result;
982 }
Zhang Ruie0d1f092014-05-28 15:23:38 +0800983
984 /*
985 * Wakeup the system if battery is critical low
986 * or lower than the alarm level
987 */
988 if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
989 (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
Maximilian Luzc6237b22020-11-05 03:06:00 +0100990 (battery->capacity_now <= battery->alarm)))
Rafael J. Wysocki33e4f802017-06-12 22:56:34 +0200991 acpi_pm_wakeup_event(&battery->device->dev);
Zhang Ruie0d1f092014-05-28 15:23:38 +0800992
Zhang Rui557d5862010-10-22 10:02:06 +0800993 return result;
Vladimir Lebedev4bd35cd2007-02-10 01:43:48 -0500994}
995
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +0100996static void acpi_battery_refresh(struct acpi_battery *battery)
997{
Andy Whitcroftc5971452012-05-03 14:48:26 +0100998 int power_unit;
999
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001000 if (!battery->bat)
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001001 return;
1002
Andy Whitcroftc5971452012-05-03 14:48:26 +01001003 power_unit = battery->power_unit;
1004
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001005 acpi_battery_get_info(battery);
Andy Whitcroftc5971452012-05-03 14:48:26 +01001006
1007 if (power_unit == battery->power_unit)
1008 return;
1009
1010 /* The battery has changed its reporting units. */
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001011 sysfs_remove_battery(battery);
1012 sysfs_add_battery(battery);
1013}
1014
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015/* --------------------------------------------------------------------------
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 Driver Interface
1017 -------------------------------------------------------------------------- */
1018
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001019static void acpi_battery_notify(struct acpi_device *device, u32 event)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001021 struct acpi_battery *battery = acpi_driver_data(device);
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001022 struct power_supply *old;
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001023
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001025 return;
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001026 old = battery->bat;
Alexander Mezinf43691c2014-06-04 02:01:23 +07001027 /*
1028 * On Acer Aspire V5-573G notifications are sometimes triggered too
1029 * early. For example, when AC is unplugged and notification is
1030 * triggered, battery state is still reported as "Full", and changes to
1031 * "Discharging" only after short delay, without any notification.
1032 */
1033 if (battery_notification_delay_ms > 0)
1034 msleep(battery_notification_delay_ms);
Rafael J. Wysockida8aeb92011-01-06 23:42:27 +01001035 if (event == ACPI_BATTERY_NOTIFY_INFO)
1036 acpi_battery_refresh(battery);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001037 acpi_battery_update(battery, false);
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001038 acpi_bus_generate_netlink_event(device->pnp.device_class,
Kay Sievers07944692008-10-30 01:18:59 +01001039 dev_name(&device->dev), event,
Vladimir Lebedev9ea7d572007-02-20 15:48:06 +03001040 acpi_battery_present(battery));
Alexander Mezin411e0f72014-03-12 00:58:47 +07001041 acpi_notifier_call_chain(device, event, acpi_battery_present(battery));
Justin P. Mattock2345baf2009-12-13 14:42:36 -08001042 /* acpi_battery_update could remove power_supply object */
Krzysztof Kozlowski297d7162015-03-12 08:44:11 +01001043 if (old && battery->bat)
1044 power_supply_changed(battery->bat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045}
1046
Kyle McMartin25be5822011-03-22 16:19:50 -04001047static int battery_notify(struct notifier_block *nb,
1048 unsigned long mode, void *_unused)
1049{
1050 struct acpi_battery *battery = container_of(nb, struct acpi_battery,
1051 pm_nb);
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001052 int result;
1053
Kyle McMartin25be5822011-03-22 16:19:50 -04001054 switch (mode) {
Lan Tianyud5a59112011-06-30 11:33:40 +08001055 case PM_POST_HIBERNATION:
Kyle McMartin25be5822011-03-22 16:19:50 -04001056 case PM_POST_SUSPEND:
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001057 if (!acpi_battery_present(battery))
1058 return 0;
1059
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001060 if (battery->bat) {
1061 acpi_battery_refresh(battery);
1062 } else {
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001063 result = acpi_battery_get_info(battery);
1064 if (result)
1065 return result;
1066
1067 result = sysfs_add_battery(battery);
1068 if (result)
1069 return result;
Dmitry Rozhkov27544352018-07-24 14:27:34 +03001070 }
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001071
1072 acpi_battery_init_alarm(battery);
1073 acpi_battery_get_state(battery);
Kyle McMartin25be5822011-03-22 16:19:50 -04001074 break;
1075 }
1076
1077 return 0;
1078}
1079
Mathias Krause048d16d2015-06-13 14:26:55 +02001080static int __init
1081battery_bix_broken_package_quirk(const struct dmi_system_id *d)
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001082{
1083 battery_bix_broken_package = 1;
1084 return 0;
1085}
1086
Mathias Krause048d16d2015-06-13 14:26:55 +02001087static int __init
1088battery_notification_delay_quirk(const struct dmi_system_id *d)
Alexander Mezinf43691c2014-06-04 02:01:23 +07001089{
1090 battery_notification_delay_ms = 1000;
1091 return 0;
1092}
1093
Hans de Goede1b799c52018-04-12 12:02:00 +02001094static int __init
1095battery_ac_is_broken_quirk(const struct dmi_system_id *d)
1096{
1097 battery_ac_is_broken = 1;
1098 return 0;
1099}
1100
Carlo Caioneec625a32018-04-18 14:04:39 +02001101static int __init
1102battery_do_not_check_pmic_quirk(const struct dmi_system_id *d)
1103{
1104 battery_check_pmic = 0;
1105 return 0;
1106}
1107
Mathias Krause048d16d2015-06-13 14:26:55 +02001108static const struct dmi_system_id bat_dmi_table[] __initconst = {
Lan Tianyua90b4032014-01-06 22:50:37 +08001109 {
Hans de Goede91afa072018-04-12 12:01:58 +02001110 /* NEC LZ750/LS */
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001111 .callback = battery_bix_broken_package_quirk,
Lan Tianyua90b4032014-01-06 22:50:37 +08001112 .matches = {
1113 DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
1114 DMI_MATCH(DMI_PRODUCT_NAME, "PC-LZ750LS"),
1115 },
1116 },
Alexander Mezinf43691c2014-06-04 02:01:23 +07001117 {
Hans de Goede91afa072018-04-12 12:01:58 +02001118 /* Acer Aspire V5-573G */
Alexander Mezinf43691c2014-06-04 02:01:23 +07001119 .callback = battery_notification_delay_quirk,
Alexander Mezinf43691c2014-06-04 02:01:23 +07001120 .matches = {
1121 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
1122 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
1123 },
1124 },
Hans de Goede1b799c52018-04-12 12:02:00 +02001125 {
1126 /* Point of View mobii wintab p800w */
1127 .callback = battery_ac_is_broken_quirk,
1128 .matches = {
1129 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1130 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1131 DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
1132 /* Above matches are too generic, add bios-date match */
1133 DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
1134 },
1135 },
Carlo Caioneec625a32018-04-18 14:04:39 +02001136 {
Hans de Goede8c3f6992020-02-23 15:29:41 +01001137 /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
Carlo Caioneec625a32018-04-18 14:04:39 +02001138 .callback = battery_do_not_check_pmic_quirk,
1139 .matches = {
1140 DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
1141 },
1142 },
1143 {
Hans de Goede8c3f6992020-02-23 15:29:41 +01001144 /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
Carlo Caioneec625a32018-04-18 14:04:39 +02001145 .callback = battery_do_not_check_pmic_quirk,
1146 .matches = {
Hans de Goede8c3f6992020-02-23 15:29:41 +01001147 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1148 DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
1149 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
Carlo Caioneec625a32018-04-18 14:04:39 +02001150 },
1151 },
Lan Tianyua90b4032014-01-06 22:50:37 +08001152 {},
1153};
1154
Lan Tianyu75646e72014-07-07 15:47:12 +08001155/*
1156 * Some machines'(E,G Lenovo Z480) ECs are not stable
1157 * during boot up and this causes battery driver fails to be
1158 * probed due to failure of getting battery information
1159 * from EC sometimes. After several retries, the operation
1160 * may work. So add retry code here and 20ms sleep between
1161 * every retries.
1162 */
1163static int acpi_battery_update_retry(struct acpi_battery *battery)
1164{
1165 int retry, ret;
1166
1167 for (retry = 5; retry; retry--) {
1168 ret = acpi_battery_update(battery, false);
1169 if (!ret)
1170 break;
1171
1172 msleep(20);
1173 }
1174 return ret;
1175}
1176
Len Brown4be44fc2005-08-05 00:44:28 -04001177static int acpi_battery_add(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178{
Len Brown4be44fc2005-08-05 00:44:28 -04001179 int result = 0;
Len Brown4be44fc2005-08-05 00:44:28 -04001180 struct acpi_battery *battery = NULL;
Jiang Liu952c63e2013-06-29 00:24:38 +08001181
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001183 return -EINVAL;
Lan Tianyu40e7fcb2014-11-23 21:22:54 +08001184
1185 if (device->dep_unmet)
1186 return -EPROBE_DEFER;
1187
Burman Yan36bcbec2006-12-19 12:56:11 -08001188 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 if (!battery)
Patrick Mocheld550d982006-06-27 00:41:40 -04001190 return -ENOMEM;
Patrick Mochel145def82006-05-19 16:54:39 -04001191 battery->device = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
1193 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
Pavel Machekdb89b4f2008-09-22 14:37:34 -07001194 device->driver_data = battery;
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001195 mutex_init(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001196 mutex_init(&battery->sysfs_lock);
Jiang Liu952c63e2013-06-29 00:24:38 +08001197 if (acpi_has_method(battery->device->handle, "_BIX"))
Alexey Starikovskiyc67fcd62009-10-15 14:31:44 +04001198 set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
Lan Tianyu75646e72014-07-07 15:47:12 +08001199
1200 result = acpi_battery_update_retry(battery);
Stefan Hajnoczieb03cb02011-07-12 09:03:29 +01001201 if (result)
1202 goto fail;
Lan Tianyu75646e72014-07-07 15:47:12 +08001203
Dmitry Rozhkovdd1fca92018-07-24 14:27:33 +03001204 pr_info(PREFIX "%s Slot [%s] (battery %s)\n",
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001205 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
1206 device->status.battery_present ? "present" : "absent");
1207
Kyle McMartin25be5822011-03-22 16:19:50 -04001208 battery->pm_nb.notifier_call = battery_notify;
1209 register_pm_notifier(&battery->pm_nb);
1210
Zhang Ruie0d1f092014-05-28 15:23:38 +08001211 device_init_wakeup(&device->dev, 1);
1212
Patrick Mocheld550d982006-06-27 00:41:40 -04001213 return result;
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001214
1215fail:
1216 sysfs_remove_battery(battery);
1217 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001218 mutex_destroy(&battery->sysfs_lock);
Stefan Hajnoczie80bba42011-07-12 09:03:28 +01001219 kfree(battery);
1220 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221}
1222
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001223static int acpi_battery_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224{
Len Brown4be44fc2005-08-05 00:44:28 -04001225 struct acpi_battery *battery = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 if (!device || !acpi_driver_data(device))
Patrick Mocheld550d982006-06-27 00:41:40 -04001228 return -EINVAL;
Zhang Ruie0d1f092014-05-28 15:23:38 +08001229 device_init_wakeup(&device->dev, 0);
Jan Engelhardt50dd0962006-10-01 00:28:50 +02001230 battery = acpi_driver_data(device);
Kyle McMartin25be5822011-03-22 16:19:50 -04001231 unregister_pm_notifier(&battery->pm_nb);
Andrey Borzenkov508df922007-10-28 12:50:09 +03001232 sysfs_remove_battery(battery);
Alexey Starikovskiy038fdea2007-09-26 19:42:46 +04001233 mutex_destroy(&battery->lock);
Sergey Senozhatsky69d94ec2011-08-06 01:34:08 +03001234 mutex_destroy(&battery->sysfs_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 kfree(battery);
Patrick Mocheld550d982006-06-27 00:41:40 -04001236 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237}
1238
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001239#ifdef CONFIG_PM_SLEEP
Jiri Kosina34c44152006-10-10 14:20:41 -07001240/* this is needed to learn about changes made in suspended state */
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001241static int acpi_battery_resume(struct device *dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001242{
1243 struct acpi_battery *battery;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001244
1245 if (!dev)
Jiri Kosina34c44152006-10-10 14:20:41 -07001246 return -EINVAL;
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001247
1248 battery = acpi_driver_data(to_acpi_device(dev));
1249 if (!battery)
1250 return -EINVAL;
1251
Alexey Starikovskiyf1d46612007-09-26 19:42:52 +04001252 battery->update_time = 0;
Lan Tianyu9e50bc12014-05-04 14:07:06 +08001253 acpi_battery_update(battery, true);
Vladimir Lebedevb6ce4082007-02-20 15:48:06 +03001254 return 0;
Jiri Kosina34c44152006-10-10 14:20:41 -07001255}
Shuah Khan7f6895c2014-02-12 20:19:06 -07001256#else
1257#define acpi_battery_resume NULL
Rafael J. Wysocki90692402012-08-09 23:00:02 +02001258#endif
Jiri Kosina34c44152006-10-10 14:20:41 -07001259
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001260static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
1261
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001262static struct acpi_driver acpi_battery_driver = {
1263 .name = "battery",
1264 .class = ACPI_BATTERY_CLASS,
1265 .ids = battery_device_ids,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001266 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001267 .ops = {
1268 .add = acpi_battery_add,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001269 .remove = acpi_battery_remove,
Bjorn Helgaasd9406692009-04-30 09:35:47 -06001270 .notify = acpi_battery_notify,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001271 },
Rafael J. Wysockia6f50dc2012-06-27 23:26:43 +02001272 .drv.pm = &acpi_battery_pm,
Alexey Starikovskiyaa650bb2007-09-26 19:42:58 +04001273};
1274
Linus Torvaldsb0cbc862009-04-11 12:45:20 -07001275static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
Hans de Goededccfae62017-04-19 14:02:10 +02001277 unsigned int i;
Luis Henriques479faaf2015-05-11 22:48:46 +01001278 int result;
1279
Alexander Mezin3f5dc082014-06-04 02:01:22 +07001280 dmi_check_system(bat_dmi_table);
Luis Henriques479faaf2015-05-11 22:48:46 +01001281
Carlo Caioneec625a32018-04-18 14:04:39 +02001282 if (battery_check_pmic) {
1283 for (i = 0; i < ARRAY_SIZE(acpi_battery_blacklist); i++)
1284 if (acpi_dev_present(acpi_battery_blacklist[i], "1", -1)) {
1285 pr_info(PREFIX ACPI_BATTERY_DEVICE_NAME
1286 ": found native %s PMIC, not loading\n",
1287 acpi_battery_blacklist[i]);
1288 return;
1289 }
1290 }
1291
Luis Henriques479faaf2015-05-11 22:48:46 +01001292 result = acpi_bus_register_driver(&acpi_battery_driver);
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001293 battery_driver_registered = (result == 0);
Arjan van de Ven0f66af52009-01-10 14:19:05 -05001294}
1295
1296static int __init acpi_battery_init(void)
1297{
Luis Henriquese234b072015-05-11 22:48:38 +01001298 if (acpi_disabled)
1299 return -ENODEV;
1300
Luis Henriqueseca21d912015-05-11 22:49:05 +01001301 async_cookie = async_schedule(acpi_battery_init_async, NULL);
Patrick Mocheld550d982006-06-27 00:41:40 -04001302 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303}
1304
Len Brown4be44fc2005-08-05 00:44:28 -04001305static void __exit acpi_battery_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
Chris Wilson5dfa0c72016-05-19 09:11:52 +01001307 async_synchronize_cookie(async_cookie + 1);
Ognjen Galicfa938542018-02-07 15:58:13 +01001308 if (battery_driver_registered) {
Hans de Goedebc39fbc2017-04-19 14:02:09 +02001309 acpi_bus_unregister_driver(&acpi_battery_driver);
Ognjen Galicfa938542018-02-07 15:58:13 +01001310 battery_hook_exit();
1311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312}
1313
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314module_init(acpi_battery_init);
1315module_exit(acpi_battery_exit);