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 #define pr_fmt(fmt) "ACPI: AC: " fmt 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/slab.h> 14 #include <linux/init.h> 15 #include <linux/types.h> 16 #include <linux/dmi.h> 17 #include <linux/delay.h> 18 #include <linux/platform_device.h> 19 #include <linux/power_supply.h> 20 #include <linux/string_choices.h> 21 #include <linux/acpi.h> 22 #include <acpi/battery.h> 23 24 #define ACPI_AC_CLASS "ac_adapter" 25 #define ACPI_AC_DEVICE_NAME "AC Adapter" 26 #define ACPI_AC_FILE_STATE "state" 27 #define ACPI_AC_NOTIFY_STATUS 0x80 28 #define ACPI_AC_STATUS_OFFLINE 0x00 29 #define ACPI_AC_STATUS_ONLINE 0x01 30 #define ACPI_AC_STATUS_UNKNOWN 0xFF 31 32 MODULE_AUTHOR("Paul Diefenbaugh"); 33 MODULE_DESCRIPTION("ACPI AC Adapter Driver"); 34 MODULE_LICENSE("GPL"); 35 36 static int acpi_ac_probe(struct platform_device *pdev); 37 static void acpi_ac_remove(struct platform_device *pdev); 38 39 static void acpi_ac_notify(acpi_handle handle, u32 event, void *data); 40 41 static const struct acpi_device_id ac_device_ids[] = { 42 {"ACPI0003", 0}, 43 {"", 0}, 44 }; 45 MODULE_DEVICE_TABLE(acpi, ac_device_ids); 46 47 #ifdef CONFIG_PM_SLEEP 48 static int acpi_ac_resume(struct device *dev); 49 #endif 50 static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); 51 52 static int ac_sleep_before_get_state_ms; 53 static int ac_only; 54 55 struct acpi_ac { 56 struct power_supply *charger; 57 struct power_supply_desc charger_desc; 58 struct acpi_device *device; 59 unsigned long long state; 60 struct notifier_block battery_nb; 61 }; 62 63 #define to_acpi_ac(x) power_supply_get_drvdata(x) 64 65 /* AC Adapter Management */ 66 static int acpi_ac_get_state(struct acpi_ac *ac) 67 { 68 acpi_status status = AE_OK; 69 70 if (!ac) 71 return -EINVAL; 72 73 if (ac_only) { 74 ac->state = 1; 75 return 0; 76 } 77 78 status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, 79 &ac->state); 80 if (ACPI_FAILURE(status)) { 81 acpi_handle_info(ac->device->handle, 82 "Error reading AC Adapter state: %s\n", 83 acpi_format_exception(status)); 84 ac->state = ACPI_AC_STATUS_UNKNOWN; 85 return -ENODEV; 86 } 87 88 return 0; 89 } 90 91 /* sysfs I/F */ 92 static int get_ac_property(struct power_supply *psy, 93 enum power_supply_property psp, 94 union power_supply_propval *val) 95 { 96 struct acpi_ac *ac = to_acpi_ac(psy); 97 98 if (!ac) 99 return -ENODEV; 100 101 if (acpi_ac_get_state(ac)) 102 return -ENODEV; 103 104 switch (psp) { 105 case POWER_SUPPLY_PROP_ONLINE: 106 val->intval = ac->state; 107 break; 108 default: 109 return -EINVAL; 110 } 111 112 return 0; 113 } 114 115 static const enum power_supply_property ac_props[] = { 116 POWER_SUPPLY_PROP_ONLINE, 117 }; 118 119 /* Driver Model */ 120 static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) 121 { 122 struct acpi_ac *ac = data; 123 struct acpi_device *adev = ac->device; 124 125 switch (event) { 126 default: 127 acpi_handle_debug(adev->handle, "Unsupported event [0x%x]\n", 128 event); 129 fallthrough; 130 case ACPI_AC_NOTIFY_STATUS: 131 case ACPI_NOTIFY_BUS_CHECK: 132 case ACPI_NOTIFY_DEVICE_CHECK: 133 /* 134 * A buggy BIOS may notify AC first and then sleep for 135 * a specific time before doing actual operations in the 136 * EC event handler (_Qxx). This will cause the AC state 137 * reported by the ACPI event to be incorrect, so wait for a 138 * specific time for the EC event handler to make progress. 139 */ 140 if (ac_sleep_before_get_state_ms > 0) 141 msleep(ac_sleep_before_get_state_ms); 142 143 acpi_ac_get_state(ac); 144 acpi_bus_generate_netlink_event(adev->pnp.device_class, 145 dev_name(&adev->dev), event, 146 (u32) ac->state); 147 acpi_notifier_call_chain(adev, event, (u32) ac->state); 148 power_supply_changed(ac->charger); 149 } 150 } 151 152 static int acpi_ac_battery_notify(struct notifier_block *nb, 153 unsigned long action, void *data) 154 { 155 struct acpi_ac *ac = container_of(nb, struct acpi_ac, battery_nb); 156 struct acpi_bus_event *event = (struct acpi_bus_event *)data; 157 158 /* 159 * On HP Pavilion dv6-6179er AC status notifications aren't triggered 160 * when adapter is plugged/unplugged. However, battery status 161 * notifications are triggered when battery starts charging or 162 * discharging. Re-reading AC status triggers lost AC notifications, 163 * if AC status has changed. 164 */ 165 if (strcmp(event->device_class, ACPI_BATTERY_CLASS) == 0 && 166 event->type == ACPI_BATTERY_NOTIFY_STATUS) 167 acpi_ac_get_state(ac); 168 169 return NOTIFY_OK; 170 } 171 172 static int __init thinkpad_e530_quirk(const struct dmi_system_id *d) 173 { 174 ac_sleep_before_get_state_ms = 1000; 175 return 0; 176 } 177 178 static int __init ac_only_quirk(const struct dmi_system_id *d) 179 { 180 ac_only = 1; 181 return 0; 182 } 183 184 /* Please keep this list alphabetically sorted */ 185 static const struct dmi_system_id ac_dmi_table[] __initconst = { 186 { 187 /* Kodlix GK45 returning incorrect state */ 188 .callback = ac_only_quirk, 189 .matches = { 190 DMI_MATCH(DMI_PRODUCT_NAME, "GK45"), 191 }, 192 }, 193 { 194 /* Lenovo Thinkpad e530, see comment in acpi_ac_notify() */ 195 .callback = thinkpad_e530_quirk, 196 .matches = { 197 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 198 DMI_MATCH(DMI_PRODUCT_NAME, "32597CG"), 199 }, 200 }, 201 {}, 202 }; 203 204 static int acpi_ac_probe(struct platform_device *pdev) 205 { 206 struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); 207 struct power_supply_config psy_cfg = {}; 208 struct acpi_ac *ac; 209 int result; 210 211 ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); 212 if (!ac) 213 return -ENOMEM; 214 215 ac->device = adev; 216 strscpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); 217 strscpy(acpi_device_class(adev), ACPI_AC_CLASS); 218 219 platform_set_drvdata(pdev, ac); 220 221 result = acpi_ac_get_state(ac); 222 if (result) 223 goto err_release_ac; 224 225 psy_cfg.drv_data = ac; 226 227 ac->charger_desc.name = acpi_device_bid(adev); 228 ac->charger_desc.type = POWER_SUPPLY_TYPE_MAINS; 229 ac->charger_desc.properties = ac_props; 230 ac->charger_desc.num_properties = ARRAY_SIZE(ac_props); 231 ac->charger_desc.get_property = get_ac_property; 232 ac->charger = power_supply_register(&pdev->dev, 233 &ac->charger_desc, &psy_cfg); 234 if (IS_ERR(ac->charger)) { 235 result = PTR_ERR(ac->charger); 236 goto err_release_ac; 237 } 238 239 pr_info("%s [%s] (%s-line)\n", acpi_device_name(adev), 240 acpi_device_bid(adev), str_on_off(ac->state)); 241 242 ac->battery_nb.notifier_call = acpi_ac_battery_notify; 243 register_acpi_notifier(&ac->battery_nb); 244 245 result = acpi_dev_install_notify_handler(adev, ACPI_ALL_NOTIFY, 246 acpi_ac_notify, ac); 247 if (result) 248 goto err_unregister; 249 250 return 0; 251 252 err_unregister: 253 power_supply_unregister(ac->charger); 254 unregister_acpi_notifier(&ac->battery_nb); 255 err_release_ac: 256 kfree(ac); 257 258 return result; 259 } 260 261 #ifdef CONFIG_PM_SLEEP 262 static int acpi_ac_resume(struct device *dev) 263 { 264 struct acpi_ac *ac = dev_get_drvdata(dev); 265 unsigned int old_state; 266 267 old_state = ac->state; 268 if (acpi_ac_get_state(ac)) 269 return 0; 270 if (old_state != ac->state) 271 power_supply_changed(ac->charger); 272 273 return 0; 274 } 275 #else 276 #define acpi_ac_resume NULL 277 #endif 278 279 static void acpi_ac_remove(struct platform_device *pdev) 280 { 281 struct acpi_ac *ac = platform_get_drvdata(pdev); 282 283 acpi_dev_remove_notify_handler(ac->device, ACPI_ALL_NOTIFY, 284 acpi_ac_notify); 285 power_supply_unregister(ac->charger); 286 unregister_acpi_notifier(&ac->battery_nb); 287 288 kfree(ac); 289 } 290 291 static struct platform_driver acpi_ac_driver = { 292 .probe = acpi_ac_probe, 293 .remove_new = acpi_ac_remove, 294 .driver = { 295 .name = "ac", 296 .acpi_match_table = ac_device_ids, 297 .pm = &acpi_ac_pm, 298 }, 299 }; 300 301 static int __init acpi_ac_init(void) 302 { 303 int result; 304 305 if (acpi_disabled) 306 return -ENODEV; 307 308 if (acpi_quirk_skip_acpi_ac_and_battery()) 309 return -ENODEV; 310 311 dmi_check_system(ac_dmi_table); 312 313 result = platform_driver_register(&acpi_ac_driver); 314 if (result < 0) 315 return -ENODEV; 316 317 return 0; 318 } 319 320 static void __exit acpi_ac_exit(void) 321 { 322 platform_driver_unregister(&acpi_ac_driver); 323 } 324 module_init(acpi_ac_init); 325 module_exit(acpi_ac_exit); 326