diff options
author | Jesper Nilsson <jesper.nilsson@axis.com> | 2007-11-30 09:54:01 -0500 |
---|---|---|
committer | Jesper Nilsson <jesper.nilsson@axis.com> | 2008-02-08 05:06:25 -0500 |
commit | 201ca54aa039eb1e5143a98311e7ea25afc57ebb (patch) | |
tree | 977d6c2baecf92f7a9fb2099494b042ea09cb7e9 /arch/cris/arch-v32 | |
parent | 0f229504f804da9c601aeb4690995904d9553b79 (diff) |
CRIS v32: New version of I2C driver.
- Add i2c_write and i2c_read as functions.
- Use spinlocks for critical regions.
- Add config item to set I2C data and clock port.
- Put unneeded testcode inside #if 0.
- Remove CVS id tag.
Diffstat (limited to 'arch/cris/arch-v32')
-rw-r--r-- | arch/cris/arch-v32/drivers/i2c.c | 199 | ||||
-rw-r--r-- | arch/cris/arch-v32/drivers/i2c.h | 2 |
2 files changed, 187 insertions, 14 deletions
diff --git a/arch/cris/arch-v32/drivers/i2c.c b/arch/cris/arch-v32/drivers/i2c.c index f1edd2e359b2..4eda3236792a 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,137 @@ 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(&i2c_lock); | ||
399 | |||
400 | do { | ||
401 | error = 0; | ||
402 | /* | ||
403 | * we don't like to be interrupted | ||
404 | */ | ||
405 | local_irq_save(flags); | ||
406 | |||
407 | i2c_start(); | ||
408 | /* | ||
409 | * send slave address | ||
410 | */ | ||
411 | i2c_outbyte((theSlave & 0xfe)); | ||
412 | /* | ||
413 | * wait for ack | ||
414 | */ | ||
415 | if (!i2c_getack()) | ||
416 | error = 1; | ||
417 | /* | ||
418 | * send data | ||
419 | */ | ||
420 | for (bytes_wrote = 0; bytes_wrote < nbytes; bytes_wrote++) { | ||
421 | memcpy(&value, data + bytes_wrote, sizeof value); | ||
422 | i2c_outbyte(value); | ||
423 | /* | ||
424 | * now it's time to wait for ack | ||
425 | */ | ||
426 | if (!i2c_getack()) | ||
427 | error |= 4; | ||
428 | } | ||
429 | /* | ||
430 | * end byte stream | ||
431 | */ | ||
432 | i2c_stop(); | ||
433 | /* | ||
434 | * enable interrupt again | ||
435 | */ | ||
436 | local_irq_restore(flags); | ||
437 | |||
438 | } while (error && cntr--); | ||
439 | |||
440 | i2c_delay(CLOCK_LOW_TIME); | ||
441 | |||
442 | spin_unlock(&i2c_lock); | ||
443 | |||
444 | return -error; | ||
445 | } | ||
446 | |||
447 | /*#--------------------------------------------------------------------------- | ||
448 | *# | ||
449 | *# FUNCTION NAME: i2c_read | ||
450 | *# | ||
451 | *# DESCRIPTION : Reads a value from an I2C device | ||
452 | *# | ||
453 | *#--------------------------------------------------------------------------*/ | ||
454 | int | ||
455 | i2c_read(unsigned char theSlave, void *data, size_t nbytes) | ||
456 | { | ||
457 | unsigned char b = 0; | ||
458 | unsigned char bytes_read = 0; | ||
459 | int error, cntr = 3; | ||
460 | unsigned long flags; | ||
461 | |||
462 | spin_lock(&i2c_lock); | ||
463 | |||
464 | do { | ||
465 | error = 0; | ||
466 | memset(data, 0, nbytes); | ||
467 | /* | ||
468 | * we don't like to be interrupted | ||
469 | */ | ||
470 | local_irq_save(flags); | ||
471 | /* | ||
472 | * generate start condition | ||
473 | */ | ||
474 | i2c_start(); | ||
475 | /* | ||
476 | * send slave address | ||
477 | */ | ||
478 | i2c_outbyte((theSlave | 0x01)); | ||
479 | /* | ||
480 | * wait for ack | ||
481 | */ | ||
482 | if (!i2c_getack()) | ||
483 | error = 1; | ||
484 | /* | ||
485 | * fetch data | ||
486 | */ | ||
487 | for (bytes_read = 0; bytes_read < nbytes; bytes_read++) { | ||
488 | b = i2c_inbyte(); | ||
489 | memcpy(data + bytes_read, &b, sizeof b); | ||
490 | |||
491 | if (bytes_read < (nbytes - 1)) | ||
492 | i2c_sendack(); | ||
493 | } | ||
494 | /* | ||
495 | * last received byte needs to be nacked | ||
496 | * instead of acked | ||
497 | */ | ||
498 | i2c_sendnack(); | ||
499 | /* | ||
500 | * end sequence | ||
501 | */ | ||
502 | i2c_stop(); | ||
503 | /* | ||
504 | * enable interrupt again | ||
505 | */ | ||
506 | local_irq_restore(flags); | ||
507 | } while (error && cntr--); | ||
508 | |||
509 | spin_unlock(&i2c_lock); | ||
510 | |||
511 | return -error; | ||
512 | } | ||
513 | |||
514 | /*#--------------------------------------------------------------------------- | ||
515 | *# | ||
378 | *# FUNCTION NAME: i2c_writereg | 516 | *# FUNCTION NAME: i2c_writereg |
379 | *# | 517 | *# |
380 | *# DESCRIPTION : Writes a value to an I2C device | 518 | *# DESCRIPTION : Writes a value to an I2C device |
@@ -387,6 +525,8 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
387 | int error, cntr = 3; | 525 | int error, cntr = 3; |
388 | unsigned long flags; | 526 | unsigned long flags; |
389 | 527 | ||
528 | spin_lock(&i2c_lock); | ||
529 | |||
390 | do { | 530 | do { |
391 | error = 0; | 531 | error = 0; |
392 | /* | 532 | /* |
@@ -431,11 +571,12 @@ i2c_writereg(unsigned char theSlave, unsigned char theReg, | |||
431 | * enable interrupt again | 571 | * enable interrupt again |
432 | */ | 572 | */ |
433 | local_irq_restore(flags); | 573 | local_irq_restore(flags); |
434 | |||
435 | } while(error && cntr--); | 574 | } while(error && cntr--); |
436 | 575 | ||
437 | i2c_delay(CLOCK_LOW_TIME); | 576 | i2c_delay(CLOCK_LOW_TIME); |
438 | 577 | ||
578 | spin_unlock(&i2c_lock); | ||
579 | |||
439 | return -error; | 580 | return -error; |
440 | } | 581 | } |
441 | 582 | ||
@@ -453,6 +594,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
453 | int error, cntr = 3; | 594 | int error, cntr = 3; |
454 | unsigned long flags; | 595 | unsigned long flags; |
455 | 596 | ||
597 | spin_lock(&i2c_lock); | ||
598 | |||
456 | do { | 599 | do { |
457 | error = 0; | 600 | error = 0; |
458 | /* | 601 | /* |
@@ -482,7 +625,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
482 | * now it's time to wait for ack | 625 | * now it's time to wait for ack |
483 | */ | 626 | */ |
484 | if(!i2c_getack()) | 627 | if(!i2c_getack()) |
485 | error = 1; | 628 | error |= 2; |
486 | /* | 629 | /* |
487 | * repeat start condition | 630 | * repeat start condition |
488 | */ | 631 | */ |
@@ -496,7 +639,7 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
496 | * wait for ack | 639 | * wait for ack |
497 | */ | 640 | */ |
498 | if(!i2c_getack()) | 641 | if(!i2c_getack()) |
499 | error = 1; | 642 | error |= 4; |
500 | /* | 643 | /* |
501 | * fetch register | 644 | * fetch register |
502 | */ | 645 | */ |
@@ -517,6 +660,8 @@ i2c_readreg(unsigned char theSlave, unsigned char theReg) | |||
517 | 660 | ||
518 | } while(error && cntr--); | 661 | } while(error && cntr--); |
519 | 662 | ||
663 | spin_unlock(&i2c_lock); | ||
664 | |||
520 | return b; | 665 | return b; |
521 | } | 666 | } |
522 | 667 | ||
@@ -583,12 +728,37 @@ static const struct file_operations i2c_fops = { | |||
583 | int __init | 728 | int __init |
584 | i2c_init(void) | 729 | i2c_init(void) |
585 | { | 730 | { |
586 | int res; | 731 | static int res; |
732 | static int first = 1; | ||
587 | 733 | ||
588 | /* Setup and enable the Port B I2C interface */ | 734 | if (!first) |
735 | return res; | ||
736 | |||
737 | first = 0; | ||
738 | |||
739 | /* Setup and enable the DATA and CLK pins */ | ||
740 | |||
741 | res = crisv32_io_get_name(&cris_i2c_data, | ||
742 | CONFIG_ETRAX_V32_I2C_DATA_PORT); | ||
743 | if (res < 0) | ||
744 | return res; | ||
745 | |||
746 | res = crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_V32_I2C_CLK_PORT); | ||
747 | crisv32_io_set_dir(&cris_i2c_clk, crisv32_io_dir_out); | ||
748 | |||
749 | return res; | ||
750 | } | ||
589 | 751 | ||
590 | crisv32_io_get_name(&cris_i2c_data, CONFIG_ETRAX_I2C_DATA_PORT); | 752 | |
591 | crisv32_io_get_name(&cris_i2c_clk, CONFIG_ETRAX_I2C_CLK_PORT); | 753 | int __init |
754 | i2c_register(void) | ||
755 | { | ||
756 | |||
757 | int res; | ||
758 | |||
759 | res = i2c_init(); | ||
760 | if (res < 0) | ||
761 | return res; | ||
592 | 762 | ||
593 | /* register char device */ | 763 | /* register char device */ |
594 | 764 | ||
@@ -598,13 +768,14 @@ i2c_init(void) | |||
598 | return res; | 768 | return res; |
599 | } | 769 | } |
600 | 770 | ||
601 | printk(KERN_INFO "I2C driver v2.2, (c) 1999-2001 Axis Communications AB\n"); | 771 | printk(KERN_INFO |
772 | "I2C driver v2.2, (c) 1999-2007 Axis Communications AB\n"); | ||
602 | 773 | ||
603 | return 0; | 774 | return 0; |
604 | } | 775 | } |
605 | 776 | ||
606 | /* this makes sure that i2c_init is called during boot */ | 777 | /* this makes sure that i2c_init is called during boot */ |
607 | 778 | ||
608 | module_init(i2c_init); | 779 | module_init(i2c_register); |
609 | 780 | ||
610 | /****************** END OF FILE i2c.c ********************************/ | 781 | /****************** END OF FILE i2c.c ********************************/ |
diff --git a/arch/cris/arch-v32/drivers/i2c.h b/arch/cris/arch-v32/drivers/i2c.h index bfe1a13f9f35..c073cf4ba016 100644 --- a/arch/cris/arch-v32/drivers/i2c.h +++ b/arch/cris/arch-v32/drivers/i2c.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | /* High level I2C actions */ | 4 | /* High level I2C actions */ |
5 | int __init i2c_init(void); | 5 | int __init i2c_init(void); |
6 | int i2c_write(unsigned char theSlave, void *data, size_t nbytes); | ||
7 | int i2c_read(unsigned char theSlave, void *data, size_t nbytes); | ||
6 | int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); | 8 | int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); |
7 | unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); | 9 | unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); |
8 | 10 | ||