123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- From 0262abfaac71799e3688285f1f30bead42b8ff7e Mon Sep 17 00:00:00 2001
- From: cbeytas <cbeytas@shaw.ca>
- Date: Mon, 24 Jun 2013 00:05:40 -0400
- Subject: [PATCH 020/114] Perform I2C combined transactions when possible
- Perform I2C combined transactions whenever possible, within the
- restrictions of the Broadcomm Serial Controller.
- Disable DONE interrupt during TA poll
- Prevent interrupt from being triggered if poll is missed and transfer
- starts and finishes.
- i2c: Make combined transactions optional and disabled by default
- ---
- drivers/i2c/busses/i2c-bcm2708.c | 31 ++++++++++++++++++++++++++++++-
- 1 file changed, 30 insertions(+), 1 deletion(-)
- --- a/drivers/i2c/busses/i2c-bcm2708.c
- +++ b/drivers/i2c/busses/i2c-bcm2708.c
- @@ -74,6 +74,9 @@ static unsigned int baudrate = CONFIG_I2
- module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
- MODULE_PARM_DESC(baudrate, "The I2C baudrate");
-
- +static bool combined = false;
- +module_param(combined, bool, 0644);
- +MODULE_PARM_DESC(combined, "Use combined transactions");
-
- struct bcm2708_i2c {
- struct i2c_adapter adapter;
- @@ -150,7 +153,7 @@ static inline void bcm2708_bsc_fifo_fill
- static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
- {
- unsigned long bus_hz;
- - u32 cdiv;
- + u32 cdiv, s;
- u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
-
- bus_hz = clk_get_rate(bi->clk);
- @@ -166,6 +169,32 @@ static inline void bcm2708_bsc_setup(str
- bcm2708_wr(bi, BSC_DIV, cdiv);
- bcm2708_wr(bi, BSC_A, bi->msg->addr);
- bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
- + if (combined)
- + {
- + /* Do the next two messages meet combined transaction criteria?
- + - Current message is a write, next message is a read
- + - Both messages to same slave address
- + - Write message can fit inside FIFO (16 bytes or less) */
- + if ( (bi->nmsgs > 1) &&
- + !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
- + (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
- + /* Fill FIFO with entire write message (16 byte FIFO) */
- + while (bi->pos < bi->msg->len)
- + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
- + /* Start write transfer (no interrupts, don't clear FIFO) */
- + bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
- + /* poll for transfer start bit (should only take 1-20 polls) */
- + do {
- + s = bcm2708_rd(bi, BSC_S);
- + } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)));
- + /* Send next read message before the write transfer finishes. */
- + bi->nmsgs--;
- + bi->msg++;
- + bi->pos = 0;
- + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
- + c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
- + }
- + }
- bcm2708_wr(bi, BSC_C, c);
- }
-
|