aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2007-07-22 02:24:51 -0400
committerLen Brown <len.brown@intel.com>2007-07-22 02:24:51 -0400
commit2e85622042cb5fd56a606e884651ffde52f21028 (patch)
tree9a6d999b6fae1b4b7b59ea22db73851f7f254ae9
parentb43035a5ec4deecd43019728ab9347df82dd121f (diff)
parent837012ede14a8fc088be3682c964da7fc6af026b (diff)
Pull ec into release branch
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/acpi/ec.c247
2 files changed, 149 insertions, 104 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 773c732b4177..a9b9ef614ae7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -225,15 +225,15 @@ T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
225S: Supported 225S: Supported
226 226
227ACPI BATTERY DRIVERS 227ACPI BATTERY DRIVERS
228P: Vladimir P. Lebedev 228P: Alexey Starikovskiy
229M: vladimir.p.lebedev@intel.com 229M: astarikovskiy@suse.de
230L: linux-acpi@vger.kernel.org 230L: linux-acpi@vger.kernel.org
231W: http://acpi.sourceforge.net/ 231W: http://acpi.sourceforge.net/
232S: Supported 232S: Supported
233 233
234ACPI EC DRIVER 234ACPI EC DRIVER
235P: Alexey Starikovskiy 235P: Alexey Starikovskiy
236M: alexey.y.starikovskiy@linux.intel.com 236M: astarikovskiy@suse.de
237L: linux-acpi@vger.kernel.org 237L: linux-acpi@vger.kernel.org
238W: http://acpi.sourceforge.net/ 238W: http://acpi.sourceforge.net/
239S: Supported 239S: Supported
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 82f496c07675..10e851021eca 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -34,25 +34,26 @@
34#include <linux/proc_fs.h> 34#include <linux/proc_fs.h>
35#include <linux/seq_file.h> 35#include <linux/seq_file.h>
36#include <linux/interrupt.h> 36#include <linux/interrupt.h>
37#include <linux/list.h>
37#include <asm/io.h> 38#include <asm/io.h>
38#include <acpi/acpi_bus.h> 39#include <acpi/acpi_bus.h>
39#include <acpi/acpi_drivers.h> 40#include <acpi/acpi_drivers.h>
40#include <acpi/actypes.h> 41#include <acpi/actypes.h>
41 42
42#define _COMPONENT ACPI_EC_COMPONENT
43ACPI_MODULE_NAME("ec");
44#define ACPI_EC_COMPONENT 0x00100000
45#define ACPI_EC_CLASS "embedded_controller" 43#define ACPI_EC_CLASS "embedded_controller"
46#define ACPI_EC_HID "PNP0C09" 44#define ACPI_EC_HID "PNP0C09"
47#define ACPI_EC_DEVICE_NAME "Embedded Controller" 45#define ACPI_EC_DEVICE_NAME "Embedded Controller"
48#define ACPI_EC_FILE_INFO "info" 46#define ACPI_EC_FILE_INFO "info"
47
49#undef PREFIX 48#undef PREFIX
50#define PREFIX "ACPI: EC: " 49#define PREFIX "ACPI: EC: "
50
51/* EC status register */ 51/* EC status register */
52#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ 52#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
53#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ 53#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
54#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ 54#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
55#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ 55#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
56
56/* EC commands */ 57/* EC commands */
57enum ec_command { 58enum ec_command {
58 ACPI_EC_COMMAND_READ = 0x80, 59 ACPI_EC_COMMAND_READ = 0x80,
@@ -61,6 +62,7 @@ enum ec_command {
61 ACPI_EC_BURST_DISABLE = 0x83, 62 ACPI_EC_BURST_DISABLE = 0x83,
62 ACPI_EC_COMMAND_QUERY = 0x84, 63 ACPI_EC_COMMAND_QUERY = 0x84,
63}; 64};
65
64/* EC events */ 66/* EC events */
65enum ec_event { 67enum ec_event {
66 ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ 68 ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */
@@ -94,6 +96,16 @@ static struct acpi_driver acpi_ec_driver = {
94 96
95/* If we find an EC via the ECDT, we need to keep a ptr to its context */ 97/* If we find an EC via the ECDT, we need to keep a ptr to its context */
96/* External interfaces use first EC only, so remember */ 98/* External interfaces use first EC only, so remember */
99typedef int (*acpi_ec_query_func) (void *data);
100
101struct acpi_ec_query_handler {
102 struct list_head node;
103 acpi_ec_query_func func;
104 acpi_handle handle;
105 void *data;
106 u8 query_bit;
107};
108
97static struct acpi_ec { 109static struct acpi_ec {
98 acpi_handle handle; 110 acpi_handle handle;
99 unsigned long gpe; 111 unsigned long gpe;
@@ -104,6 +116,7 @@ static struct acpi_ec {
104 atomic_t query_pending; 116 atomic_t query_pending;
105 atomic_t event_count; 117 atomic_t event_count;
106 wait_queue_head_t wait; 118 wait_queue_head_t wait;
119 struct list_head list;
107} *boot_ec, *first_ec; 120} *boot_ec, *first_ec;
108 121
109/* -------------------------------------------------------------------------- 122/* --------------------------------------------------------------------------
@@ -245,7 +258,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
245 258
246 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); 259 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
247 if (status) { 260 if (status) {
248 printk(KERN_DEBUG PREFIX 261 printk(KERN_ERR PREFIX
249 "input buffer is not empty, aborting transaction\n"); 262 "input buffer is not empty, aborting transaction\n");
250 goto end; 263 goto end;
251 } 264 }
@@ -394,21 +407,67 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
394/* -------------------------------------------------------------------------- 407/* --------------------------------------------------------------------------
395 Event Management 408 Event Management
396 -------------------------------------------------------------------------- */ 409 -------------------------------------------------------------------------- */
410int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
411 acpi_handle handle, acpi_ec_query_func func,
412 void *data)
413{
414 struct acpi_ec_query_handler *handler =
415 kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
416 if (!handler)
417 return -ENOMEM;
418
419 handler->query_bit = query_bit;
420 handler->handle = handle;
421 handler->func = func;
422 handler->data = data;
423 mutex_lock(&ec->lock);
424 list_add_tail(&handler->node, &ec->list);
425 mutex_unlock(&ec->lock);
426 return 0;
427}
428
429EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
430
431void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
432{
433 struct acpi_ec_query_handler *handler;
434 mutex_lock(&ec->lock);
435 list_for_each_entry(handler, &ec->list, node) {
436 if (query_bit == handler->query_bit) {
437 list_del(&handler->node);
438 kfree(handler);
439 break;
440 }
441 }
442 mutex_unlock(&ec->lock);
443}
444
445EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
397 446
398static void acpi_ec_gpe_query(void *ec_cxt) 447static void acpi_ec_gpe_query(void *ec_cxt)
399{ 448{
400 struct acpi_ec *ec = ec_cxt; 449 struct acpi_ec *ec = ec_cxt;
401 u8 value = 0; 450 u8 value = 0;
402 char object_name[8]; 451 struct acpi_ec_query_handler *handler, copy;
403 452
404 if (!ec || acpi_ec_query(ec, &value)) 453 if (!ec || acpi_ec_query(ec, &value))
405 return; 454 return;
406 455 mutex_lock(&ec->lock);
407 snprintf(object_name, 8, "_Q%2.2X", value); 456 list_for_each_entry(handler, &ec->list, node) {
408 457 if (value == handler->query_bit) {
409 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); 458 /* have custom handler for this bit */
410 459 memcpy(&copy, handler, sizeof(copy));
411 acpi_evaluate_object(ec->handle, object_name, NULL, NULL); 460 mutex_unlock(&ec->lock);
461 if (copy.func) {
462 copy.func(copy.data);
463 } else if (copy.handle) {
464 acpi_evaluate_object(copy.handle, NULL, NULL, NULL);
465 }
466 return;
467 }
468 }
469 mutex_unlock(&ec->lock);
470 printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
412} 471}
413 472
414static u32 acpi_ec_gpe_handler(void *data) 473static u32 acpi_ec_gpe_handler(void *data)
@@ -427,8 +486,7 @@ static u32 acpi_ec_gpe_handler(void *data)
427 if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { 486 if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) {
428 atomic_set(&ec->query_pending, 1); 487 atomic_set(&ec->query_pending, 1);
429 status = 488 status =
430 acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, 489 acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec);
431 ec);
432 } 490 }
433 491
434 return status == AE_OK ? 492 return status == AE_OK ?
@@ -454,57 +512,35 @@ acpi_ec_space_setup(acpi_handle region_handle,
454} 512}
455 513
456static acpi_status 514static acpi_status
457acpi_ec_space_handler(u32 function, 515acpi_ec_space_handler(u32 function, acpi_physical_address address,
458 acpi_physical_address address, 516 u32 bits, acpi_integer *value,
459 u32 bit_width,
460 acpi_integer * value,
461 void *handler_context, void *region_context) 517 void *handler_context, void *region_context)
462{ 518{
463 int result = 0;
464 struct acpi_ec *ec = handler_context; 519 struct acpi_ec *ec = handler_context;
465 u64 temp = *value; 520 int result = 0, i = 0;
466 acpi_integer f_v = 0; 521 u8 temp = 0;
467 int i = 0;
468 522
469 if ((address > 0xFF) || !value || !handler_context) 523 if ((address > 0xFF) || !value || !handler_context)
470 return AE_BAD_PARAMETER; 524 return AE_BAD_PARAMETER;
471 525
472 if (bit_width != 8 && acpi_strict) { 526 if (function != ACPI_READ && function != ACPI_WRITE)
473 return AE_BAD_PARAMETER; 527 return AE_BAD_PARAMETER;
474 }
475
476 next_byte:
477 switch (function) {
478 case ACPI_READ:
479 temp = 0;
480 result = acpi_ec_read(ec, (u8) address, (u8 *) & temp);
481 break;
482 case ACPI_WRITE:
483 result = acpi_ec_write(ec, (u8) address, (u8) temp);
484 break;
485 default:
486 result = -EINVAL;
487 goto out;
488 break;
489 }
490 528
491 bit_width -= 8; 529 if (bits != 8 && acpi_strict)
492 if (bit_width) { 530 return AE_BAD_PARAMETER;
493 if (function == ACPI_READ)
494 f_v |= temp << 8 * i;
495 if (function == ACPI_WRITE)
496 temp >>= 8;
497 i++;
498 address++;
499 goto next_byte;
500 }
501 531
502 if (function == ACPI_READ) { 532 while (bits - i > 0) {
503 f_v |= temp << 8 * i; 533 if (function == ACPI_READ) {
504 *value = f_v; 534 result = acpi_ec_read(ec, address, &temp);
535 (*value) |= ((acpi_integer)temp) << i;
536 } else {
537 temp = 0xff & ((*value) >> i);
538 result = acpi_ec_write(ec, address, temp);
539 }
540 i += 8;
541 ++address;
505 } 542 }
506 543
507 out:
508 switch (result) { 544 switch (result) {
509 case -EINVAL: 545 case -EINVAL:
510 return AE_BAD_PARAMETER; 546 return AE_BAD_PARAMETER;
@@ -597,9 +633,6 @@ static int acpi_ec_remove_fs(struct acpi_device *device)
597static acpi_status 633static acpi_status
598ec_parse_io_ports(struct acpi_resource *resource, void *context); 634ec_parse_io_ports(struct acpi_resource *resource, void *context);
599 635
600static acpi_status
601ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval);
602
603static struct acpi_ec *make_acpi_ec(void) 636static struct acpi_ec *make_acpi_ec(void)
604{ 637{
605 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); 638 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
@@ -610,13 +643,52 @@ static struct acpi_ec *make_acpi_ec(void)
610 atomic_set(&ec->event_count, 1); 643 atomic_set(&ec->event_count, 1);
611 mutex_init(&ec->lock); 644 mutex_init(&ec->lock);
612 init_waitqueue_head(&ec->wait); 645 init_waitqueue_head(&ec->wait);
646 INIT_LIST_HEAD(&ec->list);
613 647
614 return ec; 648 return ec;
615} 649}
616 650
651static acpi_status
652acpi_ec_register_query_methods(acpi_handle handle, u32 level,
653 void *context, void **return_value)
654{
655 struct acpi_namespace_node *node = handle;
656 struct acpi_ec *ec = context;
657 int value = 0;
658 if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
659 acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
660 }
661 return AE_OK;
662}
663
664static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle)
665{
666 if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS,
667 ec_parse_io_ports, ec)))
668 return -EINVAL;
669
670 /* Get GPE bit assignment (EC events). */
671 /* TODO: Add support for _GPE returning a package */
672 if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe)))
673 return -EINVAL;
674
675 /* Use the global lock for all EC transactions? */
676 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
677
678 /* Find and register all query methods */
679 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
680 acpi_ec_register_query_methods, ec, NULL);
681
682 ec->handle = handle;
683
684 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx",
685 ec->gpe, ec->command_addr, ec->data_addr);
686
687 return 0;
688}
689
617static int acpi_ec_add(struct acpi_device *device) 690static int acpi_ec_add(struct acpi_device *device)
618{ 691{
619 acpi_status status = AE_OK;
620 struct acpi_ec *ec = NULL; 692 struct acpi_ec *ec = NULL;
621 693
622 if (!device) 694 if (!device)
@@ -629,8 +701,7 @@ static int acpi_ec_add(struct acpi_device *device)
629 if (!ec) 701 if (!ec)
630 return -ENOMEM; 702 return -ENOMEM;
631 703
632 status = ec_parse_device(device->handle, 0, ec, NULL); 704 if (ec_parse_device(ec, device->handle)) {
633 if (status != AE_CTRL_TERMINATE) {
634 kfree(ec); 705 kfree(ec);
635 return -EINVAL; 706 return -EINVAL;
636 } 707 }
@@ -641,6 +712,8 @@ static int acpi_ec_add(struct acpi_device *device)
641 /* We might have incorrect info for GL at boot time */ 712 /* We might have incorrect info for GL at boot time */
642 mutex_lock(&boot_ec->lock); 713 mutex_lock(&boot_ec->lock);
643 boot_ec->global_lock = ec->global_lock; 714 boot_ec->global_lock = ec->global_lock;
715 /* Copy handlers from new ec into boot ec */
716 list_splice(&ec->list, &boot_ec->list);
644 mutex_unlock(&boot_ec->lock); 717 mutex_unlock(&boot_ec->lock);
645 kfree(ec); 718 kfree(ec);
646 ec = boot_ec; 719 ec = boot_ec;
@@ -651,22 +724,24 @@ static int acpi_ec_add(struct acpi_device *device)
651 acpi_driver_data(device) = ec; 724 acpi_driver_data(device) = ec;
652 725
653 acpi_ec_add_fs(device); 726 acpi_ec_add_fs(device);
654
655 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.",
656 acpi_device_name(device), acpi_device_bid(device),
657 (u32) ec->gpe));
658
659 return 0; 727 return 0;
660} 728}
661 729
662static int acpi_ec_remove(struct acpi_device *device, int type) 730static int acpi_ec_remove(struct acpi_device *device, int type)
663{ 731{
664 struct acpi_ec *ec; 732 struct acpi_ec *ec;
733 struct acpi_ec_query_handler *handler;
665 734
666 if (!device) 735 if (!device)
667 return -EINVAL; 736 return -EINVAL;
668 737
669 ec = acpi_driver_data(device); 738 ec = acpi_driver_data(device);
739 mutex_lock(&ec->lock);
740 list_for_each_entry(handler, &ec->list, node) {
741 list_del(&handler->node);
742 kfree(handler);
743 }
744 mutex_unlock(&ec->lock);
670 acpi_ec_remove_fs(device); 745 acpi_ec_remove_fs(device);
671 acpi_driver_data(device) = NULL; 746 acpi_driver_data(device) = NULL;
672 if (ec == first_ec) 747 if (ec == first_ec)
@@ -722,15 +797,13 @@ static int ec_install_handlers(struct acpi_ec *ec)
722 return -ENODEV; 797 return -ENODEV;
723 } 798 }
724 799
725 /* EC is fully operational, allow queries */
726 atomic_set(&ec->query_pending, 0);
727
728 return 0; 800 return 0;
729} 801}
730 802
731static int acpi_ec_start(struct acpi_device *device) 803static int acpi_ec_start(struct acpi_device *device)
732{ 804{
733 struct acpi_ec *ec; 805 struct acpi_ec *ec;
806 int ret = 0;
734 807
735 if (!device) 808 if (!device)
736 return -EINVAL; 809 return -EINVAL;
@@ -740,14 +813,14 @@ static int acpi_ec_start(struct acpi_device *device)
740 if (!ec) 813 if (!ec)
741 return -EINVAL; 814 return -EINVAL;
742 815
743 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx",
744 ec->gpe, ec->command_addr, ec->data_addr));
745
746 /* Boot EC is already working */ 816 /* Boot EC is already working */
747 if (ec == boot_ec) 817 if (ec != boot_ec)
748 return 0; 818 ret = ec_install_handlers(ec);
819
820 /* EC is fully operational, allow queries */
821 atomic_set(&ec->query_pending, 0);
749 822
750 return ec_install_handlers(ec); 823 return ret;
751} 824}
752 825
753static int acpi_ec_stop(struct acpi_device *device, int type) 826static int acpi_ec_stop(struct acpi_device *device, int type)
@@ -779,34 +852,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
779 return 0; 852 return 0;
780} 853}
781 854
782static acpi_status
783ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
784{
785 acpi_status status;
786
787 struct acpi_ec *ec = context;
788 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
789 ec_parse_io_ports, ec);
790 if (ACPI_FAILURE(status))
791 return status;
792
793 /* Get GPE bit assignment (EC events). */
794 /* TODO: Add support for _GPE returning a package */
795 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
796 if (ACPI_FAILURE(status))
797 return status;
798
799 /* Use the global lock for all EC transactions? */
800 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
801
802 ec->handle = handle;
803
804 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx",
805 ec->gpe, ec->command_addr, ec->data_addr));
806
807 return AE_CTRL_TERMINATE;
808}
809
810int __init acpi_ec_ecdt_probe(void) 855int __init acpi_ec_ecdt_probe(void)
811{ 856{
812 int ret; 857 int ret;
@@ -825,7 +870,7 @@ int __init acpi_ec_ecdt_probe(void)
825 if (ACPI_FAILURE(status)) 870 if (ACPI_FAILURE(status))
826 goto error; 871 goto error;
827 872
828 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); 873 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n");
829 874
830 boot_ec->command_addr = ecdt_ptr->control.address; 875 boot_ec->command_addr = ecdt_ptr->control.address;
831 boot_ec->data_addr = ecdt_ptr->data.address; 876 boot_ec->data_addr = ecdt_ptr->data.address;