[PATCH] Allow others to use ACPI EC interface

From: Andy Grover (agrover@groveronline.com)
Date: Wed Nov 20 2002 - 23:00:13 EST


Hi Stelian,

Do you have a system that works with ACPI?

This patch against 2.5.latest adds externally callable ec_read and
ec_write functions to the ACPI EC driver. Calling these should allow the
sonypi driver to avoid EC contention when ACPI is present.

Unfortunately I don't think sonypi will be able to remove its own EC read
and write functions, for the non-ACPI case.

Comments?

Thanks -- Regards -- Andy

===== drivers/acpi/acpi_ksyms.c 1.18 vs edited =====
--- 1.18/drivers/acpi/acpi_ksyms.c Tue Oct 22 16:14:07 2002
+++ edited/drivers/acpi/acpi_ksyms.c Wed Nov 20 19:39:04 2002
@@ -24,6 +24,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/acpi.h>
 #include "include/acpi.h"
 #include "acpi_bus.h"
 
@@ -141,3 +142,11 @@
 extern int acpi_pci_irq_lookup (int segment, int bus, int device, int pin);
 EXPORT_SYMBOL(acpi_pci_irq_lookup);
 #endif /*CONFIG_ACPI_PCI */
+
+#ifdef CONFIG_ACPI_EC
+/* ACPI EC driver (ec.c) */
+
+EXPORT_SYMBOL(ec_read);
+EXPORT_SYMBOL(ec_write);
+#endif
+
===== drivers/acpi/ec.c 1.15 vs edited =====
--- 1.15/drivers/acpi/ec.c Mon Nov 11 16:56:45 2002
+++ edited/drivers/acpi/ec.c Wed Nov 20 19:41:46 2002
@@ -92,6 +92,9 @@
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
 static struct acpi_ec *ec_ecdt;
 
+/* External interfaces use first EC only, so remember */
+static struct acpi_device *first_ec;
+
 /* --------------------------------------------------------------------------
                              Transaction Management
    -------------------------------------------------------------------------- */
@@ -236,6 +239,47 @@
         return_VALUE(result);
 }
 
