* [PATCH] i2c: move acpi code back into the core
@ 2014-09-22 21:06 Wolfram Sang
[not found] ` <1411420006-4713-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>
0 siblings, 1 reply; 13+ messages in thread
From: Wolfram Sang @ 2014-09-22 21:06 UTC (permalink / raw)
To: linux-i2c
Cc: linux-acpi, linux-kernel, Wolfram Sang, Mika Westerberg,
Lan Tianyu, Jean Delvare
Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support") renamed
the i2c-core module. This may cause regressions for distributions, so put the
ACPI code back into the core. No code was changed.
Reported-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Lan Tianyu <tianyu.lan@intel.com>
Cc: Jean Delvare <jdelvare@suse.de>
---
Lan Tianyi, this is a patch I expected to get from you, fully tested. Since we
are approaching the final release soon, I did it now. Please do test this
patch. All I can do is build test (it works for me, build robots are still
running). If nobody tests this, I have to revert the ACPI changes of this
cycle.
Jean, can you have a look, too?
We can think of something better for the next release, but for now, this should be it.
MAINTAINERS | 1 -
drivers/i2c/Makefile | 5 +-
drivers/i2c/i2c-acpi.c | 364 -------------------------------------------------
drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 346 insertions(+), 369 deletions(-)
delete mode 100644 drivers/i2c/i2c-acpi.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 809ecd680d88..e3682d0dea1e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com>
L: linux-i2c@vger.kernel.org
L: linux-acpi@vger.kernel.org
S: Maintained
-F: drivers/i2c/i2c-acpi.c
I2C-TAOS-EVM DRIVER
M: Jean Delvare <jdelvare@suse.de>
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index e0228b228256..1722f50f2473 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -2,11 +2,8 @@
# Makefile for the i2c core.
#
-i2ccore-y := i2c-core.o
-i2ccore-$(CONFIG_ACPI) += i2c-acpi.o
-
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
-obj-$(CONFIG_I2C) += i2ccore.o
+obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c
deleted file mode 100644
index 0dbc18c15c43..000000000000
--- a/drivers/i2c/i2c-acpi.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * I2C ACPI code
- *
- * Copyright (C) 2014 Intel Corp
- *
- * Author: Lan Tianyu <tianyu.lan@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-#define pr_fmt(fmt) "I2C/ACPI : " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/acpi.h>
-
-struct acpi_i2c_handler_data {
- struct acpi_connection_info info;
- struct i2c_adapter *adapter;
-};
-
-struct gsb_buffer {
- u8 status;
- u8 len;
- union {
- u16 wdata;
- u8 bdata;
- u8 data[0];
- };
-} __packed;
-
-static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
-{
- struct i2c_board_info *info = data;
-
- if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- struct acpi_resource_i2c_serialbus *sb;
-
- sb = &ares->data.i2c_serial_bus;
- if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
- info->addr = sb->slave_address;
- if (sb->access_mode == ACPI_I2C_10BIT_MODE)
- info->flags |= I2C_CLIENT_TEN;
- }
- } else if (info->irq < 0) {
- struct resource r;
-
- if (acpi_dev_resource_interrupt(ares, 0, &r))
- info->irq = r.start;
- }
-
- /* Tell the ACPI core to skip this resource */
- return 1;
-}
-
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
- void *data, void **return_value)
-{
- struct i2c_adapter *adapter = data;
- struct list_head resource_list;
- struct i2c_board_info info;
- struct acpi_device *adev;
- int ret;
-
- if (acpi_bus_get_device(handle, &adev))
- return AE_OK;
- if (acpi_bus_get_status(adev) || !adev->status.present)
- return AE_OK;
-
- memset(&info, 0, sizeof(info));
- info.acpi_node.companion = adev;
- info.irq = -1;
-
- INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list,
- acpi_i2c_add_resource, &info);
- acpi_dev_free_resource_list(&resource_list);
-
- if (ret < 0 || !info.addr)
- return AE_OK;
-
- adev->power.flags.ignore_parent = true;
- strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
- if (!i2c_new_device(adapter, &info)) {
- adev->power.flags.ignore_parent = false;
- dev_err(&adapter->dev,
- "failed to add I2C device %s from ACPI\n",
- dev_name(&adev->dev));
- }
-
- return AE_OK;
-}
-
-/**
- * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
- * @adap: pointer to adapter
- *
- * Enumerate all I2C slave devices behind this adapter by walking the ACPI
- * namespace. When a device is found it will be added to the Linux device
- * model and bound to the corresponding ACPI handle.
- */
-void acpi_i2c_register_devices(struct i2c_adapter *adap)
-{
- acpi_handle handle;
- acpi_status status;
-
- if (!adap->dev.parent)
- return;
-
- handle = ACPI_HANDLE(adap->dev.parent);
- if (!handle)
- return;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
- acpi_i2c_add_device, NULL,
- adap, NULL);
- if (ACPI_FAILURE(status))
- dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
-}
-
-#ifdef CONFIG_ACPI_I2C_OPREGION
-static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
- u8 cmd, u8 *data, u8 data_len)
-{
-
- struct i2c_msg msgs[2];
- int ret;
- u8 *buffer;
-
- buffer = kzalloc(data_len, GFP_KERNEL);
- if (!buffer)
- return AE_NO_MEMORY;
-
- msgs[0].addr = client->addr;
- msgs[0].flags = client->flags;
- msgs[0].len = 1;
- msgs[0].buf = &cmd;
-
- msgs[1].addr = client->addr;
- msgs[1].flags = client->flags | I2C_M_RD;
- msgs[1].len = data_len;
- msgs[1].buf = buffer;
-
- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (ret < 0)
- dev_err(&client->adapter->dev, "i2c read failed\n");
- else
- memcpy(data, buffer, data_len);
-
- kfree(buffer);
- return ret;
-}
-
-static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
- u8 cmd, u8 *data, u8 data_len)
-{
-
- struct i2c_msg msgs[1];
- u8 *buffer;
- int ret = AE_OK;
-
- buffer = kzalloc(data_len + 1, GFP_KERNEL);
- if (!buffer)
- return AE_NO_MEMORY;
-
- buffer[0] = cmd;
- memcpy(buffer + 1, data, data_len);
-
- msgs[0].addr = client->addr;
- msgs[0].flags = client->flags;
- msgs[0].len = data_len + 1;
- msgs[0].buf = buffer;
-
- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (ret < 0)
- dev_err(&client->adapter->dev, "i2c write failed\n");
-
- kfree(buffer);
- return ret;
-}
-
-static acpi_status
-acpi_i2c_space_handler(u32 function, acpi_physical_address command,
- u32 bits, u64 *value64,
- void *handler_context, void *region_context)
-{
- struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
- struct acpi_i2c_handler_data *data = handler_context;
- struct acpi_connection_info *info = &data->info;
- struct acpi_resource_i2c_serialbus *sb;
- struct i2c_adapter *adapter = data->adapter;
- struct i2c_client client;
- struct acpi_resource *ares;
- u32 accessor_type = function >> 16;
- u8 action = function & ACPI_IO_MASK;
- acpi_status ret = AE_OK;
- int status;
-
- ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
- if (ACPI_FAILURE(ret))
- return ret;
-
- if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- sb = &ares->data.i2c_serial_bus;
- if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- memset(&client, 0, sizeof(client));
- client.adapter = adapter;
- client.addr = sb->slave_address;
- client.flags = 0;
-
- if (sb->access_mode == ACPI_I2C_10BIT_MODE)
- client.flags |= I2C_CLIENT_TEN;
-
- switch (accessor_type) {
- case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_byte(&client);
- if (status >= 0) {
- gsb->bdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_byte(&client, gsb->bdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_BYTE:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_byte_data(&client, command);
- if (status >= 0) {
- gsb->bdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_byte_data(&client, command,
- gsb->bdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_WORD:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_word_data(&client, command);
- if (status >= 0) {
- gsb->wdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_word_data(&client, command,
- gsb->wdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_block_data(&client, command,
- gsb->data);
- if (status >= 0) {
- gsb->len = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_block_data(&client, command,
- gsb->len, gsb->data);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
- if (action == ACPI_READ) {
- status = acpi_gsb_i2c_read_bytes(&client, command,
- gsb->data, info->access_length);
- if (status > 0)
- status = 0;
- } else {
- status = acpi_gsb_i2c_write_bytes(&client, command,
- gsb->data, info->access_length);
- }
- break;
-
- default:
- pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- gsb->status = status;
-
- err:
- ACPI_FREE(ares);
- return ret;
-}
-
-
-int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
-{
- acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
- struct acpi_i2c_handler_data *data;
- acpi_status status;
-
- if (!handle)
- return -ENODEV;
-
- data = kzalloc(sizeof(struct acpi_i2c_handler_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->adapter = adapter;
- status = acpi_bus_attach_private_data(handle, (void *)data);
- if (ACPI_FAILURE(status)) {
- kfree(data);
- return -ENOMEM;
- }
-
- status = acpi_install_address_space_handler(handle,
- ACPI_ADR_SPACE_GSBUS,
- &acpi_i2c_space_handler,
- NULL,
- data);
- if (ACPI_FAILURE(status)) {
- dev_err(&adapter->dev, "Error installing i2c space handler\n");
- acpi_bus_detach_private_data(handle);
- kfree(data);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
-{
- acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
- struct acpi_i2c_handler_data *data;
- acpi_status status;
-
- if (!handle)
- return;
-
- acpi_remove_address_space_handler(handle,
- ACPI_ADR_SPACE_GSBUS,
- &acpi_i2c_space_handler);
-
- status = acpi_bus_get_private_data(handle, (void **)&data);
- if (ACPI_SUCCESS(status))
- kfree(data);
-
- acpi_bus_detach_private_data(handle);
-}
-#endif
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 632057a44615..3fbd5d5c38bf 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -27,6 +27,8 @@
OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
(c) 2013 Wolfram Sang <wsa@the-dreams.de>
+ I2C ACPI code Copyright (C) 2014 Intel Corp
+ Author: Lan Tianyu <tianyu.lan@intel.com>
*/
#include <linux/module.h>
@@ -78,6 +80,349 @@ void i2c_transfer_trace_unreg(void)
static_key_slow_dec(&i2c_trace_msg);
}
+#if defined(CONFIG_ACPI)
+struct acpi_i2c_handler_data {
+ struct acpi_connection_info info;
+ struct i2c_adapter *adapter;
+};
+
+struct gsb_buffer {
+ u8 status;
+ u8 len;
+ union {
+ u16 wdata;
+ u8 bdata;
+ u8 data[0];
+ };
+} __packed;
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+ struct i2c_board_info *info = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ struct acpi_resource_i2c_serialbus *sb;
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ info->addr = sb->slave_address;
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ info->flags |= I2C_CLIENT_TEN;
+ }
+ } else if (info->irq < 0) {
+ struct resource r;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &r))
+ info->irq = r.start;
+ }
+
+ /* Tell the ACPI core to skip this resource */
+ return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+ void *data, void **return_value)
+{
+ struct i2c_adapter *adapter = data;
+ struct list_head resource_list;
+ struct i2c_board_info info;
+ struct acpi_device *adev;
+ int ret;
+
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+ if (acpi_bus_get_status(adev) || !adev->status.present)
+ return AE_OK;
+
+ memset(&info, 0, sizeof(info));
+ info.acpi_node.companion = adev;
+ info.irq = -1;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ acpi_i2c_add_resource, &info);
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (ret < 0 || !info.addr)
+ return AE_OK;
+
+ adev->power.flags.ignore_parent = true;
+ strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+ if (!i2c_new_device(adapter, &info)) {
+ adev->power.flags.ignore_parent = false;
+ dev_err(&adapter->dev,
+ "failed to add I2C device %s from ACPI\n",
+ dev_name(&adev->dev));
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adap: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+void acpi_i2c_register_devices(struct i2c_adapter *adap)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!adap->dev.parent)
+ return;
+
+ handle = ACPI_HANDLE(adap->dev.parent);
+ if (!handle)
+ return;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_i2c_add_device, NULL,
+ adap, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+}
+
+#ifdef CONFIG_ACPI_I2C_OPREGION
+static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[2];
+ int ret;
+ u8 *buffer;
+
+ buffer = kzalloc(data_len, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = 1;
+ msgs[0].buf = &cmd;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags | I2C_M_RD;
+ msgs[1].len = data_len;
+ msgs[1].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c read failed\n");
+ else
+ memcpy(data, buffer, data_len);
+
+ kfree(buffer);
+ return ret;
+}
+
+static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[1];
+ u8 *buffer;
+ int ret = AE_OK;
+
+ buffer = kzalloc(data_len + 1, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ buffer[0] = cmd;
+ memcpy(buffer + 1, data, data_len);
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = data_len + 1;
+ msgs[0].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c write failed\n");
+
+ kfree(buffer);
+ return ret;
+}
+
+static acpi_status
+acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+ u32 bits, u64 *value64,
+ void *handler_context, void *region_context)
+{
+ struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
+ struct acpi_i2c_handler_data *data = handler_context;
+ struct acpi_connection_info *info = &data->info;
+ struct acpi_resource_i2c_serialbus *sb;
+ struct i2c_adapter *adapter = data->adapter;
+ struct i2c_client client;
+ struct acpi_resource *ares;
+ u32 accessor_type = function >> 16;
+ u8 action = function & ACPI_IO_MASK;
+ acpi_status ret = AE_OK;
+ int status;
+
+ ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
+ if (ACPI_FAILURE(ret))
+ return ret;
+
+ if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ memset(&client, 0, sizeof(client));
+ client.adapter = adapter;
+ client.addr = sb->slave_address;
+ client.flags = 0;
+
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ client.flags |= I2C_CLIENT_TEN;
+
+ switch (accessor_type) {
+ case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte(&client);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte(&client, gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BYTE:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte_data(&client, command);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte_data(&client, command,
+ gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_WORD:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_word_data(&client, command);
+ if (status >= 0) {
+ gsb->wdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_word_data(&client, command,
+ gsb->wdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_block_data(&client, command,
+ gsb->data);
+ if (status >= 0) {
+ gsb->len = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_block_data(&client, command,
+ gsb->len, gsb->data);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
+ if (action == ACPI_READ) {
+ status = acpi_gsb_i2c_read_bytes(&client, command,
+ gsb->data, info->access_length);
+ if (status > 0)
+ status = 0;
+ } else {
+ status = acpi_gsb_i2c_write_bytes(&client, command,
+ gsb->data, info->access_length);
+ }
+ break;
+
+ default:
+ pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ gsb->status = status;
+
+ err:
+ ACPI_FREE(ares);
+ return ret;
+}
+
+
+int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->adapter = adapter;
+ status = acpi_bus_attach_private_data(handle, (void *)data);
+ if (ACPI_FAILURE(status)) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ status = acpi_install_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler,
+ NULL,
+ data);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&adapter->dev, "Error installing i2c space handler\n");
+ acpi_bus_detach_private_data(handle);
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return;
+
+ acpi_remove_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler);
+
+ status = acpi_bus_get_private_data(handle, (void **)&data);
+ if (ACPI_SUCCESS(status))
+ kfree(data);
+
+ acpi_bus_detach_private_data(handle);
+}
+#endif
+#endif /* CONFIG_ACPI */
+
/* ------------------------------------------------------------------------- */
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
--
2.0.0
^ permalink raw reply related [flat|nested] 13+ messages in thread[parent not found: <1411420006-4713-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>]
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-22 21:06 [PATCH] i2c: move acpi code back into the core Wolfram Sang @ 2014-09-23 1:37 ` Lan Tianyu 0 siblings, 0 replies; 13+ messages in thread From: Lan Tianyu @ 2014-09-23 1:37 UTC (permalink / raw) To: Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mika Westerberg, Jean Delvare On 2014年09月23日 05:06, Wolfram Sang wrote: > Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support") renamed > the i2c-core module. This may cause regressions for distributions, so put the > ACPI code back into the core. No code was changed. > > Reported-by: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> > Signed-off-by: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> > Cc: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> > Cc: Lan Tianyu <tianyu.lan-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > Cc: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> > --- > > Lan Tianyi, this is a patch I expected to get from you, fully tested. Since we > are approaching the final release soon, I did it now. Please do test this > patch. All I can do is build test (it works for me, build robots are still > running). If nobody tests this, I have to revert the ACPI changes of this > cycle. Hi Wolfram: Sorry for later response due to sickness. I can't write this patch in time. Sorry again. I will test it soon. > > Jean, can you have a look, too? > > We can think of something better for the next release, but for now, this should be it. > > MAINTAINERS | 1 - > drivers/i2c/Makefile | 5 +- > drivers/i2c/i2c-acpi.c | 364 ------------------------------------------------- > drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 346 insertions(+), 369 deletions(-) > delete mode 100644 drivers/i2c/i2c-acpi.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 809ecd680d88..e3682d0dea1e 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg-VuQAYsv1560/9W2qTSuDoA@public.gmane.org.com> > L: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > L: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > S: Maintained > -F: drivers/i2c/i2c-acpi.c > > I2C-TAOS-EVM DRIVER > M: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > index e0228b228256..1722f50f2473 100644 > --- a/drivers/i2c/Makefile > +++ b/drivers/i2c/Makefile > @@ -2,11 +2,8 @@ > # Makefile for the i2c core. > # > > -i2ccore-y := i2c-core.o > -i2ccore-$(CONFIG_ACPI) += i2c-acpi.o > - > obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o > -obj-$(CONFIG_I2C) += i2ccore.o > +obj-$(CONFIG_I2C) += i2c-core.o > obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o > obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o > obj-$(CONFIG_I2C_MUX) += i2c-mux.o > diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c > deleted file mode 100644 > index 0dbc18c15c43..000000000000 > --- a/drivers/i2c/i2c-acpi.c > +++ /dev/null > @@ -1,364 +0,0 @@ > -/* > - * I2C ACPI code > - * > - * Copyright (C) 2014 Intel Corp > - * > - * Author: Lan Tianyu <tianyu.lan-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > - * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License version 2 as > - * published by the Free Software Foundation. > - * > - * This program is distributed in the hope that it will be useful, but > - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > - * for more details. > - */ > -#define pr_fmt(fmt) "I2C/ACPI : " fmt > - > -#include <linux/kernel.h> > -#include <linux/errno.h> > -#include <linux/err.h> > -#include <linux/i2c.h> > -#include <linux/acpi.h> > - > -struct acpi_i2c_handler_data { > - struct acpi_connection_info info; > - struct i2c_adapter *adapter; > -}; > - > -struct gsb_buffer { > - u8 status; > - u8 len; > - union { > - u16 wdata; > - u8 bdata; > - u8 data[0]; > - }; > -} __packed; > - > -static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) > -{ > - struct i2c_board_info *info = data; > - > - if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { > - struct acpi_resource_i2c_serialbus *sb; > - > - sb = &ares->data.i2c_serial_bus; > - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { > - info->addr = sb->slave_address; > - if (sb->access_mode == ACPI_I2C_10BIT_MODE) > - info->flags |= I2C_CLIENT_TEN; > - } > - } else if (info->irq < 0) { > - struct resource r; > - > - if (acpi_dev_resource_interrupt(ares, 0, &r)) > - info->irq = r.start; > - } > - > - /* Tell the ACPI core to skip this resource */ > - return 1; > -} > - > -static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, > - void *data, void **return_value) > -{ > - struct i2c_adapter *adapter = data; > - struct list_head resource_list; > - struct i2c_board_info info; > - struct acpi_device *adev; > - int ret; > - > - if (acpi_bus_get_device(handle, &adev)) > - return AE_OK; > - if (acpi_bus_get_status(adev) || !adev->status.present) > - return AE_OK; > - > - memset(&info, 0, sizeof(info)); > - info.acpi_node.companion = adev; > - info.irq = -1; > - > - INIT_LIST_HEAD(&resource_list); > - ret = acpi_dev_get_resources(adev, &resource_list, > - acpi_i2c_add_resource, &info); > - acpi_dev_free_resource_list(&resource_list); > - > - if (ret < 0 || !info.addr) > - return AE_OK; > - > - adev->power.flags.ignore_parent = true; > - strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); > - if (!i2c_new_device(adapter, &info)) { > - adev->power.flags.ignore_parent = false; > - dev_err(&adapter->dev, > - "failed to add I2C device %s from ACPI\n", > - dev_name(&adev->dev)); > - } > - > - return AE_OK; > -} > - > -/** > - * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > - * @adap: pointer to adapter > - * > - * Enumerate all I2C slave devices behind this adapter by walking the ACPI > - * namespace. When a device is found it will be added to the Linux device > - * model and bound to the corresponding ACPI handle. > - */ > -void acpi_i2c_register_devices(struct i2c_adapter *adap) > -{ > - acpi_handle handle; > - acpi_status status; > - > - if (!adap->dev.parent) > - return; > - > - handle = ACPI_HANDLE(adap->dev.parent); > - if (!handle) > - return; > - > - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > - acpi_i2c_add_device, NULL, > - adap, NULL); > - if (ACPI_FAILURE(status)) > - dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > -} > - > -#ifdef CONFIG_ACPI_I2C_OPREGION > -static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, > - u8 cmd, u8 *data, u8 data_len) > -{ > - > - struct i2c_msg msgs[2]; > - int ret; > - u8 *buffer; > - > - buffer = kzalloc(data_len, GFP_KERNEL); > - if (!buffer) > - return AE_NO_MEMORY; > - > - msgs[0].addr = client->addr; > - msgs[0].flags = client->flags; > - msgs[0].len = 1; > - msgs[0].buf = &cmd; > - > - msgs[1].addr = client->addr; > - msgs[1].flags = client->flags | I2C_M_RD; > - msgs[1].len = data_len; > - msgs[1].buf = buffer; > - > - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > - if (ret < 0) > - dev_err(&client->adapter->dev, "i2c read failed\n"); > - else > - memcpy(data, buffer, data_len); > - > - kfree(buffer); > - return ret; > -} > - > -static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, > - u8 cmd, u8 *data, u8 data_len) > -{ > - > - struct i2c_msg msgs[1]; > - u8 *buffer; > - int ret = AE_OK; > - > - buffer = kzalloc(data_len + 1, GFP_KERNEL); > - if (!buffer) > - return AE_NO_MEMORY; > - > - buffer[0] = cmd; > - memcpy(buffer + 1, data, data_len); > - > - msgs[0].addr = client->addr; > - msgs[0].flags = client->flags; > - msgs[0].len = data_len + 1; > - msgs[0].buf = buffer; > - > - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > - if (ret < 0) > - dev_err(&client->adapter->dev, "i2c write failed\n"); > - > - kfree(buffer); > - return ret; > -} > - > -static acpi_status > -acpi_i2c_space_handler(u32 function, acpi_physical_address command, > - u32 bits, u64 *value64, > - void *handler_context, void *region_context) > -{ > - struct gsb_buffer *gsb = (struct gsb_buffer *)value64; > - struct acpi_i2c_handler_data *data = handler_context; > - struct acpi_connection_info *info = &data->info; > - struct acpi_resource_i2c_serialbus *sb; > - struct i2c_adapter *adapter = data->adapter; > - struct i2c_client client; > - struct acpi_resource *ares; > - u32 accessor_type = function >> 16; > - u8 action = function & ACPI_IO_MASK; > - acpi_status ret = AE_OK; > - int status; > - > - ret = acpi_buffer_to_resource(info->connection, info->length, &ares); > - if (ACPI_FAILURE(ret)) > - return ret; > - > - if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - sb = &ares->data.i2c_serial_bus; > - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - memset(&client, 0, sizeof(client)); > - client.adapter = adapter; > - client.addr = sb->slave_address; > - client.flags = 0; > - > - if (sb->access_mode == ACPI_I2C_10BIT_MODE) > - client.flags |= I2C_CLIENT_TEN; > - > - switch (accessor_type) { > - case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_byte(&client); > - if (status >= 0) { > - gsb->bdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_byte(&client, gsb->bdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_BYTE: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_byte_data(&client, command); > - if (status >= 0) { > - gsb->bdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_byte_data(&client, command, > - gsb->bdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_WORD: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_word_data(&client, command); > - if (status >= 0) { > - gsb->wdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_word_data(&client, command, > - gsb->wdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_BLOCK: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_block_data(&client, command, > - gsb->data); > - if (status >= 0) { > - gsb->len = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_block_data(&client, command, > - gsb->len, gsb->data); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: > - if (action == ACPI_READ) { > - status = acpi_gsb_i2c_read_bytes(&client, command, > - gsb->data, info->access_length); > - if (status > 0) > - status = 0; > - } else { > - status = acpi_gsb_i2c_write_bytes(&client, command, > - gsb->data, info->access_length); > - } > - break; > - > - default: > - pr_info("protocol(0x%02x) is not supported.\n", accessor_type); > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - gsb->status = status; > - > - err: > - ACPI_FREE(ares); > - return ret; > -} > - > - > -int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) > -{ > - acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > - struct acpi_i2c_handler_data *data; > - acpi_status status; > - > - if (!handle) > - return -ENODEV; > - > - data = kzalloc(sizeof(struct acpi_i2c_handler_data), > - GFP_KERNEL); > - if (!data) > - return -ENOMEM; > - > - data->adapter = adapter; > - status = acpi_bus_attach_private_data(handle, (void *)data); > - if (ACPI_FAILURE(status)) { > - kfree(data); > - return -ENOMEM; > - } > - > - status = acpi_install_address_space_handler(handle, > - ACPI_ADR_SPACE_GSBUS, > - &acpi_i2c_space_handler, > - NULL, > - data); > - if (ACPI_FAILURE(status)) { > - dev_err(&adapter->dev, "Error installing i2c space handler\n"); > - acpi_bus_detach_private_data(handle); > - kfree(data); > - return -ENOMEM; > - } > - > - return 0; > -} > - > -void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) > -{ > - acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > - struct acpi_i2c_handler_data *data; > - acpi_status status; > - > - if (!handle) > - return; > - > - acpi_remove_address_space_handler(handle, > - ACPI_ADR_SPACE_GSBUS, > - &acpi_i2c_space_handler); > - > - status = acpi_bus_get_private_data(handle, (void **)&data); > - if (ACPI_SUCCESS(status)) > - kfree(data); > - > - acpi_bus_detach_private_data(handle); > -} > -#endif > diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c > index 632057a44615..3fbd5d5c38bf 100644 > --- a/drivers/i2c/i2c-core.c > +++ b/drivers/i2c/i2c-core.c > @@ -27,6 +27,8 @@ > OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de> > (based on a previous patch from Jon Smirl <jonsmirl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>) and > (c) 2013 Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> > + I2C ACPI code Copyright (C) 2014 Intel Corp > + Author: Lan Tianyu <tianyu.lan-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > */ > > #include <linux/module.h> > @@ -78,6 +80,349 @@ void i2c_transfer_trace_unreg(void) > static_key_slow_dec(&i2c_trace_msg); > } > > +#if defined(CONFIG_ACPI) > +struct acpi_i2c_handler_data { > + struct acpi_connection_info info; > + struct i2c_adapter *adapter; > +}; > + > +struct gsb_buffer { > + u8 status; > + u8 len; > + union { > + u16 wdata; > + u8 bdata; > + u8 data[0]; > + }; > +} __packed; > + > +static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) > +{ > + struct i2c_board_info *info = data; > + > + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { > + struct acpi_resource_i2c_serialbus *sb; > + > + sb = &ares->data.i2c_serial_bus; > + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { > + info->addr = sb->slave_address; > + if (sb->access_mode == ACPI_I2C_10BIT_MODE) > + info->flags |= I2C_CLIENT_TEN; > + } > + } else if (info->irq < 0) { > + struct resource r; > + > + if (acpi_dev_resource_interrupt(ares, 0, &r)) > + info->irq = r.start; > + } > + > + /* Tell the ACPI core to skip this resource */ > + return 1; > +} > + > +static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, > + void *data, void **return_value) > +{ > + struct i2c_adapter *adapter = data; > + struct list_head resource_list; > + struct i2c_board_info info; > + struct acpi_device *adev; > + int ret; > + > + if (acpi_bus_get_device(handle, &adev)) > + return AE_OK; > + if (acpi_bus_get_status(adev) || !adev->status.present) > + return AE_OK; > + > + memset(&info, 0, sizeof(info)); > + info.acpi_node.companion = adev; > + info.irq = -1; > + > + INIT_LIST_HEAD(&resource_list); > + ret = acpi_dev_get_resources(adev, &resource_list, > + acpi_i2c_add_resource, &info); > + acpi_dev_free_resource_list(&resource_list); > + > + if (ret < 0 || !info.addr) > + return AE_OK; > + > + adev->power.flags.ignore_parent = true; > + strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); > + if (!i2c_new_device(adapter, &info)) { > + adev->power.flags.ignore_parent = false; > + dev_err(&adapter->dev, > + "failed to add I2C device %s from ACPI\n", > + dev_name(&adev->dev)); > + } > + > + return AE_OK; > +} > + > +/** > + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > + * @adap: pointer to adapter > + * > + * Enumerate all I2C slave devices behind this adapter by walking the ACPI > + * namespace. When a device is found it will be added to the Linux device > + * model and bound to the corresponding ACPI handle. > + */ > +void acpi_i2c_register_devices(struct i2c_adapter *adap) > +{ > + acpi_handle handle; > + acpi_status status; > + > + if (!adap->dev.parent) > + return; > + > + handle = ACPI_HANDLE(adap->dev.parent); > + if (!handle) > + return; > + > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > + acpi_i2c_add_device, NULL, > + adap, NULL); > + if (ACPI_FAILURE(status)) > + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > +} > + > +#ifdef CONFIG_ACPI_I2C_OPREGION > +static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, > + u8 cmd, u8 *data, u8 data_len) > +{ > + > + struct i2c_msg msgs[2]; > + int ret; > + u8 *buffer; > + > + buffer = kzalloc(data_len, GFP_KERNEL); > + if (!buffer) > + return AE_NO_MEMORY; > + > + msgs[0].addr = client->addr; > + msgs[0].flags = client->flags; > + msgs[0].len = 1; > + msgs[0].buf = &cmd; > + > + msgs[1].addr = client->addr; > + msgs[1].flags = client->flags | I2C_M_RD; > + msgs[1].len = data_len; > + msgs[1].buf = buffer; > + > + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > + if (ret < 0) > + dev_err(&client->adapter->dev, "i2c read failed\n"); > + else > + memcpy(data, buffer, data_len); > + > + kfree(buffer); > + return ret; > +} > + > +static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, > + u8 cmd, u8 *data, u8 data_len) > +{ > + > + struct i2c_msg msgs[1]; > + u8 *buffer; > + int ret = AE_OK; > + > + buffer = kzalloc(data_len + 1, GFP_KERNEL); > + if (!buffer) > + return AE_NO_MEMORY; > + > + buffer[0] = cmd; > + memcpy(buffer + 1, data, data_len); > + > + msgs[0].addr = client->addr; > + msgs[0].flags = client->flags; > + msgs[0].len = data_len + 1; > + msgs[0].buf = buffer; > + > + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > + if (ret < 0) > + dev_err(&client->adapter->dev, "i2c write failed\n"); > + > + kfree(buffer); > + return ret; > +} > + > +static acpi_status > +acpi_i2c_space_handler(u32 function, acpi_physical_address command, > + u32 bits, u64 *value64, > + void *handler_context, void *region_context) > +{ > + struct gsb_buffer *gsb = (struct gsb_buffer *)value64; > + struct acpi_i2c_handler_data *data = handler_context; > + struct acpi_connection_info *info = &data->info; > + struct acpi_resource_i2c_serialbus *sb; > + struct i2c_adapter *adapter = data->adapter; > + struct i2c_client client; > + struct acpi_resource *ares; > + u32 accessor_type = function >> 16; > + u8 action = function & ACPI_IO_MASK; > + acpi_status ret = AE_OK; > + int status; > + > + ret = acpi_buffer_to_resource(info->connection, info->length, &ares); > + if (ACPI_FAILURE(ret)) > + return ret; > + > + if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + sb = &ares->data.i2c_serial_bus; > + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + memset(&client, 0, sizeof(client)); > + client.adapter = adapter; > + client.addr = sb->slave_address; > + client.flags = 0; > + > + if (sb->access_mode == ACPI_I2C_10BIT_MODE) > + client.flags |= I2C_CLIENT_TEN; > + > + switch (accessor_type) { > + case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_byte(&client); > + if (status >= 0) { > + gsb->bdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_byte(&client, gsb->bdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_BYTE: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_byte_data(&client, command); > + if (status >= 0) { > + gsb->bdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_byte_data(&client, command, > + gsb->bdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_WORD: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_word_data(&client, command); > + if (status >= 0) { > + gsb->wdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_word_data(&client, command, > + gsb->wdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_BLOCK: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_block_data(&client, command, > + gsb->data); > + if (status >= 0) { > + gsb->len = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_block_data(&client, command, > + gsb->len, gsb->data); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: > + if (action == ACPI_READ) { > + status = acpi_gsb_i2c_read_bytes(&client, command, > + gsb->data, info->access_length); > + if (status > 0) > + status = 0; > + } else { > + status = acpi_gsb_i2c_write_bytes(&client, command, > + gsb->data, info->access_length); > + } > + break; > + > + default: > + pr_info("protocol(0x%02x) is not supported.\n", accessor_type); > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + gsb->status = status; > + > + err: > + ACPI_FREE(ares); > + return ret; > +} > + > + > +int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return -ENODEV; > + > + data = kzalloc(sizeof(struct acpi_i2c_handler_data), > + GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->adapter = adapter; > + status = acpi_bus_attach_private_data(handle, (void *)data); > + if (ACPI_FAILURE(status)) { > + kfree(data); > + return -ENOMEM; > + } > + > + status = acpi_install_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler, > + NULL, > + data); > + if (ACPI_FAILURE(status)) { > + dev_err(&adapter->dev, "Error installing i2c space handler\n"); > + acpi_bus_detach_private_data(handle); > + kfree(data); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return; > + > + acpi_remove_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler); > + > + status = acpi_bus_get_private_data(handle, (void **)&data); > + if (ACPI_SUCCESS(status)) > + kfree(data); > + > + acpi_bus_detach_private_data(handle); > +} > +#endif > +#endif /* CONFIG_ACPI */ > + > /* ------------------------------------------------------------------------- */ > > static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, > -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core @ 2014-09-23 1:37 ` Lan Tianyu 0 siblings, 0 replies; 13+ messages in thread From: Lan Tianyu @ 2014-09-23 1:37 UTC (permalink / raw) To: Wolfram Sang, linux-i2c Cc: linux-acpi, linux-kernel, Mika Westerberg, Jean Delvare On 2014年09月23日 05:06, Wolfram Sang wrote: > Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support") renamed > the i2c-core module. This may cause regressions for distributions, so put the > ACPI code back into the core. No code was changed. > > Reported-by: Jean Delvare <jdelvare@suse.de> > Signed-off-by: Wolfram Sang <wsa@the-dreams.de> > Cc: Mika Westerberg <mika.westerberg@linux.intel.com> > Cc: Lan Tianyu <tianyu.lan@intel.com> > Cc: Jean Delvare <jdelvare@suse.de> > --- > > Lan Tianyi, this is a patch I expected to get from you, fully tested. Since we > are approaching the final release soon, I did it now. Please do test this > patch. All I can do is build test (it works for me, build robots are still > running). If nobody tests this, I have to revert the ACPI changes of this > cycle. Hi Wolfram: Sorry for later response due to sickness. I can't write this patch in time. Sorry again. I will test it soon. > > Jean, can you have a look, too? > > We can think of something better for the next release, but for now, this should be it. > > MAINTAINERS | 1 - > drivers/i2c/Makefile | 5 +- > drivers/i2c/i2c-acpi.c | 364 ------------------------------------------------- > drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 346 insertions(+), 369 deletions(-) > delete mode 100644 drivers/i2c/i2c-acpi.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 809ecd680d88..e3682d0dea1e 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com> > L: linux-i2c@vger.kernel.org > L: linux-acpi@vger.kernel.org > S: Maintained > -F: drivers/i2c/i2c-acpi.c > > I2C-TAOS-EVM DRIVER > M: Jean Delvare <jdelvare@suse.de> > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > index e0228b228256..1722f50f2473 100644 > --- a/drivers/i2c/Makefile > +++ b/drivers/i2c/Makefile > @@ -2,11 +2,8 @@ > # Makefile for the i2c core. > # > > -i2ccore-y := i2c-core.o > -i2ccore-$(CONFIG_ACPI) += i2c-acpi.o > - > obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o > -obj-$(CONFIG_I2C) += i2ccore.o > +obj-$(CONFIG_I2C) += i2c-core.o > obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o > obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o > obj-$(CONFIG_I2C_MUX) += i2c-mux.o > diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c > deleted file mode 100644 > index 0dbc18c15c43..000000000000 > --- a/drivers/i2c/i2c-acpi.c > +++ /dev/null > @@ -1,364 +0,0 @@ > -/* > - * I2C ACPI code > - * > - * Copyright (C) 2014 Intel Corp > - * > - * Author: Lan Tianyu <tianyu.lan@intel.com> > - * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License version 2 as > - * published by the Free Software Foundation. > - * > - * This program is distributed in the hope that it will be useful, but > - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY > - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > - * for more details. > - */ > -#define pr_fmt(fmt) "I2C/ACPI : " fmt > - > -#include <linux/kernel.h> > -#include <linux/errno.h> > -#include <linux/err.h> > -#include <linux/i2c.h> > -#include <linux/acpi.h> > - > -struct acpi_i2c_handler_data { > - struct acpi_connection_info info; > - struct i2c_adapter *adapter; > -}; > - > -struct gsb_buffer { > - u8 status; > - u8 len; > - union { > - u16 wdata; > - u8 bdata; > - u8 data[0]; > - }; > -} __packed; > - > -static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) > -{ > - struct i2c_board_info *info = data; > - > - if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { > - struct acpi_resource_i2c_serialbus *sb; > - > - sb = &ares->data.i2c_serial_bus; > - if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { > - info->addr = sb->slave_address; > - if (sb->access_mode == ACPI_I2C_10BIT_MODE) > - info->flags |= I2C_CLIENT_TEN; > - } > - } else if (info->irq < 0) { > - struct resource r; > - > - if (acpi_dev_resource_interrupt(ares, 0, &r)) > - info->irq = r.start; > - } > - > - /* Tell the ACPI core to skip this resource */ > - return 1; > -} > - > -static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, > - void *data, void **return_value) > -{ > - struct i2c_adapter *adapter = data; > - struct list_head resource_list; > - struct i2c_board_info info; > - struct acpi_device *adev; > - int ret; > - > - if (acpi_bus_get_device(handle, &adev)) > - return AE_OK; > - if (acpi_bus_get_status(adev) || !adev->status.present) > - return AE_OK; > - > - memset(&info, 0, sizeof(info)); > - info.acpi_node.companion = adev; > - info.irq = -1; > - > - INIT_LIST_HEAD(&resource_list); > - ret = acpi_dev_get_resources(adev, &resource_list, > - acpi_i2c_add_resource, &info); > - acpi_dev_free_resource_list(&resource_list); > - > - if (ret < 0 || !info.addr) > - return AE_OK; > - > - adev->power.flags.ignore_parent = true; > - strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); > - if (!i2c_new_device(adapter, &info)) { > - adev->power.flags.ignore_parent = false; > - dev_err(&adapter->dev, > - "failed to add I2C device %s from ACPI\n", > - dev_name(&adev->dev)); > - } > - > - return AE_OK; > -} > - > -/** > - * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > - * @adap: pointer to adapter > - * > - * Enumerate all I2C slave devices behind this adapter by walking the ACPI > - * namespace. When a device is found it will be added to the Linux device > - * model and bound to the corresponding ACPI handle. > - */ > -void acpi_i2c_register_devices(struct i2c_adapter *adap) > -{ > - acpi_handle handle; > - acpi_status status; > - > - if (!adap->dev.parent) > - return; > - > - handle = ACPI_HANDLE(adap->dev.parent); > - if (!handle) > - return; > - > - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > - acpi_i2c_add_device, NULL, > - adap, NULL); > - if (ACPI_FAILURE(status)) > - dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > -} > - > -#ifdef CONFIG_ACPI_I2C_OPREGION > -static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, > - u8 cmd, u8 *data, u8 data_len) > -{ > - > - struct i2c_msg msgs[2]; > - int ret; > - u8 *buffer; > - > - buffer = kzalloc(data_len, GFP_KERNEL); > - if (!buffer) > - return AE_NO_MEMORY; > - > - msgs[0].addr = client->addr; > - msgs[0].flags = client->flags; > - msgs[0].len = 1; > - msgs[0].buf = &cmd; > - > - msgs[1].addr = client->addr; > - msgs[1].flags = client->flags | I2C_M_RD; > - msgs[1].len = data_len; > - msgs[1].buf = buffer; > - > - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > - if (ret < 0) > - dev_err(&client->adapter->dev, "i2c read failed\n"); > - else > - memcpy(data, buffer, data_len); > - > - kfree(buffer); > - return ret; > -} > - > -static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, > - u8 cmd, u8 *data, u8 data_len) > -{ > - > - struct i2c_msg msgs[1]; > - u8 *buffer; > - int ret = AE_OK; > - > - buffer = kzalloc(data_len + 1, GFP_KERNEL); > - if (!buffer) > - return AE_NO_MEMORY; > - > - buffer[0] = cmd; > - memcpy(buffer + 1, data, data_len); > - > - msgs[0].addr = client->addr; > - msgs[0].flags = client->flags; > - msgs[0].len = data_len + 1; > - msgs[0].buf = buffer; > - > - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > - if (ret < 0) > - dev_err(&client->adapter->dev, "i2c write failed\n"); > - > - kfree(buffer); > - return ret; > -} > - > -static acpi_status > -acpi_i2c_space_handler(u32 function, acpi_physical_address command, > - u32 bits, u64 *value64, > - void *handler_context, void *region_context) > -{ > - struct gsb_buffer *gsb = (struct gsb_buffer *)value64; > - struct acpi_i2c_handler_data *data = handler_context; > - struct acpi_connection_info *info = &data->info; > - struct acpi_resource_i2c_serialbus *sb; > - struct i2c_adapter *adapter = data->adapter; > - struct i2c_client client; > - struct acpi_resource *ares; > - u32 accessor_type = function >> 16; > - u8 action = function & ACPI_IO_MASK; > - acpi_status ret = AE_OK; > - int status; > - > - ret = acpi_buffer_to_resource(info->connection, info->length, &ares); > - if (ACPI_FAILURE(ret)) > - return ret; > - > - if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - sb = &ares->data.i2c_serial_bus; > - if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - memset(&client, 0, sizeof(client)); > - client.adapter = adapter; > - client.addr = sb->slave_address; > - client.flags = 0; > - > - if (sb->access_mode == ACPI_I2C_10BIT_MODE) > - client.flags |= I2C_CLIENT_TEN; > - > - switch (accessor_type) { > - case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_byte(&client); > - if (status >= 0) { > - gsb->bdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_byte(&client, gsb->bdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_BYTE: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_byte_data(&client, command); > - if (status >= 0) { > - gsb->bdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_byte_data(&client, command, > - gsb->bdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_WORD: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_word_data(&client, command); > - if (status >= 0) { > - gsb->wdata = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_word_data(&client, command, > - gsb->wdata); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_BLOCK: > - if (action == ACPI_READ) { > - status = i2c_smbus_read_block_data(&client, command, > - gsb->data); > - if (status >= 0) { > - gsb->len = status; > - status = 0; > - } > - } else { > - status = i2c_smbus_write_block_data(&client, command, > - gsb->len, gsb->data); > - } > - break; > - > - case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: > - if (action == ACPI_READ) { > - status = acpi_gsb_i2c_read_bytes(&client, command, > - gsb->data, info->access_length); > - if (status > 0) > - status = 0; > - } else { > - status = acpi_gsb_i2c_write_bytes(&client, command, > - gsb->data, info->access_length); > - } > - break; > - > - default: > - pr_info("protocol(0x%02x) is not supported.\n", accessor_type); > - ret = AE_BAD_PARAMETER; > - goto err; > - } > - > - gsb->status = status; > - > - err: > - ACPI_FREE(ares); > - return ret; > -} > - > - > -int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) > -{ > - acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > - struct acpi_i2c_handler_data *data; > - acpi_status status; > - > - if (!handle) > - return -ENODEV; > - > - data = kzalloc(sizeof(struct acpi_i2c_handler_data), > - GFP_KERNEL); > - if (!data) > - return -ENOMEM; > - > - data->adapter = adapter; > - status = acpi_bus_attach_private_data(handle, (void *)data); > - if (ACPI_FAILURE(status)) { > - kfree(data); > - return -ENOMEM; > - } > - > - status = acpi_install_address_space_handler(handle, > - ACPI_ADR_SPACE_GSBUS, > - &acpi_i2c_space_handler, > - NULL, > - data); > - if (ACPI_FAILURE(status)) { > - dev_err(&adapter->dev, "Error installing i2c space handler\n"); > - acpi_bus_detach_private_data(handle); > - kfree(data); > - return -ENOMEM; > - } > - > - return 0; > -} > - > -void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) > -{ > - acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > - struct acpi_i2c_handler_data *data; > - acpi_status status; > - > - if (!handle) > - return; > - > - acpi_remove_address_space_handler(handle, > - ACPI_ADR_SPACE_GSBUS, > - &acpi_i2c_space_handler); > - > - status = acpi_bus_get_private_data(handle, (void **)&data); > - if (ACPI_SUCCESS(status)) > - kfree(data); > - > - acpi_bus_detach_private_data(handle); > -} > -#endif > diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c > index 632057a44615..3fbd5d5c38bf 100644 > --- a/drivers/i2c/i2c-core.c > +++ b/drivers/i2c/i2c-core.c > @@ -27,6 +27,8 @@ > OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de> > (based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and > (c) 2013 Wolfram Sang <wsa@the-dreams.de> > + I2C ACPI code Copyright (C) 2014 Intel Corp > + Author: Lan Tianyu <tianyu.lan@intel.com> > */ > > #include <linux/module.h> > @@ -78,6 +80,349 @@ void i2c_transfer_trace_unreg(void) > static_key_slow_dec(&i2c_trace_msg); > } > > +#if defined(CONFIG_ACPI) > +struct acpi_i2c_handler_data { > + struct acpi_connection_info info; > + struct i2c_adapter *adapter; > +}; > + > +struct gsb_buffer { > + u8 status; > + u8 len; > + union { > + u16 wdata; > + u8 bdata; > + u8 data[0]; > + }; > +} __packed; > + > +static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data) > +{ > + struct i2c_board_info *info = data; > + > + if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { > + struct acpi_resource_i2c_serialbus *sb; > + > + sb = &ares->data.i2c_serial_bus; > + if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) { > + info->addr = sb->slave_address; > + if (sb->access_mode == ACPI_I2C_10BIT_MODE) > + info->flags |= I2C_CLIENT_TEN; > + } > + } else if (info->irq < 0) { > + struct resource r; > + > + if (acpi_dev_resource_interrupt(ares, 0, &r)) > + info->irq = r.start; > + } > + > + /* Tell the ACPI core to skip this resource */ > + return 1; > +} > + > +static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, > + void *data, void **return_value) > +{ > + struct i2c_adapter *adapter = data; > + struct list_head resource_list; > + struct i2c_board_info info; > + struct acpi_device *adev; > + int ret; > + > + if (acpi_bus_get_device(handle, &adev)) > + return AE_OK; > + if (acpi_bus_get_status(adev) || !adev->status.present) > + return AE_OK; > + > + memset(&info, 0, sizeof(info)); > + info.acpi_node.companion = adev; > + info.irq = -1; > + > + INIT_LIST_HEAD(&resource_list); > + ret = acpi_dev_get_resources(adev, &resource_list, > + acpi_i2c_add_resource, &info); > + acpi_dev_free_resource_list(&resource_list); > + > + if (ret < 0 || !info.addr) > + return AE_OK; > + > + adev->power.flags.ignore_parent = true; > + strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); > + if (!i2c_new_device(adapter, &info)) { > + adev->power.flags.ignore_parent = false; > + dev_err(&adapter->dev, > + "failed to add I2C device %s from ACPI\n", > + dev_name(&adev->dev)); > + } > + > + return AE_OK; > +} > + > +/** > + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > + * @adap: pointer to adapter > + * > + * Enumerate all I2C slave devices behind this adapter by walking the ACPI > + * namespace. When a device is found it will be added to the Linux device > + * model and bound to the corresponding ACPI handle. > + */ > +void acpi_i2c_register_devices(struct i2c_adapter *adap) > +{ > + acpi_handle handle; > + acpi_status status; > + > + if (!adap->dev.parent) > + return; > + > + handle = ACPI_HANDLE(adap->dev.parent); > + if (!handle) > + return; > + > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > + acpi_i2c_add_device, NULL, > + adap, NULL); > + if (ACPI_FAILURE(status)) > + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > +} > + > +#ifdef CONFIG_ACPI_I2C_OPREGION > +static int acpi_gsb_i2c_read_bytes(struct i2c_client *client, > + u8 cmd, u8 *data, u8 data_len) > +{ > + > + struct i2c_msg msgs[2]; > + int ret; > + u8 *buffer; > + > + buffer = kzalloc(data_len, GFP_KERNEL); > + if (!buffer) > + return AE_NO_MEMORY; > + > + msgs[0].addr = client->addr; > + msgs[0].flags = client->flags; > + msgs[0].len = 1; > + msgs[0].buf = &cmd; > + > + msgs[1].addr = client->addr; > + msgs[1].flags = client->flags | I2C_M_RD; > + msgs[1].len = data_len; > + msgs[1].buf = buffer; > + > + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > + if (ret < 0) > + dev_err(&client->adapter->dev, "i2c read failed\n"); > + else > + memcpy(data, buffer, data_len); > + > + kfree(buffer); > + return ret; > +} > + > +static int acpi_gsb_i2c_write_bytes(struct i2c_client *client, > + u8 cmd, u8 *data, u8 data_len) > +{ > + > + struct i2c_msg msgs[1]; > + u8 *buffer; > + int ret = AE_OK; > + > + buffer = kzalloc(data_len + 1, GFP_KERNEL); > + if (!buffer) > + return AE_NO_MEMORY; > + > + buffer[0] = cmd; > + memcpy(buffer + 1, data, data_len); > + > + msgs[0].addr = client->addr; > + msgs[0].flags = client->flags; > + msgs[0].len = data_len + 1; > + msgs[0].buf = buffer; > + > + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); > + if (ret < 0) > + dev_err(&client->adapter->dev, "i2c write failed\n"); > + > + kfree(buffer); > + return ret; > +} > + > +static acpi_status > +acpi_i2c_space_handler(u32 function, acpi_physical_address command, > + u32 bits, u64 *value64, > + void *handler_context, void *region_context) > +{ > + struct gsb_buffer *gsb = (struct gsb_buffer *)value64; > + struct acpi_i2c_handler_data *data = handler_context; > + struct acpi_connection_info *info = &data->info; > + struct acpi_resource_i2c_serialbus *sb; > + struct i2c_adapter *adapter = data->adapter; > + struct i2c_client client; > + struct acpi_resource *ares; > + u32 accessor_type = function >> 16; > + u8 action = function & ACPI_IO_MASK; > + acpi_status ret = AE_OK; > + int status; > + > + ret = acpi_buffer_to_resource(info->connection, info->length, &ares); > + if (ACPI_FAILURE(ret)) > + return ret; > + > + if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) { > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + sb = &ares->data.i2c_serial_bus; > + if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) { > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + memset(&client, 0, sizeof(client)); > + client.adapter = adapter; > + client.addr = sb->slave_address; > + client.flags = 0; > + > + if (sb->access_mode == ACPI_I2C_10BIT_MODE) > + client.flags |= I2C_CLIENT_TEN; > + > + switch (accessor_type) { > + case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_byte(&client); > + if (status >= 0) { > + gsb->bdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_byte(&client, gsb->bdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_BYTE: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_byte_data(&client, command); > + if (status >= 0) { > + gsb->bdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_byte_data(&client, command, > + gsb->bdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_WORD: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_word_data(&client, command); > + if (status >= 0) { > + gsb->wdata = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_word_data(&client, command, > + gsb->wdata); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_BLOCK: > + if (action == ACPI_READ) { > + status = i2c_smbus_read_block_data(&client, command, > + gsb->data); > + if (status >= 0) { > + gsb->len = status; > + status = 0; > + } > + } else { > + status = i2c_smbus_write_block_data(&client, command, > + gsb->len, gsb->data); > + } > + break; > + > + case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE: > + if (action == ACPI_READ) { > + status = acpi_gsb_i2c_read_bytes(&client, command, > + gsb->data, info->access_length); > + if (status > 0) > + status = 0; > + } else { > + status = acpi_gsb_i2c_write_bytes(&client, command, > + gsb->data, info->access_length); > + } > + break; > + > + default: > + pr_info("protocol(0x%02x) is not supported.\n", accessor_type); > + ret = AE_BAD_PARAMETER; > + goto err; > + } > + > + gsb->status = status; > + > + err: > + ACPI_FREE(ares); > + return ret; > +} > + > + > +int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return -ENODEV; > + > + data = kzalloc(sizeof(struct acpi_i2c_handler_data), > + GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->adapter = adapter; > + status = acpi_bus_attach_private_data(handle, (void *)data); > + if (ACPI_FAILURE(status)) { > + kfree(data); > + return -ENOMEM; > + } > + > + status = acpi_install_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler, > + NULL, > + data); > + if (ACPI_FAILURE(status)) { > + dev_err(&adapter->dev, "Error installing i2c space handler\n"); > + acpi_bus_detach_private_data(handle); > + kfree(data); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return; > + > + acpi_remove_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler); > + > + status = acpi_bus_get_private_data(handle, (void **)&data); > + if (ACPI_SUCCESS(status)) > + kfree(data); > + > + acpi_bus_detach_private_data(handle); > +} > +#endif > +#endif /* CONFIG_ACPI */ > + > /* ------------------------------------------------------------------------- */ > > static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, > -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <5420CEC9.1030400-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>]
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-23 1:37 ` Lan Tianyu @ 2014-09-23 5:39 ` Wolfram Sang -1 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2014-09-23 5:39 UTC (permalink / raw) To: Lan Tianyu Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mika Westerberg, Jean Delvare [-- Attachment #1: Type: text/plain, Size: 172 bytes --] > Sorry for later response due to sickness. I can't write this patch in > time. Sorry again. I will test it soon. Oh, get well soon! Please say so next time, so I know. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core @ 2014-09-23 5:39 ` Wolfram Sang 0 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2014-09-23 5:39 UTC (permalink / raw) To: Lan Tianyu Cc: linux-i2c, linux-acpi, linux-kernel, Mika Westerberg, Jean Delvare [-- Attachment #1: Type: text/plain, Size: 172 bytes --] > Sorry for later response due to sickness. I can't write this patch in > time. Sorry again. I will test it soon. Oh, get well soon! Please say so next time, so I know. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-23 5:39 ` Wolfram Sang @ 2014-09-23 7:09 ` Lan Tianyu -1 siblings, 0 replies; 13+ messages in thread From: Lan Tianyu @ 2014-09-23 7:09 UTC (permalink / raw) To: Wolfram Sang Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Mika Westerberg, Jean Delvare On 2014年09月23日 13:39, Wolfram Sang wrote: > >> Sorry for later response due to sickness. I can't write this patch in >> time. Sorry again. I will test it soon. > > Oh, get well soon! Please say so next time, so I know. > Thanks. OK. I have put the patch into test system and need to wait some time. -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core @ 2014-09-23 7:09 ` Lan Tianyu 0 siblings, 0 replies; 13+ messages in thread From: Lan Tianyu @ 2014-09-23 7:09 UTC (permalink / raw) To: Wolfram Sang Cc: linux-i2c, linux-acpi, linux-kernel, Mika Westerberg, Jean Delvare On 2014年09月23日 13:39, Wolfram Sang wrote: > >> Sorry for later response due to sickness. I can't write this patch in >> time. Sorry again. I will test it soon. > > Oh, get well soon! Please say so next time, so I know. > Thanks. OK. I have put the patch into test system and need to wait some time. -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-23 7:09 ` Lan Tianyu (?) @ 2014-09-23 9:14 ` Lan Tianyu 2014-09-24 15:44 ` Wolfram Sang -1 siblings, 1 reply; 13+ messages in thread From: Lan Tianyu @ 2014-09-23 9:14 UTC (permalink / raw) To: Wolfram Sang Cc: linux-i2c, linux-acpi, linux-kernel, Mika Westerberg, Jean Delvare, Wu, Fengguang On 2014年09月23日 15:09, Lan Tianyu wrote: > On 2014年09月23日 13:39, Wolfram Sang wrote: >> >>> Sorry for later response due to sickness. I can't write this patch in >>> time. Sorry again. I will test it soon. >> >> Oh, get well soon! Please say so next time, so I know. >> > > Thanks. OK. > I have put the patch into test system and need to wait some time. > Hi Wolfram: The patch passed through the following 110 configure build test in the 0-day build test system. configs tested: 110 mips allmodconfig mips jz4740 mips allnoconfig mips fuloong2e_defconfig mips txx9 x86_64 allnoconfig sh titan_defconfig sh rsk7269_defconfig sh sh7785lcr_32bit_defconfig sh allnoconfig x86_64 randconfig-c3-0923 x86_64 randconfig-c1-0923 x86_64 randconfig-c2-0923 x86_64 randconfig-c0-0923 arm omap2plus_defconfig arm sa1100 arm allmodconfig arm prima2_defconfig arm at91_dt_defconfig arm allnoconfig arm samsung arm spear13xx_defconfig arm s3c2410_defconfig arm iop-adma arm imx_v6_v7_defconfig arm mmp arm tegra_defconfig arm arm5 arm marzen_defconfig arm at_hdmac arm ep93xx arm sh arm arm67 parisc c3000_defconfig parisc b180_defconfig parisc defconfig alpha defconfig parisc allnoconfig powerpc iss476-smp_defconfig powerpc mpc8315_rdb_defconfig mips ath79_defconfig arm bcm_defconfig powerpc gef_ppc9a_defconfig i386 randconfig-ha0-0923 i386 randconfig-ha1-0923 i386 randconfig-ha2-0923 i386 randconfig-ha3-0923 ia64 allmodconfig ia64 allnoconfig ia64 defconfig ia64 alldefconfig microblaze mmu_defconfig microblaze nommu_defconfig microblaze allyesconfig s390 allmodconfig s390 allnoconfig s390 defconfig x86_64 randconfig-ha1-0923 x86_64 randconfig-ha3-0923 x86_64 randconfig-ha0-0923 x86_64 randconfig-ha2-0923 xtensa common_defconfig m32r m32104ut_defconfig xtensa iss_defconfig m32r opsput_defconfig m32r usrv_defconfig m32r mappi3.smp_defconfig sparc defconfig sparc64 allnoconfig sparc64 defconfig i386 allyesconfig cris etrax-100lx_v2_defconfig blackfin TCM-BF537_defconfig blackfin BF561-EZKIT-SMP_defconfig blackfin BF533-EZKIT_defconfig blackfin BF526-EZBRD_defconfig i386 randconfig-r0-0923 i386 randconfig-r2-0923 i386 randconfig-r3-0923 i386 randconfig-r1-0923 x86_64 randconfig-s0-09231616 x86_64 randconfig Hi Wolfram: The patch passed through the following 110 configure build test in the 0-day build test system.-s1-09231616 x86_64 allmodconfig i386 alldefconfig i386 allmodconfig i386 allnoconfig i386 defconfig i386 randconfig-x009-0922 x86_64 randconfig-x003-0922 x86_64 randconfig-x004-0922 i386 randconfig-x006-0922 x86_64 randconfig-x001-0922 i386 randconfig-x005-0922 x86_64 randconfig-x006-0922 i386 randconfig-x001-0922 i386 randconfig-x004-0922 i386 randconfig-x003-0922 i386 randconfig-x000-0922 x86_64 randconfig-x002-0922 x86_64 randconfig-x008-0922 i386 randconfig-x008-0922 i386 randconfig-x007-0922 x86_64 randconfig-x009-0922 x86_64 randconfig-x000-0922 x86_64 randconfig-x007-0922 i386 randconfig-x002-0922 x86_64 randconfig-x005-0922 x86_64 acpi-redef x86_64 allyesdebian x86_64 nfsroot -- Best regards Tianyu Lan ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-23 9:14 ` Lan Tianyu @ 2014-09-24 15:44 ` Wolfram Sang 0 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2014-09-24 15:44 UTC (permalink / raw) To: Lan Tianyu Cc: linux-i2c, linux-acpi, linux-kernel, Mika Westerberg, Jean Delvare, Wu, Fengguang [-- Attachment #1: Type: text/plain, Size: 244 bytes --] > Hi Wolfram: > The patch passed through the following 110 configure build test in the > 0-day build test system. Thanks, but my tree gets checked automatically anyhow. What I'd need is functional tests because I don't have hardware to test. [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-22 21:06 [PATCH] i2c: move acpi code back into the core Wolfram Sang @ 2014-09-23 9:14 ` Mika Westerberg 0 siblings, 0 replies; 13+ messages in thread From: Mika Westerberg @ 2014-09-23 9:14 UTC (permalink / raw) To: Wolfram Sang Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, linux-acpi-u79uwXL29TY76Z2rM5mHXA, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Lan Tianyu, Jean Delvare On Mon, Sep 22, 2014 at 11:06:46PM +0200, Wolfram Sang wrote: > Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support") renamed > the i2c-core module. This may cause regressions for distributions, so put the > ACPI code back into the core. No code was changed. Thanks Wolfram for doing this! I tested this already and it of course works but there are few things that you are missing so this probably needs an additional iteration. > Reported-by: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> > Signed-off-by: Wolfram Sang <wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org> > Cc: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> > Cc: Lan Tianyu <tianyu.lan-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> > Cc: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> > --- > > Lan Tianyi, this is a patch I expected to get from you, fully tested. Since we > are approaching the final release soon, I did it now. Please do test this > patch. All I can do is build test (it works for me, build robots are still > running). If nobody tests this, I have to revert the ACPI changes of this > cycle. > > Jean, can you have a look, too? > > We can think of something better for the next release, but for now, this should be it. > > MAINTAINERS | 1 - > drivers/i2c/Makefile | 5 +- > drivers/i2c/i2c-acpi.c | 364 ------------------------------------------------- > drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 346 insertions(+), 369 deletions(-) > delete mode 100644 drivers/i2c/i2c-acpi.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 809ecd680d88..e3682d0dea1e 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> > L: linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > L: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org > S: Maintained > -F: drivers/i2c/i2c-acpi.c You can remove my name from MAINTANERS as well. I'm not I2C subsystem maintainer :) Of course I will still assist reviewing ACPI related changes in i2c-core.c. > I2C-TAOS-EVM DRIVER > M: Jean Delvare <jdelvare-l3A5Bk7waGM@public.gmane.org> ... > +/** > + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > + * @adap: pointer to adapter > + * > + * Enumerate all I2C slave devices behind this adapter by walking the ACPI > + * namespace. When a device is found it will be added to the Linux device > + * model and bound to the corresponding ACPI handle. > + */ > +void acpi_i2c_register_devices(struct i2c_adapter *adap) static > +{ > + acpi_handle handle; > + acpi_status status; > + > + if (!adap->dev.parent) > + return; > + > + handle = ACPI_HANDLE(adap->dev.parent); > + if (!handle) > + return; > + > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > + acpi_i2c_add_device, NULL, > + adap, NULL); > + if (ACPI_FAILURE(status)) > + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > +} > + ... > +int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) static > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return -ENODEV; > + > + data = kzalloc(sizeof(struct acpi_i2c_handler_data), > + GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->adapter = adapter; > + status = acpi_bus_attach_private_data(handle, (void *)data); > + if (ACPI_FAILURE(status)) { > + kfree(data); > + return -ENOMEM; > + } > + > + status = acpi_install_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler, > + NULL, > + data); > + if (ACPI_FAILURE(status)) { > + dev_err(&adapter->dev, "Error installing i2c space handler\n"); > + acpi_bus_detach_private_data(handle); > + kfree(data); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) static > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return; > + > + acpi_remove_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler); > + > + status = acpi_bus_get_private_data(handle, (void **)&data); > + if (ACPI_SUCCESS(status)) > + kfree(data); > + > + acpi_bus_detach_private_data(handle); > +} > +#endif I would put there #endif /* CONFIG_ACPI_I2C_OPREGION */ > +#endif /* CONFIG_ACPI */ Also please remove all ACPI related stuff in include/linux/i2c.h. That is not needed anymore. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core @ 2014-09-23 9:14 ` Mika Westerberg 0 siblings, 0 replies; 13+ messages in thread From: Mika Westerberg @ 2014-09-23 9:14 UTC (permalink / raw) To: Wolfram Sang Cc: linux-i2c, linux-acpi, linux-kernel, Lan Tianyu, Jean Delvare On Mon, Sep 22, 2014 at 11:06:46PM +0200, Wolfram Sang wrote: > Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support") renamed > the i2c-core module. This may cause regressions for distributions, so put the > ACPI code back into the core. No code was changed. Thanks Wolfram for doing this! I tested this already and it of course works but there are few things that you are missing so this probably needs an additional iteration. > Reported-by: Jean Delvare <jdelvare@suse.de> > Signed-off-by: Wolfram Sang <wsa@the-dreams.de> > Cc: Mika Westerberg <mika.westerberg@linux.intel.com> > Cc: Lan Tianyu <tianyu.lan@intel.com> > Cc: Jean Delvare <jdelvare@suse.de> > --- > > Lan Tianyi, this is a patch I expected to get from you, fully tested. Since we > are approaching the final release soon, I did it now. Please do test this > patch. All I can do is build test (it works for me, build robots are still > running). If nobody tests this, I have to revert the ACPI changes of this > cycle. > > Jean, can you have a look, too? > > We can think of something better for the next release, but for now, this should be it. > > MAINTAINERS | 1 - > drivers/i2c/Makefile | 5 +- > drivers/i2c/i2c-acpi.c | 364 ------------------------------------------------- > drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 346 insertions(+), 369 deletions(-) > delete mode 100644 drivers/i2c/i2c-acpi.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index 809ecd680d88..e3682d0dea1e 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com> > L: linux-i2c@vger.kernel.org > L: linux-acpi@vger.kernel.org > S: Maintained > -F: drivers/i2c/i2c-acpi.c You can remove my name from MAINTANERS as well. I'm not I2C subsystem maintainer :) Of course I will still assist reviewing ACPI related changes in i2c-core.c. > I2C-TAOS-EVM DRIVER > M: Jean Delvare <jdelvare@suse.de> ... > +/** > + * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter > + * @adap: pointer to adapter > + * > + * Enumerate all I2C slave devices behind this adapter by walking the ACPI > + * namespace. When a device is found it will be added to the Linux device > + * model and bound to the corresponding ACPI handle. > + */ > +void acpi_i2c_register_devices(struct i2c_adapter *adap) static > +{ > + acpi_handle handle; > + acpi_status status; > + > + if (!adap->dev.parent) > + return; > + > + handle = ACPI_HANDLE(adap->dev.parent); > + if (!handle) > + return; > + > + status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, > + acpi_i2c_add_device, NULL, > + adap, NULL); > + if (ACPI_FAILURE(status)) > + dev_warn(&adap->dev, "failed to enumerate I2C slaves\n"); > +} > + ... > +int acpi_i2c_install_space_handler(struct i2c_adapter *adapter) static > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return -ENODEV; > + > + data = kzalloc(sizeof(struct acpi_i2c_handler_data), > + GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->adapter = adapter; > + status = acpi_bus_attach_private_data(handle, (void *)data); > + if (ACPI_FAILURE(status)) { > + kfree(data); > + return -ENOMEM; > + } > + > + status = acpi_install_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler, > + NULL, > + data); > + if (ACPI_FAILURE(status)) { > + dev_err(&adapter->dev, "Error installing i2c space handler\n"); > + acpi_bus_detach_private_data(handle); > + kfree(data); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter) static > +{ > + acpi_handle handle = ACPI_HANDLE(adapter->dev.parent); > + struct acpi_i2c_handler_data *data; > + acpi_status status; > + > + if (!handle) > + return; > + > + acpi_remove_address_space_handler(handle, > + ACPI_ADR_SPACE_GSBUS, > + &acpi_i2c_space_handler); > + > + status = acpi_bus_get_private_data(handle, (void **)&data); > + if (ACPI_SUCCESS(status)) > + kfree(data); > + > + acpi_bus_detach_private_data(handle); > +} > +#endif I would put there #endif /* CONFIG_ACPI_I2C_OPREGION */ > +#endif /* CONFIG_ACPI */ Also please remove all ACPI related stuff in include/linux/i2c.h. That is not needed anymore. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] i2c: move acpi code back into the core 2014-09-23 9:14 ` Mika Westerberg (?) @ 2014-09-24 15:44 ` Wolfram Sang -1 siblings, 0 replies; 13+ messages in thread From: Wolfram Sang @ 2014-09-24 15:44 UTC (permalink / raw) To: Mika Westerberg Cc: linux-i2c, linux-acpi, linux-kernel, Lan Tianyu, Jean Delvare [-- Attachment #1: Type: text/plain, Size: 968 bytes --] > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 809ecd680d88..e3682d0dea1e 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com> > > L: linux-i2c@vger.kernel.org > > L: linux-acpi@vger.kernel.org > > S: Maintained > > -F: drivers/i2c/i2c-acpi.c > > You can remove my name from MAINTANERS as well. I'm not I2C subsystem > maintainer :) Of course I will still assist reviewing ACPI related > changes in i2c-core.c. I'd like to keep this since the header says I2C/ACPI. I am thinking of adding something like 'K: i2c_.*acpi_' but that can wait. For now, we need a working solution _very_ soon. > > +#endif > > I would put there > > #endif /* CONFIG_ACPI_I2C_OPREGION */ I didn't want to change lines not written by me, but well yeah... > Also please remove all ACPI related stuff in include/linux/i2c.h. That > is not needed anymore. Yup, thanks! [-- Attachment #2: Digital signature --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH] i2c: move acpi code back into the core
@ 2014-09-22 21:03 Wolfram Sang
0 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2014-09-22 21:03 UTC (permalink / raw)
To: linux-i2c
Cc: linux-acpi, linux-kernel, Wolfram Sang, Mika Westerberg,
Lan Tianyu
Commit 5d98e61d337c ("I2C/ACPI: Add i2c ACPI operation region support")
renamed the i2c-core module. This may cause regressions for
distributions, so put the ACPI code back into the core.
Reported-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Lan Tianyu <tianyu.lan@intel.com>
---
MAINTAINERS | 1 -
drivers/i2c/Makefile | 5 +-
drivers/i2c/i2c-acpi.c | 364 -------------------------------------------------
drivers/i2c/i2c-core.c | 345 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 346 insertions(+), 369 deletions(-)
delete mode 100644 drivers/i2c/i2c-acpi.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 809ecd680d88..e3682d0dea1e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4477,7 +4477,6 @@ M: Mika Westerberg <mika.westerberg@linux.intel.com>
L: linux-i2c@vger.kernel.org
L: linux-acpi@vger.kernel.org
S: Maintained
-F: drivers/i2c/i2c-acpi.c
I2C-TAOS-EVM DRIVER
M: Jean Delvare <jdelvare@suse.de>
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index e0228b228256..1722f50f2473 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -2,11 +2,8 @@
# Makefile for the i2c core.
#
-i2ccore-y := i2c-core.o
-i2ccore-$(CONFIG_ACPI) += i2c-acpi.o
-
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
-obj-$(CONFIG_I2C) += i2ccore.o
+obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c
deleted file mode 100644
index 0dbc18c15c43..000000000000
--- a/drivers/i2c/i2c-acpi.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * I2C ACPI code
- *
- * Copyright (C) 2014 Intel Corp
- *
- * Author: Lan Tianyu <tianyu.lan@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-#define pr_fmt(fmt) "I2C/ACPI : " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/acpi.h>
-
-struct acpi_i2c_handler_data {
- struct acpi_connection_info info;
- struct i2c_adapter *adapter;
-};
-
-struct gsb_buffer {
- u8 status;
- u8 len;
- union {
- u16 wdata;
- u8 bdata;
- u8 data[0];
- };
-} __packed;
-
-static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
-{
- struct i2c_board_info *info = data;
-
- if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- struct acpi_resource_i2c_serialbus *sb;
-
- sb = &ares->data.i2c_serial_bus;
- if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
- info->addr = sb->slave_address;
- if (sb->access_mode == ACPI_I2C_10BIT_MODE)
- info->flags |= I2C_CLIENT_TEN;
- }
- } else if (info->irq < 0) {
- struct resource r;
-
- if (acpi_dev_resource_interrupt(ares, 0, &r))
- info->irq = r.start;
- }
-
- /* Tell the ACPI core to skip this resource */
- return 1;
-}
-
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
- void *data, void **return_value)
-{
- struct i2c_adapter *adapter = data;
- struct list_head resource_list;
- struct i2c_board_info info;
- struct acpi_device *adev;
- int ret;
-
- if (acpi_bus_get_device(handle, &adev))
- return AE_OK;
- if (acpi_bus_get_status(adev) || !adev->status.present)
- return AE_OK;
-
- memset(&info, 0, sizeof(info));
- info.acpi_node.companion = adev;
- info.irq = -1;
-
- INIT_LIST_HEAD(&resource_list);
- ret = acpi_dev_get_resources(adev, &resource_list,
- acpi_i2c_add_resource, &info);
- acpi_dev_free_resource_list(&resource_list);
-
- if (ret < 0 || !info.addr)
- return AE_OK;
-
- adev->power.flags.ignore_parent = true;
- strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
- if (!i2c_new_device(adapter, &info)) {
- adev->power.flags.ignore_parent = false;
- dev_err(&adapter->dev,
- "failed to add I2C device %s from ACPI\n",
- dev_name(&adev->dev));
- }
-
- return AE_OK;
-}
-
-/**
- * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
- * @adap: pointer to adapter
- *
- * Enumerate all I2C slave devices behind this adapter by walking the ACPI
- * namespace. When a device is found it will be added to the Linux device
- * model and bound to the corresponding ACPI handle.
- */
-void acpi_i2c_register_devices(struct i2c_adapter *adap)
-{
- acpi_handle handle;
- acpi_status status;
-
- if (!adap->dev.parent)
- return;
-
- handle = ACPI_HANDLE(adap->dev.parent);
- if (!handle)
- return;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
- acpi_i2c_add_device, NULL,
- adap, NULL);
- if (ACPI_FAILURE(status))
- dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
-}
-
-#ifdef CONFIG_ACPI_I2C_OPREGION
-static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
- u8 cmd, u8 *data, u8 data_len)
-{
-
- struct i2c_msg msgs[2];
- int ret;
- u8 *buffer;
-
- buffer = kzalloc(data_len, GFP_KERNEL);
- if (!buffer)
- return AE_NO_MEMORY;
-
- msgs[0].addr = client->addr;
- msgs[0].flags = client->flags;
- msgs[0].len = 1;
- msgs[0].buf = &cmd;
-
- msgs[1].addr = client->addr;
- msgs[1].flags = client->flags | I2C_M_RD;
- msgs[1].len = data_len;
- msgs[1].buf = buffer;
-
- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (ret < 0)
- dev_err(&client->adapter->dev, "i2c read failed\n");
- else
- memcpy(data, buffer, data_len);
-
- kfree(buffer);
- return ret;
-}
-
-static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
- u8 cmd, u8 *data, u8 data_len)
-{
-
- struct i2c_msg msgs[1];
- u8 *buffer;
- int ret = AE_OK;
-
- buffer = kzalloc(data_len + 1, GFP_KERNEL);
- if (!buffer)
- return AE_NO_MEMORY;
-
- buffer[0] = cmd;
- memcpy(buffer + 1, data, data_len);
-
- msgs[0].addr = client->addr;
- msgs[0].flags = client->flags;
- msgs[0].len = data_len + 1;
- msgs[0].buf = buffer;
-
- ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
- if (ret < 0)
- dev_err(&client->adapter->dev, "i2c write failed\n");
-
- kfree(buffer);
- return ret;
-}
-
-static acpi_status
-acpi_i2c_space_handler(u32 function, acpi_physical_address command,
- u32 bits, u64 *value64,
- void *handler_context, void *region_context)
-{
- struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
- struct acpi_i2c_handler_data *data = handler_context;
- struct acpi_connection_info *info = &data->info;
- struct acpi_resource_i2c_serialbus *sb;
- struct i2c_adapter *adapter = data->adapter;
- struct i2c_client client;
- struct acpi_resource *ares;
- u32 accessor_type = function >> 16;
- u8 action = function & ACPI_IO_MASK;
- acpi_status ret = AE_OK;
- int status;
-
- ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
- if (ACPI_FAILURE(ret))
- return ret;
-
- if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- sb = &ares->data.i2c_serial_bus;
- if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- memset(&client, 0, sizeof(client));
- client.adapter = adapter;
- client.addr = sb->slave_address;
- client.flags = 0;
-
- if (sb->access_mode == ACPI_I2C_10BIT_MODE)
- client.flags |= I2C_CLIENT_TEN;
-
- switch (accessor_type) {
- case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_byte(&client);
- if (status >= 0) {
- gsb->bdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_byte(&client, gsb->bdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_BYTE:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_byte_data(&client, command);
- if (status >= 0) {
- gsb->bdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_byte_data(&client, command,
- gsb->bdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_WORD:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_word_data(&client, command);
- if (status >= 0) {
- gsb->wdata = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_word_data(&client, command,
- gsb->wdata);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
- if (action == ACPI_READ) {
- status = i2c_smbus_read_block_data(&client, command,
- gsb->data);
- if (status >= 0) {
- gsb->len = status;
- status = 0;
- }
- } else {
- status = i2c_smbus_write_block_data(&client, command,
- gsb->len, gsb->data);
- }
- break;
-
- case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
- if (action == ACPI_READ) {
- status = acpi_gsb_i2c_read_bytes(&client, command,
- gsb->data, info->access_length);
- if (status > 0)
- status = 0;
- } else {
- status = acpi_gsb_i2c_write_bytes(&client, command,
- gsb->data, info->access_length);
- }
- break;
-
- default:
- pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
- ret = AE_BAD_PARAMETER;
- goto err;
- }
-
- gsb->status = status;
-
- err:
- ACPI_FREE(ares);
- return ret;
-}
-
-
-int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
-{
- acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
- struct acpi_i2c_handler_data *data;
- acpi_status status;
-
- if (!handle)
- return -ENODEV;
-
- data = kzalloc(sizeof(struct acpi_i2c_handler_data),
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- data->adapter = adapter;
- status = acpi_bus_attach_private_data(handle, (void *)data);
- if (ACPI_FAILURE(status)) {
- kfree(data);
- return -ENOMEM;
- }
-
- status = acpi_install_address_space_handler(handle,
- ACPI_ADR_SPACE_GSBUS,
- &acpi_i2c_space_handler,
- NULL,
- data);
- if (ACPI_FAILURE(status)) {
- dev_err(&adapter->dev, "Error installing i2c space handler\n");
- acpi_bus_detach_private_data(handle);
- kfree(data);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
-{
- acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
- struct acpi_i2c_handler_data *data;
- acpi_status status;
-
- if (!handle)
- return;
-
- acpi_remove_address_space_handler(handle,
- ACPI_ADR_SPACE_GSBUS,
- &acpi_i2c_space_handler);
-
- status = acpi_bus_get_private_data(handle, (void **)&data);
- if (ACPI_SUCCESS(status))
- kfree(data);
-
- acpi_bus_detach_private_data(handle);
-}
-#endif
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 632057a44615..3fbd5d5c38bf 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -27,6 +27,8 @@
OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
(based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
(c) 2013 Wolfram Sang <wsa@the-dreams.de>
+ I2C ACPI code Copyright (C) 2014 Intel Corp
+ Author: Lan Tianyu <tianyu.lan@intel.com>
*/
#include <linux/module.h>
@@ -78,6 +80,349 @@ void i2c_transfer_trace_unreg(void)
static_key_slow_dec(&i2c_trace_msg);
}
+#if defined(CONFIG_ACPI)
+struct acpi_i2c_handler_data {
+ struct acpi_connection_info info;
+ struct i2c_adapter *adapter;
+};
+
+struct gsb_buffer {
+ u8 status;
+ u8 len;
+ union {
+ u16 wdata;
+ u8 bdata;
+ u8 data[0];
+ };
+} __packed;
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+ struct i2c_board_info *info = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ struct acpi_resource_i2c_serialbus *sb;
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ info->addr = sb->slave_address;
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ info->flags |= I2C_CLIENT_TEN;
+ }
+ } else if (info->irq < 0) {
+ struct resource r;
+
+ if (acpi_dev_resource_interrupt(ares, 0, &r))
+ info->irq = r.start;
+ }
+
+ /* Tell the ACPI core to skip this resource */
+ return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+ void *data, void **return_value)
+{
+ struct i2c_adapter *adapter = data;
+ struct list_head resource_list;
+ struct i2c_board_info info;
+ struct acpi_device *adev;
+ int ret;
+
+ if (acpi_bus_get_device(handle, &adev))
+ return AE_OK;
+ if (acpi_bus_get_status(adev) || !adev->status.present)
+ return AE_OK;
+
+ memset(&info, 0, sizeof(info));
+ info.acpi_node.companion = adev;
+ info.irq = -1;
+
+ INIT_LIST_HEAD(&resource_list);
+ ret = acpi_dev_get_resources(adev, &resource_list,
+ acpi_i2c_add_resource, &info);
+ acpi_dev_free_resource_list(&resource_list);
+
+ if (ret < 0 || !info.addr)
+ return AE_OK;
+
+ adev->power.flags.ignore_parent = true;
+ strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+ if (!i2c_new_device(adapter, &info)) {
+ adev->power.flags.ignore_parent = false;
+ dev_err(&adapter->dev,
+ "failed to add I2C device %s from ACPI\n",
+ dev_name(&adev->dev));
+ }
+
+ return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adap: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+void acpi_i2c_register_devices(struct i2c_adapter *adap)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!adap->dev.parent)
+ return;
+
+ handle = ACPI_HANDLE(adap->dev.parent);
+ if (!handle)
+ return;
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ acpi_i2c_add_device, NULL,
+ adap, NULL);
+ if (ACPI_FAILURE(status))
+ dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+}
+
+#ifdef CONFIG_ACPI_I2C_OPREGION
+static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[2];
+ int ret;
+ u8 *buffer;
+
+ buffer = kzalloc(data_len, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = 1;
+ msgs[0].buf = &cmd;
+
+ msgs[1].addr = client->addr;
+ msgs[1].flags = client->flags | I2C_M_RD;
+ msgs[1].len = data_len;
+ msgs[1].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c read failed\n");
+ else
+ memcpy(data, buffer, data_len);
+
+ kfree(buffer);
+ return ret;
+}
+
+static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
+ u8 cmd, u8 *data, u8 data_len)
+{
+
+ struct i2c_msg msgs[1];
+ u8 *buffer;
+ int ret = AE_OK;
+
+ buffer = kzalloc(data_len + 1, GFP_KERNEL);
+ if (!buffer)
+ return AE_NO_MEMORY;
+
+ buffer[0] = cmd;
+ memcpy(buffer + 1, data, data_len);
+
+ msgs[0].addr = client->addr;
+ msgs[0].flags = client->flags;
+ msgs[0].len = data_len + 1;
+ msgs[0].buf = buffer;
+
+ ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+ if (ret < 0)
+ dev_err(&client->adapter->dev, "i2c write failed\n");
+
+ kfree(buffer);
+ return ret;
+}
+
+static acpi_status
+acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+ u32 bits, u64 *value64,
+ void *handler_context, void *region_context)
+{
+ struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
+ struct acpi_i2c_handler_data *data = handler_context;
+ struct acpi_connection_info *info = &data->info;
+ struct acpi_resource_i2c_serialbus *sb;
+ struct i2c_adapter *adapter = data->adapter;
+ struct i2c_client client;
+ struct acpi_resource *ares;
+ u32 accessor_type = function >> 16;
+ u8 action = function & ACPI_IO_MASK;
+ acpi_status ret = AE_OK;
+ int status;
+
+ ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
+ if (ACPI_FAILURE(ret))
+ return ret;
+
+ if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ sb = &ares->data.i2c_serial_bus;
+ if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ memset(&client, 0, sizeof(client));
+ client.adapter = adapter;
+ client.addr = sb->slave_address;
+ client.flags = 0;
+
+ if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+ client.flags |= I2C_CLIENT_TEN;
+
+ switch (accessor_type) {
+ case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte(&client);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte(&client, gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BYTE:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_byte_data(&client, command);
+ if (status >= 0) {
+ gsb->bdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_byte_data(&client, command,
+ gsb->bdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_WORD:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_word_data(&client, command);
+ if (status >= 0) {
+ gsb->wdata = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_word_data(&client, command,
+ gsb->wdata);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
+ if (action == ACPI_READ) {
+ status = i2c_smbus_read_block_data(&client, command,
+ gsb->data);
+ if (status >= 0) {
+ gsb->len = status;
+ status = 0;
+ }
+ } else {
+ status = i2c_smbus_write_block_data(&client, command,
+ gsb->len, gsb->data);
+ }
+ break;
+
+ case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
+ if (action == ACPI_READ) {
+ status = acpi_gsb_i2c_read_bytes(&client, command,
+ gsb->data, info->access_length);
+ if (status > 0)
+ status = 0;
+ } else {
+ status = acpi_gsb_i2c_write_bytes(&client, command,
+ gsb->data, info->access_length);
+ }
+ break;
+
+ default:
+ pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
+ ret = AE_BAD_PARAMETER;
+ goto err;
+ }
+
+ gsb->status = status;
+
+ err:
+ ACPI_FREE(ares);
+ return ret;
+}
+
+
+int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return -ENODEV;
+
+ data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->adapter = adapter;
+ status = acpi_bus_attach_private_data(handle, (void *)data);
+ if (ACPI_FAILURE(status)) {
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ status = acpi_install_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler,
+ NULL,
+ data);
+ if (ACPI_FAILURE(status)) {
+ dev_err(&adapter->dev, "Error installing i2c space handler\n");
+ acpi_bus_detach_private_data(handle);
+ kfree(data);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{
+ acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+ struct acpi_i2c_handler_data *data;
+ acpi_status status;
+
+ if (!handle)
+ return;
+
+ acpi_remove_address_space_handler(handle,
+ ACPI_ADR_SPACE_GSBUS,
+ &acpi_i2c_space_handler);
+
+ status = acpi_bus_get_private_data(handle, (void **)&data);
+ if (ACPI_SUCCESS(status))
+ kfree(data);
+
+ acpi_bus_detach_private_data(handle);
+}
+#endif
+#endif /* CONFIG_ACPI */
+
/* ------------------------------------------------------------------------- */
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
--
2.0.0
^ permalink raw reply related [flat|nested] 13+ messages in threadend of thread, other threads:[~2014-09-24 15:44 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-22 21:06 [PATCH] i2c: move acpi code back into the core Wolfram Sang
[not found] ` <1411420006-4713-1-git-send-email-wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org>
2014-09-23 1:37 ` Lan Tianyu
2014-09-23 1:37 ` Lan Tianyu
[not found] ` <5420CEC9.1030400-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-09-23 5:39 ` Wolfram Sang
2014-09-23 5:39 ` Wolfram Sang
2014-09-23 7:09 ` Lan Tianyu
2014-09-23 7:09 ` Lan Tianyu
2014-09-23 9:14 ` Lan Tianyu
2014-09-24 15:44 ` Wolfram Sang
2014-09-23 9:14 ` Mika Westerberg
2014-09-23 9:14 ` Mika Westerberg
2014-09-24 15:44 ` Wolfram Sang
-- strict thread matches above, loose matches on Subject: below --
2014-09-22 21:03 Wolfram Sang
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.