xref: /linux/drivers/gpio/gpiolib-acpi-quirks.c (revision aacc73ceeb8bf664426f0e53db2778a59325bd9f)
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