Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 263671
b: refs/heads/master
c: 96219c3
h: refs/heads/master
i:
  263669: e9fbcd5
  263667: 40fc635
  263663: 975bbad
v: v3
  • Loading branch information
Doug Anderson authored and Ben Dooks committed Sep 6, 2011
1 parent d9bd0da commit ffed1a8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 048e29cff95168ea3a9f176e84cc0bae54d0ae64
refs/heads/master: 96219c3a257cc8ba3b3cae67efdc88be37cf7c9d
46 changes: 32 additions & 14 deletions trunk/drivers/i2c/busses/i2c-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,30 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)

/* Rounds down to not include partial word at the end of buf */
words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
if (words_to_transfer > tx_fifo_avail)
words_to_transfer = tx_fifo_avail;

i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);

buf += words_to_transfer * BYTES_PER_FIFO_WORD;
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
tx_fifo_avail -= words_to_transfer;
/* It's very common to have < 4 bytes, so optimize that case. */
if (words_to_transfer) {
if (words_to_transfer > tx_fifo_avail)
words_to_transfer = tx_fifo_avail;

/*
* Update state before writing to FIFO. If this casues us
* to finish writing all bytes (AKA buf_remaining goes to 0) we
* have a potential for an interrupt (PACKET_XFER_COMPLETE is
* not maskable). We need to make sure that the isr sees
* buf_remaining as 0 and doesn't call us back re-entrantly.
*/
buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
tx_fifo_avail -= words_to_transfer;
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf +
words_to_transfer * BYTES_PER_FIFO_WORD;
barrier();

i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);

buf += words_to_transfer * BYTES_PER_FIFO_WORD;
}

/*
* If there is a partial word at the end of buf, handle it manually to
Expand All @@ -287,14 +303,15 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
if (tx_fifo_avail > 0 && buf_remaining > 0) {
BUG_ON(buf_remaining > 3);
memcpy(&val, buf, buf_remaining);

/* Again update before writing to FIFO to make sure isr sees. */
i2c_dev->msg_buf_remaining = 0;
i2c_dev->msg_buf = NULL;
barrier();

i2c_writel(i2c_dev, val, I2C_TX_FIFO);
buf_remaining = 0;
tx_fifo_avail--;
}

BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0);
i2c_dev->msg_buf_remaining = buf_remaining;
i2c_dev->msg_buf = buf;
return 0;
}

Expand Down Expand Up @@ -411,9 +428,10 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
}

if ((status & I2C_INT_PACKET_XFER_COMPLETE) &&
!i2c_dev->msg_buf_remaining)
if (status & I2C_INT_PACKET_XFER_COMPLETE) {
BUG_ON(i2c_dev->msg_buf_remaining);
complete(&i2c_dev->msg_complete);
}

i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc)
Expand Down

0 comments on commit ffed1a8

Please sign in to comment.