Subject: [PATCH] [acpi ec] Add address space handler and setup on device start - Create drivers/acpi/drivers/ec/addr.c - Add ec_addr_{init,exit}() - Register address space handler for all access - Call when device is started/stopped Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/ec/Makefile | 2 - drivers/acpi/drivers/ec/addr.c | 77 ++++++++++++++++++++++++++++++++++++++ drivers/acpi/drivers/ec/driver.c | 14 ++++++- drivers/acpi/drivers/ec/ec.h | 6 +++ 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 drivers/acpi/drivers/ec/addr.c applies-to: dbc61e90d5d1a3f0fc19930eb5504bf77e4b6783 0d3dd68952fae5c3bc5f02cf10afb5cbee80b2c8 diff --git a/drivers/acpi/drivers/ec/Makefile b/drivers/acpi/drivers/ec/Makefile index 0cdbf89..0de3770 100644 --- a/drivers/acpi/drivers/ec/Makefile +++ b/drivers/acpi/drivers/ec/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_ACPI_EC) += ec.o ec-y := driver.o device.o event.o poll.o intr.o ec-y += setup.o -ec-y += resource.o gpe.o read.o write.o +ec-y += resource.o gpe.o addr.o read.o write.o ec-$(CONFIG_ACPI_DM_PROC) += proc.o ec-$(CONFIG_ACPI_DM_SYSFS) += sysfs.o diff --git a/drivers/acpi/drivers/ec/addr.c b/drivers/acpi/drivers/ec/addr.c new file mode 100644 index 0000000..a3a7b89 --- /dev/null +++ b/drivers/acpi/drivers/ec/addr.c @@ -0,0 +1,77 @@ +/*** + * drivers/acpi/drivers/ec/addr.c - Address space handler for EC devices + * + * Copyright (C) 2006 Patrick Mochel + * + * Based on drivers/acpi/ec.c, which was + * + * Copyright (C) 2004 Luming Yu + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * This file is released under the GPLv2. + */ + +#include "ec.h" + + +static acpi_status addr_space_setup(acpi_handle region_handle, u32 function, + void * handler_context, + void ** return_context) +{ + /* + * The EC Objcet is in the handler context and is needed + * when calling the address space handler callback. + */ + *return_context = (function != ACPI_REGION_DEACTIVATE) ? + handler_context : NULL; + return AE_OK; +} + +static acpi_status addr_space_handler(u32 function, acpi_physical_address addr, + u32 bit_width, acpi_integer * value, + void * handler_context, + void * region_context) +{ + struct acpi_ec * ec = handler_context; + acpi_status status = AE_OK; + int ret; + + if (bit_width != 8 && acpi_strict) { + err("bit width should be 8"); + return AE_BAD_PARAMETER; + } + + if (function == ACPI_READ) + ret = acpi_ec_read(ec, (u8)addr, (u32 *)value); + else if (function == ACPI_WRITE) + ret = acpi_ec_write(ec, (u8)addr, (u8)*value); + else + ret = -EINVAL; + + if (ret == -EINVAL) + status = AE_BAD_PARAMETER; + else if (ret == -ENODEV) + status = AE_NOT_FOUND; + else if (ret == -ETIME) + status = AE_TIME; + return status; +} + + +int ec_addr_init(struct acpi_ec * ec) +{ + acpi_status status; + status = acpi_install_address_space_handler(ec->e_handle, + ACPI_ADR_SPACE_EC, + addr_space_handler, + addr_space_setup, ec); + return ACPI_SUCCESS(status) ? 0 : -ENODEV; +} + +void ec_addr_exit(struct acpi_ec * ec) +{ + acpi_remove_address_space_handler(ec->e_handle, + ACPI_ADR_SPACE_EC, + addr_space_handler); +} diff --git a/drivers/acpi/drivers/ec/driver.c b/drivers/acpi/drivers/ec/driver.c index 5761e91..a6aa5c6 100644 --- a/drivers/acpi/drivers/ec/driver.c +++ b/drivers/acpi/drivers/ec/driver.c @@ -77,8 +77,19 @@ static int ec_remove(struct acpi_dev * a static int ec_start(struct acpi_dev * ad) { struct acpi_ec * ec = dev_get_drvdata(&ad->dev); + int ret; - return ec_gpe_init(ec); + ret = ec_gpe_init(ec); + if (ret) + return ret; + + ret = ec_addr_init(ec); + if (ret) { + ec_gpe_exit(ec); + return ret; + } + + return ret; } @@ -86,6 +97,7 @@ static int ec_stop(struct acpi_dev * ad) { struct acpi_ec * ec = dev_get_drvdata(&ad->dev); + ec_addr_exit(ec); ec_gpe_exit(ec); return 0; } diff --git a/drivers/acpi/drivers/ec/ec.h b/drivers/acpi/drivers/ec/ec.h index 7935ced..f926be3 100644 --- a/drivers/acpi/drivers/ec/ec.h +++ b/drivers/acpi/drivers/ec/ec.h @@ -88,6 +88,12 @@ extern int ec_gpe_init(struct acpi_ec * extern void ec_gpe_exit(struct acpi_ec * ec); /* + * addr.c + */ +extern int ec_addr_init(struct acpi_ec * ec); +extern void ec_addr_exit(struct acpi_ec * ec); + +/* * read/write functionality */ extern int acpi_ec_read(struct acpi_ec * ec, u8 addr, u32 * data); --- 0.99.9.GIT