GNU Linux-libre 5.10.215-gnu1
[releases.git] / drivers / acpi / ac.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $)
4  *
5  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/slab.h>
12 #include <linux/init.h>
13 #include <linux/types.h>
14 #include <linux/dmi.h>
15 #include <linux/delay.h>
16 #include <linux/platform_device.h>
17 #include <linux/power_supply.h>
18 #include <linux/acpi.h>
19 #include <acpi/battery.h>
20
21 #define PREFIX "ACPI: "
22
23 #define ACPI_AC_CLASS                   "ac_adapter"
24 #define ACPI_AC_DEVICE_NAME             "AC Adapter"
25 #define ACPI_AC_FILE_STATE              "state"
26 #define ACPI_AC_NOTIFY_STATUS           0x80
27 #define ACPI_AC_STATUS_OFFLINE          0x00
28 #define ACPI_AC_STATUS_ONLINE           0x01
29 #define ACPI_AC_STATUS_UNKNOWN          0xFF
30
31 #define _COMPONENT              ACPI_AC_COMPONENT
32 ACPI_MODULE_NAME("ac");
33
34 MODULE_AUTHOR("Paul Diefenbaugh");
35 MODULE_DESCRIPTION("ACPI AC Adapter Driver");
36 MODULE_LICENSE("GPL");
37
38
39 static int acpi_ac_add(struct acpi_device *device);
40 static int acpi_ac_remove(struct acpi_device *device);
41 static void acpi_ac_notify(struct acpi_device *device, u32 event);
42
43 struct acpi_ac_bl {
44         const char *hid;
45         int hrv;
46 };
47
48 static const struct acpi_device_id ac_device_ids[] = {
49         {"ACPI0003", 0},
50         {"", 0},
51 };
52 MODULE_DEVICE_TABLE(acpi, ac_device_ids);
53
54 /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
55 static const struct acpi_ac_bl acpi_ac_blacklist[] = {
56         { "INT33F4", -1 }, /* X-Powers AXP288 PMIC */
57         { "INT34D3",  3 }, /* Intel Cherrytrail Whiskey Cove PMIC */
58 };
59
60 #ifdef CONFIG_PM_SLEEP
61 static int acpi_ac_resume(struct device *dev);
62 #endif
63 static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
64
65 static int ac_sleep_before_get_state_ms;
66 static int ac_check_pmic = 1;
67 static int ac_only;
68
69 static struct acpi_driver acpi_ac_driver = {
70         .name = "ac",
71         .class = ACPI_AC_CLASS,
72         .ids = ac_device_ids,
73         .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
74         .ops = {
75                 .add = acpi_ac_add,
76                 .remove = acpi_ac_remove,
77                 .notify = acpi_ac_notify,
78                 },
79         .drv.pm = &acpi_ac_pm,
80 };
81
82 struct acpi_ac {
83         struct power_supply *charger;
84         struct power_supply_desc charger_desc;
85         struct acpi_device * device;
86         unsigned long long state;
87         struct notifier_block battery_nb;
88 };
89
90 #define to_acpi_ac(x) power_supply_get_drvdata(x)
91
92 /* --------------------------------------------------------------------------
93                                AC Adapter Management
94    -------------------------------------------------------------------------- */
95
96 static int acpi_ac_get_state(struct acpi_ac *ac)
97 {
98         acpi_status status = AE_OK;
99
100         if (!ac)
101                 return -EINVAL;
102
103         if (ac_only) {
104                 ac->state = 1;
105                 return 0;
106         }
107
108         status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL,
109                                        &ac->state);
110         if (ACPI_FAILURE(status)) {
111                 ACPI_EXCEPTION((AE_INFO, status,
112                                 "Error reading AC Adapter state"));
113                 ac->state = ACPI_AC_STATUS_UNKNOWN;
114                 return -ENODEV;
115         }
116
117         return 0;
118 }
119
120 /* --------------------------------------------------------------------------
121                             sysfs I/F
122    -------------------------------------------------------------------------- */
123 static int get_ac_property(struct power_supply *psy,
124                            enum power_supply_property psp,
125                            union power_supply_propval *val)
126 {
127         struct acpi_ac *ac = to_acpi_ac(psy);
128
129         if (!ac)
130                 return -ENODEV;
131
132         if (acpi_ac_get_state(ac))
133                 return -ENODEV;
134
135         switch (psp) {
136         case POWER_SUPPLY_PROP_ONLINE:
137                 val->intval = ac->state;
138                 break;
139         default:
140                 return -EINVAL;
141         }
142         return 0;
143 }
144
145 static enum power_supply_property ac_props[] = {
146         POWER_SUPPLY_PROP_ONLINE,
147 };
148
149 /* --------------------------------------------------------------------------
150                                    Driver Model
151    -------------------------------------------------------------------------- */
152
153 static void acpi_ac_notify(struct acpi_device *device, u32 event)
154 {
155         struct acpi_ac *ac = acpi_driver_data(device);
156
157         if (!ac)
158                 return;
159
160         switch (event) {
161         default:
162                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
163                                   "Unsupported event [0x%x]\n", event));
164                 fallthrough;
165         case ACPI_AC_NOTIFY_STATUS:
166         case ACPI_NOTIFY_BUS_CHECK:
167         case ACPI_NOTIFY_DEVICE_CHECK:
168                 /*
169                  * A buggy BIOS may notify AC first and then sleep for
170                  * a specific time before doing actual operations in the
171                  * EC event handler (_Qxx). This will cause the AC state
172                  * reported by the ACPI event to be incorrect, so wait for a
173                  * specific time for the EC event handler to make progress.
174                  */
175                 if (ac_sleep_before_get_state_ms > 0)
176                         msleep(ac_sleep_before_get_state_ms);
177
178                 acpi_ac_get_state(ac);
179                 acpi_bus_generate_netlink_event(device->pnp.device_class,
180                                                   dev_name(&device->dev), event,
181                                                   (u32) ac->state);
182                 acpi_notifier_call_chain(device, event, (u32) ac->state);
183                 kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
184         }
185
186         return;
187 }
188
189 static int acpi_ac_battery_notify(struct notifier_block *nb,
190                                   unsigned long action, void *data)
191 {
192         struct acpi_ac *ac = container_of(nb, struct acpi_ac, battery_nb);
193         struct acpi_bus_event *event = (struct acpi_bus_event *)data;
194
195         /*
196          * On HP Pavilion dv6-6179er AC status notifications aren't triggered
197          * when adapter is plugged/unplugged. However, battery status
198          * notifcations are triggered when battery starts charging or
199          * discharging. Re-reading AC status triggers lost AC notifications,
200          * if AC status has changed.
201          */
202         if (strcmp(event->device_class, ACPI_BATTERY_CLASS) == 0 &&
203             event->type == ACPI_BATTERY_NOTIFY_STATUS)
204                 acpi_ac_get_state(ac);
205
206         return NOTIFY_OK;
207 }
208
209 static int __init thinkpad_e530_quirk(const struct dmi_system_id *d)
210 {
211         ac_sleep_before_get_state_ms = 1000;
212         return 0;
213 }
214
215 static int __init ac_do_not_check_pmic_quirk(const struct dmi_system_id *d)
216 {
217         ac_check_pmic = 0;
218         return 0;
219 }
220
221 static int __init ac_only_quirk(const struct dmi_system_id *d)
222 {
223         ac_only = 1;
224         return 0;
225 }
226
227 /* Please keep this list alphabetically sorted */
228 static const struct dmi_system_id ac_dmi_table[]  __initconst = {
229         {
230                 /* ECS EF20EA, AXP288 PMIC but uses separate fuel-gauge */
231                 .callback = ac_do_not_check_pmic_quirk,
232                 .matches = {
233                         DMI_MATCH(DMI_PRODUCT_NAME, "EF20EA"),
234                 },
235         },
236         {
237                 /* Kodlix GK45 returning incorrect state */
238                 .callback = ac_only_quirk,
239                 .matches = {
240                         DMI_MATCH(DMI_PRODUCT_NAME, "GK45"),
241                 },
242         },
243         {
244                 /* Lenovo Ideapad Miix 320, AXP288 PMIC, separate fuel-gauge */
245                 .callback = ac_do_not_check_pmic_quirk,
246                 .matches = {
247                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
248                         DMI_MATCH(DMI_PRODUCT_NAME, "80XF"),
249                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
250                 },
251         },
252         {
253                 /* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */
254                 .callback = thinkpad_e530_quirk,
255                 .matches = {
256                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
257                         DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"),
258                 },
259         },
260         {},
261 };
262
263 static int acpi_ac_add(struct acpi_device *device)
264 {
265         struct power_supply_config psy_cfg = {};
266         int result = 0;
267         struct acpi_ac *ac = NULL;
268
269
270         if (!device)
271                 return -EINVAL;
272
273         ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
274         if (!ac)
275                 return -ENOMEM;
276
277         ac->device = device;
278         strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
279         strcpy(acpi_device_class(device), ACPI_AC_CLASS);
280         device->driver_data = ac;
281
282         result = acpi_ac_get_state(ac);
283         if (result)
284                 goto end;
285
286         psy_cfg.drv_data = ac;
287
288         ac->charger_desc.name = acpi_device_bid(device);
289         ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS;
290         ac->charger_desc.properties = ac_props;
291         ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
292         ac->charger_desc.get_property = get_ac_property;
293         ac->charger = power_supply_register(&ac->device->dev,
294                                             &ac->charger_desc, &psy_cfg);
295         if (IS_ERR(ac->charger)) {
296                 result = PTR_ERR(ac->charger);
297                 goto end;
298         }
299
300         printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
301                acpi_device_name(device), acpi_device_bid(device),
302                ac->state ? "on-line" : "off-line");
303
304         ac->battery_nb.notifier_call = acpi_ac_battery_notify;
305         register_acpi_notifier(&ac->battery_nb);
306 end:
307         if (result) {
308                 kfree(ac);
309         }
310
311         return result;
312 }
313
314 #ifdef CONFIG_PM_SLEEP
315 static int acpi_ac_resume(struct device *dev)
316 {
317         struct acpi_ac *ac;
318         unsigned old_state;
319
320         if (!dev)
321                 return -EINVAL;
322
323         ac = acpi_driver_data(to_acpi_device(dev));
324         if (!ac)
325                 return -EINVAL;
326
327         old_state = ac->state;
328         if (acpi_ac_get_state(ac))
329                 return 0;
330         if (old_state != ac->state)
331                 kobject_uevent(&ac->charger->dev.kobj, KOBJ_CHANGE);
332         return 0;
333 }
334 #else
335 #define acpi_ac_resume NULL
336 #endif
337
338 static int acpi_ac_remove(struct acpi_device *device)
339 {
340         struct acpi_ac *ac = NULL;
341
342
343         if (!device || !acpi_driver_data(device))
344                 return -EINVAL;
345
346         ac = acpi_driver_data(device);
347
348         power_supply_unregister(ac->charger);
349         unregister_acpi_notifier(&ac->battery_nb);
350
351         kfree(ac);
352
353         return 0;
354 }
355
356 static int __init acpi_ac_init(void)
357 {
358         unsigned int i;
359         int result;
360
361         if (acpi_disabled)
362                 return -ENODEV;
363
364         dmi_check_system(ac_dmi_table);
365
366         if (ac_check_pmic) {
367                 for (i = 0; i < ARRAY_SIZE(acpi_ac_blacklist); i++)
368                         if (acpi_dev_present(acpi_ac_blacklist[i].hid, "1",
369                                              acpi_ac_blacklist[i].hrv)) {
370                                 pr_info(PREFIX "AC: found native %s PMIC, not loading\n",
371                                         acpi_ac_blacklist[i].hid);
372                                 return -ENODEV;
373                         }
374         }
375
376         result = acpi_bus_register_driver(&acpi_ac_driver);
377         if (result < 0) {
378                 return -ENODEV;
379         }
380
381         return 0;
382 }
383
384 static void __exit acpi_ac_exit(void)
385 {
386         acpi_bus_unregister_driver(&acpi_ac_driver);
387 }
388 module_init(acpi_ac_init);
389 module_exit(acpi_ac_exit);