aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWolfram Sang <wsa@the-dreams.de>2014-09-22 13:41:00 -0400
committerWolfram Sang <wsa@the-dreams.de>2014-09-25 10:07:15 -0400
commit17f4a5c47f28de9ea59182f48d07f8c44ee5dcc9 (patch)
tree05959f33300e0e93cb9b8f4ffb29ef593521c37e /drivers
parentb4a7bd7a386dc6b0bb49cb47614e06e8295d495a (diff)
i2c: move acpi code back into the core
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> Tested-by: Lan Tianyu <tianyu.lan@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/Makefile5
-rw-r--r--drivers/i2c/i2c-acpi.c364
-rw-r--r--drivers/i2c/i2c-core.c354
3 files changed, 355 insertions, 368 deletions
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 @@
2# Makefile for the i2c core. 2# Makefile for the i2c core.
3# 3#
4 4
5i2ccore-y := i2c-core.o
6i2ccore-$(CONFIG_ACPI) += i2c-acpi.o
7
8obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o 5obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
9obj-$(CONFIG_I2C) += i2ccore.o 6obj-$(CONFIG_I2C) += i2c-core.o
10obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o 7obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
11obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o 8obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
12obj-$(CONFIG_I2C_MUX) += i2c-mux.o 9obj-$(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 @@
1/*
2 * I2C ACPI code
3 *
4 * Copyright (C) 2014 Intel Corp
5 *
6 * Author: Lan Tianyu <tianyu.lan@intel.com>
7 *
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.
11 *
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
15 * for more details.
16 */
17#define pr_fmt(fmt) "I2C/ACPI : " fmt
18
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>
24
25struct acpi_i2c_handler_data {
26 struct acpi_connection_info info;
27 struct i2c_adapter *adapter;
28};
29
30struct gsb_buffer {
31 u8 status;
32 u8 len;
33 union {
34 u16 wdata;
35 u8 bdata;
36 u8 data[0];
37 };
38} __packed;
39
40static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
41{
42 struct i2c_board_info *info = data;
43
44 if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
45 struct acpi_resource_i2c_serialbus *sb;
46
47 sb = &ares->data.i2c_serial_bus;
48 if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
49 info->addr = sb->slave_address;
50 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
51 info->flags |= I2C_CLIENT_TEN;
52 }
53 } else if (info->irq < 0) {
54 struct resource r;
55
56 if (acpi_dev_resource_interrupt(ares, 0, &r))
57 info->irq = r.start;
58 }
59
60 /* Tell the ACPI core to skip this resource */
61 return 1;
62}
63
64static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
65 void *data, void **return_value)
66{
67 struct i2c_adapter *adapter = data;
68 struct list_head resource_list;
69 struct i2c_board_info info;
70 struct acpi_device *adev;
71 int ret;
72
73 if (acpi_bus_get_device(handle, &adev))
74 return AE_OK;
75 if (acpi_bus_get_status(adev) || !adev->status.present)
76 return AE_OK;
77
78 memset(&info, 0, sizeof(info));
79 info.acpi_node.companion = adev;
80 info.irq = -1;
81
82 INIT_LIST_HEAD(&resource_list);
83 ret = acpi_dev_get_resources(adev, &resource_list,
84 acpi_i2c_add_resource, &info);
85 acpi_dev_free_resource_list(&resource_list);
86
87 if (ret < 0 || !info.addr)
88 return AE_OK;
89
90 adev->power.flags.ignore_parent = true;
91 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
92 if (!i2c_new_device(adapter, &info)) {
93 adev->power.flags.ignore_parent = false;
94 dev_err(&adapter->dev,
95 "failed to add I2C device %s from ACPI\n",
96 dev_name(&adev->dev));
97 }
98
99 return AE_OK;
100}
101
102/**
103 * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
104 * @adap: pointer to adapter
105 *
106 * Enumerate all I2C slave devices behind this adapter by walking the ACPI
107 * namespace. When a device is found it will be added to the Linux device
108 * model and bound to the corresponding ACPI handle.
109 */
110void acpi_i2c_register_devices(struct i2c_adapter *adap)
111{
112 acpi_handle handle;
113 acpi_status status;
114
115 if (!adap->dev.parent)
116 return;
117
118 handle = ACPI_HANDLE(adap->dev.parent);
119 if (!handle)
120 return;
121
122 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
123 acpi_i2c_add_device, NULL,
124 adap, NULL);
125 if (ACPI_FAILURE(status))
126 dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
127}
128
129#ifdef CONFIG_ACPI_I2C_OPREGION
130static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
131 u8 cmd, u8 *data, u8 data_len)
132{
133
134 struct i2c_msg msgs[2];
135 int ret;
136 u8 *buffer;
137
138 buffer = kzalloc(data_len, GFP_KERNEL);
139 if (!buffer)
140 return AE_NO_MEMORY;
141
142 msgs[0].addr = client->addr;
143 msgs[0].flags = client->flags;
144 msgs[0].len = 1;
145 msgs[0].buf = &cmd;
146
147 msgs[1].addr = client->addr;
148 msgs[1].flags = client->flags | I2C_M_RD;
149 msgs[1].len = data_len;
150 msgs[1].buf = buffer;
151
152 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
153 if (ret < 0)
154 dev_err(&client->adapter->dev, "i2c read failed\n");
155 else
156 memcpy(data, buffer, data_len);
157
158 kfree(buffer);
159 return ret;
160}
161
162static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
163 u8 cmd, u8 *data, u8 data_len)
164{
165
166 struct i2c_msg msgs[1];
167 u8 *buffer;
168 int ret = AE_OK;
169
170 buffer = kzalloc(data_len + 1, GFP_KERNEL);
171 if (!buffer)
172 return AE_NO_MEMORY;
173
174 buffer[0] = cmd;
175 memcpy(buffer + 1, data, data_len);
176
177 msgs[0].addr = client->addr;
178 msgs[0].flags = client->flags;
179 msgs[0].len = data_len + 1;
180 msgs[0].buf = buffer;
181
182 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
183 if (ret < 0)
184 dev_err(&client->adapter->dev, "i2c write failed\n");
185
186 kfree(buffer);
187 return ret;
188}
189
190static acpi_status
191acpi_i2c_space_handler(u32 function, acpi_physical_address command,
192 u32 bits, u64 *value64,
193 void *handler_context, void *region_context)
194{
195 struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
196 struct acpi_i2c_handler_data *data = handler_context;
197 struct acpi_connection_info *info = &data->info;
198 struct acpi_resource_i2c_serialbus *sb;
199 struct i2c_adapter *adapter = data->adapter;
200 struct i2c_client client;
201 struct acpi_resource *ares;
202 u32 accessor_type = function >> 16;
203 u8 action = function & ACPI_IO_MASK;
204 acpi_status ret = AE_OK;
205 int status;
206
207 ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
208 if (ACPI_FAILURE(ret))
209 return ret;
210
211 if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
212 ret = AE_BAD_PARAMETER;
213 goto err;
214 }
215
216 sb = &ares->data.i2c_serial_bus;
217 if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
218 ret = AE_BAD_PARAMETER;
219 goto err;
220 }
221
222 memset(&client, 0, sizeof(client));
223 client.adapter = adapter;
224 client.addr = sb->slave_address;
225 client.flags = 0;
226
227 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
228 client.flags |= I2C_CLIENT_TEN;
229
230 switch (accessor_type) {
231 case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
232 if (action == ACPI_READ) {
233 status = i2c_smbus_read_byte(&client);
234 if (status >= 0) {
235 gsb->bdata = status;
236 status = 0;
237 }
238 } else {
239 status = i2c_smbus_write_byte(&client, gsb->bdata);
240 }
241 break;
242
243 case ACPI_GSB_ACCESS_ATTRIB_BYTE:
244 if (action == ACPI_READ) {
245 status = i2c_smbus_read_byte_data(&client, command);
246 if (status >= 0) {
247 gsb->bdata = status;
248 status = 0;
249 }
250 } else {
251 status = i2c_smbus_write_byte_data(&client, command,
252 gsb->bdata);
253 }
254 break;
255
256 case ACPI_GSB_ACCESS_ATTRIB_WORD:
257 if (action == ACPI_READ) {
258 status = i2c_smbus_read_word_data(&client, command);
259 if (status >= 0) {
260 gsb->wdata = status;
261 status = 0;
262 }
263 } else {
264 status = i2c_smbus_write_word_data(&client, command,
265 gsb->wdata);
266 }
267 break;
268
269 case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
270 if (action == ACPI_READ) {
271 status = i2c_smbus_read_block_data(&client, command,
272 gsb->data);
273 if (status >= 0) {
274 gsb->len = status;
275 status = 0;
276 }
277 } else {
278 status = i2c_smbus_write_block_data(&client, command,
279 gsb->len, gsb->data);
280 }
281 break;
282
283 case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
284 if (action == ACPI_READ) {
285 status = acpi_gsb_i2c_read_bytes(&client, command,
286 gsb->data, info->access_length);
287 if (status > 0)
288 status = 0;
289 } else {
290 status = acpi_gsb_i2c_write_bytes(&client, command,
291 gsb->data, info->access_length);
292 }
293 break;
294
295 default:
296 pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
297 ret = AE_BAD_PARAMETER;
298 goto err;
299 }
300
301 gsb->status = status;
302
303 err:
304 ACPI_FREE(ares);
305 return ret;
306}
307
308
309int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
310{
311 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
312 struct acpi_i2c_handler_data *data;
313 acpi_status status;
314
315 if (!handle)
316 return -ENODEV;
317
318 data = kzalloc(sizeof(struct acpi_i2c_handler_data),
319 GFP_KERNEL);
320 if (!data)
321 return -ENOMEM;
322
323 data->adapter = adapter;
324 status = acpi_bus_attach_private_data(handle, (void *)data);
325 if (ACPI_FAILURE(status)) {
326 kfree(data);
327 return -ENOMEM;
328 }
329
330 status = acpi_install_address_space_handler(handle,
331 ACPI_ADR_SPACE_GSBUS,
332 &acpi_i2c_space_handler,
333 NULL,
334 data);
335 if (ACPI_FAILURE(status)) {
336 dev_err(&adapter->dev, "Error installing i2c space handler\n");
337 acpi_bus_detach_private_data(handle);
338 kfree(data);
339 return -ENOMEM;
340 }
341
342 return 0;
343}
344
345void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
346{
347 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
348 struct acpi_i2c_handler_data *data;
349 acpi_status status;
350
351 if (!handle)
352 return;
353
354 acpi_remove_address_space_handler(handle,
355 ACPI_ADR_SPACE_GSBUS,
356 &acpi_i2c_space_handler);
357
358 status = acpi_bus_get_private_data(handle, (void **)&data);
359 if (ACPI_SUCCESS(status))
360 kfree(data);
361
362 acpi_bus_detach_private_data(handle);
363}
364#endif
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 632057a44615..b696ac7e6d86 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -27,6 +27,8 @@
27 OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de> 27 OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de>
28 (based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and 28 (based on a previous patch from Jon Smirl <jonsmirl@gmail.com>) and
29 (c) 2013 Wolfram Sang <wsa@the-dreams.de> 29 (c) 2013 Wolfram Sang <wsa@the-dreams.de>
30 I2C ACPI code Copyright (C) 2014 Intel Corp
31 Author: Lan Tianyu <tianyu.lan@intel.com>
30 */ 32 */
31 33
32#include <linux/module.h> 34#include <linux/module.h>
@@ -78,6 +80,358 @@ void i2c_transfer_trace_unreg(void)
78 static_key_slow_dec(&i2c_trace_msg); 80 static_key_slow_dec(&i2c_trace_msg);
79} 81}
80 82
83#if defined(CONFIG_ACPI)
84struct acpi_i2c_handler_data {
85 struct acpi_connection_info info;
86 struct i2c_adapter *adapter;
87};
88
89struct gsb_buffer {
90 u8 status;
91 u8 len;
92 union {
93 u16 wdata;
94 u8 bdata;
95 u8 data[0];
96 };
97} __packed;
98
99static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
100{
101 struct i2c_board_info *info = data;
102
103 if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
104 struct acpi_resource_i2c_serialbus *sb;
105
106 sb = &ares->data.i2c_serial_bus;
107 if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
108 info->addr = sb->slave_address;
109 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
110 info->flags |= I2C_CLIENT_TEN;
111 }
112 } else if (info->irq < 0) {
113 struct resource r;
114
115 if (acpi_dev_resource_interrupt(ares, 0, &r))
116 info->irq = r.start;
117 }
118
119 /* Tell the ACPI core to skip this resource */
120 return 1;
121}
122
123static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
124 void *data, void **return_value)
125{
126 struct i2c_adapter *adapter = data;
127 struct list_head resource_list;
128 struct i2c_board_info info;
129 struct acpi_device *adev;
130 int ret;
131
132 if (acpi_bus_get_device(handle, &adev))
133 return AE_OK;
134 if (acpi_bus_get_status(adev) || !adev->status.present)
135 return AE_OK;
136
137 memset(&info, 0, sizeof(info));
138 info.acpi_node.companion = adev;
139 info.irq = -1;
140
141 INIT_LIST_HEAD(&resource_list);
142 ret = acpi_dev_get_resources(adev, &resource_list,
143 acpi_i2c_add_resource, &info);
144 acpi_dev_free_resource_list(&resource_list);
145
146 if (ret < 0 || !info.addr)
147 return AE_OK;
148
149 adev->power.flags.ignore_parent = true;
150 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
151 if (!i2c_new_device(adapter, &info)) {
152 adev->power.flags.ignore_parent = false;
153 dev_err(&adapter->dev,
154 "failed to add I2C device %s from ACPI\n",
155 dev_name(&adev->dev));
156 }
157
158 return AE_OK;
159}
160
161/**
162 * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
163 * @adap: pointer to adapter
164 *
165 * Enumerate all I2C slave devices behind this adapter by walking the ACPI
166 * namespace. When a device is found it will be added to the Linux device
167 * model and bound to the corresponding ACPI handle.
168 */
169static void acpi_i2c_register_devices(struct i2c_adapter *adap)
170{
171 acpi_handle handle;
172 acpi_status status;
173
174 if (!adap->dev.parent)
175 return;
176
177 handle = ACPI_HANDLE(adap->dev.parent);
178 if (!handle)
179 return;
180
181 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
182 acpi_i2c_add_device, NULL,
183 adap, NULL);
184 if (ACPI_FAILURE(status))
185 dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
186}
187
188#else /* CONFIG_ACPI */
189static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
190#endif /* CONFIG_ACPI */
191
192#ifdef CONFIG_ACPI_I2C_OPREGION
193static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
194 u8 cmd, u8 *data, u8 data_len)
195{
196
197 struct i2c_msg msgs[2];
198 int ret;
199 u8 *buffer;
200
201 buffer = kzalloc(data_len, GFP_KERNEL);
202 if (!buffer)
203 return AE_NO_MEMORY;
204
205 msgs[0].addr = client->addr;
206 msgs[0].flags = client->flags;
207 msgs[0].len = 1;
208 msgs[0].buf = &cmd;
209
210 msgs[1].addr = client->addr;
211 msgs[1].flags = client->flags | I2C_M_RD;
212 msgs[1].len = data_len;
213 msgs[1].buf = buffer;
214
215 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
216 if (ret < 0)
217 dev_err(&client->adapter->dev, "i2c read failed\n");
218 else
219 memcpy(data, buffer, data_len);
220
221 kfree(buffer);
222 return ret;
223}
224
225static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
226 u8 cmd, u8 *data, u8 data_len)
227{
228
229 struct i2c_msg msgs[1];
230 u8 *buffer;
231 int ret = AE_OK;
232
233 buffer = kzalloc(data_len + 1, GFP_KERNEL);
234 if (!buffer)
235 return AE_NO_MEMORY;
236
237 buffer[0] = cmd;
238 memcpy(buffer + 1, data, data_len);
239
240 msgs[0].addr = client->addr;
241 msgs[0].flags = client->flags;
242 msgs[0].len = data_len + 1;
243 msgs[0].buf = buffer;
244
245 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
246 if (ret < 0)
247 dev_err(&client->adapter->dev, "i2c write failed\n");
248
249 kfree(buffer);
250 return ret;
251}
252
253static acpi_status
254acpi_i2c_space_handler(u32 function, acpi_physical_address command,
255 u32 bits, u64 *value64,
256 void *handler_context, void *region_context)
257{
258 struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
259 struct acpi_i2c_handler_data *data = handler_context;
260 struct acpi_connection_info *info = &data->info;
261 struct acpi_resource_i2c_serialbus *sb;
262 struct i2c_adapter *adapter = data->adapter;
263 struct i2c_client client;
264 struct acpi_resource *ares;
265 u32 accessor_type = function >> 16;
266 u8 action = function & ACPI_IO_MASK;
267 acpi_status ret = AE_OK;
268 int status;
269
270 ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
271 if (ACPI_FAILURE(ret))
272 return ret;
273
274 if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
275 ret = AE_BAD_PARAMETER;
276 goto err;
277 }
278
279 sb = &ares->data.i2c_serial_bus;
280 if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
281 ret = AE_BAD_PARAMETER;
282 goto err;
283 }
284
285 memset(&client, 0, sizeof(client));
286 client.adapter = adapter;
287 client.addr = sb->slave_address;
288 client.flags = 0;
289
290 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
291 client.flags |= I2C_CLIENT_TEN;
292
293 switch (accessor_type) {
294 case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
295 if (action == ACPI_READ) {
296 status = i2c_smbus_read_byte(&client);
297 if (status >= 0) {
298 gsb->bdata = status;
299 status = 0;
300 }
301 } else {
302 status = i2c_smbus_write_byte(&client, gsb->bdata);
303 }
304 break;
305
306 case ACPI_GSB_ACCESS_ATTRIB_BYTE:
307 if (action == ACPI_READ) {
308 status = i2c_smbus_read_byte_data(&client, command);
309 if (status >= 0) {
310 gsb->bdata = status;
311 status = 0;
312 }
313 } else {
314 status = i2c_smbus_write_byte_data(&client, command,
315 gsb->bdata);
316 }
317 break;
318
319 case ACPI_GSB_ACCESS_ATTRIB_WORD:
320 if (action == ACPI_READ) {
321 status = i2c_smbus_read_word_data(&client, command);
322 if (status >= 0) {
323 gsb->wdata = status;
324 status = 0;
325 }
326 } else {
327 status = i2c_smbus_write_word_data(&client, command,
328 gsb->wdata);
329 }
330 break;
331
332 case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
333 if (action == ACPI_READ) {
334 status = i2c_smbus_read_block_data(&client, command,
335 gsb->data);
336 if (status >= 0) {
337 gsb->len = status;
338 status = 0;
339 }
340 } else {
341 status = i2c_smbus_write_block_data(&client, command,
342 gsb->len, gsb->data);
343 }
344 break;
345
346 case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
347 if (action == ACPI_READ) {
348 status = acpi_gsb_i2c_read_bytes(&client, command,
349 gsb->data, info->access_length);
350 if (status > 0)
351 status = 0;
352 } else {
353 status = acpi_gsb_i2c_write_bytes(&client, command,
354 gsb->data, info->access_length);
355 }
356 break;
357
358 default:
359 pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
360 ret = AE_BAD_PARAMETER;
361 goto err;
362 }
363
364 gsb->status = status;
365
366 err:
367 ACPI_FREE(ares);
368 return ret;
369}
370
371
372static int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
373{
374 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
375 struct acpi_i2c_handler_data *data;
376 acpi_status status;
377
378 if (!handle)
379 return -ENODEV;
380
381 data = kzalloc(sizeof(struct acpi_i2c_handler_data),
382 GFP_KERNEL);
383 if (!data)
384 return -ENOMEM;
385
386 data->adapter = adapter;
387 status = acpi_bus_attach_private_data(handle, (void *)data);
388 if (ACPI_FAILURE(status)) {
389 kfree(data);
390 return -ENOMEM;
391 }
392
393 status = acpi_install_address_space_handler(handle,
394 ACPI_ADR_SPACE_GSBUS,
395 &acpi_i2c_space_handler,
396 NULL,
397 data);
398 if (ACPI_FAILURE(status)) {
399 dev_err(&adapter->dev, "Error installing i2c space handler\n");
400 acpi_bus_detach_private_data(handle);
401 kfree(data);
402 return -ENOMEM;
403 }
404
405 return 0;
406}
407
408static void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
409{
410 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
411 struct acpi_i2c_handler_data *data;
412 acpi_status status;
413
414 if (!handle)
415 return;
416
417 acpi_remove_address_space_handler(handle,
418 ACPI_ADR_SPACE_GSBUS,
419 &acpi_i2c_space_handler);
420
421 status = acpi_bus_get_private_data(handle, (void **)&data);
422 if (ACPI_SUCCESS(status))
423 kfree(data);
424
425 acpi_bus_detach_private_data(handle);
426}
427#else /* CONFIG_ACPI_I2C_OPREGION */
428static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
429{ }
430
431static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
432{ return 0; }
433#endif /* CONFIG_ACPI_I2C_OPREGION */
434
81/* ------------------------------------------------------------------------- */ 435/* ------------------------------------------------------------------------- */
82 436
83static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, 437static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,