added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / i2c / busses / i2c-serial.c
blobf0d4ccc49c033d11e0f996184283273ccf0ec60a
1 /*
2 i2c-serial.c - I2C Driver for I2C on serial port
3 Copyright (c) 2007 Momtchil Momtchev <momtchil@momtchev.com>
4 Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
5 Simon Vogl
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 /* This interfaces to the I2C bus connected to a serial port */
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/pci.h>
29 #include <linux/types.h>
30 #include <linux/fcntl.h>
31 #include <linux/interrupt.h>
32 #include <linux/i2c.h>
33 #include <linux/i2c-algo-bit.h>
34 #include <linux/tty.h>
35 #include <linux/poll.h>
36 #include <linux/input.h>
37 #include <linux/serio.h>
38 #include <asm/io.h>
39 #include <linux/errno.h>
40 #include <linux/proc_fs.h>
42 #define I2CSERIAL_DEBUG 0
44 #if I2CSERIAL_DEBUG==1
45 #define VERSION "1.15d"
46 #else
47 #define VERSION "1.15"
48 #endif
50 #define I2CSERIAL_STATS
53 * History
54 * v1.00 by Momtchil
55 * v1.01 (and following) by Brice Marnier <marnier@aldebaran-robotics.com>
56 * adapted to match new PSoC protocol
57 * v1.03 - support for PSoC Watchdog reset
58 * v1.04 - speed enhancement
59 * v1.05 - i2c_transfer support, firmware version display at startup
60 * v1.06 - escape sequence bugfix
61 * v1.07 - added consistent error codes
62 * timeout down to 5ms
63 * v1.08 - reduced logging in potentially repetitive error cases
64 * v1.10 - /proc/i2cstats version info and error statistics
65 * v1.11 - timeout = 52 (make the flasher work)
66 * v1.12 - send reset to the psoc in i2c mode too
67 * v1.13 - handle wakeup order from the psoc
68 * - cedric gestes <gestes@aldebaran-robotics.com>
69 * v1.14 - handle i2c_smbus_read_i2c_block_data
70 * - code factorisation
71 * - cedric gestes <gestes@aldebaran-robotics.com>
72 * v1.15 - init return
73 * todo (one day /sys/... equivalent ?)
74 * */
76 #define DRV_NAME "Serial I2C/SMBus driver"
77 const char drv_name[] = DRV_NAME;
79 MODULE_AUTHOR("Momtchil Momtchev <momtchil@momtchev.com>, Brice Marnier <briareos@hecatonchires.com>");
80 MODULE_DESCRIPTION(DRV_NAME);
81 MODULE_LICENSE("GPL");
82 MODULE_VERSION(VERSION);
84 #define TIMEOUT msecs_to_jiffies(52)
85 //#define TIMEOUT_RESET msecs_to_jiffies(50)
86 #define I2C_SERIAL_BUFFER_LENGTH 256
88 #include "psoc-protocol.h"
90 /* PSoC is idle */
91 #define I2C_STATE_IDLE 0x01
92 /* Sending on serial */
93 #define I2C_STATE_SEND 0x02
94 /* Waiting for reply, probably [Esc]*/
95 #define I2C_STATE_WAIT 0x04
96 /* Waiting for raw input data or [Esc]*/
97 #define I2C_STATE_READ 0x06
98 /* Waiting for input after ESCAPE_CHAR */
99 #define I2C_STATE_CMD 0x08
100 /* Waiting for watchdog reset, i.e. [Esc]'z' after ~8ms idle*/
101 /* WAIT_WATCHDOG is 0x10 + IDLE, to be detected as an idle mode */
102 #define I2C_STATE_WAIT_WATCHDOG 0x11
103 /* Version request running = waiting for constant length string reply */
104 #define I2C_STATE_VERSION 0x20
106 #define I2C_ERROR_NAK ( -EAGAIN) // "Ressource temporarily unavailable"
107 #define I2C_ERROR_ADDRNAK ( -ENXIO) // "No such device or address"
108 #define I2C_ERROR_BUSY ( -EBUSY) // "Device or resource busy"
109 #define I2C_ERROR_STALL ( -EIO) // "Input/output error"
110 #define I2C_ERROR_TIMEOUT (-ETIMEDOUT) // "Connection timed out"
111 #define I2C_ERROR_OVERBUFF (-EOVERFLOW) // "Value too large..."
112 #define I2C_ERROR_RESET (-ECANCELED) // "Operation canceled"
113 #define I2C_ERROR_MTF (-ENOMEDIUM)
115 static DECLARE_WAIT_QUEUE_HEAD(wq);
119 * 2.6.22.9 hacked to support read with size diff than 32
120 * in newer kernel 2.6.23 or later
121 * the previous I2C_SMBUS_I2C_BLOCK_DATA has been renamed
122 * I2C_SMBUS_I2C_BLOCK_BROKEN
124 * but I dont want to make that change here
125 * CTAF
127 #define I2C_SMBUS_I2C_BLOCK_DATA_ALL_SIZE 8
132 /* {{{ i2c_data
133 * structure for I2C-serial data
134 * */
135 struct i2c_data {
136 struct i2c_adapter adapter;
137 struct i2c_client *client;
138 int state;
139 int error;
140 int jiffies;
141 unsigned char * irq_buffer; /* can point either to buffer below, or to provided buffer for I2C transfers */
142 unsigned char buffer[I2C_SERIAL_BUFFER_LENGTH];
143 unsigned int pos; /* position inside the buffer */
144 u8 reply_count; /* number of replies to wait for before command completion */
145 // u8 addr; /* last used address (useless) */
146 }; // }}}
148 #ifdef I2CSERIAL_STATS
149 struct i2cserial_stats__ {
150 char firmware_version[8];
151 long int serio_access;
152 long int serio_err;
153 int smbrq;
154 int smb_err;
155 int i2crq;
156 int i2c_err;
157 } i2cserial_stats ;
158 # define STAT(x) {x;}
159 #else
160 # define STAT(x) {;}
161 #endif
163 #define I2CS_ERR(fmt, arg...) printk(KERN_ERR "i2c_serial {%s}: " fmt "\n" , __FUNCTION__ , ## arg)
164 #define I2CS_INFO(fmt, arg...) printk(KERN_INFO "i2c_serial [%s]: " fmt "\n" , __FUNCTION__ , ## arg)
165 #if I2CSERIAL_DEBUG==1
166 #define I2CS_DEBUG(fmt, arg...) printk(KERN_DEBUG "i2c_serial (%s): " fmt "\n" , __FUNCTION__ , ## arg)
167 #else
168 #define I2CS_DEBUG(fmt, arg...) while (0) {}
169 #endif
173 * internal function to handle i2c buffer
175 static inline char *serial_append_escaped_byte(unsigned char *p, unsigned char c)
177 if (c == ESCAPE_CHAR)
178 *p++ = ESCAPE_CHAR;
179 *p++ = c;
180 return p;
183 static unsigned char *serial_append_read(unsigned char *p, unsigned char address, unsigned char size)
185 *p++ = ESCAPE_CHAR;
186 *p++ = CMD_READ;
187 *p++ = (unsigned char)(address & 0x7f);
188 p = serial_append_escaped_byte(p, size);
189 return p;
192 static unsigned char *serial_append_write(unsigned char *p, unsigned char address, unsigned char data)
194 *p++ = ESCAPE_CHAR;
195 *p++ = CMD_WRITE;
196 *p++ = (unsigned char)(address & 0x7f);
197 p = serial_append_escaped_byte(p, (unsigned char)(data & 0xff));
198 return p;
201 static unsigned char *serial_append_write_block(unsigned char *p,
202 unsigned char address,
203 unsigned char *data,
204 unsigned char size)
206 int i = 0;
208 *p++ = ESCAPE_CHAR;
209 *p++ = CMD_WRITE;
210 *p++ = (unsigned char)(address & 0x7f);
211 for(i = 0; i< size; ++i) {
212 p = serial_append_escaped_byte(p, data[i]);
214 return p;
217 static unsigned char *serial_append_footer(unsigned char *p)
219 *p++ = ESCAPE_CHAR;
220 *p++ = CMD_EOT;
221 return p;
226 /* {{{ i2c_serial_get_version : ask PSoC for firmware version
227 * */
228 static inline char* i2c_serial_get_version(struct i2c_adapter *adapter) {
230 struct serio *serio = adapter->algo_data;
231 struct i2c_data *i2cd = serio_get_drvdata(serio);
232 unsigned int i = 0;
234 for (i=0; i<8; ++i) {
235 i2cd->buffer[i] = 0;
236 STAT(i2cserial_stats.firmware_version[i] = 0);
238 i2cd->irq_buffer = &(i2cd->buffer[0]);
240 I2CS_DEBUG("Asking for PSoC firmware version...");
241 I2CS_DEBUG("serio_write(0x%02x)", (unsigned)ESCAPE_CHAR);
243 STAT(i2cserial_stats.serio_access++;)
244 if (serio_write(serio, ESCAPE_CHAR) < 0) {
245 I2CS_ERR("serio_write(0x%02x) failed", (unsigned)ESCAPE_CHAR);
246 STAT(i2cserial_stats.serio_err++);
249 I2CS_DEBUG("serio_write(0x%02x)", (unsigned)CMD_VERSION);
250 STAT(i2cserial_stats.serio_access++);
251 if (serio_write(serio, CMD_VERSION) < 0) {
252 I2CS_ERR("serio_write(0x%02x) failed", (unsigned)CMD_VERSION);
253 STAT(i2cserial_stats.serio_err++);
256 i2cd->state = I2C_STATE_WAIT;
257 wait_event_interruptible_timeout(wq, i2cd->state == I2C_STATE_IDLE, TIMEOUT);
259 STAT(strncpy(i2cserial_stats.firmware_version, i2cd->buffer, 7));
260 // no need to check : if things went wrong, buffer is empty anyway...
261 return i2cd->buffer;
262 } // i2c_serial_get_version }}}
265 //{{{ i2c_serio_i2c_xfer
266 static s32 i2c_serio_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg messages[], int num) {
268 struct serio *serio ;
269 struct i2c_data *i2cd ;
270 unsigned int i=0;
271 unsigned char *p, *q;
272 s32 ret = 0;
273 s32 tmp = 0;
275 if (!adapter) {
276 printk(KERN_ERR "i2c-serial (%s): NULL adapter !", __FUNCTION__);
277 return -EINVAL;
280 serio = adapter->algo_data;
281 i2cd = serio_get_drvdata(serio);
282 I2CS_DEBUG("J:%ld - %d I2C msg", jiffies, num);
283 STAT(i2cserial_stats.i2crq++);
284 for (i=0; i<num; ++i) {
286 if (messages[i].len > (I2C_SERIAL_BUFFER_LENGTH-1) ) {
287 I2CS_ERR("Cannot handle requests more than %d bytes long (asked=%d) !", (I2C_SERIAL_BUFFER_LENGTH-1), messages[i].len);
288 ret = -EMSGSIZE; // Message too long
289 break;
292 if ( ! (i2cd->state & I2C_STATE_IDLE) )
293 wait_event_interruptible_timeout(wq, (i2cd->state &I2C_STATE_IDLE) == I2C_STATE_IDLE, TIMEOUT);
295 if ( (i2cd->state & I2C_STATE_IDLE) != I2C_STATE_IDLE ) {
296 I2CS_ERR("PSoC jammed !"); /* TODO reset PSoC*/
297 i2cd->state = I2C_STATE_IDLE;
300 i2cd->jiffies = jiffies;
301 i2cd->error = 0;
302 i2cd->reply_count = 1;
304 p = i2cd->buffer;
305 if (messages[i].flags & I2C_M_RD) {
306 p = serial_append_read(p, messages[i].addr, messages[i].len);
307 i2cd->state = I2C_STATE_READ;
308 /* prepare irq_buffer */
309 i2cd->irq_buffer = messages[i].buf;
310 i2cd->pos = 0;
311 } else {
312 p = serial_append_write_block(p, messages[i].addr, messages[i].buf, messages[i].len);
313 p = serial_append_footer(p);
314 i2cd->state = I2C_STATE_WAIT;
317 /* send command via serio */
318 tmp=0;
319 for (q=i2cd->buffer; q<p; q++) {
320 STAT(i2cserial_stats.serio_access++);
321 tmp+=ret=serio_write(serio, *q);
322 if (ret < 0) {
323 STAT(i2cserial_stats.serio_err++);
326 if ( tmp < 0 ) {
327 I2CS_DEBUG("serio_write() errors (%d)", -tmp);
328 break;
331 // wait for interrupt return
332 wait_event_interruptible_timeout(wq, (i2cd->state & I2C_STATE_IDLE) == I2C_STATE_IDLE, TIMEOUT);
334 if (! (i2cd->state & I2C_STATE_IDLE) ) {
335 // I2CS_INFO("Interrupt timed out...");
336 #if I2CSERIAL_DEBUG==1
337 char tmp_str[1024];
338 int idx=0;
339 idx=sprintf(&tmp_str[0],"{");
340 for(q=i2cd->buffer; q<p; ++q) {
341 idx+=sprintf(&tmp_str[idx],"%02x,", *q);
343 idx+=sprintf(&tmp_str[idx],"}");
344 tmp_str[idx]=0;
345 I2CS_DEBUG("J:%d+%u time out sending buffer[]=%s", i2cd->jiffies, (unsigned)(jiffies - i2cd->jiffies), tmp_str);
346 #endif
347 i2cd->state = I2C_STATE_WAIT_WATCHDOG;
348 // I2CS_DEBUG("serio_write(0x%02x)", (unsigned)ESCAPE_CHAR);
349 #ifdef I2CSERIAL_STATS
350 STAT(i2cserial_stats.serio_access++);
351 #endif
352 ret=serio_write(serio, ESCAPE_CHAR);
353 if (ret < 0) {
354 STAT(i2cserial_stats.serio_err++);
356 STAT(i2cserial_stats.serio_access++);
357 ret=serio_write(serio, CMD_RESET);
358 if (ret < 0) {
359 STAT(i2cserial_stats.serio_err++);
361 wait_event_interruptible_timeout(wq, i2cd->state == I2C_STATE_IDLE, TIMEOUT);
362 ret=-ETIME; // "Timer expired"
363 break;
366 I2CS_DEBUG("xfer complete in %u jif", (unsigned)(jiffies - i2cd->jiffies));
368 // handle return values (errors and buffers)
369 if (i2cd->error) {
370 #if I2CSERIAL_DEBUG==1
371 char tmp_str[1024];
372 int idx=0;
373 idx=sprintf(&tmp_str[0],"{");
374 for(q=i2cd->buffer; q<p; ++q) {
375 idx+=sprintf(&tmp_str[idx],"%02x,", *q);
377 idx+=sprintf(&tmp_str[idx],"}");
378 tmp_str[idx]=0;
379 I2CS_DEBUG("error(%d) sending buffer[]=%s", i2cd->error, tmp_str);
380 #endif
381 ret=i2cd->error;
382 i2cd->error=0;
383 break;
385 ret+=messages[i].len;
387 if (ret < 0) {
388 STAT(i2cserial_stats.i2c_err++);
390 return ret;
391 } //i2c_serio_i2c_xfer }}}
393 /* {{{ i2c_serio_smbus_xfer : SMBus transfer callback */
394 static s32 i2c_serio_smbus_xfer(struct i2c_adapter *adapter,
395 u16 address,
396 unsigned short flags,
397 char rw,
398 u8 command,
399 int size,
400 union i2c_smbus_data *data)
402 struct serio *serio = adapter->algo_data;
403 struct i2c_data *i2cd = serio_get_drvdata(serio);
404 unsigned char *p, *i;
405 int ret=0;
406 int tmp=0;
408 I2CS_DEBUG("J:%lu @%x (rw=%d), cmd%02x, sz%d, dp%p", jiffies,
409 (unsigned)address, (int)rw, (unsigned)command, (int)size, data);
410 STAT(i2cserial_stats.smbrq++);
412 if ( ! (i2cd->state & I2C_STATE_IDLE) )
413 wait_event_interruptible_timeout(wq, (i2cd->state &I2C_STATE_IDLE) == I2C_STATE_IDLE, TIMEOUT);
415 if ( ! (i2cd->state & I2C_STATE_IDLE) ) {
416 I2CS_ERR("PSoC jammed..."); /* TODO : reset */
417 i2cd->state = I2C_STATE_IDLE;
420 do {
422 i2cd->pos = 0;
423 p = i2cd->buffer;
425 i2cd->reply_count = 1;
427 switch (size) {
429 case I2C_SMBUS_BYTE:
430 if (rw == I2C_SMBUS_WRITE) {
431 p = serial_append_write(p, address, command);
432 p = serial_append_footer(p);
433 } else {
434 p = serial_append_read(p, address, 1);
436 break;
438 case I2C_SMBUS_BYTE_DATA:
439 if (rw == I2C_SMBUS_WRITE){
440 p = serial_append_write(p, address, command);
441 p = serial_append_escaped_byte(p, (unsigned char)(data->byte & 0xff));
442 p = serial_append_footer(p);
443 } else {
444 p = serial_append_write(p, address, command);
445 p = serial_append_footer(p);
446 p = serial_append_read(p, address, 1);
447 i2cd->reply_count = 2;
449 break;
452 * DATA_ALL_SIZE : tweak (see i2c-dev.c) to pass arbitrary size
453 * tweak not needed in future kernel
454 * I think the transition with newer kernel will be smooth:
455 * just remove I2C_SMBUS_I2C_BLOCK_DATA_ALL_SIZE
456 * but verify what I2C_SMBUS_I2C_BLOCK_DATA and I2C_SMBUS_I2C_BLOCK_BROKEN do
458 case I2C_SMBUS_I2C_BLOCK_DATA:
459 // case I2C_SMBUS_I2C_BLOCK_DATA_ALL_SIZE:
460 if (rw == I2C_SMBUS_WRITE) {
461 p = serial_append_write(p, address, command);
462 for(i = data->block + 1; i <= data->block + data->block[0]; i++)
463 p = serial_append_escaped_byte(p, *i);
464 p = serial_append_footer(p);
465 } else {
466 I2CS_DEBUG("read_block_data: %d", data->block[0]);
467 p = serial_append_write(p, address, command);
468 p = serial_append_footer(p);
469 //we will receive data block + 1 (the size)
470 p = serial_append_read(p, address, data->block[0] + 1);
471 i2cd->reply_count = 2;
473 break;
475 case I2C_SMBUS_BLOCK_DATA:
476 if (rw == I2C_SMBUS_WRITE) {
477 p = serial_append_write(p, address, command);
478 for(i = data->block; i <= data->block + data->block[0]; i++)
479 p = serial_append_escaped_byte(p, *i);
480 p = serial_append_footer(p);
481 } else {
483 * we can't handle this case : because the size is not specified
484 * the psoc need to read the first byte (the size) from the slave
485 * then he can nack when all data is received
487 * psoc doesnt handle this case
489 I2CS_ERR("Unsupported transaction size %d", size);
491 break;
493 default:
494 I2CS_ERR("Unsupported transaction size %d", size);
495 ret=-ENOTSUPP;
496 break;
499 //i2cd->jiffies = jiffies;
500 if (rw == I2C_SMBUS_WRITE) {
501 i2cd->state = I2C_STATE_WAIT;
502 } else {
503 i2cd->state = I2C_STATE_READ;
504 /* prepare irq_buffer */
505 i2cd->irq_buffer = &(i2cd->buffer[0]);
508 I2CS_DEBUG("send %dB seriobuf", p-i2cd->buffer);
510 /* send command via serio */
511 tmp=0;
512 for (i = i2cd->buffer; i < p; i++) {
513 STAT(i2cserial_stats.serio_access++);
514 tmp+=ret=serio_write(serio, *i);
515 if (ret < 0) {
516 STAT(i2cserial_stats.serio_err++);
519 if ( tmp < 0 ) {
520 I2CS_DEBUG("serio_write() errors (%d)", -tmp);
523 /* command is always sent in 0 jiffies ! (buffered)
524 I2CS_DEBUG("command sent in %u jiffies", (unsigned)(jiffies - i2cd->jiffies));
526 i2cd->jiffies = jiffies;
527 i2cd->error = 0;
528 i2cd->pos = 0;
530 wait_event_interruptible_timeout(wq, (i2cd->state & I2C_STATE_IDLE) == I2C_STATE_IDLE, TIMEOUT);
532 if (! (i2cd->state & I2C_STATE_IDLE) ) {
533 #if I2CSERIAL_DEBUG==1
534 char tmp_str[256];
535 int idx=0;
536 idx=sprintf(&tmp_str[0],"{");
537 for(i=i2cd->buffer; i<p; ++i) {
538 idx+=sprintf(&tmp_str[idx],"%02x,", *i);
540 idx+=sprintf(&tmp_str[idx],"}");
541 tmp_str[idx]=0;
542 I2CS_DEBUG("J:%d+%u time out sending buffer[]=%s", i2cd->jiffies, (unsigned)(jiffies - i2cd->jiffies), tmp_str);
543 #endif
544 I2CS_DEBUG("serio_write time out (err:%d), sending reset request...", i2cd->error);
545 i2cd->state = I2C_STATE_WAIT_WATCHDOG;
547 STAT(i2cserial_stats.serio_access++);
548 ret=serio_write(serio, ESCAPE_CHAR);
549 if (ret < 0) {
550 STAT(i2cserial_stats.serio_err++);
553 STAT(i2cserial_stats.serio_access++);
554 ret=serio_write(serio, CMD_RESET);
555 if (ret < 0) {
556 STAT(i2cserial_stats.serio_err++);
558 wait_event_interruptible_timeout(wq, i2cd->state == I2C_STATE_IDLE, TIMEOUT);
559 ret= -EIO;
560 break;
563 /* TODO : extended error handling */
564 if (i2cd->error) {
565 #if I2CSERIAL_DEBUG==1
566 char tmp_str[256];
567 int idx=0;
568 idx=sprintf(&tmp_str[0],"{");
569 for(i=i2cd->buffer; i<p; ++i) {
570 idx+=sprintf(&tmp_str[idx],"%02x,", *i);
572 idx+=sprintf(&tmp_str[idx],"}");
573 tmp_str[idx]=0;
574 I2CS_DEBUG("error(%d) sending buffer[]=%s", i2cd->error, tmp_str);
575 #endif
576 ret=i2cd->error;
577 i2cd->error=0;
578 break;
581 if (rw == I2C_SMBUS_READ) {
582 if (size == I2C_SMBUS_I2C_BLOCK_DATA_ALL_SIZE)
584 int j;
585 int sz = data->block[0];
587 if (sz > i2cd->pos)
588 sz = i2cd->pos;
589 if (sz > 32)
590 sz = 32;
591 I2CS_DEBUG("read_block_data return: %d", sz);
592 for(j = 0; j < sz; ++j)
593 data->block[j+1] = i2cd->buffer[j];
595 else
596 data->byte = i2cd->buffer[0];
600 ret=0;
602 } while (0) ;
604 I2CS_DEBUG("xfer complete in %u jif", (unsigned)(jiffies - i2cd->jiffies));
605 if ( ret < 0 ) {
606 STAT(i2cserial_stats.smb_err++);
608 return ret;
609 } //i2c_serio_smbus_xfer }}}
611 /* {{{ i2c_serio_func ireturn supported I2C/SMBus functionnalities */
612 static u32 i2c_serio_func(struct i2c_adapter *adapter)
615 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
616 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
617 I2C_FUNC_SMBUS_I2C_BLOCK;
619 return I2C_FUNC_SMBUS_BYTE |
620 I2C_FUNC_SMBUS_BYTE_DATA |
621 I2C_FUNC_SMBUS_BLOCK_DATA |
622 I2C_FUNC_SMBUS_I2C_BLOCK;
623 } // i2c_serio_func }}}
625 static const struct i2c_algorithm i2c_algo = {
626 .master_xfer = i2c_serio_i2c_xfer,
627 .smbus_xfer = i2c_serio_smbus_xfer,
628 .functionality = i2c_serio_func,
631 /* {{{ i2c_interrupt : serial interrupt service routine
632 - store serial data into irqbuffer
634 static irqreturn_t i2c_interrupt(struct serio *serio, unsigned char data,
635 unsigned int flags)
637 struct i2c_data *i2cd = NULL;
639 i2cd = serio_get_drvdata(serio);
641 I2CS_DEBUG("%02x[%x],%d+%u", (unsigned)data, flags, i2cd->jiffies, (unsigned)(jiffies - i2cd->jiffies));
643 switch (i2cd->state) {
644 case I2C_STATE_WAIT:
645 /* we're waiting for reply (but no data), we must read [Esc]. Ignore
646 * anything else*/
647 if (data == ESCAPE_CHAR) {
648 i2cd->state = I2C_STATE_CMD;
649 i2cd->error = 0;
650 //I2CS_DEBUG("Command ACK in %d jiffies", (int)(jiffies - i2cd->jiffies));
652 break;
654 case I2C_STATE_CMD:
655 switch (data) {
656 case ESCAPE_CHAR: //escaped ESC caracter
657 if (i2cd->pos >= I2C_SERIAL_BUFFER_LENGTH) {
658 I2CS_ERR("Buffer overflow ! (0x%02x)", data);
659 } else {
660 i2cd->irq_buffer[i2cd->pos++] = data;
661 //i2cd->state=I2C_STATE_READ;
663 break;
664 case REPLY_NAK:
665 i2cd->error=I2C_ERROR_ADDRNAK;
666 I2CS_DEBUG("Slave not existing (0x%02x).", data);
667 i2cd->reply_count--;
668 break;
669 case REPLY_ADDRNAK:
670 i2cd->error=I2C_ERROR_NAK;
671 I2CS_DEBUG("Slave not responding (0x%02x).", data);
672 i2cd->reply_count--;
673 break;
674 case REPLY_OVERFLOW:
675 i2cd->error=I2C_ERROR_OVERBUFF;
676 I2CS_DEBUG("PSoC buffer overflow.");
677 i2cd->reply_count--;
678 break;
679 case 'F':
680 i2cd->error=I2C_ERROR_MTF;
681 I2CS_DEBUG("Master transmit failure (Wow, how can it happen ?).");
682 i2cd->reply_count--;
683 break;
684 case REPLY_STALLED:
685 i2cd->error=I2C_ERROR_STALL;
686 I2CS_DEBUG("I2C bus stalled.");
687 i2cd->reply_count--;
688 break;
689 case REPLY_TIMEOUT:
690 i2cd->error=I2C_ERROR_TIMEOUT;
691 I2CS_DEBUG("No activity within timeout period.");
692 i2cd->reply_count--;
693 break;
694 case REPLY_CANCELREAD:
695 case REPLY_CANCELWRITE:
696 i2cd->error=I2C_ERROR_BUSY;
697 I2CS_DEBUG("Device busy (or garbled), command refused.");
698 i2cd->reply_count--;
699 break;
700 case CMD_RESET:
701 i2cd->error=I2C_ERROR_RESET;
702 I2CS_DEBUG("Device reset (watchdog timed out).");
703 i2cd->reply_count=0;
704 break;
705 case CMD_VERSION:
706 i2cd->reply_count=4;
707 i2cd->pos=0;
708 i2cd->state=I2C_STATE_VERSION;
709 break;
711 case CMD_WAKEUP:
712 I2CS_DEBUG("Received wakeup command from PSoC.");
713 break;
715 default:
716 if (data>='A' && data <='Z') {
717 /* write subcommand completed successfully */
718 i2cd->reply_count--;
719 break;
721 if (data>='a' && data <='z') {
722 /* read subcommand completed successfully */
723 i2cd->reply_count--;
724 break;
726 I2CS_INFO("Ignoring unexpected 'ESC-Ox%02x' from PSoC.", data);
728 if (i2cd->reply_count==0) {
729 /* command completed , PSoC will reset soon if no more commands
730 * we must have another wait state, which will not wake_up*/
731 i2cd->state = I2C_STATE_WAIT_WATCHDOG;
732 wake_up_interruptible(&wq);
733 } else {
734 if (i2cd->state != I2C_STATE_VERSION) {
735 i2cd->state = I2C_STATE_READ;
738 break;
740 case I2C_STATE_VERSION:
741 i2cd->irq_buffer[i2cd->pos++] = data;
742 if (--i2cd->reply_count == 0) {
743 i2cd->state = I2C_STATE_WAIT_WATCHDOG;
744 wake_up_interruptible(&wq);
746 break;
748 case I2C_STATE_WAIT_WATCHDOG:
749 if (data==ESCAPE_CHAR) {
750 //ignore it; if it is a reply, we should be in WAIT state
752 if (data==CMD_RESET) {
753 // PSoC WDR complete, nothing more should come
754 i2cd->state = I2C_STATE_IDLE;
756 break;
758 case I2C_STATE_READ:
759 if (data==ESCAPE_CHAR) {
760 i2cd->state = I2C_STATE_CMD;
761 } else {
762 if (i2cd->pos >= I2C_SERIAL_BUFFER_LENGTH) {
763 I2CS_ERR("Buffer overflow !! (0x%02x)", data);
764 } else {
765 i2cd->irq_buffer[i2cd->pos++] = data;
768 break;
770 default:
771 /* invalid I2C_STATE */
772 I2CS_DEBUG("Spurious int. data %02x state %d",
773 (unsigned)data, i2cd->state);
775 return IRQ_HANDLED;
776 } // i2c_interrupt }}}
778 /* {{{ i2c_disconnect : serial port disconnection callback */
779 static void i2c_disconnect(struct serio *serio)
781 struct i2c_data *i2cd = serio_get_drvdata(serio);
783 i2c_del_adapter(&i2cd->adapter);
784 serio_close(serio);
785 serio_set_drvdata(serio, NULL);
786 kfree(i2cd);
787 } // i2c_disconnect }}}
789 /* {{{ i2c_connect : line discipline registration
790 + I2C adapter registration
792 static int i2c_connect(struct serio *serio, struct serio_driver *drv)
794 struct i2c_data *i2cd;
795 struct i2c_adapter *adapter;
796 int err;
798 I2CS_DEBUG("i2c_connect");
800 i2cd = kzalloc(sizeof(struct i2c_data), GFP_KERNEL);
801 if (!i2cd) {
802 err = -ENOMEM;
803 goto exit;
805 i2cd->state = I2C_STATE_IDLE;
807 serio_set_drvdata(serio, i2cd);
809 I2CS_DEBUG("Opening serio with driver '%s'.", drv->description);
811 err = serio_open(serio, drv);
812 if (err) {
813 I2CS_ERR("serio_open failed %d", err);
814 goto exit_kfree;
817 adapter = &i2cd->adapter;
818 adapter->owner = THIS_MODULE;
819 adapter->algo = &i2c_algo;
820 adapter->algo_data = serio;
821 adapter->dev.parent = &serio->dev;
822 adapter->id = I2C_HW_B_SER;
824 strlcpy(adapter->name, DRV_NAME, strlen(DRV_NAME));
826 err = i2c_add_adapter(adapter);
827 if (err) {
828 I2CS_DEBUG("adapter registration failed.");
829 goto exit_close;
832 I2CS_INFO("I2C over serial port registered.");
834 I2CS_INFO("PSoC firmware version '%s'.", i2c_serial_get_version(adapter));
836 return 0;
838 exit_close:
839 serio_close(serio);
840 exit_kfree:
841 serio_set_drvdata(serio, NULL);
842 kfree(i2cd);
843 exit:
844 return err;
845 } // i2c_connect }}}
847 /* descripteur du line discipline */
848 static struct serio_device_id i2c_serio_ids[] = {
850 .type = SERIO_RS232,
851 .proto = 0x77,
852 .id = SERIO_ANY,
853 .extra = SERIO_ANY,
855 { 0 }
857 MODULE_DEVICE_TABLE(serio, i2c_serio_ids);
859 /* descripteur du driver serio */
860 static struct serio_driver i2c_drv = {
861 .driver = {
862 .name = "i2c_serio",
864 .description = "I2C on serial port PSoC (Aldebaran)",
865 .id_table = i2c_serio_ids,
866 .connect = i2c_connect,
867 .disconnect = i2c_disconnect,
868 .interrupt = i2c_interrupt,
871 #ifdef I2CSERIAL_STATS
872 /* {{{ proc_i2cstats_read : report debugging statistical info to /proc
873 * TODO check len is always<count !!!! */
874 int proc_i2cstats_read(char* buf, char** start, off_t offset,
875 int count, int* eof, void* data) {
876 int len=0;
877 len += sprintf(buf+len,"I2C-serial driver version '%s'\n", VERSION);
878 len += sprintf(buf+len,"PSoC firmware version '%s'\n", i2cserial_stats.firmware_version);
879 len += sprintf(buf+len,"I2C_xfr: %8d, %d error(s)\n", i2cserial_stats.i2crq, i2cserial_stats.i2c_err);
880 len += sprintf(buf+len,"SMBus : %8d, %d error(s)\n", i2cserial_stats.smbrq, i2cserial_stats.smb_err);
881 len += sprintf(buf+len,"Serial : %8ld B, %ld error(s)\n", i2cserial_stats.serio_access, i2cserial_stats.serio_err);
882 0[eof]=1;
883 return len;
884 } // }}}
885 #endif
887 /* initialisation du module et enregistrement du driver serio */
888 static int __init i2c_serio_init(void)
890 int ret=0;
891 I2CS_INFO("I2C serio driver ver %s", VERSION);
892 ret = serio_register_driver(&i2c_drv);
893 #ifdef I2CSERIAL_STATS
894 for (ret=0; ret<sizeof(struct i2cserial_stats__); ++ret) {
895 *((char*)(&i2cserial_stats) + ret) = '\0';
897 create_proc_read_entry("i2cstats", 0, NULL, proc_i2cstats_read, NULL);
898 #endif
899 return 0;
902 static void __exit i2c_serio_exit(void)
904 STAT(remove_proc_entry("i2cstats", NULL));
905 serio_unregister_driver(&i2c_drv);
908 module_init(i2c_serio_init);
909 module_exit(i2c_serio_exit);