aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/algos/i2c-algo-pca.c
diff options
context:
space:
mode:
authorWolfram Sang <w.sang@pengutronix.de>2009-03-28 16:34:45 -0400
committerJean Delvare <khali@linux-fr.org>2009-03-28 16:34:45 -0400
commit2378bc09b91b0702fac7823828a614fd8016a29f (patch)
tree26539b17077028baba2741cf0e78fc01225a7d36 /drivers/i2c/algos/i2c-algo-pca.c
parent8e99ada8deaa9033600cd2c7d0a9366b0e99ab68 (diff)
i2c-algo-pca: Use timeout for checking the state machine
We now timeout also if the state machine does not change within the given time. For that, the driver-specific completion-functions are extended to return true or false depending on the timeout. This then gets checked in the algorithm. Signed-off-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/algos/i2c-algo-pca.c')
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index 9e134fad7bda..f68e5f8e23ee 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -60,14 +60,14 @@ static void pca9665_reset(void *pd)
60 * 60 *
61 * returns after the start condition has occurred 61 * returns after the start condition has occurred
62 */ 62 */
63static void pca_start(struct i2c_algo_pca_data *adap) 63static int pca_start(struct i2c_algo_pca_data *adap)
64{ 64{
65 int sta = pca_get_con(adap); 65 int sta = pca_get_con(adap);
66 DEB2("=== START\n"); 66 DEB2("=== START\n");
67 sta |= I2C_PCA_CON_STA; 67 sta |= I2C_PCA_CON_STA;
68 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); 68 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
69 pca_set_con(adap, sta); 69 pca_set_con(adap, sta);
70 pca_wait(adap); 70 return pca_wait(adap);
71} 71}
72 72
73/* 73/*
@@ -75,14 +75,14 @@ static void pca_start(struct i2c_algo_pca_data *adap)
75 * 75 *
76 * return after the repeated start condition has occurred 76 * return after the repeated start condition has occurred
77 */ 77 */
78static void pca_repeated_start(struct i2c_algo_pca_data *adap) 78static int pca_repeated_start(struct i2c_algo_pca_data *adap)
79{ 79{
80 int sta = pca_get_con(adap); 80 int sta = pca_get_con(adap);
81 DEB2("=== REPEATED START\n"); 81 DEB2("=== REPEATED START\n");
82 sta |= I2C_PCA_CON_STA; 82 sta |= I2C_PCA_CON_STA;
83 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); 83 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
84 pca_set_con(adap, sta); 84 pca_set_con(adap, sta);
85 pca_wait(adap); 85 return pca_wait(adap);
86} 86}
87 87
88/* 88/*
@@ -108,7 +108,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
108 * 108 *
109 * returns after the address has been sent 109 * returns after the address has been sent
110 */ 110 */
111static void pca_address(struct i2c_algo_pca_data *adap, 111static int pca_address(struct i2c_algo_pca_data *adap,
112 struct i2c_msg *msg) 112 struct i2c_msg *msg)
113{ 113{
114 int sta = pca_get_con(adap); 114 int sta = pca_get_con(adap);
@@ -125,7 +125,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
125 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); 125 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
126 pca_set_con(adap, sta); 126 pca_set_con(adap, sta);
127 127
128 pca_wait(adap); 128 return pca_wait(adap);
129} 129}
130 130
131/* 131/*
@@ -133,7 +133,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
133 * 133 *
134 * Returns after the byte has been transmitted 134 * Returns after the byte has been transmitted
135 */ 135 */
136static void pca_tx_byte(struct i2c_algo_pca_data *adap, 136static int pca_tx_byte(struct i2c_algo_pca_data *adap,
137 __u8 b) 137 __u8 b)
138{ 138{
139 int sta = pca_get_con(adap); 139 int sta = pca_get_con(adap);
@@ -143,7 +143,7 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
143 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); 143 sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
144 pca_set_con(adap, sta); 144 pca_set_con(adap, sta);
145 145
146 pca_wait(adap); 146 return pca_wait(adap);
147} 147}
148 148
149/* 149/*
@@ -163,7 +163,7 @@ static void pca_rx_byte(struct i2c_algo_pca_data *adap,
163 * 163 *
164 * Returns after next byte has arrived. 164 * Returns after next byte has arrived.
165 */ 165 */
166static void pca_rx_ack(struct i2c_algo_pca_data *adap, 166static int pca_rx_ack(struct i2c_algo_pca_data *adap,
167 int ack) 167 int ack)
168{ 168{
169 int sta = pca_get_con(adap); 169 int sta = pca_get_con(adap);
@@ -174,7 +174,7 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
174 sta |= I2C_PCA_CON_AA; 174 sta |= I2C_PCA_CON_AA;
175 175
176 pca_set_con(adap, sta); 176 pca_set_con(adap, sta);
177 pca_wait(adap); 177 return pca_wait(adap);
178} 178}
179 179
180static int pca_xfer(struct i2c_adapter *i2c_adap, 180static int pca_xfer(struct i2c_adapter *i2c_adap,
@@ -187,6 +187,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
187 int numbytes = 0; 187 int numbytes = 0;
188 int state; 188 int state;
189 int ret; 189 int ret;
190 int completed = 1;
190 unsigned long timeout = jiffies + i2c_adap->timeout; 191 unsigned long timeout = jiffies + i2c_adap->timeout;
191 192
192 while (pca_status(adap) != 0xf8) { 193 while (pca_status(adap) != 0xf8) {
@@ -232,18 +233,19 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
232 233
233 switch (state) { 234 switch (state) {
234 case 0xf8: /* On reset or stop the bus is idle */ 235 case 0xf8: /* On reset or stop the bus is idle */
235 pca_start(adap); 236 completed = pca_start(adap);
236 break; 237 break;
237 238
238 case 0x08: /* A START condition has been transmitted */ 239 case 0x08: /* A START condition has been transmitted */
239 case 0x10: /* A repeated start condition has been transmitted */ 240 case 0x10: /* A repeated start condition has been transmitted */
240 pca_address(adap, msg); 241 completed = pca_address(adap, msg);
241 break; 242 break;
242 243
243 case 0x18: /* SLA+W has been transmitted; ACK has been received */ 244 case 0x18: /* SLA+W has been transmitted; ACK has been received */
244 case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */ 245 case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
245 if (numbytes < msg->len) { 246 if (numbytes < msg->len) {
246 pca_tx_byte(adap, msg->buf[numbytes]); 247 completed = pca_tx_byte(adap,
248 msg->buf[numbytes]);
247 numbytes++; 249 numbytes++;
248 break; 250 break;
249 } 251 }
@@ -251,7 +253,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
251 if (curmsg == num) 253 if (curmsg == num)
252 pca_stop(adap); 254 pca_stop(adap);
253 else 255 else
254 pca_repeated_start(adap); 256 completed = pca_repeated_start(adap);
255 break; 257 break;
256 258
257 case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */ 259 case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
@@ -260,21 +262,22 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
260 goto out; 262 goto out;
261 263
262 case 0x40: /* SLA+R has been transmitted; ACK has been received */ 264 case 0x40: /* SLA+R has been transmitted; ACK has been received */
263 pca_rx_ack(adap, msg->len > 1); 265 completed = pca_rx_ack(adap, msg->len > 1);
264 break; 266 break;
265 267
266 case 0x50: /* Data bytes has been received; ACK has been returned */ 268 case 0x50: /* Data bytes has been received; ACK has been returned */
267 if (numbytes < msg->len) { 269 if (numbytes < msg->len) {
268 pca_rx_byte(adap, &msg->buf[numbytes], 1); 270 pca_rx_byte(adap, &msg->buf[numbytes], 1);
269 numbytes++; 271 numbytes++;
270 pca_rx_ack(adap, numbytes < msg->len - 1); 272 completed = pca_rx_ack(adap,
273 numbytes < msg->len - 1);
271 break; 274 break;
272 } 275 }
273 curmsg++; numbytes = 0; 276 curmsg++; numbytes = 0;
274 if (curmsg == num) 277 if (curmsg == num)
275 pca_stop(adap); 278 pca_stop(adap);
276 else 279 else
277 pca_repeated_start(adap); 280 completed = pca_repeated_start(adap);
278 break; 281 break;
279 282
280 case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */ 283 case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
@@ -297,7 +300,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
297 if (curmsg == num) 300 if (curmsg == num)
298 pca_stop(adap); 301 pca_stop(adap);
299 else 302 else
300 pca_repeated_start(adap); 303 completed = pca_repeated_start(adap);
301 } else { 304 } else {
302 DEB2("NOT ACK sent after data byte received. " 305 DEB2("NOT ACK sent after data byte received. "
303 "Not final byte. numbytes %d. len %d\n", 306 "Not final byte. numbytes %d. len %d\n",
@@ -323,6 +326,8 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
323 break; 326 break;
324 } 327 }
325 328
329 if (!completed)
330 goto out;
326 } 331 }
327 332
328 ret = curmsg; 333 ret = curmsg;