blob: c4e47effa9f54010b49475944131f6c66e0a6cf8 [file] [log] [blame]
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +08001/*
2 * I2C bridge driver for the Greybus "generic" I2C module.
3 *
4 * Copyright 2014 Google Inc.
5 *
6 * Released under the GPLv2 only.
7 */
8
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/i2c.h>
Alex Eldere1e9dbd2014-10-01 21:54:11 -050013
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080014#include "greybus.h"
15
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -070016struct gb_i2c_device {
Alex Eldered8800d2014-10-16 06:35:38 -050017 struct gb_connection *connection;
18 u8 version_major;
19 u8 version_minor;
20
21 u32 functionality;
22 u16 timeout_msec;
23 u8 retries;
24
25 struct i2c_adapter *adapter;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080026};
27
Alex Eldered8800d2014-10-16 06:35:38 -050028/* Version of the Greybus i2c protocol we support */
29#define GB_I2C_VERSION_MAJOR 0x00
30#define GB_I2C_VERSION_MINOR 0x01
31
32/* Greybus i2c request types */
33#define GB_I2C_TYPE_INVALID 0x00
34#define GB_I2C_TYPE_PROTOCOL_VERSION 0x01
35#define GB_I2C_TYPE_FUNCTIONALITY 0x02
36#define GB_I2C_TYPE_TIMEOUT 0x03
37#define GB_I2C_TYPE_RETRIES 0x04
38#define GB_I2C_TYPE_TRANSFER 0x05
39#define GB_I2C_TYPE_RESPONSE 0x80 /* OR'd with rest */
40
41#define GB_I2C_RETRIES_DEFAULT 3
42#define GB_I2C_TIMEOUT_DEFAULT 1000 /* milliseconds */
43
44/* version request has no payload */
45struct gb_i2c_proto_version_response {
46 __u8 status;
47 __u8 major;
48 __u8 minor;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080049};
50
Alex Eldered8800d2014-10-16 06:35:38 -050051/* functionality request has no payload */
52struct gb_i2c_functionality_response {
53 __u8 status;
54 __le32 functionality;
55};
56
57struct gb_i2c_timeout_request {
58 __le16 msec;
59};
60struct gb_i2c_timeout_response {
61 __u8 status;
62};
63
64struct gb_i2c_retries_request {
65 __u8 retries;
66};
67struct gb_i2c_retries_response {
68 __u8 status;
69};
70
71/*
72 * Outgoing data immediately follows the op count and ops array.
73 * The data for each write (master -> slave) op in the array is sent
74 * in order, with no (e.g. pad) bytes separating them.
75 *
76 * Short reads cause the entire transfer request to fail So response
77 * payload consists only of bytes read, and the number of bytes is
78 * exactly what was specified in the corresponding op. Like
79 * outgoing data, the incoming data is in order and contiguous.
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +080080 */
Alex Eldered8800d2014-10-16 06:35:38 -050081struct gb_i2c_transfer_op {
82 __le16 addr;
83 __le16 flags;
84 __le16 size;
85};
86
87struct gb_i2c_transfer_request {
88 __le16 op_count;
89 struct gb_i2c_transfer_op ops[0]; /* op_count of these */
90};
91struct gb_i2c_transfer_response {
92 __u8 status;
93 __u8 data[0]; /* inbound data */
94};
95
96/*
97 * This request only uses the connection field, and if successful,
98 * fills in the major and minor protocol version of the target.
99 */
100static int gb_i2c_proto_version_operation(struct gb_i2c_device *gb_i2c_dev)
101{
102 struct gb_connection *connection = gb_i2c_dev->connection;
103 struct gb_operation *operation;
104 struct gb_i2c_proto_version_response *response;
105 int ret;
106
107 /* A protocol version request has no payload */
108 operation = gb_operation_create(connection,
109 GB_I2C_TYPE_PROTOCOL_VERSION,
110 0, sizeof(*response));
111 if (!operation)
112 return -ENOMEM;
113
114 /* Synchronous operation--no callback */
115 ret = gb_operation_request_send(operation, NULL);
116 if (ret) {
117 pr_err("version operation failed (%d)\n", ret);
118 goto out;
119 }
120
121 response = operation->response_payload;
122 if (response->status) {
123 gb_connection_err(connection, "version response %hhu",
124 response->status);
125 ret = -EIO;
126 } else {
127 if (response->major > GB_I2C_VERSION_MAJOR) {
128 pr_err("unsupported major version (%hhu > %hhu)\n",
129 response->major, GB_I2C_VERSION_MAJOR);
130 ret = -ENOTSUPP;
131 goto out;
132 }
133 gb_i2c_dev->version_major = response->major;
134 gb_i2c_dev->version_minor = response->minor;
135 }
136out:
137
138 gb_operation_destroy(operation);
139
140 return ret;
141}
142
143/*
144 * Map Greybus i2c functionality bits into Linux ones
145 */
146static u32 gb_i2c_functionality_map(u32 gb_i2c_functionality)
147{
148 return gb_i2c_functionality; /* All bits the same for now */
149}
150
151static int gb_i2c_functionality_operation(struct gb_i2c_device *gb_i2c_dev)
152{
153 struct gb_connection *connection = gb_i2c_dev->connection;
154 struct gb_operation *operation;
155 struct gb_i2c_functionality_response *response;
156 u32 functionality;
157 int ret;
158
159 /* A functionality request has no payload */
160 operation = gb_operation_create(connection,
161 GB_I2C_TYPE_FUNCTIONALITY,
162 0, sizeof(*response));
163 if (!operation)
164 return -ENOMEM;
165
166 /* Synchronous operation--no callback */
167 ret = gb_operation_request_send(operation, NULL);
168 if (ret) {
169 pr_err("functionality operation failed (%d)\n", ret);
170 goto out;
171 }
172
173 response = operation->response_payload;
174 if (response->status) {
175 gb_connection_err(connection, "functionality response %hhu",
176 response->status);
177 ret = -EIO;
178 } else {
179 functionality = le32_to_cpu(response->functionality);
180 gb_i2c_dev->functionality =
181 gb_i2c_functionality_map(functionality);
182 }
183out:
184 gb_operation_destroy(operation);
185
186 return ret;
187}
188
189static int gb_i2c_timeout_operation(struct gb_i2c_device *gb_i2c_dev, u16 msec)
190{
191 struct gb_connection *connection = gb_i2c_dev->connection;
192 struct gb_operation *operation;
193 struct gb_i2c_timeout_request *request;
194 struct gb_i2c_timeout_response *response;
195 int ret;
196
197 operation = gb_operation_create(connection, GB_I2C_TYPE_TIMEOUT,
198 sizeof(*request), sizeof(*response));
199 if (!operation)
200 return -ENOMEM;
201 request = operation->request_payload;
202 request->msec = cpu_to_le16(msec);
203
204 /* Synchronous operation--no callback */
205 ret = gb_operation_request_send(operation, NULL);
206 if (ret) {
207 pr_err("timeout operation failed (%d)\n", ret);
208 goto out;
209 }
210
211 response = operation->response_payload;
212 if (response->status) {
213 gb_connection_err(connection, "timeout response %hhu",
214 response->status);
215 ret = -EIO;
216 } else {
217 gb_i2c_dev->timeout_msec = msec;
218 }
219out:
220 gb_operation_destroy(operation);
221
222 return ret;
223}
224
225static int gb_i2c_retries_operation(struct gb_i2c_device *gb_i2c_dev,
226 u8 retries)
227{
228 struct gb_connection *connection = gb_i2c_dev->connection;
229 struct gb_operation *operation;
230 struct gb_i2c_retries_request *request;
231 struct gb_i2c_retries_response *response;
232 int ret;
233
234 operation = gb_operation_create(connection, GB_I2C_TYPE_RETRIES,
235 sizeof(*request), sizeof(*response));
236 if (!operation)
237 return -ENOMEM;
238 request = operation->request_payload;
239 request->retries = retries;
240
241 /* Synchronous operation--no callback */
242 ret = gb_operation_request_send(operation, NULL);
243 if (ret) {
244 pr_err("retries operation failed (%d)\n", ret);
245 goto out;
246 }
247
248 response = operation->response_payload;
249 if (response->status) {
250 gb_connection_err(connection, "retries response %hhu",
251 response->status);
252 ret = -EIO;
253 } else {
254 gb_i2c_dev->retries = retries;
255 }
256out:
257 gb_operation_destroy(operation);
258
259 return ret;
260}
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800261
262
Alex Eldered8800d2014-10-16 06:35:38 -0500263/*
264 * Map Linux i2c_msg flags into Greybus i2c transfer op flags.
265 */
266static u16 gb_i2c_transfer_op_flags_map(u16 flags)
267{
268 return flags; /* All flags the same for now */
269}
270
271static void
272gb_i2c_fill_transfer_op(struct gb_i2c_transfer_op *op, struct i2c_msg *msg)
273{
274 u16 flags = gb_i2c_transfer_op_flags_map(msg->flags);
275
276 op->addr = cpu_to_le16(msg->addr);
277 op->flags = cpu_to_le16(flags);
278 op->size = cpu_to_le16(msg->len);
279}
280
281static struct gb_operation *
282gb_i2c_transfer_request(struct gb_connection *connection,
283 struct i2c_msg *msgs, u32 msg_count)
284{
285 struct gb_i2c_transfer_request *request;
286 struct gb_operation *operation;
287 struct gb_i2c_transfer_op *op;
288 struct i2c_msg *msg;
289 u32 data_out_size = 0;
290 u32 data_in_size = 1; /* Response begins with a status byte */
291 size_t request_size;
292 void *data;
293 u16 op_count;
294 u32 i;
295
296 if (msg_count > (u32)U16_MAX) {
297 gb_connection_err(connection, "msg_count (%u) too big",
298 msg_count);
299 return NULL;
300 }
301 op_count = (u16)msg_count;
302
303 /*
304 * In addition to space for all message descriptors we need
305 * to have enough to hold all outbound message data.
306 */
307 msg = msgs;
308 for (i = 0; i < msg_count; i++, msg++)
309 if (msg->flags & I2C_M_RD)
310 data_in_size += (u32)msg->len;
311 else
312 data_out_size += (u32)msg->len;
313
314 request_size = sizeof(struct gb_i2c_transfer_request);
315 request_size += msg_count * sizeof(struct gb_i2c_transfer_op);
316 request_size += data_out_size;
317
318 /* Response consists only of incoming data */
319 operation = gb_operation_create(connection, GB_I2C_TYPE_TRANSFER,
320 request_size, data_in_size);
321 if (!operation)
322 return NULL;
323
324 request = operation->request_payload;
325 request->op_count = cpu_to_le16(op_count);
326 /* Fill in the ops array */
327 op = &request->ops[0];
328 msg = msgs;
329 for (i = 0; i < msg_count; i++)
330 gb_i2c_fill_transfer_op(op++, msg++);
331
332 if (!data_out_size)
333 return operation;
334
335 /* Copy over the outgoing data; it starts after the last op */
336 data = op;
337 msg = msgs;
338 for (i = 0; i < msg_count; i++) {
339 if (!(msg->flags & I2C_M_RD)) {
340 memcpy(data, msg->buf, msg->len);
341 data += msg->len;
342 }
343 msg++;
344 }
345
346 return operation;
347}
348
349static void gb_i2c_transfer_response(struct i2c_msg *msgs, u32 msg_count,
350 void *data)
351{
352 struct i2c_msg *msg = msgs;
353 u32 i;
354
355 for (i = 0; i < msg_count; i++) {
356 if (msg->flags & I2C_M_RD) {
357 memcpy(msg->buf, data, msg->len);
358 data += msg->len;
359 }
360 msg++;
361 }
362}
363
364static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev,
365 struct i2c_msg *msgs, u32 msg_count)
366{
367 struct gb_connection *connection = gb_i2c_dev->connection;
368 struct gb_i2c_transfer_response *response;
369 struct gb_operation *operation;
370 int ret;
371
372 operation = gb_i2c_transfer_request(connection, msgs, msg_count);
373 if (!operation)
374 return -ENOMEM;
375
376 /* Synchronous operation--no callback */
377 ret = gb_operation_request_send(operation, NULL);
378 if (ret) {
379 pr_err("transfer operation failed (%d)\n", ret);
380 goto out;
381 }
382
383 response = operation->response_payload;
384 if (response->status) {
385 gb_connection_err(connection, "transfer response %hhu",
386 response->status);
387 ret = -EIO;
388 } else {
389 gb_i2c_transfer_response(msgs, msg_count, response->data);
390 ret = msg_count;
391 }
392out:
393 gb_operation_destroy(operation);
394
395 return ret;
396}
397
398static int gb_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
399 int msg_count)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800400{
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700401 struct gb_i2c_device *gb_i2c_dev;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800402
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700403 gb_i2c_dev = i2c_get_adapdata(adap);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800404
Alex Eldered8800d2014-10-16 06:35:38 -0500405 return gb_i2c_transfer_operation(gb_i2c_dev, msgs, msg_count);
406}
407
408#if 0
409/* Later */
410static int gb_i2c_smbus_xfer(struct i2c_adapter *adap,
411 u16 addr, unsigned short flags, char read_write,
412 u8 command, int size, union i2c_smbus_data *data)
413{
414 struct gb_i2c_device *gb_i2c_dev;
415
416 gb_i2c_dev = i2c_get_adapdata(adap);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800417
418 return 0;
419}
Alex Eldered8800d2014-10-16 06:35:38 -0500420#endif
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800421
Alex Eldered8800d2014-10-16 06:35:38 -0500422static u32 gb_i2c_functionality(struct i2c_adapter *adap)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800423{
Alex Eldered8800d2014-10-16 06:35:38 -0500424 struct gb_i2c_device *gb_i2c_dev = i2c_get_adapdata(adap);
425
426 return gb_i2c_dev->functionality;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800427}
428
Alex Eldered8800d2014-10-16 06:35:38 -0500429static const struct i2c_algorithm gb_i2c_algorithm = {
430 .master_xfer = gb_i2c_master_xfer,
431 /* .smbus_xfer = gb_i2c_smbus_xfer, */
432 .functionality = gb_i2c_functionality,
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800433};
434
Alex Eldered8800d2014-10-16 06:35:38 -0500435/*
436 * Do initial setup of the i2c device. This includes verifying we
437 * can support it (based on the protocol version it advertises).
438 * If that's OK, we get and cached its functionality bits, and
439 * set up the retry count and timeout.
440 *
441 * Note: gb_i2c_dev->connection is assumed to have been valid.
442 */
443static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev)
444{
445 int ret;
446
447 /* First thing we need to do is check the version */
448 ret = gb_i2c_proto_version_operation(gb_i2c_dev);
449 if (ret)
450 return ret;
451
452 /* Assume the functionality never changes, just get it once */
453 ret = gb_i2c_functionality_operation(gb_i2c_dev);
454 if (ret)
455 return ret;
456
457 /* Set up our default retry count and timeout */
458 ret = gb_i2c_retries_operation(gb_i2c_dev, GB_I2C_RETRIES_DEFAULT);
459 if (ret)
460 return ret;
461
462 return gb_i2c_timeout_operation(gb_i2c_dev, GB_I2C_TIMEOUT_DEFAULT);
463}
464
465int gb_i2c_device_init(struct gb_connection *connection)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800466{
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700467 struct gb_i2c_device *gb_i2c_dev;
Alex Eldered8800d2014-10-16 06:35:38 -0500468 struct i2c_adapter *adapter = NULL;
469 int ret;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800470
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700471 gb_i2c_dev = kzalloc(sizeof(*gb_i2c_dev), GFP_KERNEL);
472 if (!gb_i2c_dev)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800473 return -ENOMEM;
Alex Eldered8800d2014-10-16 06:35:38 -0500474
475 gb_i2c_dev->connection = connection; /* refcount? */
476
477 ret = gb_i2c_device_setup(gb_i2c_dev);
478 if (ret)
479 goto out_err;
480
481 /* Looks good; allocate and set up our i2c adapter */
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800482 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
483 if (!adapter) {
Alex Eldered8800d2014-10-16 06:35:38 -0500484 ret = -ENOMEM;
485 goto out_err;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800486 }
487
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800488 adapter->owner = THIS_MODULE;
489 adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
Alex Eldered8800d2014-10-16 06:35:38 -0500490 adapter->algo = &gb_i2c_algorithm;
491 /* adapter->algo_data = what? */
492 adapter->timeout = gb_i2c_dev->timeout_msec * HZ / 1000;
493 adapter->retries = gb_i2c_dev->retries;
494
495 /* XXX I think this parent device is wrong, but it uses existing code */
496 adapter->dev.parent = &connection->interface->gmod->dev;
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +0800497 snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter");
Alex Eldered8800d2014-10-16 06:35:38 -0500498 i2c_set_adapdata(adapter, gb_i2c_dev);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800499
Alex Eldered8800d2014-10-16 06:35:38 -0500500 ret = i2c_add_adapter(adapter);
501 if (ret)
502 goto out_err;
503
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700504 gb_i2c_dev->adapter = adapter;
Alex Eldered8800d2014-10-16 06:35:38 -0500505 connection->private = gb_i2c_dev;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800506
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800507 return 0;
Alex Eldered8800d2014-10-16 06:35:38 -0500508out_err:
Greg Kroah-Hartman53419e02014-08-11 17:01:15 +0800509 kfree(adapter);
Alex Eldered8800d2014-10-16 06:35:38 -0500510 /* kref_put(gb_i2c_dev->connection) */
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700511 kfree(gb_i2c_dev);
Alex Eldered8800d2014-10-16 06:35:38 -0500512
513 return ret;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800514}
515
Alex Eldered8800d2014-10-16 06:35:38 -0500516void gb_i2c_device_exit(struct gb_connection *connection)
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800517{
Alex Eldered8800d2014-10-16 06:35:38 -0500518 struct gb_i2c_device *gb_i2c_dev = connection->private;
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800519
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700520 i2c_del_adapter(gb_i2c_dev->adapter);
521 kfree(gb_i2c_dev->adapter);
Alex Eldered8800d2014-10-16 06:35:38 -0500522 /* kref_put(gb_i2c_dev->connection) */
Greg Kroah-Hartman3d9efaa2014-08-30 16:49:59 -0700523 kfree(gb_i2c_dev);
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800524}
525
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -0700526#if 0
Greg Kroah-Hartmanc8a797a2014-08-11 15:30:45 +0800527module_greybus_driver(i2c_gb_driver);
528MODULE_LICENSE("GPL");
529MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");
Greg Kroah-Hartman199d68d2014-08-30 16:20:22 -0700530#endif