1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/acpi.h>
20
21#define ACPI_LID_DEVICE "LID0"
22
23static int ec_wake_gpe = -EINVAL;
24
25
26
27
28
29static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
30 void *data)
31{
32 return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
33}
34
35
36
37
38static int cros_ec_get_ec_wake_gpe(struct device *dev)
39{
40 struct acpi_device *cros_acpi_dev;
41 struct acpi_device *adev;
42 acpi_handle handle;
43 acpi_status status;
44 int ret;
45
46 cros_acpi_dev = ACPI_COMPANION(dev);
47
48 if (!cros_acpi_dev || !cros_acpi_dev->parent ||
49 !cros_acpi_dev->parent->handle)
50 return -EINVAL;
51
52 status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
53 &handle);
54 if (ACPI_FAILURE(status))
55 return -EINVAL;
56
57 ret = acpi_bus_get_device(handle, &adev);
58 if (ret)
59 return ret;
60
61 return adev->wakeup.gpe_number;
62}
63
64int cros_ec_acpi_install_gpe_handler(struct device *dev)
65{
66 acpi_status status;
67
68 ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
69
70 if (ec_wake_gpe < 0)
71 return ec_wake_gpe;
72
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;
78
79 dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
80
81 return 0;
82}
83
84void cros_ec_acpi_remove_gpe_handler(void)
85{
86 acpi_status status;
87
88 if (ec_wake_gpe < 0)
89 return;
90
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");
95}
96
97void cros_ec_acpi_clear_gpe(void)
98{
99 if (ec_wake_gpe < 0)
100 return;
101
102 acpi_clear_gpe(NULL, ec_wake_gpe);
103}
104