Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux/fpc-iii.git] / drivers / mfd / cros_ec_acpi_gpe.c
blob56d305dab2d487f7b07b8c9f5424320823aea03a
1 /*
2 * ChromeOS EC multi-function device
4 * Copyright (C) 2017 Google, Inc
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * The ChromeOS EC multi function device is used to mux all the requests
16 * to the EC device for its multiple features: keyboard controller,
17 * battery charging and regulator control, firmware update.
19 #include <linux/acpi.h>
21 #define ACPI_LID_DEVICE "LID0"
23 static int ec_wake_gpe = -EINVAL;
26 * This handler indicates to ACPI core that this GPE should stay enabled for
27 * lid to work in suspend to idle path.
29 static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
30 void *data)
32 return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
36 * Get ACPI GPE for LID0 device.
38 static int cros_ec_get_ec_wake_gpe(struct device *dev)
40 struct acpi_device *cros_acpi_dev;
41 struct acpi_device *adev;
42 acpi_handle handle;
43 acpi_status status;
44 int ret;
46 cros_acpi_dev = ACPI_COMPANION(dev);
48 if (!cros_acpi_dev || !cros_acpi_dev->parent ||
49 !cros_acpi_dev->parent->handle)
50 return -EINVAL;
52 status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
53 &handle);
54 if (ACPI_FAILURE(status))
55 return -EINVAL;
57 ret = acpi_bus_get_device(handle, &adev);
58 if (ret)
59 return ret;
61 return adev->wakeup.gpe_number;
64 int cros_ec_acpi_install_gpe_handler(struct device *dev)
66 acpi_status status;
68 ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
70 if (ec_wake_gpe < 0)
71 return ec_wake_gpe;
73 status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
74 ACPI_GPE_EDGE_TRIGGERED,
75 &cros_ec_gpe_handler, NULL);
76 if (ACPI_FAILURE(status))
77 return -ENODEV;
79 dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
81 return 0;
84 void cros_ec_acpi_remove_gpe_handler(void)
86 acpi_status status;
88 if (ec_wake_gpe < 0)
89 return;
91 status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
92 &cros_ec_gpe_handler);
93 if (ACPI_FAILURE(status))
94 pr_err("failed to remove gpe handler\n");
97 void cros_ec_acpi_clear_gpe(void)
99 if (ec_wake_gpe < 0)
100 return;
102 acpi_clear_gpe(NULL, ec_wake_gpe);