aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c107
1 files changed, 12 insertions, 95 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 9c7fce6a42e8..0f232e719daf 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -112,11 +112,6 @@ static struct acpi_ec *ec_ecdt;
112static struct acpi_device *first_ec; 112static struct acpi_device *first_ec;
113static int acpi_ec_mode = EC_INTR; 113static int acpi_ec_mode = EC_INTR;
114 114
115static void acpi_ec_gpe_poll_query(void *ec_cxt);
116static void acpi_ec_gpe_intr_query(void *ec_cxt);
117static u32 acpi_ec_gpe_poll_handler(void *data);
118static u32 acpi_ec_gpe_intr_handler(void *data);
119
120/* -------------------------------------------------------------------------- 115/* --------------------------------------------------------------------------
121 Transaction Management 116 Transaction Management
122 -------------------------------------------------------------------------- */ 117 -------------------------------------------------------------------------- */
@@ -428,21 +423,13 @@ static int acpi_ec_query(struct acpi_ec *ec, u32 * data)
428 Event Management 423 Event Management
429 -------------------------------------------------------------------------- */ 424 -------------------------------------------------------------------------- */
430 425
431union acpi_ec_query_data { 426struct acpi_ec_query_data {
432 acpi_handle handle; 427 acpi_handle handle;
433 u8 data; 428 u8 data;
434}; 429};
435 430
436static void acpi_ec_gpe_query(void *ec_cxt) 431static void acpi_ec_gpe_query(void *ec_cxt)
437{ 432{
438 if (acpi_ec_mode == EC_POLL)
439 acpi_ec_gpe_poll_query(ec_cxt);
440 else
441 acpi_ec_gpe_intr_query(ec_cxt);
442}
443
444static void acpi_ec_gpe_poll_query(void *ec_cxt)
445{
446 struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; 433 struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
447 u32 value = 0; 434 u32 value = 0;
448 static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; 435 static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
@@ -454,18 +441,8 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt)
454 if (!ec_cxt) 441 if (!ec_cxt)
455 goto end; 442 goto end;
456 443
457 if (down_interruptible (&ec->sem)) {
458 return;
459 }
460 value = acpi_ec_read_status(ec); 444 value = acpi_ec_read_status(ec);
461 up(&ec->sem);
462 445
463 /* TBD: Implement asynch events!
464 * NOTE: All we care about are EC-SCI's. Other EC events are
465 * handled via polling (yuck!). This is because some systems
466 * treat EC-SCIs as level (versus EDGE!) triggered, preventing
467 * a purely interrupt-driven approach (grumble, grumble).
468 */
469 if (!(value & ACPI_EC_FLAG_SCI)) 446 if (!(value & ACPI_EC_FLAG_SCI))
470 goto end; 447 goto end;
471 448
@@ -475,96 +452,36 @@ static void acpi_ec_gpe_poll_query(void *ec_cxt)
475 object_name[2] = hex[((value >> 4) & 0x0F)]; 452 object_name[2] = hex[((value >> 4) & 0x0F)];
476 object_name[3] = hex[(value & 0x0F)]; 453 object_name[3] = hex[(value & 0x0F)];
477 454
478 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); 455 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name));
479 456
480 acpi_evaluate_object(ec->handle, object_name, NULL, NULL); 457 acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
481 458
482 end: 459 end:
483 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); 460 acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR);
484} 461}
485static void acpi_ec_gpe_intr_query(void *ec_cxt)
486{
487 struct acpi_ec *ec = (struct acpi_ec *)ec_cxt;
488 u32 value;
489 int result = -ENODATA;
490 static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
491 const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
492 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
493 };
494
495
496 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI)
497 result = acpi_ec_query(ec, &value);
498
499 if (result)
500 goto end;
501
502 object_name[2] = hex[((value >> 4) & 0x0F)];
503 object_name[3] = hex[(value & 0x0F)];
504
505 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
506
507 acpi_evaluate_object(ec->handle, object_name, NULL, NULL);
508 end:
509 return;
510}
511 462
512static u32 acpi_ec_gpe_handler(void *data) 463static u32 acpi_ec_gpe_handler(void *data)
513{ 464{
514 if (acpi_ec_mode == EC_POLL)
515 return acpi_ec_gpe_poll_handler(data);
516 else
517 return acpi_ec_gpe_intr_handler(data);
518}
519static u32 acpi_ec_gpe_poll_handler(void *data)
520{
521 acpi_status status = AE_OK;
522 struct acpi_ec *ec = (struct acpi_ec *)data;
523
524 if (!ec)
525 return ACPI_INTERRUPT_NOT_HANDLED;
526
527 acpi_disable_gpe(NULL, ec->gpe_bit, ACPI_ISR);
528
529 status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec);
530
531 if (status == AE_OK)
532 return ACPI_INTERRUPT_HANDLED;
533 else
534 return ACPI_INTERRUPT_NOT_HANDLED;
535}
536static u32 acpi_ec_gpe_intr_handler(void *data)
537{
538 acpi_status status = AE_OK; 465 acpi_status status = AE_OK;
539 u32 value; 466 u32 value;
467 u8 exec_mode;
540 struct acpi_ec *ec = (struct acpi_ec *)data; 468 struct acpi_ec *ec = (struct acpi_ec *)data;
541 469
542 if (!ec)
543 return ACPI_INTERRUPT_NOT_HANDLED;
544
545 acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); 470 acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR);
546 value = acpi_ec_read_status(ec); 471 value = acpi_ec_read_status(ec);
547 472
548 switch (ec->expect_event) { 473 if (acpi_ec_mode == EC_INTR) {
549 case ACPI_EC_EVENT_OBF_1: 474 if (acpi_ec_check_status(value, ec->expect_event)) {
550 if (!(value & ACPI_EC_FLAG_OBF)) 475 ec->expect_event = 0;
551 break; 476 wake_up(&ec->wait);
552 ec->expect_event = 0; 477 }
553 wake_up(&ec->wait); 478 exec_mode = OSL_EC_BURST_HANDLER;
554 break; 479 } else {
555 case ACPI_EC_EVENT_IBF_0: 480 exec_mode = OSL_EC_POLL_HANDLER;
556 if ((value & ACPI_EC_FLAG_IBF))
557 break;
558 ec->expect_event = 0;
559 wake_up(&ec->wait);
560 break;
561 default:
562 break;
563 } 481 }
564 482
565 if (value & ACPI_EC_FLAG_SCI) { 483 if (value & ACPI_EC_FLAG_SCI) {
566 status = acpi_os_execute(OSL_EC_BURST_HANDLER, 484 status = acpi_os_execute(exec_mode, acpi_ec_gpe_query, ec);
567 acpi_ec_gpe_query, ec);
568 return status == AE_OK ? 485 return status == AE_OK ?
569 ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; 486 ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
570 } 487 }