|
@@ -513,7 +513,17 @@ static void img_i2c_soft_reset(struct img_i2c *i2c)
|
|
|
SCB_CONTROL_CLK_ENABLE | SCB_CONTROL_SOFT_RESET);
|
|
|
}
|
|
|
|
|
|
-/* enable or release transaction halt for control of repeated starts */
|
|
|
+/*
|
|
|
+ * Enable or release transaction halt for control of repeated starts.
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
static void img_i2c_transaction_halt(struct img_i2c *i2c, bool t_halt)
|
|
|
{
|
|
|
u32 val;
|
|
@@ -582,7 +592,6 @@ static void img_i2c_read(struct img_i2c *i2c)
|
|
|
img_i2c_writel(i2c, SCB_READ_ADDR_REG, i2c->msg.addr);
|
|
|
img_i2c_writel(i2c, SCB_READ_COUNT_REG, i2c->msg.len);
|
|
|
|
|
|
- img_i2c_transaction_halt(i2c, false);
|
|
|
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
|
|
|
}
|
|
|
|
|
@@ -596,7 +605,6 @@ static void img_i2c_write(struct img_i2c *i2c)
|
|
|
img_i2c_writel(i2c, SCB_WRITE_ADDR_REG, i2c->msg.addr);
|
|
|
img_i2c_writel(i2c, SCB_WRITE_COUNT_REG, i2c->msg.len);
|
|
|
|
|
|
- img_i2c_transaction_halt(i2c, false);
|
|
|
mod_timer(&i2c->check_timer, jiffies + msecs_to_jiffies(1));
|
|
|
img_i2c_write_fifo(i2c);
|
|
|
|
|
@@ -862,7 +870,7 @@ static unsigned int img_i2c_auto(struct img_i2c *i2c,
|
|
|
|
|
|
/* Enable transaction halt on start bit */
|
|
|
if (!i2c->last_msg && line_status & LINESTAT_START_BIT_DET) {
|
|
|
- img_i2c_transaction_halt(i2c, true);
|
|
|
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
|
|
|
/* we're no longer interested in the slave event */
|
|
|
i2c->int_enable &= ~INT_SLAVE_EVENT;
|
|
|
}
|
|
@@ -1084,12 +1092,31 @@ static int img_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
|
|
|
img_i2c_writel(i2c, SCB_INT_CLEAR_REG, ~0);
|
|
|
img_i2c_writel(i2c, SCB_CLEAR_REG, ~0);
|
|
|
|
|
|
- if (atomic)
|
|
|
+ if (atomic) {
|
|
|
img_i2c_atomic_start(i2c);
|
|
|
- else if (msg->flags & I2C_M_RD)
|
|
|
- img_i2c_read(i2c);
|
|
|
- else
|
|
|
- img_i2c_write(i2c);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Enable transaction halt if not the last message in
|
|
|
+ * the queue so that we can control repeated starts.
|
|
|
+ */
|
|
|
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
|
|
|
+
|
|
|
+ if (msg->flags & I2C_M_RD)
|
|
|
+ img_i2c_read(i2c);
|
|
|
+ else
|
|
|
+ img_i2c_write(i2c);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Release and then enable transaction halt, to
|
|
|
+ * allow only a single byte to proceed.
|
|
|
+ * This doesn't have an effect on the initial transfer
|
|
|
+ * but will allow the following transfers to start
|
|
|
+ * processing if the previous transfer was marked as
|
|
|
+ * complete while the i2c block was halted.
|
|
|
+ */
|
|
|
+ img_i2c_transaction_halt(i2c, false);
|
|
|
+ img_i2c_transaction_halt(i2c, !i2c->last_msg);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&i2c->lock, flags);
|
|
|
|
|
|
time_left = wait_for_completion_timeout(&i2c->msg_complete,
|