diff options
author | Jean Delvare <khali@linux-fr.org> | 2009-09-18 16:45:43 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-09-18 16:45:43 -0400 |
commit | 27693ce5f372c0af3b0730f5152b35432afa0fd7 (patch) | |
tree | e408ab73b8f1815a89a935992bec4332f0ff116a /drivers/i2c/busses/i2c-taos-evm.c | |
parent | 6a891a3111fe701517bb31c2204304724c7299c8 (diff) |
i2c-taos-evm: Switch echo off to improve performance
When echo is on, we waste time reading back our orders. Switching echo
off makes performance much better: SMBus byte data transactions are 47%
faster and byte transactions are 24% faster.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-taos-evm.c')
-rw-r--r-- | drivers/i2c/busses/i2c-taos-evm.c | 45 |
1 files changed, 24 insertions, 21 deletions
diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index 224aa12ee7c8..dd39c1eb03ed 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c | |||
@@ -32,10 +32,12 @@ | |||
32 | 32 | ||
33 | #define TAOS_STATE_INIT 0 | 33 | #define TAOS_STATE_INIT 0 |
34 | #define TAOS_STATE_IDLE 1 | 34 | #define TAOS_STATE_IDLE 1 |
35 | #define TAOS_STATE_SEND 2 | 35 | #define TAOS_STATE_EOFF 2 |
36 | #define TAOS_STATE_RECV 3 | 36 | #define TAOS_STATE_RECV 3 |
37 | 37 | ||
38 | #define TAOS_CMD_RESET 0x12 | 38 | #define TAOS_CMD_RESET 0x12 |
39 | #define TAOS_CMD_ECHO_ON '+' | ||
40 | #define TAOS_CMD_ECHO_OFF '-' | ||
39 | 41 | ||
40 | static DECLARE_WAIT_QUEUE_HEAD(wq); | 42 | static DECLARE_WAIT_QUEUE_HEAD(wq); |
41 | 43 | ||
@@ -102,17 +104,9 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | |||
102 | 104 | ||
103 | /* Send the transaction to the TAOS EVM */ | 105 | /* Send the transaction to the TAOS EVM */ |
104 | dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer); | 106 | dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer); |
105 | taos->pos = 0; | 107 | for (p = taos->buffer; *p; p++) |
106 | taos->state = TAOS_STATE_SEND; | 108 | serio_write(serio, *p); |
107 | serio_write(serio, taos->buffer[0]); | 109 | |
108 | wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, | ||
109 | msecs_to_jiffies(250)); | ||
110 | if (taos->state != TAOS_STATE_IDLE) { | ||
111 | dev_err(&adapter->dev, "Transaction failed " | ||
112 | "(state=%d, pos=%d)\n", taos->state, taos->pos); | ||
113 | taos->addr = 0; | ||
114 | return -EIO; | ||
115 | } | ||
116 | taos->addr = addr; | 110 | taos->addr = addr; |
117 | 111 | ||
118 | /* Start the transaction and read the answer */ | 112 | /* Start the transaction and read the answer */ |
@@ -122,7 +116,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | |||
122 | wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, | 116 | wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, |
123 | msecs_to_jiffies(150)); | 117 | msecs_to_jiffies(150)); |
124 | if (taos->state != TAOS_STATE_IDLE | 118 | if (taos->state != TAOS_STATE_IDLE |
125 | || taos->pos != 6) { | 119 | || taos->pos != 5) { |
126 | dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n", | 120 | dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n", |
127 | taos->pos); | 121 | taos->pos); |
128 | return -EIO; | 122 | return -EIO; |
@@ -130,7 +124,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, | |||
130 | dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer); | 124 | dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer); |
131 | 125 | ||
132 | /* Interpret the returned string */ | 126 | /* Interpret the returned string */ |
133 | p = taos->buffer + 2; | 127 | p = taos->buffer + 1; |
134 | p[3] = '\0'; | 128 | p[3] = '\0'; |
135 | if (!strcmp(p, "NAK")) | 129 | if (!strcmp(p, "NAK")) |
136 | return -ENODEV; | 130 | return -ENODEV; |
@@ -173,13 +167,9 @@ static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data, | |||
173 | wake_up_interruptible(&wq); | 167 | wake_up_interruptible(&wq); |
174 | } | 168 | } |
175 | break; | 169 | break; |
176 | case TAOS_STATE_SEND: | 170 | case TAOS_STATE_EOFF: |
177 | if (taos->buffer[++taos->pos]) | 171 | taos->state = TAOS_STATE_IDLE; |
178 | serio_write(serio, taos->buffer[taos->pos]); | 172 | wake_up_interruptible(&wq); |
179 | else { | ||
180 | taos->state = TAOS_STATE_IDLE; | ||
181 | wake_up_interruptible(&wq); | ||
182 | } | ||
183 | break; | 173 | break; |
184 | case TAOS_STATE_RECV: | 174 | case TAOS_STATE_RECV: |
185 | taos->buffer[taos->pos++] = data; | 175 | taos->buffer[taos->pos++] = data; |
@@ -257,6 +247,19 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) | |||
257 | } | 247 | } |
258 | strlcpy(adapter->name, name, sizeof(adapter->name)); | 248 | strlcpy(adapter->name, name, sizeof(adapter->name)); |
259 | 249 | ||
250 | /* Turn echo off for better performance */ | ||
251 | taos->state = TAOS_STATE_EOFF; | ||
252 | serio_write(serio, TAOS_CMD_ECHO_OFF); | ||
253 | |||
254 | wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, | ||
255 | msecs_to_jiffies(250)); | ||
256 | if (taos->state != TAOS_STATE_IDLE) { | ||
257 | err = -ENODEV; | ||
258 | dev_err(&adapter->dev, "Echo off failed " | ||
259 | "(state=%d)\n", taos->state); | ||
260 | goto exit_close; | ||
261 | } | ||
262 | |||
260 | err = i2c_add_adapter(adapter); | 263 | err = i2c_add_adapter(adapter); |
261 | if (err) | 264 | if (err) |
262 | goto exit_close; | 265 | goto exit_close; |