aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-i801.c
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2012-07-24 08:13:58 -0400
committerJean Delvare <khali@endymion.delvare>2012-07-24 08:13:58 -0400
commit6cad93c4bbd62ecfa2e1b3a95c1ac4f6f27764c7 (patch)
tree1b9a3e650be2333d68fe61673c09daf925c16e76 /drivers/i2c/busses/i2c-i801.c
parent37af871112e1dec1e39dfac782f0be5926be1c88 (diff)
i2c-i801: Consolidate polling
(Based on earlier work by Daniel Kurtz.) Come up with a consistent, driver-wide strategy for event polling. For intermediate steps of byte-by-byte block transactions, check for BYTE_DONE or any error flag being set. At the end of every transaction (regardless of PEC being used), check for both BUSY being cleared and INTR or any error flag being set. This ensures proper action for all transaction types. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: Daniel Kurtz <djkurtz@chromium.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r--drivers/i2c/busses/i2c-i801.c108
1 files changed, 53 insertions, 55 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 569a282e3347..a1ce4e68b49a 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -206,13 +206,17 @@ static int i801_check_pre(struct i801_priv *priv)
206 return 0; 206 return 0;
207} 207}
208 208
209/* Convert the status register to an error code, and clear it. */ 209/*
210static int i801_check_post(struct i801_priv *priv, int status, int timeout) 210 * Convert the status register to an error code, and clear it.
211 * Note that status only contains the bits we want to clear, not the
212 * actual register value.
213 */
214static int i801_check_post(struct i801_priv *priv, int status)
211{ 215{
212 int result = 0; 216 int result = 0;
213 217
214 /* If the SMBus is still busy, we give up */ 218 /* If the SMBus is still busy, we give up */
215 if (timeout) { 219 if (unlikely(status < 0)) {
216 dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); 220 dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
217 /* try to stop the current command */ 221 /* try to stop the current command */
218 dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); 222 dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
@@ -245,64 +249,68 @@ static int i801_check_post(struct i801_priv *priv, int status, int timeout)
245 dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); 249 dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n");
246 } 250 }
247 251
248 if (result) { 252 /* Clear status flags except BYTE_DONE, to be cleared by caller */
249 /* Clear error flags */ 253 outb_p(status, SMBHSTSTS(priv));
250 outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv));
251 status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS;
252 if (status) {
253 dev_warn(&priv->pci_dev->dev, "Failed clearing status "
254 "flags at end of transaction (%02x)\n",
255 status);
256 }
257 }
258 254
259 return result; 255 return result;
260} 256}
261 257
262static int i801_transaction(struct i801_priv *priv, int xact) 258/* Wait for BUSY being cleared and either INTR or an error flag being set */
259static int i801_wait_intr(struct i801_priv *priv)
263{ 260{
264 int status;
265 int result;
266 int timeout = 0; 261 int timeout = 0;
267 262 int status;
268 result = i801_check_pre(priv);
269 if (result < 0)
270 return result;
271
272 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
273 * SMBSCMD are passed in xact */
274 outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
275 263
276 /* We will always wait for a fraction of a second! */ 264 /* We will always wait for a fraction of a second! */
277 do { 265 do {
278 usleep_range(250, 500); 266 usleep_range(250, 500);
279 status = inb_p(SMBHSTSTS(priv)); 267 status = inb_p(SMBHSTSTS(priv));
280 } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES)); 268 } while (((status & SMBHSTSTS_HOST_BUSY) ||
269 !(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR))) &&
270 (timeout++ < MAX_RETRIES));
281 271
282 result = i801_check_post(priv, status, timeout > MAX_RETRIES); 272 if (timeout > MAX_RETRIES) {
283 if (result < 0) 273 dev_dbg(&priv->pci_dev->dev, "INTR Timeout!\n");
284 return result; 274 return -ETIMEDOUT;
285 275 }
286 outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); 276 return status & (STATUS_ERROR_FLAGS | SMBHSTSTS_INTR);
287 return 0;
288} 277}
289 278
290/* wait for INTR bit as advised by Intel */ 279/* Wait for either BYTE_DONE or an error flag being set */
291static void i801_wait_hwpec(struct i801_priv *priv) 280static int i801_wait_byte_done(struct i801_priv *priv)
292{ 281{
293 int timeout = 0; 282 int timeout = 0;
294 int status; 283 int status;
295 284
285 /* We will always wait for a fraction of a second! */
296 do { 286 do {
297 usleep_range(250, 500); 287 usleep_range(250, 500);
298 status = inb_p(SMBHSTSTS(priv)); 288 status = inb_p(SMBHSTSTS(priv));
299 } while ((!(status & SMBHSTSTS_INTR)) 289 } while (!(status & (STATUS_ERROR_FLAGS | SMBHSTSTS_BYTE_DONE)) &&
300 && (timeout++ < MAX_RETRIES)); 290 (timeout++ < MAX_RETRIES));
291
292 if (timeout > MAX_RETRIES) {
293 dev_dbg(&priv->pci_dev->dev, "BYTE_DONE Timeout!\n");
294 return -ETIMEDOUT;
295 }
296 return status & STATUS_ERROR_FLAGS;
297}
298
299static int i801_transaction(struct i801_priv *priv, int xact)
300{
301 int status;
302 int result;
301 303
302 if (timeout > MAX_RETRIES) 304 result = i801_check_pre(priv);
303 dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n"); 305 if (result < 0)
306 return result;
304 307
305 outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); 308 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
309 * SMBSCMD are passed in xact */
310 outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
311
312 status = i801_wait_intr(priv);
313 return i801_check_post(priv, status);
306} 314}
307 315
308static int i801_block_transaction_by_block(struct i801_priv *priv, 316static int i801_block_transaction_by_block(struct i801_priv *priv,
@@ -353,7 +361,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
353 int smbcmd; 361 int smbcmd;
354 int status; 362 int status;
355 int result; 363 int result;
356 int timeout;
357 364
358 result = i801_check_pre(priv); 365 result = i801_check_pre(priv);
359 if (result < 0) 366 if (result < 0)
@@ -381,17 +388,9 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
381 outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START, 388 outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
382 SMBHSTCNT(priv)); 389 SMBHSTCNT(priv));
383 390
384 /* We will always wait for a fraction of a second! */ 391 status = i801_wait_byte_done(priv);
385 timeout = 0; 392 if (status)
386 do { 393 goto exit;
387 usleep_range(250, 500);
388 status = inb_p(SMBHSTSTS(priv));
389 } while (!(status & (SMBHSTSTS_BYTE_DONE | STATUS_ERROR_FLAGS))
390 && (timeout++ < MAX_RETRIES));
391
392 result = i801_check_post(priv, status, timeout > MAX_RETRIES);
393 if (result < 0)
394 return result;
395 394
396 if (i == 1 && read_write == I2C_SMBUS_READ 395 if (i == 1 && read_write == I2C_SMBUS_READ
397 && command != I2C_SMBUS_I2C_BLOCK_DATA) { 396 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
@@ -418,10 +417,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
418 outb_p(data->block[i+1], SMBBLKDAT(priv)); 417 outb_p(data->block[i+1], SMBBLKDAT(priv));
419 418
420 /* signals SMBBLKDAT ready */ 419 /* signals SMBBLKDAT ready */
421 outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); 420 outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
422 } 421 }
423 422
424 return 0; 423 status = i801_wait_intr(priv);
424exit:
425 return i801_check_post(priv, status);
425} 426}
426 427
427static int i801_set_block_buffer_mode(struct i801_priv *priv) 428static int i801_set_block_buffer_mode(struct i801_priv *priv)
@@ -476,9 +477,6 @@ static int i801_block_transaction(struct i801_priv *priv,
476 read_write, 477 read_write,
477 command, hwpec); 478 command, hwpec);
478 479
479 if (result == 0 && hwpec)
480 i801_wait_hwpec(priv);
481
482 if (command == I2C_SMBUS_I2C_BLOCK_DATA 480 if (command == I2C_SMBUS_I2C_BLOCK_DATA
483 && read_write == I2C_SMBUS_WRITE) { 481 && read_write == I2C_SMBUS_WRITE) {
484 /* restore saved configuration register value */ 482 /* restore saved configuration register value */