diff options
| -rw-r--r-- | drivers/acpi/ec.c | 124 |
1 files changed, 45 insertions, 79 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 0f232e719daf..ae05e8c11480 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -72,7 +72,7 @@ enum { | |||
| 72 | 72 | ||
| 73 | enum { | 73 | enum { |
| 74 | EC_INTR = 1, /* Output buffer full */ | 74 | EC_INTR = 1, /* Output buffer full */ |
| 75 | EC_POLL, /* Input buffer empty */ | 75 | EC_POLL, /* Input buffer empty */ |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static int acpi_ec_remove(struct acpi_device *device, int type); | 78 | static int acpi_ec_remove(struct acpi_device *device, int type); |
| @@ -91,22 +91,20 @@ static struct acpi_driver acpi_ec_driver = { | |||
| 91 | .stop = acpi_ec_stop, | 91 | .stop = acpi_ec_stop, |
| 92 | }, | 92 | }, |
| 93 | }; | 93 | }; |
| 94 | |||
| 95 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | ||
| 94 | struct acpi_ec { | 96 | struct acpi_ec { |
| 95 | acpi_handle handle; | 97 | acpi_handle handle; |
| 96 | unsigned long uid; | 98 | unsigned long uid; |
| 97 | unsigned long gpe_bit; | 99 | unsigned long gpe_bit; |
| 98 | struct acpi_generic_address status_addr; | 100 | unsigned long command_addr; |
| 99 | struct acpi_generic_address command_addr; | 101 | unsigned long data_addr; |
| 100 | struct acpi_generic_address data_addr; | ||
| 101 | unsigned long global_lock; | 102 | unsigned long global_lock; |
| 102 | struct semaphore sem; | 103 | struct semaphore sem; |
| 103 | unsigned int expect_event; | 104 | unsigned int expect_event; |
| 104 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ | 105 | atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ |
| 105 | wait_queue_head_t wait; | 106 | wait_queue_head_t wait; |
| 106 | }; | 107 | } *ec_ecdt; |
| 107 | |||
| 108 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | ||
| 109 | static struct acpi_ec *ec_ecdt; | ||
| 110 | 108 | ||
| 111 | /* External interfaces use first EC only, so remember */ | 109 | /* External interfaces use first EC only, so remember */ |
| 112 | static struct acpi_device *first_ec; | 110 | static struct acpi_device *first_ec; |
| @@ -116,34 +114,28 @@ static int acpi_ec_mode = EC_INTR; | |||
| 116 | Transaction Management | 114 | Transaction Management |
| 117 | -------------------------------------------------------------------------- */ | 115 | -------------------------------------------------------------------------- */ |
| 118 | 116 | ||
| 119 | static u32 acpi_ec_read_status(struct acpi_ec *ec) | 117 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
| 120 | { | 118 | { |
| 121 | u32 status = 0; | 119 | return inb(ec->command_addr); |
| 122 | |||
| 123 | acpi_hw_low_level_read(8, &status, &ec->status_addr); | ||
| 124 | return status; | ||
| 125 | } | 120 | } |
| 126 | 121 | ||
| 127 | static u32 acpi_ec_read_data(struct acpi_ec *ec) | 122 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
| 128 | { | 123 | { |
| 129 | u32 data = 0; | 124 | return inb(ec->data_addr); |
| 130 | |||
| 131 | acpi_hw_low_level_read(8, &data, &ec->data_addr); | ||
| 132 | return data; | ||
| 133 | } | 125 | } |
| 134 | 126 | ||
| 135 | static void acpi_ec_write_cmd(struct acpi_ec *ec, u32 command) | 127 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
| 136 | { | 128 | { |
| 137 | acpi_hw_low_level_write(8, command, &ec->command_addr); | 129 | outb(command, ec->command_addr); |
| 138 | } | 130 | } |
| 139 | 131 | ||
| 140 | static void acpi_ec_write_data(struct acpi_ec *ec, u32 data) | 132 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
| 141 | { | 133 | { |
| 142 | acpi_hw_low_level_write(8, data, &ec->data_addr); | 134 | outb(data, ec->data_addr); |
| 143 | } | 135 | } |
| 144 | 136 | ||
| 145 | static int acpi_ec_check_status(u32 status, u8 event) { | 137 | static int acpi_ec_check_status(u8 status, u8 event) |
| 146 | 138 | { | |
| 147 | switch (event) { | 139 | switch (event) { |
| 148 | case ACPI_EC_EVENT_OBF_1: | 140 | case ACPI_EC_EVENT_OBF_1: |
| 149 | if (status & ACPI_EC_FLAG_OBF) | 141 | if (status & ACPI_EC_FLAG_OBF) |
| @@ -201,8 +193,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, u8 event) | |||
| 201 | */ | 193 | */ |
| 202 | int acpi_ec_enter_burst_mode(struct acpi_ec *ec) | 194 | int acpi_ec_enter_burst_mode(struct acpi_ec *ec) |
| 203 | { | 195 | { |
| 204 | u32 tmp = 0; | 196 | u8 tmp = 0; |
| 205 | u32 status = 0; | 197 | u8 status = 0; |
| 206 | 198 | ||
| 207 | 199 | ||
| 208 | status = acpi_ec_read_status(ec); | 200 | status = acpi_ec_read_status(ec); |
| @@ -227,7 +219,7 @@ int acpi_ec_enter_burst_mode(struct acpi_ec *ec) | |||
| 227 | 219 | ||
| 228 | int acpi_ec_leave_burst_mode(struct acpi_ec *ec) | 220 | int acpi_ec_leave_burst_mode(struct acpi_ec *ec) |
| 229 | { | 221 | { |
| 230 | u32 status = 0; | 222 | u8 status = 0; |
| 231 | 223 | ||
| 232 | 224 | ||
| 233 | status = acpi_ec_read_status(ec); | 225 | status = acpi_ec_read_status(ec); |
| @@ -268,14 +260,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
| 268 | } | 260 | } |
| 269 | 261 | ||
| 270 | for (; rdata_len > 0; rdata_len --) { | 262 | for (; rdata_len > 0; rdata_len --) { |
| 271 | u32 d; | ||
| 272 | |||
| 273 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); | 263 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); |
| 274 | if (result) | 264 | if (result) |
| 275 | return result; | 265 | return result; |
| 276 | 266 | ||
| 277 | d = acpi_ec_read_data(ec); | 267 | *(rdata++) = acpi_ec_read_data(ec); |
| 278 | *(rdata++) = (u8) d; | ||
| 279 | } | 268 | } |
| 280 | 269 | ||
| 281 | return 0; | 270 | return 0; |
| @@ -320,7 +309,7 @@ end: | |||
| 320 | return status; | 309 | return status; |
| 321 | } | 310 | } |
| 322 | 311 | ||
| 323 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u32 * data) | 312 | static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) |
| 324 | { | 313 | { |
| 325 | int result; | 314 | int result; |
| 326 | u8 d; | 315 | u8 d; |
| @@ -330,6 +319,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u32 * data) | |||
| 330 | *data = d; | 319 | *data = d; |
| 331 | return result; | 320 | return result; |
| 332 | } | 321 | } |
| 322 | |||
| 333 | static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) | 323 | static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) |
| 334 | { | 324 | { |
| 335 | u8 wdata[2] = { address, data }; | 325 | u8 wdata[2] = { address, data }; |
| @@ -340,11 +330,11 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) | |||
| 340 | /* | 330 | /* |
| 341 | * Externally callable EC access functions. For now, assume 1 EC only | 331 | * Externally callable EC access functions. For now, assume 1 EC only |
| 342 | */ | 332 | */ |
| 343 | int ec_read(u8 addr, u8 * val) | 333 | int ec_read(u8 addr, u8 *val) |
| 344 | { | 334 | { |
| 345 | struct acpi_ec *ec; | 335 | struct acpi_ec *ec; |
| 346 | int err; | 336 | int err; |
| 347 | u32 temp_data; | 337 | u8 temp_data; |
| 348 | 338 | ||
| 349 | if (!first_ec) | 339 | if (!first_ec) |
| 350 | return -ENODEV; | 340 | return -ENODEV; |
| @@ -394,7 +384,7 @@ extern int ec_transaction(u8 command, | |||
| 394 | wdata_len, rdata, rdata_len); | 384 | wdata_len, rdata, rdata_len); |
| 395 | } | 385 | } |
| 396 | 386 | ||
| 397 | static int acpi_ec_query(struct acpi_ec *ec, u32 * data) | 387 | static int acpi_ec_query(struct acpi_ec *ec, u8 *data) |
| 398 | { | 388 | { |
| 399 | int result; | 389 | int result; |
| 400 | u8 d; | 390 | u8 d; |
| @@ -431,14 +421,10 @@ struct acpi_ec_query_data { | |||
| 431 | static void acpi_ec_gpe_query(void *ec_cxt) | 421 | static void acpi_ec_gpe_query(void *ec_cxt) |
| 432 | { | 422 | { |
| 433 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; | 423 | struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; |
| 434 | u32 value = 0; | 424 | u8 value = 0; |
| 435 | static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; | 425 | static char object_name[8]; |
| 436 | const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', | ||
| 437 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||
| 438 | }; | ||
| 439 | |||
| 440 | 426 | ||
| 441 | if (!ec_cxt) | 427 | if (!ec) |
| 442 | goto end; | 428 | goto end; |
| 443 | 429 | ||
| 444 | value = acpi_ec_read_status(ec); | 430 | value = acpi_ec_read_status(ec); |
| @@ -449,8 +435,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) | |||
| 449 | if (acpi_ec_query(ec, &value)) | 435 | if (acpi_ec_query(ec, &value)) |
| 450 | goto end; | 436 | goto end; |
| 451 | 437 | ||
| 452 | object_name[2] = hex[((value >> 4) & 0x0F)]; | 438 | snprintf(object_name, 8, "_Q%2.2X", value); |
| 453 | object_name[3] = hex[(value & 0x0F)]; | ||
| 454 | 439 | ||
| 455 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); | 440 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); |
| 456 | 441 | ||
| @@ -463,8 +448,7 @@ static void acpi_ec_gpe_query(void *ec_cxt) | |||
| 463 | static u32 acpi_ec_gpe_handler(void *data) | 448 | static u32 acpi_ec_gpe_handler(void *data) |
| 464 | { | 449 | { |
| 465 | acpi_status status = AE_OK; | 450 | acpi_status status = AE_OK; |
| 466 | u32 value; | 451 | u8 value; |
| 467 | u8 exec_mode; | ||
| 468 | struct acpi_ec *ec = (struct acpi_ec *)data; | 452 | struct acpi_ec *ec = (struct acpi_ec *)data; |
| 469 | 453 | ||
| 470 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); | 454 | acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); |
| @@ -475,13 +459,10 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 475 | ec->expect_event = 0; | 459 | ec->expect_event = 0; |
| 476 | wake_up(&ec->wait); | 460 | wake_up(&ec->wait); |
| 477 | } | 461 | } |
| 478 | exec_mode = OSL_EC_BURST_HANDLER; | ||
| 479 | } else { | ||
| 480 | exec_mode = OSL_EC_POLL_HANDLER; | ||
| 481 | } | 462 | } |
| 482 | 463 | ||
| 483 | if (value & ACPI_EC_FLAG_SCI) { | 464 | if (value & ACPI_EC_FLAG_SCI) { |
| 484 | status = acpi_os_execute(exec_mode, acpi_ec_gpe_query, ec); | 465 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); |
| 485 | return status == AE_OK ? | 466 | return status == AE_OK ? |
| 486 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 467 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
| 487 | } | 468 | } |
| @@ -535,7 +516,7 @@ acpi_ec_space_handler(u32 function, | |||
| 535 | switch (function) { | 516 | switch (function) { |
| 536 | case ACPI_READ: | 517 | case ACPI_READ: |
| 537 | temp = 0; | 518 | temp = 0; |
| 538 | result = acpi_ec_read(ec, (u8) address, (u32 *) & temp); | 519 | result = acpi_ec_read(ec, (u8) address, (u8 *) &temp); |
| 539 | break; | 520 | break; |
| 540 | case ACPI_WRITE: | 521 | case ACPI_WRITE: |
| 541 | result = acpi_ec_write(ec, (u8) address, (u8) temp); | 522 | result = acpi_ec_write(ec, (u8) address, (u8) temp); |
| @@ -595,8 +576,8 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset) | |||
| 595 | seq_printf(seq, "gpe bit: 0x%02x\n", | 576 | seq_printf(seq, "gpe bit: 0x%02x\n", |
| 596 | (u32) ec->gpe_bit); | 577 | (u32) ec->gpe_bit); |
| 597 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", | 578 | seq_printf(seq, "ports: 0x%02x, 0x%02x\n", |
| 598 | (u32) ec->status_addr.address, | 579 | (u32) ec->command_addr, |
| 599 | (u32) ec->data_addr.address); | 580 | (u32) ec->data_addr); |
| 600 | seq_printf(seq, "use global lock: %s\n", | 581 | seq_printf(seq, "use global lock: %s\n", |
| 601 | ec->global_lock ? "yes" : "no"); | 582 | ec->global_lock ? "yes" : "no"); |
| 602 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); | 583 | acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); |
| @@ -752,7 +733,6 @@ static acpi_status | |||
| 752 | acpi_ec_io_ports(struct acpi_resource *resource, void *context) | 733 | acpi_ec_io_ports(struct acpi_resource *resource, void *context) |
| 753 | { | 734 | { |
| 754 | struct acpi_ec *ec = (struct acpi_ec *)context; | 735 | struct acpi_ec *ec = (struct acpi_ec *)context; |
| 755 | struct acpi_generic_address *addr; | ||
| 756 | 736 | ||
| 757 | if (resource->type != ACPI_RESOURCE_TYPE_IO) { | 737 | if (resource->type != ACPI_RESOURCE_TYPE_IO) { |
| 758 | return AE_OK; | 738 | return AE_OK; |
| @@ -763,19 +743,14 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context) | |||
| 763 | * the second address region returned is the status/command | 743 | * the second address region returned is the status/command |
| 764 | * port. | 744 | * port. |
| 765 | */ | 745 | */ |
| 766 | if (ec->data_addr.register_bit_width == 0) { | 746 | if (ec->data_addr == 0) { |
| 767 | addr = &ec->data_addr; | 747 | ec->data_addr = resource->data.io.minimum; |
| 768 | } else if (ec->command_addr.register_bit_width == 0) { | 748 | } else if (ec->command_addr == 0) { |
| 769 | addr = &ec->command_addr; | 749 | ec->command_addr = resource->data.io.minimum; |
| 770 | } else { | 750 | } else { |
| 771 | return AE_CTRL_TERMINATE; | 751 | return AE_CTRL_TERMINATE; |
| 772 | } | 752 | } |
| 773 | 753 | ||
| 774 | addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; | ||
| 775 | addr->register_bit_width = 8; | ||
| 776 | addr->register_bit_offset = 0; | ||
| 777 | addr->address = resource->data.io.minimum; | ||
| 778 | |||
| 779 | return AE_OK; | 754 | return AE_OK; |
| 780 | } | 755 | } |
| 781 | 756 | ||
| @@ -798,19 +773,14 @@ static int acpi_ec_start(struct acpi_device *device) | |||
| 798 | */ | 773 | */ |
| 799 | status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, | 774 | status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, |
| 800 | acpi_ec_io_ports, ec); | 775 | acpi_ec_io_ports, ec); |
| 801 | if (ACPI_FAILURE(status) | 776 | if (ACPI_FAILURE(status) || ec->command_addr == 0) { |
| 802 | || ec->command_addr.register_bit_width == 0) { | ||
| 803 | ACPI_EXCEPTION((AE_INFO, status, | 777 | ACPI_EXCEPTION((AE_INFO, status, |
| 804 | "Error getting I/O port addresses")); | 778 | "Error getting I/O port addresses")); |
| 805 | return -ENODEV; | 779 | return -ENODEV; |
| 806 | } | 780 | } |
| 807 | 781 | ||
| 808 | ec->status_addr = ec->command_addr; | 782 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", |
| 809 | 783 | ec->gpe_bit, ec->command_addr, ec->data_addr)); | |
| 810 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x", | ||
| 811 | (u32) ec->gpe_bit, | ||
| 812 | (u32) ec->command_addr.address, | ||
| 813 | (u32) ec->data_addr.address)); | ||
| 814 | 784 | ||
| 815 | /* | 785 | /* |
| 816 | * Install GPE handler | 786 | * Install GPE handler |
| @@ -877,7 +847,6 @@ acpi_fake_ecdt_callback(acpi_handle handle, | |||
| 877 | acpi_ec_io_ports, ec_ecdt); | 847 | acpi_ec_io_ports, ec_ecdt); |
| 878 | if (ACPI_FAILURE(status)) | 848 | if (ACPI_FAILURE(status)) |
| 879 | return status; | 849 | return status; |
| 880 | ec_ecdt->status_addr = ec_ecdt->command_addr; | ||
| 881 | 850 | ||
| 882 | ec_ecdt->uid = -1; | 851 | ec_ecdt->uid = -1; |
| 883 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); | 852 | acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); |
| @@ -890,10 +859,8 @@ acpi_fake_ecdt_callback(acpi_handle handle, | |||
| 890 | ec_ecdt->global_lock = TRUE; | 859 | ec_ecdt->global_lock = TRUE; |
| 891 | ec_ecdt->handle = handle; | 860 | ec_ecdt->handle = handle; |
| 892 | 861 | ||
| 893 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02x, ports=0x%2x, 0x%2x", | 862 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", |
| 894 | (u32) ec_ecdt->gpe_bit, | 863 | ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr)); |
| 895 | (u32) ec_ecdt->command_addr.address, | ||
| 896 | (u32) ec_ecdt->data_addr.address)); | ||
| 897 | 864 | ||
| 898 | return AE_CTRL_TERMINATE; | 865 | return AE_CTRL_TERMINATE; |
| 899 | } | 866 | } |
| @@ -961,9 +928,8 @@ static int __init acpi_ec_get_real_ecdt(void) | |||
| 961 | if (acpi_ec_mode == EC_INTR) { | 928 | if (acpi_ec_mode == EC_INTR) { |
| 962 | init_waitqueue_head(&ec_ecdt->wait); | 929 | init_waitqueue_head(&ec_ecdt->wait); |
| 963 | } | 930 | } |
| 964 | ec_ecdt->command_addr = ecdt_ptr->ec_control; | 931 | ec_ecdt->command_addr = ecdt_ptr->ec_control.address; |
| 965 | ec_ecdt->status_addr = ecdt_ptr->ec_control; | 932 | ec_ecdt->data_addr = ecdt_ptr->ec_data.address; |
| 966 | ec_ecdt->data_addr = ecdt_ptr->ec_data; | ||
| 967 | ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; | 933 | ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; |
| 968 | /* use the GL just to be safe */ | 934 | /* use the GL just to be safe */ |
| 969 | ec_ecdt->global_lock = TRUE; | 935 | ec_ecdt->global_lock = TRUE; |
