diff options
Diffstat (limited to 'arch/cris/arch-v32/drivers/i2c.c')
-rw-r--r-- | arch/cris/arch-v32/drivers/i2c.c | 206 |
1 files changed, 170 insertions, 36 deletions
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c index f1edd2e359b2..c2fb7a5c1396 100644 --- a/arch/cris/arch-v32/drivers/i2c.c +++ b/arch/cris/arch-v32/drivers/i2c.c | |||
@@ -19,10 +19,10 @@ | |||
19 | *! | 19 | *! |
20 | *! --------------------------------------------------------------------------- | 20 | *! --------------------------------------------------------------------------- |
21 | *! | 21 | *! |
22 | *! (C) Copyright 1999-2002 Axis Communications AB, LUND, SWEDEN | 22 | *! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN |
23 | *! | 23 | *! |
24 | *!***************************************************************************/ | 24 | *!***************************************************************************/ |
25 | /* $Id: i2c.c,v 1.2 2005/05/09 15:29:49 starvik Exp $ */ | 25 | |
26 | /****************** INCLUDE FILES SECTION ***********************************/ | 26 | /****************** INCLUDE FILES SECTION ***********************************/ |
27 | 27 | ||
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
@@ -79,6 +79,8 @@ static const char i2c_name[] = "i2c"; | |||
79 | 79 | ||
80 | #define i2c_delay(usecs) udelay(usecs) | 80 | #define i2c_delay(usecs) udelay(usecs) |
81 | 81 | ||
82 | static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */ | ||
83 | |||
82 | /****************** VARIABLE SECTION ************************************/ | 84 | /****************** VARIABLE SECTION ************************************/ |
83 | 85 | ||
84 | static struct crisv32_iopin cris_i2c_clk; | 86 | static struct crisv32_iopin cris_i2c_clk; |
@@ -252,6 +254,7 @@ i2c_getack(void) | |||
252 | * generate ACK clock pulse | 254 | * generate ACK clock pulse |
253 | */ | 255 | */ |
254 | i2c_clk(I2C_CLOCK_HIGH); | 256 | i2c_clk(I2C_CLOCK_HIGH); |
257 | #if 0 | ||
255 | /* | 258 | /* |
256 | * Use PORT PB instead of I2C | 259 | * Use PORT PB instead of I2C |
257 | * for input. (I2C not working) | 260 | * for input. (I2C not working) |
@@ -264,6 +267,8 @@ i2c_getack(void) | |||
264 | i2c_data(1); | 267 | i2c_data(1); |
265 | i2c_disable(); | 268 | i2c_disable(); |
266 | i2c_dir_in(); | 269 | i2c_dir_in(); |
270 | #endif | ||
271 | |||
267 | /* | 272 | /* |
268 | * now wait for ack | 273 | * now wait for ack |
269 | */ | 274 | */ |
@@ -271,11 +276,11 @@ i2c_getack(void) | |||
271 | /* | 276 | /* |
272 | * check for ack | 277 | * check for ack |
273 | */ | 278 | */ |
274 | if(i2c_getbit()) | 279 | if (i2c_getbit()) |
275 | ack = 0; | 280 | ack = 0; |
276 | i2c_delay(CLOCK_HIGH_TIME/2); | 281 | i2c_delay(CLOCK_HIGH_TIME/2); |
277 | if(!ack){ | 282 | if (!ack) { |
278 | if(!i2c_getbit()) /* receiver pulled SDA low */ | 283 | if (!i2c_getbit()) /* receiver pulld SDA low */ |
279 | ack = 1; | 284 | ack = 1; |
280 | i2c_delay(CLOCK_HIGH_TIME/2); | 285 | i2c_delay(CLOCK_HIGH_TIME/2); |
281 | } | 286 | } |
@@ -285,6 +290,7 @@ i2c_getack(void) | |||
285 | * before we enable our output. If we keep data high | 290 | * before we enable our output. If we keep data high |
286 | * and enable output, we would generate a stop condition. | 291 | * and enable output, we would generate a stop condition. |
287 | */ | 292 | */ |
293 | #if 0 | ||
288 | i2c_data(I2C_DATA_LOW); | 294 | i2c_data(I2C_DATA_LOW); |
289 | 295 | ||
290 | /* | 296 | /* |
@@ -292,6 +298,7 @@ i2c_getack(void) | |||
292 | */ | 298 | */ |
293 | i2c_enable(); | 299 | i2c_enable(); |
294 | i2c_dir_out(); | 300 | i2c_dir_out(); |
301 | #endif | ||
295 | i2c_clk(I2C_CLOCK_LOW); | 302 | i2c_clk(I2C_CLOCK_LOW); |
296 | i2c_delay(CLOCK_HIGH_TIME/4); | 303 | i2c_delay(CLOCK_HIGH_TIME/4); |
297 | /* | 304 | /* |
@@ -375,6 +382,121 @@ i2c_sendnack(void) | |||
375 | 382 | ||
376 | /*#--------------------------------------------------------------------------- | 383 | /*#--------------------------------------------------------------------------- |
377 | *# | 384 | *# |
385 | *# FUNCTION NAME: i2c_write | ||
386 | *# | ||
387 | *# DESCRIPTION : Writes a value to an I2C device | ||
388 | *# | ||
389 | *#--------------------------------------------------------------------------*/ | ||
390 | int | ||
391 | i2c_write(unsigned char theSlave, void *data, size_t nbytes) | ||
392 | { | ||
393 | int error, cntr = 3; | ||
394 | unsigned char bytes_wrote = 0; | ||
395 | unsigned char value; | ||
396 | unsigned long flags; | ||
397 | |||
398 | spin_lock_irqsave(&i2c_lock, flags); | ||
399 | |||
400 | do { | ||
401 | error = 0; | ||
402 | |||
403 | i2c_start(); | ||
404 | /* | ||
405 | * send slave address | ||
406 | */ | ||
407 | i2c_outbyte((theSlave & 0xfe)); | ||
408 | /* | ||
409 | * wait for ack | ||
410 | */ | ||
411 | if (!i2c_getack()) | ||
412 | error = 1; | ||
413 | /* | ||
414 | * send data | ||
415 | */ | ||
416 | for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) { | ||
417 | memcpy(&value, data + bytes_wrote, sizeof value); | ||
418 | i2c_outbyte(value); | ||
419 | /* | ||
420 | * now it's time to wait for ack | ||
421 | */ | ||
422 | if (!i2c_getack()) | ||
423 | error |= 4; | ||
424 | } | ||
425 | /* | ||
426 | * end byte stream | ||
427 | */ | ||
428 | i2c_stop(); | ||
429 | |||
430 | } while (error && cntr--); | ||
431 | |||
432 | i2c_delay(CLOCK_LOW_TIME); | ||
433 | |||
434 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
435 | |||
436 | return -error; | ||
437 | } | ||
438 | |||
439 | /*#--------------------------------------------------------------------------- | ||
440 | *# | ||
441 | *# FUNCTION NAME: i2c_read | ||
442 | *# | ||
443 | *# DESCRIPTION : Reads a value from an I2C device | ||
444 | *# | ||
445 | *#--------------------------------------------------------------------------*/ | ||
446 | int | ||
447 | i2c_read(unsigned char theSlave, void *data, size_t nbytes) | ||
448 | { | ||
449 | unsigned char b = 0; | ||
450 | unsigned char bytes_read = 0; | ||
451 | int error, cntr = 3; | ||
452 | unsigned long flags; | ||
453 | |||
454 | spin_lock_irqsave(&i2c_lock, flags); | ||
455 | |||
456 | do { | ||
457 | error = 0; | ||
458 | memset(data, 0, nbytes); | ||
459 | /* | ||
460 | * generate start condition | ||
461 | */ | ||
462 | i2c_start(); | ||
463 | /* | ||
464 | * send slave address | ||
465 | */ | ||
466 | i2c_outbyte((theSlave | 0x01)); | ||
467 | /* | ||
468 | * wait for ack | ||
469 | */ | ||
470 | if (!i2c_getack()) | ||
471 | error = 1; | ||
472 | /* | ||
473 | * fetch data | ||
474 | */ | ||
475 | for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { | ||
476 | b = i2c_inbyte(); | ||
477 | memcpy(data + bytes_read, &b, sizeof b); | ||
478 | |||
479 | if (bytes_read < (nbytes - 1)) | ||
480 | i2c_sendack(); | ||
481 | } | ||
482 | /* | ||
483 | * last received byte needs to be nacked | ||
484 | * instead of acked | ||
485 | */ | ||
486 | i2c_sendnack(); | ||
487 | /* | ||
488 | * end sequence | ||
489 | */ | ||
490 | i2c_stop(); | ||
491 | } while (error && cntr--); | ||
492 | |||
493 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
494 | |||
495 | return -error; | ||
496 | } | ||
497 | |||
498 | /*#--------------------------------------------------------------------------- | ||
499 | *# | ||
378 | *# FUNCTION NAME: i2c_writereg | 500 | *# FUNCTION NAME: i2c_writereg |
379 | *# | 501 | *# |
380 | *# DESCRIPTION : Writes a value to an I2C device | 502 | *# DESCRIPTION : Writes a value to an I2C device |
@@ -387,12 +509,10 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
387 | int error, cntr = 3; | 509 | int error, cntr = 3; |
388 | unsigned long flags; | 510 | unsigned long flags; |
389 | 511 | ||
512 | spin_lock_irqsave(&i2c_lock, flags); | ||
513 | |||
390 | do { | 514 | do { |
391 | error = 0; | 515 | error = 0; |
392 | /* | ||
393 | * we don't like to be interrupted | ||
394 | */ | ||
395 | local_irq_save(flags); | ||
396 | 516 | ||
397 | i2c_start(); | 517 | i2c_start(); |
398 | /* | 518 | /* |
@@ -427,15 +547,12 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
427 | * end byte stream | 547 | * end byte stream |
428 | */ | 548 | */ |
429 | i2c_stop(); | 549 | i2c_stop(); |
430 | /* | ||
431 | * enable interrupt again | ||
432 | */ | ||
433 | local_irq_restore(flags); | ||
434 | |||
435 | } while(error && cntr--); | 550 | } while(error && cntr--); |
436 | 551 | ||
437 | i2c_delay(CLOCK_LOW_TIME); | 552 | i2c_delay(CLOCK_LOW_TIME); |
438 | 553 | ||
554 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
555 | |||
439 | return -error; | 556 | return -error; |
440 | } | 557 | } |
441 | 558 | ||
@@ -453,13 +570,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
453 | int error, cntr = 3; | 570 | int error, cntr = 3; |
454 | unsigned long flags; | 571 | unsigned long flags; |
455 | 572 | ||
573 | spin_lock_irqsave(&i2c_lock, flags); | ||
574 | |||
456 | do { | 575 | do { |
457 | error = 0; | 576 | error = 0; |
458 | /* | 577 | /* |
459 | * we don't like to be interrupted | ||
460 | */ | ||
461 | local_irq_save(flags); | ||
462 | /* | ||
463 | * generate start condition | 578 | * generate start condition |
464 | */ | 579 | */ |
465 | i2c_start(); | 580 | i2c_start(); |
@@ -482,7 +597,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
482 | * now it's time to wait for ack | 597 | * now it's time to wait for ack |
483 | */ | 598 | */ |
484 | if(!i2c_getack()) | 599 | if(!i2c_getack()) |
485 | error = 1; | 600 | error |= 2; |
486 | /* | 601 | /* |
487 | * repeat start condition | 602 | * repeat start condition |
488 | */ | 603 | */ |
@@ -496,7 +611,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
496 | * wait for ack | 611 | * wait for ack |
497 | */ | 612 | */ |
498 | if(!i2c_getack()) | 613 | if(!i2c_getack()) |
499 | error = 1; | 614 | error |= 4; |
500 | /* | 615 | /* |
501 | * fetch register | 616 | * fetch register |
502 | */ | 617 | */ |
@@ -510,13 +625,11 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
510 | * end sequence | 625 | * end sequence |
511 | */ | 626 | */ |
512 | i2c_stop(); | 627 | i2c_stop(); |
513 | /* | ||
514 | * enable interrupt again | ||
515 | */ | ||
516 | local_irq_restore(flags); | ||
517 | 628 | ||
518 | } while(error && cntr--); | 629 | } while(error && cntr--); |
519 | 630 | ||
631 | spin_unlock_irqrestore(&i2c_lock, flags); | ||
632 | |||
520 | return b; | 633 | return b; |
521 | } | 634 | } |
522 | 635 | ||
@@ -540,7 +653,7 @@ i2c_ioctl(struct inode *inode, struct file *file, | |||
540 | unsigned int cmd, unsigned long arg) | 653 | unsigned int cmd, unsigned long arg) |
541 | { | 654 | { |
542 | if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { | 655 | if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { |
543 | return -EINVAL; | 656 | return -ENOTTY; |
544 | } | 657 | } |
545 | 658 | ||
546 | switch (_IOC_NR(cmd)) { | 659 | switch (_IOC_NR(cmd)) { |
@@ -580,31 +693,52 @@ static const struct file_operations i2c_fops = { | |||
580 | .release = i2c_release, | 693 | .release = i2c_release, |
581 | }; | 694 | }; |
582 | 695 | ||
583 | int __init | 696 | static int __init i2c_init(void) |
584 | i2c_init(void) | ||
585 | { | 697 | { |
586 | int res; | 698 | static int res; |
699 | static int first = 1; | ||
587 | 700 | ||
588 | /* Setup and enable the Port B I2C interface */ | 701 | if (!first) |
702 | return res; | ||
589 | 703 | ||
590 | crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT); | 704 | first = 0; |
591 | crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT); | 705 | |
706 | /* Setup and enable the DATA and CLK pins */ | ||
707 | |||
708 | res = crisv32_io_get_name(&cris_i2c_data, | ||
709 | CONFIG_ETRAX_V32_I2C_DATA_PORT); | ||
710 | if (res < 0) | ||
711 | return res; | ||
712 | |||
713 | res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT); | ||
714 | crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out); | ||
715 | |||
716 | return res; | ||
717 | } | ||
718 | |||
719 | |||
720 | static int __init i2c_register(void) | ||
721 | { | ||
722 | int res; | ||
723 | |||
724 | res = i2c_init(); | ||
725 | if (res < 0) | ||
726 | return res; | ||
592 | 727 | ||
593 | /* register char device */ | 728 | /* register char device */ |
594 | 729 | ||
595 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); | 730 | res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); |
596 | if(res < 0) { | 731 | if (res < 0) { |
597 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); | 732 | printk(KERN_ERR "i2c: couldn't get a major number.\n"); |
598 | return res; | 733 | return res; |
599 | } | 734 | } |
600 | 735 | ||
601 | printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); | 736 | printk(KERN_INFO |
737 | "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n"); | ||
602 | 738 | ||
603 | return 0; | 739 | return 0; |
604 | } | 740 | } |
605 | |||
606 | /* this makes sure that i2c_init is called during boot */ | 741 | /* this makes sure that i2c_init is called during boot */ |
607 | 742 | module_init(i2c_register); | |
608 | module_init(i2c_init); | ||
609 | 743 | ||
610 | /****************** END OF FILE i2c.c ********************************/ | 744 | /****************** END OF FILE i2c.c ********************************/ |