]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/acpi/ec.c
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[linux-2.6-omap-h63xx.git] / drivers / acpi / ec.c
index 187981a3e8811b6e45c0dd812bd1725976dbecca..82f496c07675c66e3cf76020cfbf81fc3dc4139f 100644 (file)
@@ -1,6 +1,8 @@
 /*
- *  acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
+ *  ec.c - ACPI Embedded Controller Driver (v2.0)
  *
+ *  Copyright (C) 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
+ *  Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com>
  *  Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
@@ -94,7 +96,6 @@ static struct acpi_driver acpi_ec_driver = {
 /* External interfaces use first EC only, so remember */
 static struct acpi_ec {
        acpi_handle handle;
-       unsigned long uid;
        unsigned long gpe;
        unsigned long command_addr;
        unsigned long data_addr;
@@ -146,9 +147,10 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
        return 0;
 }
 
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event,
+                        unsigned count, int force_poll)
 {
-       if (acpi_ec_mode == EC_POLL) {
+       if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) {
                unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
                while (time_before(jiffies, delay)) {
                        if (acpi_ec_check_status(ec, event, 0))
@@ -172,14 +174,15 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
 
 static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
                                        const u8 * wdata, unsigned wdata_len,
-                                       u8 * rdata, unsigned rdata_len)
+                                       u8 * rdata, unsigned rdata_len,
+                                       int force_poll)
 {
        int result = 0;
        unsigned count = atomic_read(&ec->event_count);
        acpi_ec_write_cmd(ec, command);
 
        for (; wdata_len > 0; --wdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
                if (result) {
                        printk(KERN_ERR PREFIX
                               "write_cmd timeout, command = %d\n", command);
@@ -190,7 +193,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
        }
 
        if (!rdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
                if (result) {
                        printk(KERN_ERR PREFIX
                               "finish-write timeout, command = %d\n", command);
@@ -201,7 +204,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
        }
 
        for (; rdata_len > 0; --rdata_len) {
-               result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count);
+               result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll);
                if (result) {
                        printk(KERN_ERR PREFIX "read timeout, command = %d\n",
                               command);
@@ -216,7 +219,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 
 static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
                               const u8 * wdata, unsigned wdata_len,
-                              u8 * rdata, unsigned rdata_len)
+                              u8 * rdata, unsigned rdata_len,
+                              int force_poll)
 {
        int status;
        u32 glk;
@@ -239,7 +243,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
        /* Make sure GPE is enabled before doing transaction */
        acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
-       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
+       status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
        if (status) {
                printk(KERN_DEBUG PREFIX
                       "input buffer is not empty, aborting transaction\n");
@@ -248,7 +252,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
 
        status = acpi_ec_transaction_unlocked(ec, command,
                                              wdata, wdata_len,
-                                             rdata, rdata_len);
+                                             rdata, rdata_len,
+                                             force_poll);
 
       end:
 
@@ -266,12 +271,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
 int acpi_ec_burst_enable(struct acpi_ec *ec)
 {
        u8 d;
-       return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1);
+       return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
 }
 
 int acpi_ec_burst_disable(struct acpi_ec *ec)
 {
-       return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0);
+       return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
 }
 
 static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@@ -280,7 +285,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
        u8 d;
 
        result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
-                                    &address, 1, &d, 1);
+                                    &address, 1, &d, 1, 0);
        *data = d;
        return result;
 }
@@ -289,7 +294,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
 {
        u8 wdata[2] = { address, data };
        return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
-                                  wdata, 2, NULL, 0);
+                                  wdata, 2, NULL, 0, 0);
 }
 
 /*
@@ -348,13 +353,15 @@ EXPORT_SYMBOL(ec_write);
 
 int ec_transaction(u8 command,
                   const u8 * wdata, unsigned wdata_len,
-                  u8 * rdata, unsigned rdata_len)
+                  u8 * rdata, unsigned rdata_len,
+                  int force_poll)
 {
        if (!first_ec)
                return -ENODEV;
 
        return acpi_ec_transaction(first_ec, command, wdata,
-                                  wdata_len, rdata, rdata_len);
+                                  wdata_len, rdata, rdata_len,
+                                  force_poll);
 }
 
 EXPORT_SYMBOL(ec_transaction);
@@ -373,7 +380,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
         * bit to be cleared (and thus clearing the interrupt source).
         */
 
