aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch')
-rwxr-xr-xtarget/linux/brcm2708/patches-3.18/0020-Perform-I2C-combined-transactions-when-possible.patch77
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
+