diff options
Diffstat (limited to 'target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch')
-rwxr-xr-x | target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch b/target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch new file mode 100755 index 0000000000..236f9c6030 --- /dev/null +++ b/target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch @@ -0,0 +1,77 @@ +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(-) + +diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c +index 09203c0..7d385a3 100644 +--- a/drivers/i2c/busses/i2c-bcm2708.c ++++ b/drivers/i2c/busses/i2c-bcm2708.c +@@ -74,6 +74,9 @@ static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; + 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(struct bcm2708_i2c *bi) + 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(struct bcm2708_i2c *bi) + 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); + } + +-- +1.8.3.2 + |