aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2012-09-12 06:58:10 -0400
committerWolfram Sang <w.sang@pengutronix.de>2012-09-12 09:03:34 -0400
commitdd74548ddece4b9d68e5528287a272fa552c81d0 (patch)
tree311ad1b64bc252f65fb8956f7a19ae38f302143c /drivers/i2c
parent4a7ec4eda58269a507501f240955d99312fdfd5f (diff)
i2c: omap: resize fifos before each message
This patch will try to avoid the usage of draining feature by reconfiguring the FIFO the start condition of each message based on the message's size. By doing that, we will be better utilizing the FIFO when doing big transfers. While at that also drop the now unneeded check for dev->buf_len as we always know the amount of data to be transmitted. Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Shubhrajyoti D <shubhrajyoti@ti.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 4af123fab63c..f33bc5a55074 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -193,6 +193,7 @@ struct omap_i2c_dev {
193 u8 *regs; 193 u8 *regs;
194 size_t buf_len; 194 size_t buf_len;
195 struct i2c_adapter adapter; 195 struct i2c_adapter adapter;
196 u8 threshold;
196 u8 fifo_size; /* use as flag and value 197 u8 fifo_size; /* use as flag and value
197 * fifo_size==0 implies no fifo 198 * fifo_size==0 implies no fifo
198 * if set, should be trsh+1 199 * if set, should be trsh+1
@@ -418,13 +419,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
418 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); 419 omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
419 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); 420 omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
420 421
421 if (dev->fifo_size) {
422 /* Note: setup required fifo size - 1. RTRSH and XTRSH */
423 buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
424 (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
425 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
426 }
427
428 /* Take the I2C module out of reset: */ 422 /* Take the I2C module out of reset: */
429 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); 423 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
430 424
@@ -462,6 +456,45 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
462 return 0; 456 return 0;
463} 457}
464 458
459static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
460{
461 u16 buf;
462
463 if (dev->flags & OMAP_I2C_FLAG_NO_FIFO)
464 return;
465
466 /*
467 * Set up notification threshold based on message size. We're doing
468 * this to try and avoid draining feature as much as possible. Whenever
469 * we have big messages to transfer (bigger than our total fifo size)
470 * then we might use draining feature to transfer the remaining bytes.
471 */
472
473 dev->threshold = clamp(size, (u8) 1, dev->fifo_size);
474
475 buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
476
477 if (is_rx) {
478 /* Clear RX Threshold */
479 buf &= ~(0x3f << 8);
480 buf |= ((dev->threshold - 1) << 8) | OMAP_I2C_BUF_RXFIF_CLR;
481 } else {
482 /* Clear TX Threshold */
483 buf &= ~0x3f;
484 buf |= (dev->threshold - 1) | OMAP_I2C_BUF_TXFIF_CLR;
485 }
486
487 omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
488
489 if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
490 dev->b_hw = 1; /* Enable hardware fixes */
491
492 /* calculate wakeup latency constraint for MPU */
493 if (dev->set_mpu_wkup_lat != NULL)
494 dev->latency = (1000000 * dev->threshold) /
495 (1000 * dev->speed / 8);
496}
497
465/* 498/*
466 * Low level master read/write transaction. 499 * Low level master read/write transaction.
467 */ 500 */
@@ -478,6 +511,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
478 if (msg->len == 0) 511 if (msg->len == 0)
479 return -EINVAL; 512 return -EINVAL;
480 513
514 dev->receiver = !!(msg->flags & I2C_M_RD);
515 omap_i2c_resize_fifo(dev, msg->len, dev->receiver);
516
481 omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr); 517 omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
482 518
483 /* REVISIT: Could the STB bit of I2C_CON be used with probing? */ 519 /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
@@ -493,7 +529,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
493 529
494 INIT_COMPLETION(dev->cmd_complete); 530 INIT_COMPLETION(dev->cmd_complete);
495 dev->cmd_err = 0; 531 dev->cmd_err = 0;
496 dev->receiver = !!(msg->flags & I2C_M_RD);
497 532
498 w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; 533 w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
499 534
@@ -760,12 +795,6 @@ static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes,
760 u16 w; 795 u16 w;
761 796
762 while (num_bytes--) { 797 while (num_bytes--) {
763 if (!dev->buf_len) {
764 dev_err(dev->dev, "%s without data",
765 is_rdr ? "RDR" : "RRDY");
766 break;
767 }
768
769 w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); 798 w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
770 *dev->buf++ = w; 799 *dev->buf++ = w;
771 dev->buf_len--; 800 dev->buf_len--;
@@ -775,10 +804,8 @@ static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes,
775 * omap4 is 8 bit wide 804 * omap4 is 8 bit wide
776 */ 805 */
777 if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) { 806 if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
778 if (dev->buf_len) { 807 *dev->buf++ = w >> 8;
779 *dev->buf++ = w >> 8; 808 dev->buf_len--;
780 dev->buf_len--;
781 }
782 } 809 }
783 } 810 }
784} 811}
@@ -789,12 +816,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
789 u16 w; 816 u16 w;
790 817
791 while (num_bytes--) { 818 while (num_bytes--) {
792 if (!dev->buf_len) {
793 dev_err(dev->dev, "%s without data",
794 is_xdr ? "XDR" : "XRDY");
795 break;
796 }
797
798 w = *dev->buf++; 819 w = *dev->buf++;
799 dev->buf_len--; 820 dev->buf_len--;
800 821
@@ -803,10 +824,8 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
803 * omap4 is 8 bit wide 824 * omap4 is 8 bit wide
804 */ 825 */
805 if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) { 826 if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
806 if (dev->buf_len) { 827 w |= *dev->buf++ << 8;
807 w |= *dev->buf++ << 8; 828 dev->buf_len--;
808 dev->buf_len--;
809 }
810 } 829 }
811 830
812 if (dev->errata & I2C_OMAP_ERRATA_I462) { 831 if (dev->errata & I2C_OMAP_ERRATA_I462) {
@@ -901,8 +920,8 @@ complete:
901 if (stat & OMAP_I2C_STAT_RRDY) { 920 if (stat & OMAP_I2C_STAT_RRDY) {
902 u8 num_bytes = 1; 921 u8 num_bytes = 1;
903 922
904 if (dev->fifo_size) 923 if (dev->threshold)
905 num_bytes = dev->fifo_size; 924 num_bytes = dev->threshold;
906 925
907 omap_i2c_receive_data(dev, num_bytes, false); 926 omap_i2c_receive_data(dev, num_bytes, false);
908 omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY); 927 omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
@@ -929,8 +948,8 @@ complete:
929 u8 num_bytes = 1; 948 u8 num_bytes = 1;
930 int ret; 949 int ret;
931 950
932 if (dev->fifo_size) 951 if (dev->threshold)
933 num_bytes = dev->fifo_size; 952 num_bytes = dev->threshold;
934 953
935 ret = omap_i2c_transmit_data(dev, num_bytes, false); 954 ret = omap_i2c_transmit_data(dev, num_bytes, false);
936 stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); 955 stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);