|
@@ -128,12 +128,13 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
|
|
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
|
|
static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
/* --------------------------------------------------------------------------
|
|
- Transaction Management
|
|
|
|
- -------------------------------------------------------------------------- */
|
|
|
|
|
|
+ * Transaction Management
|
|
|
|
+ * -------------------------------------------------------------------------- */
|
|
|
|
|
|
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
|
static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
|
{
|
|
{
|
|
u8 x = inb(ec->command_addr);
|
|
u8 x = inb(ec->command_addr);
|
|
|
|
+
|
|
pr_debug("EC_SC(R) = 0x%2.2x "
|
|
pr_debug("EC_SC(R) = 0x%2.2x "
|
|
"SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
|
|
"SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n",
|
|
x,
|
|
x,
|
|
@@ -148,6 +149,7 @@ static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
|
|
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
|
|
static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
|
|
{
|
|
{
|
|
u8 x = inb(ec->data_addr);
|
|
u8 x = inb(ec->data_addr);
|
|
|
|
+
|
|
pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
|
|
pr_debug("EC_DATA(R) = 0x%2.2x\n", x);
|
|
return x;
|
|
return x;
|
|
}
|
|
}
|
|
@@ -189,6 +191,7 @@ static int ec_transaction_completed(struct acpi_ec *ec)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
+
|
|
spin_lock_irqsave(&ec->lock, flags);
|
|
spin_lock_irqsave(&ec->lock, flags);
|
|
if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
|
|
if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
|
|
ret = 1;
|
|
ret = 1;
|
|
@@ -288,6 +291,7 @@ static int ec_poll(struct acpi_ec *ec)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
int repeat = 5; /* number of command restarts */
|
|
int repeat = 5; /* number of command restarts */
|
|
|
|
+
|
|
while (repeat--) {
|
|
while (repeat--) {
|
|
unsigned long delay = jiffies +
|
|
unsigned long delay = jiffies +
|
|
msecs_to_jiffies(ec_delay);
|
|
msecs_to_jiffies(ec_delay);
|
|
@@ -320,6 +324,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
|
|
{
|
|
{
|
|
unsigned long tmp;
|
|
unsigned long tmp;
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
+
|
|
if (EC_FLAGS_MSI)
|
|
if (EC_FLAGS_MSI)
|
|
udelay(ACPI_EC_MSI_UDELAY);
|
|
udelay(ACPI_EC_MSI_UDELAY);
|
|
/* start transaction */
|
|
/* start transaction */
|
|
@@ -347,6 +352,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
|
|
{
|
|
{
|
|
int status;
|
|
int status;
|
|
u32 glk;
|
|
u32 glk;
|
|
|
|
+
|
|
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
|
|
if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
if (t->rdata)
|
|
if (t->rdata)
|
|
@@ -410,7 +416,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec)
|
|
acpi_ec_transaction(ec, &t) : 0;
|
|
acpi_ec_transaction(ec, &t) : 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
|
|
|
|
|
|
+static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
|
|
{
|
|
{
|
|
int result;
|
|
int result;
|
|
u8 d;
|
|
u8 d;
|
|
@@ -446,10 +452,9 @@ int ec_read(u8 addr, u8 *val)
|
|
if (!err) {
|
|
if (!err) {
|
|
*val = temp_data;
|
|
*val = temp_data;
|
|
return 0;
|
|
return 0;
|
|
- } else
|
|
|
|
- return err;
|
|
|
|
|
|
+ }
|
|
|
|
+ return err;
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL(ec_read);
|
|
EXPORT_SYMBOL(ec_read);
|
|
|
|
|
|
int ec_write(u8 addr, u8 val)
|
|
int ec_write(u8 addr, u8 val)
|
|
@@ -463,22 +468,21 @@ int ec_write(u8 addr, u8 val)
|
|
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL(ec_write);
|
|
EXPORT_SYMBOL(ec_write);
|
|
|
|
|
|
int ec_transaction(u8 command,
|
|
int ec_transaction(u8 command,
|
|
- const u8 * wdata, unsigned wdata_len,
|
|
|
|
- u8 * rdata, unsigned rdata_len)
|
|
|
|
|
|
+ const u8 *wdata, unsigned wdata_len,
|
|
|
|
+ u8 *rdata, unsigned rdata_len)
|
|
{
|
|
{
|
|
struct transaction t = {.command = command,
|
|
struct transaction t = {.command = command,
|
|
.wdata = wdata, .rdata = rdata,
|
|
.wdata = wdata, .rdata = rdata,
|
|
.wlen = wdata_len, .rlen = rdata_len};
|
|
.wlen = wdata_len, .rlen = rdata_len};
|
|
|
|
+
|
|
if (!first_ec)
|
|
if (!first_ec)
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
|
|
|
|
return acpi_ec_transaction(first_ec, &t);
|
|
return acpi_ec_transaction(first_ec, &t);
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL(ec_transaction);
|
|
EXPORT_SYMBOL(ec_transaction);
|
|
|
|
|
|
/* Get the handle to the EC device */
|
|
/* Get the handle to the EC device */
|
|
@@ -488,7 +492,6 @@ acpi_handle ec_get_handle(void)
|
|
return NULL;
|
|
return NULL;
|
|
return first_ec->handle;
|
|
return first_ec->handle;
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL(ec_get_handle);
|
|
EXPORT_SYMBOL(ec_get_handle);
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -552,13 +555,14 @@ void acpi_ec_unblock_transactions_early(void)
|
|
clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
|
|
clear_bit(EC_FLAGS_BLOCKED, &first_ec->flags);
|
|
}
|
|
}
|
|
|
|
|
|
-static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data)
|
|
|
|
|
|
+static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 *data)
|
|
{
|
|
{
|
|
int result;
|
|
int result;
|
|
u8 d;
|
|
u8 d;
|
|
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
|
struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
|
|
.wdata = NULL, .rdata = &d,
|
|
.wdata = NULL, .rdata = &d,
|
|
.wlen = 0, .rlen = 1};
|
|
.wlen = 0, .rlen = 1};
|
|
|
|
+
|
|
if (!ec || !data)
|
|
if (!ec || !data)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
/*
|
|
/*
|
|
@@ -584,6 +588,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|
{
|
|
{
|
|
struct acpi_ec_query_handler *handler =
|
|
struct acpi_ec_query_handler *handler =
|
|
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
|
|
kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
|
|
|
|
+
|
|
if (!handler)
|
|
if (!handler)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
@@ -596,12 +601,12 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
|
|
mutex_unlock(&ec->mutex);
|
|
mutex_unlock(&ec->mutex);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
|
|
EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
|
|
|
|
|
|
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|
void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|
{
|
|
{
|
|
struct acpi_ec_query_handler *handler, *tmp;
|
|
struct acpi_ec_query_handler *handler, *tmp;
|
|
|
|
+
|
|
mutex_lock(&ec->mutex);
|
|
mutex_lock(&ec->mutex);
|
|
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
|
|
list_for_each_entry_safe(handler, tmp, &ec->list, node) {
|
|
if (query_bit == handler->query_bit) {
|
|
if (query_bit == handler->query_bit) {
|
|
@@ -611,12 +616,12 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
|
|
}
|
|
}
|
|
mutex_unlock(&ec->mutex);
|
|
mutex_unlock(&ec->mutex);
|
|
}
|
|
}
|
|
-
|
|
|
|
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
|
EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
|
|
|
|
|
|
static void acpi_ec_run(void *cxt)
|
|
static void acpi_ec_run(void *cxt)
|
|
{
|
|
{
|
|
struct acpi_ec_query_handler *handler = cxt;
|
|
struct acpi_ec_query_handler *handler = cxt;
|
|
|
|
+
|
|
if (!handler)
|
|
if (!handler)
|
|
return;
|
|
return;
|
|
pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
|
|
pr_debug("##### Query(0x%02x) started #####\n", handler->query_bit);
|
|
@@ -660,6 +665,7 @@ static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data)
|
|
static void acpi_ec_gpe_query(void *ec_cxt)
|
|
static void acpi_ec_gpe_query(void *ec_cxt)
|
|
{
|
|
{
|
|
struct acpi_ec *ec = ec_cxt;
|
|
struct acpi_ec *ec = ec_cxt;
|
|
|
|
+
|
|
if (!ec)
|
|
if (!ec)
|
|
return;
|
|
return;
|
|
mutex_lock(&ec->mutex);
|
|
mutex_lock(&ec->mutex);
|
|
@@ -694,8 +700,8 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
|
|
}
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
/* --------------------------------------------------------------------------
|
|
- Address Space Management
|
|
|
|
- -------------------------------------------------------------------------- */
|
|
|
|
|
|
+ * Address Space Management
|
|
|
|
+ * -------------------------------------------------------------------------- */
|
|
|
|
|
|
static acpi_status
|
|
static acpi_status
|
|
acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
|
acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
|
@@ -726,27 +732,26 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
|
switch (result) {
|
|
switch (result) {
|
|
case -EINVAL:
|
|
case -EINVAL:
|
|
return AE_BAD_PARAMETER;
|
|
return AE_BAD_PARAMETER;
|
|
- break;
|
|
|
|
case -ENODEV:
|
|
case -ENODEV:
|
|
return AE_NOT_FOUND;
|
|
return AE_NOT_FOUND;
|
|
- break;
|
|
|
|
case -ETIME:
|
|
case -ETIME:
|
|
return AE_TIME;
|
|
return AE_TIME;
|
|
- break;
|
|
|
|
default:
|
|
default:
|
|
return AE_OK;
|
|
return AE_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
/* --------------------------------------------------------------------------
|
|
- Driver Interface
|
|
|
|
- -------------------------------------------------------------------------- */
|
|
|
|
|
|
+ * Driver Interface
|
|
|
|
+ * -------------------------------------------------------------------------- */
|
|
|
|
+
|
|
static acpi_status
|
|
static acpi_status
|
|
ec_parse_io_ports(struct acpi_resource *resource, void *context);
|
|
ec_parse_io_ports(struct acpi_resource *resource, void *context);
|
|
|
|
|
|
static struct acpi_ec *make_acpi_ec(void)
|
|
static struct acpi_ec *make_acpi_ec(void)
|
|
{
|
|
{
|
|
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
|
struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
|
|
|
|
+
|
|
if (!ec)
|
|
if (!ec)
|
|
return NULL;
|
|
return NULL;
|
|
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
|
|
ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
|
|
@@ -769,9 +774,8 @@ acpi_ec_register_query_methods(acpi_handle handle, u32 level,
|
|
|
|
|
|
status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
|
|
status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
|
|
|
|
|
|
- if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1) {
|
|
|
|
|
|
+ if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1)
|
|
acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
|
|
acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
|
|
- }
|
|
|
|
return AE_OK;
|
|
return AE_OK;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -780,7 +784,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|
{
|
|
{
|
|
acpi_status status;
|
|
acpi_status status;
|
|
unsigned long long tmp = 0;
|
|
unsigned long long tmp = 0;
|
|
-
|
|
|
|
struct acpi_ec *ec = context;
|
|
struct acpi_ec *ec = context;
|
|
|
|
|
|
/* clear addr values, ec_parse_io_ports depend on it */
|
|
/* clear addr values, ec_parse_io_ports depend on it */
|
|
@@ -808,6 +811,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
|
|
static int ec_install_handlers(struct acpi_ec *ec)
|
|
static int ec_install_handlers(struct acpi_ec *ec)
|
|
{
|
|
{
|
|
acpi_status status;
|
|
acpi_status status;
|
|
|
|
+
|
|
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
|
|
if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
|
|
return 0;
|
|
return 0;
|
|
status = acpi_install_gpe_handler(NULL, ec->gpe,
|
|
status = acpi_install_gpe_handler(NULL, ec->gpe,
|
|
@@ -1105,7 +1109,8 @@ int __init acpi_ec_ecdt_probe(void)
|
|
boot_ec->data_addr = ecdt_ptr->data.address;
|
|
boot_ec->data_addr = ecdt_ptr->data.address;
|
|
boot_ec->gpe = ecdt_ptr->gpe;
|
|
boot_ec->gpe = ecdt_ptr->gpe;
|
|
boot_ec->handle = ACPI_ROOT_OBJECT;
|
|
boot_ec->handle = ACPI_ROOT_OBJECT;
|
|
- acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle);
|
|
|
|
|
|
+ acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
|
|
|
|
+ &boot_ec->handle);
|
|
/* Don't trust ECDT, which comes from ASUSTek */
|
|
/* Don't trust ECDT, which comes from ASUSTek */
|
|
if (!EC_FLAGS_VALIDATE_ECDT)
|
|
if (!EC_FLAGS_VALIDATE_ECDT)
|
|
goto install;
|
|
goto install;
|
|
@@ -1189,6 +1194,5 @@ static void __exit acpi_ec_exit(void)
|
|
{
|
|
{
|
|
|
|
|
|
acpi_bus_unregister_driver(&acpi_ec_driver);
|
|
acpi_bus_unregister_driver(&acpi_ec_driver);
|
|
- return;
|
|
|
|
}
|
|
}
|
|
#endif /* 0 */
|
|
#endif /* 0 */
|