1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * ACPI quirks for GPIO ACPI helpers
4 *
5 * Author: Hans de Goede <hdegoede@redhat.com>
6 */
7
8 #include <linux/dmi.h>
9 #include <linux/kstrtox.h>
10 #include <linux/list.h>
11 #include <linux/module.h>
12 #include <linux/mutex.h>
13 #include <linux/printk.h>
14 #include <linux/string.h>
15 #include <linux/types.h>
16
17 #include "gpiolib-acpi.h"
18
19 static int run_edge_events_on_boot = -1;
20 module_param(run_edge_events_on_boot, int, 0444);
21 MODULE_PARM_DESC(run_edge_events_on_boot,
22 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
23
24 static char *ignore_wake;
25 module_param(ignore_wake, charp, 0444);
26 MODULE_PARM_DESC(ignore_wake,
27 "controller@pin combos on which to ignore the ACPI wake flag "
28 "ignore_wake=controller@pin[,controller@pin[,...]]");
29
30 static char *ignore_interrupt;
31 module_param(ignore_interrupt, charp, 0444);
32 MODULE_PARM_DESC(ignore_interrupt,
33 "controller@pin combos on which to ignore interrupt "
34 "ignore_interrupt=controller@pin[,controller@pin[,...]]");
35
36 /*
37 * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init
38 * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a
39 * late_initcall_sync() handler, so that other builtin drivers can register their
40 * OpRegions before the event handlers can run. This list contains GPIO chips
41 * for which the acpi_gpiochip_request_irqs() call has been deferred.
42 */
43 static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock);
44 static LIST_HEAD(acpi_gpio_deferred_req_irqs_list);
45 static bool acpi_gpio_deferred_req_irqs_done;
46
acpi_gpio_add_to_deferred_list(struct list_head * list)47 bool acpi_gpio_add_to_deferred_list(struct list_head *list)
48 {
49 bool defer;
50
51 mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
52 defer = !acpi_gpio_deferred_req_irqs_done;
53 if (defer)
54 list_add(list, &acpi_gpio_deferred_req_irqs_list);
55 mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
56
57 return defer;
58 }
59
acpi_gpio_remove_from_deferred_list(struct list_head * list)60 void acpi_gpio_remove_from_deferred_list(struct list_head *list)
61 {
62 mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
63 if (!list_empty(list))
64 list_del_init(list);
65 mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
66 }
67
acpi_gpio_need_run_edge_events_on_boot(void)68 int acpi_gpio_need_run_edge_events_on_boot(void)
69 {
70 return run_edge_events_on_boot;
71 }
72
acpi_gpio_in_ignore_list(enum acpi_gpio_ignore_list list,const char * controller_in,unsigned int pin_in)73 bool acpi_gpio_in_ignore_list(enum acpi_gpio_ignore_list list,
74 const char *controller_in, unsigned int pin_in)
75 {
76 const char *ignore_list, *controller, *pin_str;
77 unsigned int pin;
78 char *endp;
79 int len;
80
81 switch (list) {
82 case ACPI_GPIO_IGNORE_WAKE:
83 ignore_list = ignore_wake;
84 break;
85 case ACPI_GPIO_IGNORE_INTERRUPT:
86 ignore_list = ignore_interrupt;
87 break;
88 default:
89 return false;
90 }
91
92 controller = ignore_list;
93 while (controller) {
94 pin_str = strchr(controller, '@');
95 if (!pin_str)
96 goto err;
97
98 len = pin_str - controller;
99 if (len == strlen(controller_in) &&
100 strncmp(controller, controller_in, len) == 0) {
101 pin = simple_strtoul(pin_str + 1, &endp, 10);
102 if (*endp != 0 && *endp != ',')
103 goto err;
104
105 if (pin == pin_in)
106 return true;
107 }
108
109 controller = strchr(controller, ',');
110 if (controller)
111 controller++;
112 }
113
114 return false;
115 err:
116 pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_...: %s\n", ignore_list);
117 return false;
118 }
119
120 /* Run deferred acpi_gpiochip_request_irqs() */
acpi_gpio_handle_deferred_request_irqs(void)121 static int __init acpi_gpio_handle_deferred_request_irqs(void)
122 {
123 mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
124 acpi_gpio_process_deferred_list(&acpi_gpio_deferred_req_irqs_list);
125 acpi_gpio_deferred_req_irqs_done = true;
126 mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
127
128 return 0;
129 }
130 /* We must use _sync so that this runs after the first deferred_probe run */
131 late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
132
133 struct acpi_gpiolib_dmi_quirk {
134 bool no_edge_events_on_boot;
135 char *ignore_wake;
136 char *ignore_interrupt;
137 };
138
139 static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
140 {
141 /*
142 * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
143 * a non existing micro-USB-B connector which puts the HDMI
144 * DDC pins in GPIO mode, breaking HDMI support.
145 */
146 .matches = {
147 DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
148 DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
149 },
150 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
151 .no_edge_events_on_boot = true,
152 },
153 },
154 {
155 /*
156 * The Terra Pad 1061 has a micro-USB-B id-pin handler, which
157 * instead of controlling the actual micro-USB-B turns the 5V
158 * boost for its USB-A connector off. The actual micro-USB-B
159 * connector is wired for charging only.
160 */
161 .matches = {
162 DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
163 DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
164 },
165 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
166 .no_edge_events_on_boot = true,
167 },
168 },
169 {
170 /*
171 * The Dell Venue 10 Pro 5055, with Bay Trail SoC + TI PMIC uses an
172 * external embedded-controller connected via I2C + an ACPI GPIO
173 * event handler on INT33FFC:02 pin 12, causing spurious wakeups.
174 */
175 .matches = {
176 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
177 DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
178 },
179 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
180 .ignore_wake = "INT33FC:02@12",
181 },
182 },
183 {
184 /*
185 * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
186 * external embedded-controller connected via I2C + an ACPI GPIO
187 * event handler on INT33FF:01 pin 0, causing spurious wakeups.
188 * When suspending by closing the LID, the power to the USB
189 * keyboard is turned off, causing INT0002 ACPI events to
190 * trigger once the XHCI controller notices the keyboard is
191 * gone. So INT0002 events cause spurious wakeups too. Ignoring
192 * EC wakes breaks wakeup when opening the lid, the user needs
193 * to press the power-button to wakeup the system. The
194 * alternative is suspend simply not working, which is worse.
195 */
196 .matches = {
197 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
198 DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
199 },
200 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
201 .ignore_wake = "INT33FF:01@0,INT0002:00@2",
202 },
203 },
204 {
205 /*
206 * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
207 * external embedded-controller connected via I2C + an ACPI GPIO
208 * event handler on INT33FC:02 pin 28, causing spurious wakeups.
209 */
210 .matches = {
211 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
212 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
213 DMI_MATCH(DMI_BOARD_NAME, "815D"),
214 },
215 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
216 .ignore_wake = "INT33FC:02@28",
217 },
218 },
219 {
220 /*
221 * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
222 * external embedded-controller connected via I2C + an ACPI GPIO
223 * event handler on INT33FF:01 pin 0, causing spurious wakeups.
224 */
225 .matches = {
226 DMI_MATCH(DMI_SYS_VENDOR, "HP"),
227 DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
228 DMI_MATCH(DMI_BOARD_NAME, "813E"),
229 },
230 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
231 .ignore_wake = "INT33FF:01@0",
232 },
233 },
234 {
235 /*
236 * Interrupt storm caused from edge triggered floating pin
237 * Found in BIOS UX325UAZ.300
238 * https://bugzilla.kernel.org/show_bug.cgi?id=216208
239 */
240 .matches = {
241 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
242 DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UAZ_UM325UAZ"),
243 },
244 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
245 .ignore_interrupt = "AMDI0030:00@18",
246 },
247 },
248 {
249 /*
250 * Spurious wakeups from TP_ATTN# pin
251 * Found in BIOS 1.7.8
252 * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
253 */
254 .matches = {
255 DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
256 },
257 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
258 .ignore_wake = "ELAN0415:00@9",
259 },
260 },
261 {
262 /*
263 * Spurious wakeups from TP_ATTN# pin
264 * Found in BIOS 1.7.8
265 * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
266 */
267 .matches = {
268 DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
269 },
270 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
271 .ignore_wake = "ELAN0415:00@9",
272 },
273 },
274 {
275 /*
276 * Spurious wakeups from TP_ATTN# pin
277 * Found in BIOS 1.7.7
278 */
279 .matches = {
280 DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
281 },
282 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
283 .ignore_wake = "SYNA1202:00@16",
284 },
285 },
286 {
287 /*
288 * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to
289 * a "dolby" button. At the ACPI level an _AEI event-handler
290 * is connected which sets an ACPI variable to 1 on both
291 * edges. This variable can be polled + cleared to 0 using
292 * WMI. But since the variable is set on both edges the WMI
293 * interface is pretty useless even when polling.
294 * So instead the x86-android-tablets code instantiates
295 * a gpio-keys platform device for it.
296 * Ignore the _AEI handler for the pin, so that it is not busy.
297 */
298 .matches = {
299 DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
300 DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
301 },
302 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
303 .ignore_interrupt = "INT33FC:00@3",
304 },
305 },
306 {
307 /*
308 * Spurious wakeups from TP_ATTN# pin
309 * Found in BIOS 0.35
310 * https://gitlab.freedesktop.org/drm/amd/-/issues/3073
311 */
312 .matches = {
313 DMI_MATCH(DMI_SYS_VENDOR, "GPD"),
314 DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"),
315 },
316 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
317 .ignore_wake = "PNP0C50:00@8",
318 },
319 },
320 {
321 /*
322 * Spurious wakeups from GPIO 11
323 * Found in BIOS 1.04
324 * https://gitlab.freedesktop.org/drm/amd/-/issues/3954
325 */
326 .matches = {
327 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
328 DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"),
329 },
330 .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
331 .ignore_interrupt = "AMDI0030:00@11",
332 },
333 },
334 {} /* Terminating entry */
335 };
336
acpi_gpio_setup_params(void)337 static int __init acpi_gpio_setup_params(void)
338 {
339 const struct acpi_gpiolib_dmi_quirk *quirk = NULL;
340 const struct dmi_system_id *id;
341
342 id = dmi_first_match(gpiolib_acpi_quirks);
343 if (id)
344 quirk = id->driver_data;
345
346 if (run_edge_events_on_boot < 0) {
347 if (quirk && quirk->no_edge_events_on_boot)
348 run_edge_events_on_boot = 0;
349 else
350 run_edge_events_on_boot = 1;
351 }
352
353 if (ignore_wake == NULL && quirk && quirk->ignore_wake)
354 ignore_wake = quirk->ignore_wake;
355
356 if (ignore_interrupt == NULL && quirk && quirk->ignore_interrupt)
357 ignore_interrupt = quirk->ignore_interrupt;
358
359 return 0;
360 }
361
362 /* Directly after dmi_setup() which runs as core_initcall() */
363 postcore_initcall(acpi_gpio_setup_params);
364