Merge tag 'mmc-v3.17-1' of git://git.linaro.org/people/ulf.hansson/mmc
[deliverable/linux.git] / drivers / i2c / i2c-acpi.c
CommitLineData
5d98e61d
LT
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
da3c6647
LT
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
5d98e61d
LT
129static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
130 u8 cmd, u8 *data, u8 data_len)
131{
132
133 struct i2c_msg msgs[2];
134 int ret;
135 u8 *buffer;
136
137 buffer = kzalloc(data_len, GFP_KERNEL);
138 if (!buffer)
139 return AE_NO_MEMORY;
140
141 msgs[0].addr = client->addr;
142 msgs[0].flags = client->flags;
143 msgs[0].len = 1;
144 msgs[0].buf = &cmd;
145
146 msgs[1].addr = client->addr;
147 msgs[1].flags = client->flags | I2C_M_RD;
148 msgs[1].len = data_len;
149 msgs[1].buf = buffer;
150
151 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
152 if (ret < 0)
153 dev_err(&client->adapter->dev, "i2c read failed\n");
154 else
155 memcpy(data, buffer, data_len);
156
157 kfree(buffer);
158 return ret;
159}
160
161static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
162 u8 cmd, u8 *data, u8 data_len)
163{
164
165 struct i2c_msg msgs[1];
166 u8 *buffer;
167 int ret = AE_OK;
168
169 buffer = kzalloc(data_len + 1, GFP_KERNEL);
170 if (!buffer)
171 return AE_NO_MEMORY;
172
173 buffer[0] = cmd;
174 memcpy(buffer + 1, data, data_len);
175
176 msgs[0].addr = client->addr;
177 msgs[0].flags = client->flags;
178 msgs[0].len = data_len + 1;
179 msgs[0].buf = buffer;
180
181 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
182 if (ret < 0)
183 dev_err(&client->adapter->dev, "i2c write failed\n");
184
185 kfree(buffer);
186 return ret;
187}
188
189static acpi_status
190acpi_i2c_space_handler(u32 function, acpi_physical_address command,
191 u32 bits, u64 *value64,
192 void *handler_context, void *region_context)
193{
194 struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
195 struct acpi_i2c_handler_data *data = handler_context;
196 struct acpi_connection_info *info = &data->info;
197 struct acpi_resource_i2c_serialbus *sb;
198 struct i2c_adapter *adapter = data->adapter;
199 struct i2c_client client;
200 struct acpi_resource *ares;
201 u32 accessor_type = function >> 16;
202 u8 action = function & ACPI_IO_MASK;
203 acpi_status ret = AE_OK;
204 int status;
205
206 ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
207 if (ACPI_FAILURE(ret))
208 return ret;
209
210 if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
211 ret = AE_BAD_PARAMETER;
212 goto err;
213 }
214
215 sb = &ares->data.i2c_serial_bus;
216 if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
217 ret = AE_BAD_PARAMETER;
218 goto err;
219 }
220
221 memset(&client, 0, sizeof(client));
222 client.adapter = adapter;
223 client.addr = sb->slave_address;
224 client.flags = 0;
225
226 if (sb->access_mode == ACPI_I2C_10BIT_MODE)
227 client.flags |= I2C_CLIENT_TEN;
228
229 switch (accessor_type) {
230 case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
231 if (action == ACPI_READ) {
232 status = i2c_smbus_read_byte(&client);
233 if (status >= 0) {
234 gsb->bdata = status;
235 status = 0;
236 }
237 } else {
238 status = i2c_smbus_write_byte(&client, gsb->bdata);
239 }
240 break;
241
242 case ACPI_GSB_ACCESS_ATTRIB_BYTE:
243 if (action == ACPI_READ) {
244 status = i2c_smbus_read_byte_data(&client, command);
245 if (status >= 0) {
246 gsb->bdata = status;
247 status = 0;
248 }
249 } else {
250 status = i2c_smbus_write_byte_data(&client, command,
251 gsb->bdata);
252 }
253 break;
254
255 case ACPI_GSB_ACCESS_ATTRIB_WORD:
256 if (action == ACPI_READ) {
257 status = i2c_smbus_read_word_data(&client, command);
258 if (status >= 0) {
259 gsb->wdata = status;
260 status = 0;
261 }
262 } else {
263 status = i2c_smbus_write_word_data(&client, command,
264 gsb->wdata);
265 }
266 break;
267
268 case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
269 if (action == ACPI_READ) {
270 status = i2c_smbus_read_block_data(&client, command,
271 gsb->data);
272 if (status >= 0) {
273 gsb->len = status;
274 status = 0;
275 }
276 } else {
277 status = i2c_smbus_write_block_data(&client, command,
278 gsb->len, gsb->data);
279 }
280 break;
281
282 case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
283 if (action == ACPI_READ) {
284 status = acpi_gsb_i2c_read_bytes(&client, command,
285 gsb->data, info->access_length);
286 if (status > 0)
287 status = 0;
288 } else {
289 status = acpi_gsb_i2c_write_bytes(&client, command,
290 gsb->data, info->access_length);
291 }
292 break;
293
294 default:
295 pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
296 ret = AE_BAD_PARAMETER;
297 goto err;
298 }
299
300 gsb->status = status;
301
302 err:
303 ACPI_FREE(ares);
304 return ret;
305}
306
307
308int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
309{
310 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
311 struct acpi_i2c_handler_data *data;
312 acpi_status status;
313
314 if (!handle)
315 return -ENODEV;
316
317 data = kzalloc(sizeof(struct acpi_i2c_handler_data),
318 GFP_KERNEL);
319 if (!data)
320 return -ENOMEM;
321
322 data->adapter = adapter;
323 status = acpi_bus_attach_private_data(handle, (void *)data);
324 if (ACPI_FAILURE(status)) {
325 kfree(data);
326 return -ENOMEM;
327 }
328
329 status = acpi_install_address_space_handler(handle,
330 ACPI_ADR_SPACE_GSBUS,
331 &acpi_i2c_space_handler,
332 NULL,
333 data);
334 if (ACPI_FAILURE(status)) {
335 dev_err(&adapter->dev, "Error installing i2c space handler\n");
336 acpi_bus_detach_private_data(handle);
337 kfree(data);
338 return -ENOMEM;
339 }
340
341 return 0;
342}
343
344void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
345{
346 acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
347 struct acpi_i2c_handler_data *data;
348 acpi_status status;
349
350 if (!handle)
351 return;
352
353 acpi_remove_address_space_handler(handle,
354 ACPI_ADR_SPACE_GSBUS,
355 &acpi_i2c_space_handler);
356
357 status = acpi_bus_get_private_data(handle, (void **)&data);
358 if (ACPI_SUCCESS(status))
359 kfree(data);
360
361 acpi_bus_detach_private_data(handle);
362}
This page took 0.040995 seconds and 5 git commands to generate.