-       result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+       result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
        if (result)
                return result;
 
@@ -409,6 +416,7 @@ static u32 acpi_ec_gpe_handler(void *data)
        acpi_status status = AE_OK;
        u8 value;
        struct acpi_ec *ec = data;
+
        atomic_inc(&ec->event_count);
 
        if (acpi_ec_mode == EC_INTR) {
@@ -525,13 +533,11 @@ static int acpi_ec_read_info(struct seq_file *seq, void *offset)
        if (!ec)
                goto end;
 
-       seq_printf(seq, "gpe:                 0x%02x\n", (u32) ec->gpe);
-       seq_printf(seq, "ports:                   0x%02x, 0x%02x\n",
-                  (u32) ec->command_addr, (u32) ec->data_addr);
-       seq_printf(seq, "use global lock:         %s\n",
+       seq_printf(seq, "gpe:\t\t\t0x%02x\n", (u32) ec->gpe);
+       seq_printf(seq, "ports:\t\t\t0x%02x, 0x%02x\n",
+                  (unsigned)ec->command_addr, (unsigned)ec->data_addr);
+       seq_printf(seq, "use global lock:\t%s\n",
                   ec->global_lock ? "yes" : "no");
-       acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
-
       end:
        return 0;
 }
@@ -600,7 +606,7 @@ static struct acpi_ec *make_acpi_ec(void)
        if (!ec)
                return NULL;
 
-       atomic_set(&ec->query_pending, 0);
+       atomic_set(&ec->query_pending, 1);
        atomic_set(&ec->event_count, 1);
        mutex_init(&ec->lock);
        init_waitqueue_head(&ec->wait);
@@ -655,15 +661,13 @@ static int acpi_ec_add(struct acpi_device *device)
 
 static int acpi_ec_remove(struct acpi_device *device, int type)
 {
-       struct acpi_ec *ec = NULL;
+       struct acpi_ec *ec;
 
        if (!device)
                return -EINVAL;
 
        ec = acpi_driver_data(device);
-
        acpi_ec_remove_fs(device);
-
        acpi_driver_data(device) = NULL;
        if (ec == first_ec)
                first_ec = NULL;
@@ -671,7 +675,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
        /* Don't touch boot EC */
        if (boot_ec != ec)
                kfree(ec);
-
        return 0;
 }
 
@@ -680,22 +683,20 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context)
 {
        struct acpi_ec *ec = context;
 
-       if (resource->type != ACPI_RESOURCE_TYPE_IO) {
+       if (resource->type != ACPI_RESOURCE_TYPE_IO)
                return AE_OK;
-       }
 
        /*
         * The first address region returned is the data port, and
         * the second address region returned is the status/command
         * port.
         */
-       if (ec->data_addr == 0) {
+       if (ec->data_addr == 0)
                ec->data_addr = resource->data.io.minimum;
-       } else if (ec->command_addr == 0) {
+       else if (ec->command_addr == 0)
                ec->command_addr = resource->data.io.minimum;
-       } else {
+       else
                return AE_CTRL_TERMINATE;
-       }
 
        return AE_OK;
 }
@@ -708,6 +709,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
                                          &acpi_ec_gpe_handler, ec);
        if (ACPI_FAILURE(status))
                return -ENODEV;
+
        acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME);
        acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
@@ -720,6 +722,9 @@ static int ec_install_handlers(struct acpi_ec *ec)
                return -ENODEV;
        }
 
+       /* EC is fully operational, allow queries */
+       atomic_set(&ec->query_pending, 0);
+
        return 0;
 }
 
@@ -825,7 +830,6 @@ int __init acpi_ec_ecdt_probe(void)
        boot_ec->command_addr = ecdt_ptr->control.address;
        boot_ec->data_addr = ecdt_ptr->data.address;
        boot_ec->gpe = ecdt_ptr->gpe;
-       boot_ec->uid = ecdt_ptr->uid;
        boot_ec->handle = ACPI_ROOT_OBJECT;
 
        ret = ec_install_handlers(boot_ec);