aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSifan Naeem <sifan.naeem@imgtec.com>2015-11-19 04:35:17 -0500
committerWolfram Sang <wsa@the-dreams.de>2016-01-02 16:05:21 -0500
commitc20821a7f0a55377eccd88c89bd76a2cca22a1b4 (patch)
tree5875ac7438196809303b3a7741270e7cb02ffdd0
parentc7b0a7c10752fa9a30f719848f4350fa02fdb8e5 (diff)
i2c: img-scb: support repeated starts on IP v3.3
In version 3.3 of the IP when transaction halt is set, an interrupt will be generated after each byte of a transfer instead of after every transfer but before the stop bit. Due to this behaviour we have to be careful that every time we release the transaction halt we have to re-enable it straight away so that we only process a single byte, not doing so will result in all remaining bytes been processed and a stop bit being issued, which will prevent us having a repeated start. This change will have no effect on earlier versions of the IP. Signed-off-by: Sifan Naeem <sifan.naeem@imgtec.com> Acked-by: James Hogan <james.hogan@imgtec.com> Reviewed-by: James Hartley <james.hartley@imgtec.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-img-scb.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c
index 991118f837be..379ef9c31664 100644
--- a/drivers/i2c/busses/i2c-img-scb.c
+++ b/drivers/i2c/busses/i2c-img-scb.c
@@ -513,7 +513,17 @@ static void img_i2c_soft_reset(struct img_i2c *i2c)
513 SCB_CONTROL_CLK_ENABLE | SCB_CONTROL_SOFT_RESET); 513 SCB_CONTROL_CLK_ENABLE | SCB_CONTROL_SOFT_RESET);
514} 514}
515 515
516/* enable or release transaction halt for control of repeated starts */ 516/*
517 * Enable or release transaction halt for control of repeated starts.
518 * In version 3.3 of the IP when transaction halt is set, an interrupt
519 * will be generated after each byte of a transfer instead of after
520 * every transfer but before the stop bit.
521 * Due to this behaviour we have to be careful that every time we
522 * release the transaction halt we have to re-enable it straight away
523 * so that we only process a single byte, not doing so will result in
524 * all remaining bytes been processed and a stop bit being issued,
525 * which will prevent us having a repeated start.
526 */
517static void img_i2c_transaction_halt(struct img_i2c *i2c, bool t_halt) 527static void img_i2c_transaction_halt(struct img_i2c *i2c, bool t_halt)
518{ 528{
519 u32 val; 529 u32 val;
@@ -582,7 +592,6 @@ static void img_i2c_read(struct img_i2c *i2c)
582 img_i2c_writel(i2c, SCB_READ_ADDR_REG, i2c->msg.addr); 592 img_i2c_writel(i2c, SCB_READ_ADDR_REG, i2c->msg.addr);
583 img_i2c_writel(i2c, SCB_READ_COUNT_REG, i2c->msg.len); 593 img_i2c_writel(i2c, SCB_READ_COUNT_REG, i2c->msg.len);
584 594
585 img_i2c_transaction_halt(i2c, false);
586 mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1)); 595 mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
587} 596}
588 597
@@ -596,7 +605,6 @@ static void img_i2c_write(struct img_i2c *i2c)
596 img_i2c_writel(i2c, SCB_WRITE_ADDR_REG, i2c->msg.addr); 605 img_i2c_writel(i2c, SCB_WRITE_ADDR_REG, i2c->msg.addr);
597 img_i2c_writel(i2c, SCB_WRITE_COUNT_REG, i2c->msg.len); 606 img_i2c_writel(i2c, SCB_WRITE_COUNT_REG, i2c->msg.len);
598 607
599 img_i2c_transaction_halt(i2c, false);
600 mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1)); 608 mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
601 img_i2c_write_fifo(i2c); 609 img_i2c_write_fifo(i2c);
602 610
@@ -862,7 +870,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
862 870
863 /* Enable transaction halt on start bit */ 871 /* Enable transaction halt on start bit */
864 if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) { 872 if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
865 img_i2c_transaction_halt(i2c, true); 873 img_i2c_transaction_halt(i2c, !i2c->last_msg);
866 /* we're no longer interested in the slave event */ 874 /* we're no longer interested in the slave event */
867 i2c->int_enable &= ~INT_SLAVE_EVENT; 875 i2c->int_enable &= ~INT_SLAVE_EVENT;
868 } 876 }
@@ -1084,12 +1092,31 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
1084 img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0); 1092 img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
1085 img_i2c_writel(i2c, SCB_CLEAR_REG, ~0); 1093 img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
1086 1094
1087 if (atomic) 1095 if (atomic) {
1088 img_i2c_atomic_start(i2c); 1096 img_i2c_atomic_start(i2c);
1089 else if (msg->flags & I2C_M_RD) 1097 } else {
1090 img_i2c_read(i2c); 1098 /*
1091 else 1099 * Enable transaction halt if not the last message in
1092 img_i2c_write(i2c); 1100 * the queue so that we can control repeated starts.
1101 */
1102 img_i2c_transaction_halt(i2c, !i2c->last_msg);
1103
1104 if (msg->flags & I2C_M_RD)
1105 img_i2c_read(i2c);
1106 else
1107 img_i2c_write(i2c);
1108
1109 /*
1110 * Release and then enable transaction halt, to
1111 * allow only a single byte to proceed.
1112 * This doesn't have an effect on the initial transfer
1113 * but will allow the following transfers to start
1114 * processing if the previous transfer was marked as
1115 * complete while the i2c block was halted.
1116 */
1117 img_i2c_transaction_halt(i2c, false);
1118 img_i2c_transaction_halt(i2c, !i2c->last_msg);
1119 }
1093 spin_unlock_irqrestore(&i2c->lock, flags); 1120 spin_unlock_irqrestore(&i2c->lock, flags);
1094 1121
1095 time_left = wait_for_completion_timeout(&i2c->msg_complete, 1122 time_left = wait_for_completion_timeout(&i2c->msg_complete,