eba94a521fd07b22b5849bb125a029833bd2714a
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-3.14 / 0018-Perform-I2C-combined-transactions-when-possible.patch
1 From d002a24f7ff4ca8b63d08e33fd2d88af84501267 Mon Sep 17 00:00:00 2001
2 From: cbeytas <cbeytas@shaw.ca>
3 Date: Mon, 24 Jun 2013 00:05:40 -0400
4 Subject: [PATCH 18/54] Perform I2C combined transactions when possible
5
6 Perform I2C combined transactions whenever possible, within the
7 restrictions of the Broadcomm Serial Controller.
8
9 Disable DONE interrupt during TA poll
10
11 Prevent interrupt from being triggered if poll is missed and transfer
12 starts and finishes.
13
14 i2c: Make combined transactions optional and disabled by default
15 ---
16 drivers/i2c/busses/i2c-bcm2708.c | 31 ++++++++++++++++++++++++++++++-
17 1 file changed, 30 insertions(+), 1 deletion(-)
18
19 diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c
20 index b3d96f0..05531db 100644
21 --- a/drivers/i2c/busses/i2c-bcm2708.c
22 +++ b/drivers/i2c/busses/i2c-bcm2708.c
23 @@ -74,6 +74,9 @@ static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE;
24 module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
25 MODULE_PARM_DESC(baudrate, "The I2C baudrate");
26
27 +static bool combined = false;
28 +module_param(combined, bool, 0644);
29 +MODULE_PARM_DESC(combined, "Use combined transactions");
30
31 struct bcm2708_i2c {
32 struct i2c_adapter adapter;
33 @@ -150,7 +153,7 @@ static inline void bcm2708_bsc_fifo_fill(struct bcm2708_i2c *bi)
34 static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
35 {
36 unsigned long bus_hz;
37 - u32 cdiv;
38 + u32 cdiv, s;
39 u32 c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_ST | BSC_C_CLEAR_1;
40
41 bus_hz = clk_get_rate(bi->clk);
42 @@ -166,6 +169,32 @@ static inline void bcm2708_bsc_setup(struct bcm2708_i2c *bi)
43 bcm2708_wr(bi, BSC_DIV, cdiv);
44 bcm2708_wr(bi, BSC_A, bi->msg->addr);
45 bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
46 + if (combined)
47 + {
48 + /* Do the next two messages meet combined transaction criteria?
49 + - Current message is a write, next message is a read
50 + - Both messages to same slave address
51 + - Write message can fit inside FIFO (16 bytes or less) */
52 + if ( (bi->nmsgs > 1) &&
53 + !(bi->msg[0].flags & I2C_M_RD) && (bi->msg[1].flags & I2C_M_RD) &&
54 + (bi->msg[0].addr == bi->msg[1].addr) && (bi->msg[0].len <= 16)) {
55 + /* Fill FIFO with entire write message (16 byte FIFO) */
56 + while (bi->pos < bi->msg->len)
57 + bcm2708_wr(bi, BSC_FIFO, bi->msg->buf[bi->pos++]);
58 + /* Start write transfer (no interrupts, don't clear FIFO) */
59 + bcm2708_wr(bi, BSC_C, BSC_C_I2CEN | BSC_C_ST);
60 + /* poll for transfer start bit (should only take 1-20 polls) */
61 + do {
62 + s = bcm2708_rd(bi, BSC_S);
63 + } while (!(s & (BSC_S_TA | BSC_S_ERR | BSC_S_CLKT | BSC_S_DONE)));
64 + /* Send next read message before the write transfer finishes. */
65 + bi->nmsgs--;
66 + bi->msg++;
67 + bi->pos = 0;
68 + bcm2708_wr(bi, BSC_DLEN, bi->msg->len);
69 + c = BSC_C_I2CEN | BSC_C_INTD | BSC_C_INTR | BSC_C_ST | BSC_C_READ;
70 + }
71 + }
72 bcm2708_wr(bi, BSC_C, c);
73 }
74
75 --
76 1.9.1
77