2121#include "gpiolib.h"
2222#include "gpiolib-acpi.h"
2323
24- #define QUIRK_NO_EDGE_EVENTS_ON_BOOT 0x01l
25- #define QUIRK_NO_WAKEUP 0x02l
26-
2724static int run_edge_events_on_boot = -1 ;
2825module_param (run_edge_events_on_boot , int , 0444 );
2926MODULE_PARM_DESC (run_edge_events_on_boot ,
3027 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto" );
3128
32- static int honor_wakeup = -1 ;
33- module_param (honor_wakeup , int , 0444 );
34- MODULE_PARM_DESC (honor_wakeup ,
35- "Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto" );
29+ static char * ignore_wake ;
30+ module_param (ignore_wake , charp , 0444 );
31+ MODULE_PARM_DESC (ignore_wake ,
32+ "controller@pin combos on which to ignore the ACPI wake flag "
33+ "ignore_wake=controller@pin[,controller@pin[,...]]" );
34+
35+ struct acpi_gpiolib_dmi_quirk {
36+ bool no_edge_events_on_boot ;
37+ char * ignore_wake ;
38+ };
3639
3740/**
3841 * struct acpi_gpio_event - ACPI GPIO event handler data
@@ -202,6 +205,57 @@ static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
202205 acpi_gpiochip_request_irq (acpi_gpio , event );
203206}
204207
208+ static bool acpi_gpio_in_ignore_list (const char * controller_in , int pin_in )
209+ {
210+ const char * controller , * pin_str ;
211+ int len , pin ;
212+ char * endp ;
213+
214+ controller = ignore_wake ;
215+ while (controller ) {
216+ pin_str = strchr (controller , '@' );
217+ if (!pin_str )
218+ goto err ;
219+
220+ len = pin_str - controller ;
221+ if (len == strlen (controller_in ) &&
222+ strncmp (controller , controller_in , len ) == 0 ) {
223+ pin = simple_strtoul (pin_str + 1 , & endp , 10 );
224+ if (* endp != 0 && * endp != ',' )
225+ goto err ;
226+
227+ if (pin == pin_in )
228+ return true;
229+ }
230+
231+ controller = strchr (controller , ',' );
232+ if (controller )
233+ controller ++ ;
234+ }
235+
236+ return false;
237+ err :
238+ pr_err_once ("Error invalid value for gpiolib_acpi.ignore_wake: %s\n" ,
239+ ignore_wake );
240+ return false;
241+ }
242+
243+ static bool acpi_gpio_irq_is_wake (struct device * parent ,
244+ struct acpi_resource_gpio * agpio )
245+ {
246+ int pin = agpio -> pin_table [0 ];
247+
248+ if (agpio -> wake_capable != ACPI_WAKE_CAPABLE )
249+ return false;
250+
251+ if (acpi_gpio_in_ignore_list (dev_name (parent ), pin )) {
252+ dev_info (parent , "Ignoring wakeup on pin %d\n" , pin );
253+ return false;
254+ }
255+
256+ return true;
257+ }
258+
205259/* Always returns AE_OK so that we keep looping over the resources */
206260static acpi_status acpi_gpiochip_alloc_event (struct acpi_resource * ares ,
207261 void * context )
@@ -289,7 +343,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
289343 event -> handle = evt_handle ;
290344 event -> handler = handler ;
291345 event -> irq = irq ;
292- event -> irq_is_wake = honor_wakeup && agpio -> wake_capable == ACPI_WAKE_CAPABLE ;
346+ event -> irq_is_wake = acpi_gpio_irq_is_wake ( chip -> parent , agpio ) ;
293347 event -> pin = pin ;
294348 event -> desc = desc ;
295349
@@ -1328,7 +1382,9 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
13281382 DMI_MATCH (DMI_SYS_VENDOR , "MINIX" ),
13291383 DMI_MATCH (DMI_PRODUCT_NAME , "Z83-4" ),
13301384 },
1331- .driver_data = (void * )QUIRK_NO_EDGE_EVENTS_ON_BOOT ,
1385+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1386+ .no_edge_events_on_boot = true,
1387+ },
13321388 },
13331389 {
13341390 /*
@@ -1341,50 +1397,82 @@ static const struct dmi_system_id gpiolib_acpi_quirks[] = {
13411397 DMI_MATCH (DMI_SYS_VENDOR , "Wortmann_AG" ),
13421398 DMI_MATCH (DMI_PRODUCT_NAME , "TERRA_PAD_1061" ),
13431399 },
1344- .driver_data = (void * )QUIRK_NO_EDGE_EVENTS_ON_BOOT ,
1400+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1401+ .no_edge_events_on_boot = true,
1402+ },
13451403 },
13461404 {
13471405 /*
1348- * Various HP X2 10 Cherry Trail models use an external
1349- * embedded-controller connected via I2C + an ACPI GPIO
1350- * event handler. The embedded controller generates various
1351- * spurious wakeup events when suspended. So disable wakeup
1352- * for its handler (it uses the only ACPI GPIO event handler).
1353- * This breaks wakeup when opening the lid, the user needs
1406+ * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
1407+ * external embedded-controller connected via I2C + an ACPI GPIO
1408+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
1409+ * When suspending by closing the LID, the power to the USB
1410+ * keyboard is turned off, causing INT0002 ACPI events to
1411+ * trigger once the XHCI controller notices the keyboard is
1412+ * gone. So INT0002 events cause spurious wakeups too. Ignoring
1413+ * EC wakes breaks wakeup when opening the lid, the user needs
13541414 * to press the power-button to wakeup the system. The
13551415 * alternative is suspend simply not working, which is worse.
13561416 */
13571417 .matches = {
13581418 DMI_MATCH (DMI_SYS_VENDOR , "HP" ),
13591419 DMI_MATCH (DMI_PRODUCT_NAME , "HP x2 Detachable 10-p0XX" ),
13601420 },
1361- .driver_data = (void * )QUIRK_NO_WAKEUP ,
1421+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1422+ .ignore_wake = "INT33FF:01@0,INT0002:00@2" ,
1423+ },
1424+ },
1425+ {
1426+ /*
1427+ * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
1428+ * external embedded-controller connected via I2C + an ACPI GPIO
1429+ * event handler on INT33FC:02 pin 28, causing spurious wakeups.
1430+ */
1431+ .matches = {
1432+ DMI_MATCH (DMI_SYS_VENDOR , "Hewlett-Packard" ),
1433+ DMI_MATCH (DMI_PRODUCT_NAME , "HP Pavilion x2 Detachable" ),
1434+ DMI_MATCH (DMI_BOARD_NAME , "815D" ),
1435+ },
1436+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1437+ .ignore_wake = "INT33FC:02@28" ,
1438+ },
1439+ },
1440+ {
1441+ /*
1442+ * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
1443+ * external embedded-controller connected via I2C + an ACPI GPIO
1444+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
1445+ */
1446+ .matches = {
1447+ DMI_MATCH (DMI_SYS_VENDOR , "HP" ),
1448+ DMI_MATCH (DMI_PRODUCT_NAME , "HP Pavilion x2 Detachable" ),
1449+ DMI_MATCH (DMI_BOARD_NAME , "813E" ),
1450+ },
1451+ .driver_data = & (struct acpi_gpiolib_dmi_quirk ) {
1452+ .ignore_wake = "INT33FF:01@0" ,
1453+ },
13621454 },
13631455 {} /* Terminating entry */
13641456};
13651457
13661458static int acpi_gpio_setup_params (void )
13671459{
1460+ const struct acpi_gpiolib_dmi_quirk * quirk = NULL ;
13681461 const struct dmi_system_id * id ;
1369- long quirks = 0 ;
13701462
13711463 id = dmi_first_match (gpiolib_acpi_quirks );
13721464 if (id )
1373- quirks = ( long ) id -> driver_data ;
1465+ quirk = id -> driver_data ;
13741466
13751467 if (run_edge_events_on_boot < 0 ) {
1376- if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT )
1468+ if (quirk && quirk -> no_edge_events_on_boot )
13771469 run_edge_events_on_boot = 0 ;
13781470 else
13791471 run_edge_events_on_boot = 1 ;
13801472 }
13811473
1382- if (honor_wakeup < 0 ) {
1383- if (quirks & QUIRK_NO_WAKEUP )
1384- honor_wakeup = 0 ;
1385- else
1386- honor_wakeup = 1 ;
1387- }
1474+ if (ignore_wake == NULL && quirk && quirk -> ignore_wake )
1475+ ignore_wake = quirk -> ignore_wake ;
13881476
13891477 return 0 ;
13901478}
0 commit comments