Lines 1-7
Link Here
|
1 |
/* |
1 |
/* |
2 |
* ec.c - ACPI Embedded Controller Driver (v2.0) |
2 |
* ec.c - ACPI Embedded Controller Driver (v2.0) |
3 |
* |
3 |
* |
4 |
* Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> |
4 |
* Copyright (C) 2006 - 2008 Alexey Starikovskiy <astarikovskiy@suse.de> |
5 |
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com> |
5 |
* Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com> |
6 |
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com> |
6 |
* Copyright (C) 2004 Luming Yu <luming.yu@intel.com> |
7 |
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
7 |
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
Lines 73-86
enum ec_event {
Link Here
|
73 |
|
73 |
|
74 |
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
74 |
#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
75 |
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
75 |
#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
76 |
#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ |
|
|
77 |
|
76 |
|
78 |
enum { |
77 |
enum { |
79 |
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ |
78 |
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ |
80 |
EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
79 |
EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
81 |
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ |
80 |
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ |
82 |
EC_FLAGS_NO_GPE, /* Don't use GPE mode */ |
81 |
EC_FLAGS_NO_GPE, /* Don't use GPE mode */ |
83 |
EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ |
82 |
EC_FLAGS_GPE_STORM, /* GPE storm during transaction detected */ |
84 |
}; |
83 |
}; |
85 |
|
84 |
|
86 |
/* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
85 |
/* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
Lines 105-111
static struct acpi_ec {
Link Here
|
105 |
struct mutex lock; |
104 |
struct mutex lock; |
106 |
wait_queue_head_t wait; |
105 |
wait_queue_head_t wait; |
107 |
struct list_head list; |
106 |
struct list_head list; |
108 |
struct delayed_work work; |
|
|
109 |
atomic_t irq_count; |
107 |
atomic_t irq_count; |
110 |
u8 handlers_installed; |
108 |
u8 handlers_installed; |
111 |
} *boot_ec, *first_ec; |
109 |
} *boot_ec, *first_ec; |
Lines 155-175
static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
Link Here
|
155 |
return 0; |
153 |
return 0; |
156 |
} |
154 |
} |
157 |
|
155 |
|
158 |
static void ec_schedule_ec_poll(struct acpi_ec *ec) |
|
|
159 |
{ |
160 |
if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) |
161 |
schedule_delayed_work(&ec->work, |
162 |
msecs_to_jiffies(ACPI_EC_DELAY)); |
163 |
} |
164 |
|
165 |
static void ec_switch_to_poll_mode(struct acpi_ec *ec) |
156 |
static void ec_switch_to_poll_mode(struct acpi_ec *ec) |
166 |
{ |
157 |
{ |
167 |
set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
158 |
set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
168 |
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
159 |
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
169 |
acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
|
|
170 |
set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); |
171 |
} |
160 |
} |
172 |
|
161 |
|
|
|
162 |
static void acpi_ec_gpe_query(void *ec_cxt); |
163 |
|
173 |
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
164 |
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
174 |
{ |
165 |
{ |
175 |
atomic_set(&ec->irq_count, 0); |
166 |
atomic_set(&ec->irq_count, 0); |
Lines 185-191
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
Link Here
|
185 |
pr_info(PREFIX "missing confirmations, " |
176 |
pr_info(PREFIX "missing confirmations, " |
186 |
"switch off interrupt mode.\n"); |
177 |
"switch off interrupt mode.\n"); |
187 |
ec_switch_to_poll_mode(ec); |
178 |
ec_switch_to_poll_mode(ec); |
188 |
ec_schedule_ec_poll(ec); |
|
|
189 |
return 0; |
179 |
return 0; |
190 |
} |
180 |
} |
191 |
} else { |
181 |
} else { |
Lines 196-201
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
Link Here
|
196 |
return 0; |
186 |
return 0; |
197 |
msleep(1); |
187 |
msleep(1); |
198 |
} |
188 |
} |
|
|
189 |
if ((acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) && |
190 |
(!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))) |
191 |
acpi_os_execute(OSL_EC_BURST_HANDLER, |
192 |
acpi_ec_gpe_query, ec); |
199 |
} |
193 |
} |
200 |
pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
194 |
pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
201 |
acpi_ec_read_status(ec), |
195 |
acpi_ec_read_status(ec), |
Lines 468-473
static void acpi_ec_gpe_query(void *ec_cxt)
Link Here
|
468 |
if (!ec || acpi_ec_query(ec, &value)) |
462 |
if (!ec || acpi_ec_query(ec, &value)) |
469 |
return; |
463 |
return; |
470 |
mutex_lock(&ec->lock); |
464 |
mutex_lock(&ec->lock); |
|
|
465 |
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) |
466 |
acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
471 |
list_for_each_entry(handler, &ec->list, node) { |
467 |
list_for_each_entry(handler, &ec->list, node) { |
472 |
if (value == handler->query_bit) { |
468 |
if (value == handler->query_bit) { |
473 |
/* have custom handler for this bit */ |
469 |
/* have custom handler for this bit */ |
Lines 488-533
static u32 acpi_ec_gpe_handler(void *data)
Link Here
|
488 |
{ |
484 |
{ |
489 |
acpi_status status = AE_OK; |
485 |
acpi_status status = AE_OK; |
490 |
struct acpi_ec *ec = data; |
486 |
struct acpi_ec *ec = data; |
491 |
u8 state = acpi_ec_read_status(ec); |
|
|
492 |
|
487 |
|
493 |
pr_debug(PREFIX "~~~> interrupt\n"); |
488 |
pr_debug(PREFIX "~~~> interrupt\n"); |
494 |
atomic_inc(&ec->irq_count); |
489 |
atomic_inc(&ec->irq_count); |
495 |
if (atomic_read(&ec->irq_count) > 5) { |
490 |
if (atomic_read(&ec->irq_count) > 5 && |
|
|
491 |
!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
496 |
pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); |
492 |
pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); |
497 |
ec_switch_to_poll_mode(ec); |
493 |
set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
498 |
goto end; |
494 |
goto end; |
499 |
} |
495 |
} |
500 |
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
496 |
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
501 |
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) |
497 |
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) |
502 |
wake_up(&ec->wait); |
498 |
wake_up(&ec->wait); |
503 |
|
499 |
|
504 |
if (state & ACPI_EC_FLAG_SCI) { |
500 |
if ((acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) && |
505 |
if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) |
501 |
(!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))) { |
506 |
status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
502 |
status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
507 |
acpi_ec_gpe_query, ec); |
503 |
acpi_ec_gpe_query, ec); |
|
|
504 |
if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { |
505 |
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
506 |
acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR); |
507 |
} |
508 |
} else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
508 |
} else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
509 |
!test_bit(EC_FLAGS_NO_GPE, &ec->flags) && |
509 |
!test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { |
510 |
in_interrupt()) { |
|
|
511 |
/* this is non-query, must be confirmation */ |
510 |
/* this is non-query, must be confirmation */ |
512 |
if (printk_ratelimit()) |
511 |
if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags) && |
|
|
512 |
printk_ratelimit()) |
513 |
pr_info(PREFIX "non-query interrupt received," |
513 |
pr_info(PREFIX "non-query interrupt received," |
514 |
" switching to interrupt mode\n"); |
514 |
" switching to interrupt mode\n"); |
515 |
set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
515 |
set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
516 |
clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); |
|
|
517 |
} |
516 |
} |
518 |
end: |
517 |
end: |
519 |
ec_schedule_ec_poll(ec); |
|
|
520 |
return ACPI_SUCCESS(status) ? |
518 |
return ACPI_SUCCESS(status) ? |
521 |
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
519 |
ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
522 |
} |
520 |
} |
523 |
|
521 |
|
524 |
static void do_ec_poll(struct work_struct *work) |
|
|
525 |
{ |
526 |
struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); |
527 |
atomic_set(&ec->irq_count, 0); |
528 |
(void)acpi_ec_gpe_handler(ec); |
529 |
} |
530 |
|
531 |
/* -------------------------------------------------------------------------- |
522 |
/* -------------------------------------------------------------------------- |
532 |
Address Space Management |
523 |
Address Space Management |
533 |
-------------------------------------------------------------------------- */ |
524 |
-------------------------------------------------------------------------- */ |
Lines 669-675
static struct acpi_ec *make_acpi_ec(void)
Link Here
|
669 |
mutex_init(&ec->lock); |
660 |
mutex_init(&ec->lock); |
670 |
init_waitqueue_head(&ec->wait); |
661 |
init_waitqueue_head(&ec->wait); |
671 |
INIT_LIST_HEAD(&ec->list); |
662 |
INIT_LIST_HEAD(&ec->list); |
672 |
INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); |
|
|
673 |
atomic_set(&ec->irq_count, 0); |
663 |
atomic_set(&ec->irq_count, 0); |
674 |
return ec; |
664 |
return ec; |
675 |
} |
665 |
} |
Lines 709-723
ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
Link Here
|
709 |
return AE_CTRL_TERMINATE; |
699 |
return AE_CTRL_TERMINATE; |
710 |
} |
700 |
} |
711 |
|
701 |
|
712 |
static void ec_poll_stop(struct acpi_ec *ec) |
|
|
713 |
{ |
714 |
clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); |
715 |
cancel_delayed_work(&ec->work); |
716 |
} |
717 |
|
718 |
static void ec_remove_handlers(struct acpi_ec *ec) |
702 |
static void ec_remove_handlers(struct acpi_ec *ec) |
719 |
{ |
703 |
{ |
720 |
ec_poll_stop(ec); |
|
|
721 |
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
704 |
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
722 |
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) |
705 |
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) |
723 |
pr_err(PREFIX "failed to remove space handler\n"); |
706 |
pr_err(PREFIX "failed to remove space handler\n"); |
Lines 860-866
static int acpi_ec_start(struct acpi_device *device)
Link Here
|
860 |
|
843 |
|
861 |
/* EC is fully operational, allow queries */ |
844 |
/* EC is fully operational, allow queries */ |
862 |
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
845 |
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
863 |
ec_schedule_ec_poll(ec); |
|
|
864 |
return ret; |
846 |
return ret; |
865 |
} |
847 |
} |
866 |
|
848 |
|