4 * Copyright (C) 2014 Intel Corp
6 * Author: Lan Tianyu <tianyu.lan@intel.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #define pr_fmt(fmt) "I2C/ACPI : " fmt
19 #include <linux/kernel.h>
20 #include <linux/errno.h>
21 #include <linux/err.h>
22 #include <linux/i2c.h>
23 #include <linux/acpi.h>
25 struct acpi_i2c_handler_data {
26 struct acpi_connection_info info;
27 struct i2c_adapter *adapter;
40 static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
41 u8 cmd, u8 *data, u8 data_len)
44 struct i2c_msg msgs[2];
48 buffer = kzalloc(data_len, GFP_KERNEL);
52 msgs[0].addr = client->addr;
53 msgs[0].flags = client->flags;
57 msgs[1].addr = client->addr;
58 msgs[1].flags = client->flags | I2C_M_RD;
59 msgs[1].len = data_len;
62 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
64 dev_err(&client->adapter->dev, "i2c read failed\n");
66 memcpy(data, buffer, data_len);
72 static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
73 u8 cmd, u8 *data, u8 data_len)
76 struct i2c_msg msgs[1];
80 buffer = kzalloc(data_len + 1, GFP_KERNEL);
85 memcpy(buffer + 1, data, data_len);
87 msgs[0].addr = client->addr;
88 msgs[0].flags = client->flags;
89 msgs[0].len = data_len + 1;
92 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
94 dev_err(&client->adapter->dev, "i2c write failed\n");
101 acpi_i2c_space_handler(u32 function, acpi_physical_address command,
102 u32 bits, u64 *value64,
103 void *handler_context, void *region_context)
105 struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
106 struct acpi_i2c_handler_data *data = handler_context;
107 struct acpi_connection_info *info = &data->info;
108 struct acpi_resource_i2c_serialbus *sb;
109 struct i2c_adapter *adapter = data->adapter;
110 struct i2c_client client;
111 struct acpi_resource *ares;
112 u32 accessor_type = function >> 16;
113 u8 action = function & ACPI_IO_MASK;
114 acpi_status ret = AE_OK;
117 ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
118 if (ACPI_FAILURE(ret))
121 if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
122 ret = AE_BAD_PARAMETER;
126 sb = &ares->data.i2c_serial_bus;
127 if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
128 ret = AE_BAD_PARAMETER;
132 memset(&client, 0, sizeof(client));
133 client.adapter = adapter;
134 client.addr = sb->slave_address;
137 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
138 client.flags |= I2C_CLIENT_TEN;
140 switch (accessor_type) {
141 case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
142 if (action == ACPI_READ) {
143 status = i2c_smbus_read_byte(&client);
149 status = i2c_smbus_write_byte(&client, gsb->bdata);
153 case ACPI_GSB_ACCESS_ATTRIB_BYTE:
154 if (action == ACPI_READ) {
155 status = i2c_smbus_read_byte_data(&client, command);
161 status = i2c_smbus_write_byte_data(&client, command,
166 case ACPI_GSB_ACCESS_ATTRIB_WORD:
167 if (action == ACPI_READ) {
168 status = i2c_smbus_read_word_data(&client, command);
174 status = i2c_smbus_write_word_data(&client, command,
179 case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
180 if (action == ACPI_READ) {
181 status = i2c_smbus_read_block_data(&client, command,
188 status = i2c_smbus_write_block_data(&client, command,
189 gsb->len, gsb->data);
193 case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
194 if (action == ACPI_READ) {
195 status = acpi_gsb_i2c_read_bytes(&client, command,
196 gsb->data, info->access_length);
200 status = acpi_gsb_i2c_write_bytes(&client, command,
201 gsb->data, info->access_length);
206 pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
207 ret = AE_BAD_PARAMETER;
211 gsb->status = status;
219 int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
221 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
222 struct acpi_i2c_handler_data *data;
228 data = kzalloc(sizeof(struct acpi_i2c_handler_data),
233 data->adapter = adapter;
234 status = acpi_bus_attach_private_data(handle, (void *)data);
235 if (ACPI_FAILURE(status)) {
240 status = acpi_install_address_space_handler(handle,
241 ACPI_ADR_SPACE_GSBUS,
242 &acpi_i2c_space_handler,
245 if (ACPI_FAILURE(status)) {
246 dev_err(&adapter->dev, "Error installing i2c space handler\n");
247 acpi_bus_detach_private_data(handle);
255 void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
257 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
258 struct acpi_i2c_handler_data *data;
264 acpi_remove_address_space_handler(handle,
265 ACPI_ADR_SPACE_GSBUS,
266 &acpi_i2c_space_handler);
268 status = acpi_bus_get_private_data(handle, (void **)&data);
269 if (ACPI_SUCCESS(status))
272 acpi_bus_detach_private_data(handle);