+/*
+ * Externally callable EC access functions. For now, assume 1 EC only
+ */
+int
+ec_read(u8 addr, u8 *val)
+{
+ struct acpi_ec *ec;
+ int err;
+ u32 temp_data;
+
+ if (!first_ec)
+ return -ENODEV;
+
+ ec = acpi_driver_data(first_ec);
+
+ err = acpi_ec_read(ec, addr, &temp_data);
+
+ if (!err) {
+ *val = temp_data;
+ return 0;
+ }
+ else
+ return err;
+}
+
+int
+ec_write(u8 addr, u8 val)
+{
+ struct acpi_ec *ec;
+ int err;
+
+ if (!first_ec)
+ return -ENODEV;
+
+ ec = acpi_driver_data(first_ec);
+
+ err = acpi_ec_write(ec, addr, val);
+
+ return err;
+}
+
 
 static int
 acpi_ec_query (
@@ -540,11 +584,15 @@
         acpi_evaluate_integer(ec->handle, "_GLK", NULL, &ec->global_lock);
 
         /* If our UID matches the UID for the ECDT-enumerated EC,
- we already found this EC, so abort. */
+ we now have the *real* EC info, so kill the makeshift one.*/
         acpi_evaluate_integer(ec->handle, "_UID", NULL, &uid);
         if (ec_ecdt && ec_ecdt->uid == uid) {
- result = -ENODEV;
- goto end;
+ acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
+
+ acpi_remove_gpe_handler(ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
+
+ kfree(ec_ecdt);
         }
 
         /* Get GPE bit assignment (EC events). */
@@ -564,6 +612,9 @@
                 acpi_device_name(device), acpi_device_bid(device),
                 (u32) ec->gpe_bit);
 
+ if (!first_ec)
+ first_ec = device;
+
 end:
         if (result)
                 kfree(ec);
@@ -584,7 +635,7 @@
         if (!device)
                 return_VALUE(-EINVAL);
 
- ec = (struct acpi_ec *) acpi_driver_data(device);
+ ec = acpi_driver_data(device);
 
         acpi_ec_remove_fs(device);
 
@@ -609,7 +660,7 @@
         if (!device)
                 return_VALUE(-EINVAL);
 
- ec = (struct acpi_ec *) acpi_driver_data(device);
+ ec = acpi_driver_data(device);
 
         if (!ec)
                 return_VALUE(-EINVAL);
@@ -688,7 +739,7 @@
         if (!device)
                 return_VALUE(-EINVAL);
 
- ec = (struct acpi_ec *) acpi_driver_data(device);
+ ec = acpi_driver_data(device);
 
         status = acpi_remove_address_space_handler(ec->handle,
                 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
@@ -711,50 +762,50 @@
 
         status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
                 (acpi_table_header **) &ecdt_ptr);
- if (ACPI_SUCCESS(status)) {
- printk(KERN_INFO PREFIX "Found ECDT\n");
+ if (ACPI_FAILURE(status))
+ return 0;
+
+ printk(KERN_INFO PREFIX "Found ECDT\n");
+
+ /*
+ * Generate a temporary ec context to use until the namespace is scanned
+ */
+ ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
+ if (!ec_ecdt)
+ return -ENOMEM;
+ memset(ec_ecdt, 0, sizeof(struct acpi_ec));
+
+ ec_ecdt->command_addr = ecdt_ptr->ec_control;
+ ec_ecdt->status_addr = ecdt_ptr->ec_control;
+ ec_ecdt->data_addr = ecdt_ptr->ec_data;
+ ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
+ ec_ecdt->lock = SPIN_LOCK_UNLOCKED;
+ /* use the GL just to be safe */
+ ec_ecdt->global_lock = TRUE;
+ ec_ecdt->uid = ecdt_ptr->uid;
 
- /*
- * TODO: When the new driver model allows it, simply tell the
- * EC driver it has a new device via that, instead if this.
- */
- ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL);
- if (!ec_ecdt)
- return -ENOMEM;
- memset(ec_ecdt, 0, sizeof(struct acpi_ec));
-
- ec_ecdt->command_addr = ecdt_ptr->ec_control;
- ec_ecdt->status_addr = ecdt_ptr->ec_control;
- ec_ecdt->data_addr = ecdt_ptr->ec_data;
- ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit;
- ec_ecdt->lock = SPIN_LOCK_UNLOCKED;
- /* use the GL just to be safe */
- ec_ecdt->global_lock = TRUE;
- ec_ecdt->uid = ecdt_ptr->uid;
-
- status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
- if (ACPI_FAILURE(status)) {
- goto error;
- }
-
- /*
- * Install GPE handler
- */
- status = acpi_install_gpe_handler(ec_ecdt->gpe_bit,
- ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
- ec_ecdt);
- if (ACPI_FAILURE(status)) {
- goto error;
- }
-
- status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
- &acpi_ec_space_setup, ec_ecdt);
- if (ACPI_FAILURE(status)) {
- acpi_remove_gpe_handler(ec_ecdt->gpe_bit,
- &acpi_ec_gpe_handler);
- goto error;
- }
+ status = acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle);
+ if (ACPI_FAILURE(status)) {
+ goto error;
+ }
+
+ /*
+ * Install GPE handler
+ */
+ status = acpi_install_gpe_handler(ec_ecdt->gpe_bit,
+ ACPI_EVENT_EDGE_TRIGGERED, &acpi_ec_gpe_handler,
+ ec_ecdt);
+ if (ACPI_FAILURE(status)) {
+ goto error;
+ }
+
+ status = acpi_install_address_space_handler (ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_EC, &acpi_ec_space_handler,
+ &acpi_ec_space_setup, ec_ecdt);
+ if (ACPI_FAILURE(status)) {
+ acpi_remove_gpe_handler(ec_ecdt->gpe_bit,
+ &acpi_ec_gpe_handler);
+ goto error;
         }
 
         return 0;
@@ -796,20 +847,6 @@
 /* EC driver currently not unloadable */
 #if 0
 static void __exit
-acpi_ec_ecdt_exit (void)
-{
- if (!ec_ecdt)
- return;
-
- acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
- ACPI_ADR_SPACE_EC, &acpi_ec_space_handler);
-
- acpi_remove_gpe_handler(ec_ecdt->gpe_bit, &acpi_ec_gpe_handler);
-
- kfree(ec_ecdt);
-}
-
-static void __exit
 acpi_ec_exit (void)
 {
         ACPI_FUNCTION_TRACE("acpi_ec_exit");
@@ -817,8 +854,6 @@
         acpi_bus_unregister_driver(&acpi_ec_driver);
 
         remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
-
- acpi_ec_ecdt_exit();
 
         return_VOID;
 }
===== include/linux/acpi.h 1.17 vs edited =====
--- 1.17/include/linux/acpi.h Tue Oct 22 15:58:43 2002
+++ edited/include/linux/acpi.h Wed Nov 20 19:38:22 2002
@@ -419,6 +419,12 @@
 
 #endif /*CONFIG_ACPI_PCI*/
 
+#ifdef CONFIG_ACPI_EC
+
+int ec_read(u8 addr, u8 *val);
+int ec_write(u8 addr, u8 val);
+
+#endif /*CONFIG_ACPI_EC*/
 
 #ifdef CONFIG_ACPI
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Nov 23 2002 - 22:00:35 EST