aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2008-11-21 16:39:46 -0500
committerTony Lindgren <tony@atomide.com>2008-11-21 16:39:46 -0500
commitb6ee52c39999b2f3bcd9e26f0edf1f07599cf40e (patch)
tree9bae229905eb207fe2c01fa6b9bfb6d623b96384 /drivers/i2c
parent4574eb6892a13bc91aac8676457d46798935d653 (diff)
i2c-omap: FIFO handling support and broken hw workaround for i2c-omap
Based on an earlier patch from Nishant Menon: - Transfers can use FIFO on FIFO capable devices - Prevents errors for HSI2C if FIFO is not used - Implemented errenous handling of STT-STP handling on SDP2430 Also merged in is a fix from Jaron Marini to fix occasional i2c hang if OMAP_I2C_CON_STT remains asserted. Signed-off-by: Jason P Marini <jason.marini@gmail.com> Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c190
1 files changed, 150 insertions, 40 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b0aa0f8b564b..9ae4b74f3d1a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -55,8 +55,11 @@
55#define OMAP_I2C_SCLL_REG 0x34 55#define OMAP_I2C_SCLL_REG 0x34
56#define OMAP_I2C_SCLH_REG 0x38 56#define OMAP_I2C_SCLH_REG 0x38
57#define OMAP_I2C_SYSTEST_REG 0x3c 57#define OMAP_I2C_SYSTEST_REG 0x3c
58#define OMAP_I2C_BUFSTAT_REG 0x40
58 59
59/* I2C Interrupt Enable Register (OMAP_I2C_IE): */ 60/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
61#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
62#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
60#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */ 63#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */
61#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */ 64#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */
62#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */ 65#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */
@@ -64,7 +67,8 @@
64#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */ 67#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */
65 68
66/* I2C Status Register (OMAP_I2C_STAT): */ 69/* I2C Status Register (OMAP_I2C_STAT): */
67#define OMAP_I2C_STAT_SBD (1 << 15) /* Single byte data */ 70#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */
71#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */
68#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */ 72#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */
69#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */ 73#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */
70#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ 74#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */
@@ -78,12 +82,14 @@
78 82
79/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */ 83/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
80#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */ 84#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */
85#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */
81#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */ 86#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */
87#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */
82 88
83/* I2C Configuration Register (OMAP_I2C_CON): */ 89/* I2C Configuration Register (OMAP_I2C_CON): */
84#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ 90#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */
85#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ 91#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */
86#define OMAP_I2C_CON_OPMODE (1 << 12) /* High Speed support */ 92#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */
87#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ 93#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */
88#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ 94#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */
89#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ 95#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */
@@ -127,7 +133,12 @@ struct omap_i2c_dev {
127 u8 *buf; 133 u8 *buf;
128 size_t buf_len; 134 size_t buf_len;
129 struct i2c_adapter adapter; 135 struct i2c_adapter adapter;
136 u8 fifo_size; /* use as flag and value
137 * fifo_size==0 implies no fifo
138 * if set, should be trsh+1
139 */
130 unsigned rev1:1; 140 unsigned rev1:1;
141 unsigned b_hw:1; /* bad h/w fixes */
131 unsigned idle:1; 142 unsigned idle:1;
132 u16 iestate; /* Saved interrupt register */ 143 u16 iestate; /* Saved interrupt register */
133}; 144};
@@ -297,6 +308,14 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
297 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); 308 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
298 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); 309 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
299 310
311 if (dev->fifo_size)
312 /* Note: setup required fifo size - 1 */
313 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
314 (dev->fifo_size - 1) << 8 | /* RTRSH */
315 OMAP_I2C_BUF_RXFIF_CLR |
316 (dev->fifo_size - 1) | /* XTRSH */
317 OMAP_I2C_BUF_TXFIF_CLR);
318
300 /* Take the I2C module out of reset: */ 319 /* Take the I2C module out of reset: */
301 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); 320 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
302 321
@@ -304,7 +323,8 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
304 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 323 omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
305 (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | 324 (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
306 OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | 325 OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
307 OMAP_I2C_IE_AL)); 326 OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
327 (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
308 return 0; 328 return 0;
309} 329}
310 330
@@ -351,6 +371,11 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
351 371
352 omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); 372 omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
353 373
374 /* Clear the FIFO Buffers */
375 w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
376 w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR;
377 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w);
378
354 init_completion(&dev->cmd_complete); 379 init_completion(&dev->cmd_complete);
355 dev->cmd_err = 0; 380 dev->cmd_err = 0;
356 381
@@ -358,17 +383,40 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
358 383
359 /* High speed configuration */ 384 /* High speed configuration */
360 if (dev->speed > 400) 385 if (dev->speed > 400)
361 w |= OMAP_I2C_CON_OPMODE; 386 w |= OMAP_I2C_CON_OPMODE_HS;
362 387
363 if (msg->flags & I2C_M_TEN) 388 if (msg->flags & I2C_M_TEN)
364 w |= OMAP_I2C_CON_XA; 389 w |= OMAP_I2C_CON_XA;
365 if (!(msg->flags & I2C_M_RD)) 390 if (!(msg->flags & I2C_M_RD))
366 w |= OMAP_I2C_CON_TRX; 391 w |= OMAP_I2C_CON_TRX;
367 if (stop) 392 if (!dev->b_hw && stop)
368 w |= OMAP_I2C_CON_STP; 393 w |= OMAP_I2C_CON_STP;
369 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); 394 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
370 395
371 /* 396 /*
397 * Don't write stt and stp together on some hardware.
398 */
399 if (dev->b_hw && stop) {
400 unsigned long delay = jiffies + OMAP_I2C_TIMEOUT;
401 u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
402 while (con & OMAP_I2C_CON_STT) {
403 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
404
405 /* Let the user know if i2c is in a bad state */
406 if (time_after(jiffies, delay)) {
407 dev_err(dev->dev, "controller timed out "
408 "waiting for start condition to finish\n");
409 return -ETIMEDOUT;
410 }
411 cpu_relax();
412 }
413
414 w |= OMAP_I2C_CON_STP;
415 w &= ~OMAP_I2C_CON_STT;
416 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
417 }
418
419 /*
372 * REVISIT: We should abort the transfer on signals, but the bus goes 420 * REVISIT: We should abort the transfer on signals, but the bus goes
373 * into arbitration and we're currently unable to recover from it. 421 * into arbitration and we're currently unable to recover from it.
374 */ 422 */
@@ -516,7 +564,7 @@ omap_i2c_isr(int this_irq, void *dev_id)
516 struct omap_i2c_dev *dev = dev_id; 564 struct omap_i2c_dev *dev = dev_id;
517 u16 bits; 565 u16 bits;
518 u16 stat, w; 566 u16 stat, w;
519 int count = 0; 567 int err, count = 0;
520 568
521 if (dev->idle) 569 if (dev->idle)
522 return IRQ_NONE; 570 return IRQ_NONE;
@@ -531,39 +579,94 @@ omap_i2c_isr(int this_irq, void *dev_id)
531 579
532 omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); 580 omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
533 581
534 if (stat & OMAP_I2C_STAT_ARDY) { 582 err = 0;
535 omap_i2c_complete_cmd(dev, 0); 583 if (stat & OMAP_I2C_STAT_NACK) {
536 continue; 584 err |= OMAP_I2C_STAT_NACK;
585 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
586 OMAP_I2C_CON_STP);
537 } 587 }
538 if (stat & OMAP_I2C_STAT_RRDY) { 588 if (stat & OMAP_I2C_STAT_AL) {
539 w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); 589 dev_err(dev->dev, "Arbitration lost\n");
540 if (dev->buf_len) { 590 err |= OMAP_I2C_STAT_AL;
541 *dev->buf++ = w; 591 }
542 dev->buf_len--; 592 if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
593 OMAP_I2C_STAT_AL))
594 omap_i2c_complete_cmd(dev, err);
595 if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
596 u8 num_bytes = 1;
597 if (dev->fifo_size) {
598 if (stat & OMAP_I2C_STAT_RRDY)
599 num_bytes = dev->fifo_size;
600 else
601 num_bytes = omap_i2c_read_reg(dev,
602 OMAP_I2C_BUFSTAT_REG);
603 }
604 while (num_bytes) {
605 num_bytes--;
606 w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
543 if (dev->buf_len) { 607 if (dev->buf_len) {
544 *dev->buf++ = w >> 8; 608 *dev->buf++ = w;
545 dev->buf_len--; 609 dev->buf_len--;
610 /* Data reg from 2430 is 8 bit wide */
611 if (!cpu_is_omap2430()) {
612 if (dev->buf_len) {
613 *dev->buf++ = w >> 8;
614 dev->buf_len--;
615 }
616 }
617 } else {
618 if (stat & OMAP_I2C_STAT_RRDY)
619 dev_err(dev->dev,
620 "RRDY IRQ while no data"
621 " requested\n");
622 if (stat & OMAP_I2C_STAT_RDR)
623 dev_err(dev->dev,
624 "RDR IRQ while no data"
625 " requested\n");
626 break;
546 } 627 }
547 } else 628 }
548 dev_err(dev->dev, "RRDY IRQ while no data " 629 omap_i2c_ack_stat(dev,
549 "requested\n"); 630 stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
550 omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
551 continue; 631 continue;
552 } 632 }
553 if (stat & OMAP_I2C_STAT_XRDY) { 633 if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
554 w = 0; 634 u8 num_bytes = 1;
555 if (dev->buf_len) { 635 if (dev->fifo_size) {
556 w = *dev->buf++; 636 if (stat & OMAP_I2C_STAT_XRDY)
557 dev->buf_len--; 637 num_bytes = dev->fifo_size;
638 else
639 num_bytes = omap_i2c_read_reg(dev,
640 OMAP_I2C_BUFSTAT_REG);
641 }
642 while (num_bytes) {
643 num_bytes--;
644 w = 0;
558 if (dev->buf_len) { 645 if (dev->buf_len) {
559 w |= *dev->buf++ << 8; 646 w = *dev->buf++;
560 dev->buf_len--; 647 dev->buf_len--;
648 /* Data reg from 2430 is 8 bit wide */
649 if (!cpu_is_omap2430()) {
650 if (dev->buf_len) {
651 w |= *dev->buf++ << 8;
652 dev->buf_len--;
653 }
654 }
655 } else {
656 if (stat & OMAP_I2C_STAT_XRDY)
657 dev_err(dev->dev,
658 "XRDY IRQ while no "
659 "data to send\n");
660 if (stat & OMAP_I2C_STAT_XDR)
661 dev_err(dev->dev,
662 "XDR IRQ while no "
663 "data to send\n");
664 break;
561 } 665 }
562 } else 666 omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
563 dev_err(dev->dev, "XRDY IRQ while no " 667 }
564 "data to send\n"); 668 omap_i2c_ack_stat(dev,
565 omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); 669 stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
566 omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
567 continue; 670 continue;
568 } 671 }
569 if (stat & OMAP_I2C_STAT_ROVR) { 672 if (stat & OMAP_I2C_STAT_ROVR) {
@@ -571,18 +674,9 @@ omap_i2c_isr(int this_irq, void *dev_id)
571 dev->cmd_err |= OMAP_I2C_STAT_ROVR; 674 dev->cmd_err |= OMAP_I2C_STAT_ROVR;
572 } 675 }
573 if (stat & OMAP_I2C_STAT_XUDF) { 676 if (stat & OMAP_I2C_STAT_XUDF) {
574 dev_err(dev->dev, "Transmit overflow\n"); 677 dev_err(dev->dev, "Transmit underflow\n");
575 dev->cmd_err |= OMAP_I2C_STAT_XUDF; 678 dev->cmd_err |= OMAP_I2C_STAT_XUDF;
576 } 679 }
577 if (stat & OMAP_I2C_STAT_NACK) {
578 omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
579 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
580 OMAP_I2C_CON_STP);
581 }
582 if (stat & OMAP_I2C_STAT_AL) {
583 dev_err(dev->dev, "Arbitration lost\n");
584 omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
585 }
586 } 680 }
587 681
588 return count ? IRQ_HANDLED : IRQ_NONE; 682 return count ? IRQ_HANDLED : IRQ_NONE;
@@ -651,6 +745,22 @@ omap_i2c_probe(struct platform_device *pdev)
651 if (cpu_is_omap15xx()) 745 if (cpu_is_omap15xx())
652 dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20; 746 dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
653 747
748 if (cpu_is_omap2430()) {
749 u16 s;
750
751 /* Set up the fifo size - Get total size */
752 s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
753 dev->fifo_size = 0x8 << s;
754
755 /*
756 * Set up notification threshold as half the total available
757 * size. This is to ensure that we can handle the status on int
758 * call back latencies.
759 */
760 dev->fifo_size = (dev->fifo_size / 2);
761 dev->b_hw = 1; /* Enable hardware fixes */
762 }
763
654 /* reset ASAP, clearing any IRQs */ 764 /* reset ASAP, clearing any IRQs */
655 omap_i2c_init(dev); 765 omap_i2c_init(dev);
656 766