diff options
Diffstat (limited to 'drivers/acpi/ec.c')
-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; |