summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorLuming Yu <luming.yu@intel.com>2005-09-27 06:43:00 +0200
committerLen Brown <len.brown@intel.com>2005-12-02 03:00:53 +0100
commit06a2a3855e20ed3df380d69b37130ba86bec8001 (patch)
treefc413825ef15496af219a527cbf0d21d9deff4f3 /drivers/acpi/ec.c
parentLinux v2.6.15-rc4 (diff)
downloadlinux-06a2a3855e20ed3df380d69b37130ba86bec8001.tar.xz
linux-06a2a3855e20ed3df380d69b37130ba86bec8001.zip
[ACPI] Disable EC burst mode w/o disabling EC interrupts
Need to de-couple the concept of polling/interrupts vs burst/non-burst. http://bugzilla.kernel.org/show_bug.cgi?id=4980 Signed-off-by: Luming Yu <luming.yu@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c36
1 files changed, 20 insertions, 16 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 7e1a445955bc..6edfbe6f187c 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -213,19 +213,14 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
smp_mb();
switch (event) {
- case ACPI_EC_EVENT_OBF:
- if (acpi_ec_read_status(ec) & event) {
- ec->burst.expect_event = 0;
- return_VALUE(0);
- }
- break;
-
case ACPI_EC_EVENT_IBE:
if (~acpi_ec_read_status(ec) & event) {
ec->burst.expect_event = 0;
return_VALUE(0);
}
break;
+ default:
+ break;
}
result = wait_event_timeout(ec->burst.wait,
@@ -255,7 +250,11 @@ static int acpi_ec_burst_wait(union acpi_ec *ec, unsigned int event)
return_VALUE(-ETIME);
}
-static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
+/*
+ * Note: samsung nv5000 doesn't work with ec burst mode.
+ * http://bugzilla.kernel.org/show_bug.cgi?id=4980
+ */
+int acpi_ec_enter_burst_mode(union acpi_ec *ec)
{
u32 tmp = 0;
int status = 0;
@@ -270,8 +269,6 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
&ec->common.command_addr);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
- if (status)
- return_VALUE(-EINVAL);
acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
if (tmp != 0x90) { /* Burst ACK byte */
return_VALUE(-EINVAL);
@@ -285,13 +282,25 @@ static int acpi_ec_enter_burst_mode(union acpi_ec *ec)
return_VALUE(-1);
}
-static int acpi_ec_leave_burst_mode(union acpi_ec *ec)
+int acpi_ec_leave_burst_mode(union acpi_ec *ec)
{
+ int status = 0;
ACPI_FUNCTION_TRACE("acpi_ec_leave_burst_mode");
+ status = acpi_ec_read_status(ec);
+ if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
+ status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ if(status)
+ goto end;
+ acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
+ acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
+ }
atomic_set(&ec->burst.leaving_burst, 1);
return_VALUE(0);
+end:
+ printk("leave burst_mode:error \n");
+ return_VALUE(-1);
}
static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
@@ -424,7 +433,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- acpi_ec_enter_burst_mode(ec);
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
printk("read EC, IB not empty\n");
@@ -448,7 +456,6 @@ static int acpi_ec_burst_read(union acpi_ec *ec, u8 address, u32 * data)
*data, address));
end:
- acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)
@@ -476,8 +483,6 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
WARN_ON(in_interrupt());
down(&ec->burst.sem);
- acpi_ec_enter_burst_mode(ec);
-
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
if (status) {
printk("write EC, IB not empty\n");
@@ -500,7 +505,6 @@ static int acpi_ec_burst_write(union acpi_ec *ec, u8 address, u8 data)
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n",
data, address));
- acpi_ec_leave_burst_mode(ec);
up(&ec->burst.sem);
if (ec->common.global_lock)