aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-i801.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r--drivers/i2c/busses/i2c-i801.c85
1 files changed, 78 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 003196fffd2..898dcf9c7ad 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -166,6 +166,13 @@ struct i801_priv {
166 /* isr processing */ 166 /* isr processing */
167 wait_queue_head_t waitq; 167 wait_queue_head_t waitq;
168 u8 status; 168 u8 status;
169
170 /* Command state used by isr for byte-by-byte block transactions */
171 u8 cmd;
172 bool is_read;
173 int count;
174 int len;
175 u8 *data;
169}; 176};
170 177
171static struct pci_driver i801_driver; 178static struct pci_driver i801_driver;
@@ -373,14 +380,60 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
373 return 0; 380 return 0;
374} 381}
375 382
383static void i801_isr_byte_done(struct i801_priv *priv)
384{
385 if (priv->is_read) {
386 /* For SMBus block reads, length is received with first byte */
387 if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
388 (priv->count == 0)) {
389 priv->len = inb_p(SMBHSTDAT0(priv));
390 if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
391 dev_err(&priv->pci_dev->dev,
392 "Illegal SMBus block read size %d\n",
393 priv->len);
394 /* FIXME: Recover */
395 priv->len = I2C_SMBUS_BLOCK_MAX;
396 } else {
397 dev_dbg(&priv->pci_dev->dev,
398 "SMBus block read size is %d\n",
399 priv->len);
400 }
401 priv->data[-1] = priv->len;
402 }
403
404 /* Read next byte */
405 if (priv->count < priv->len)
406 priv->data[priv->count++] = inb(SMBBLKDAT(priv));
407 else
408 dev_dbg(&priv->pci_dev->dev,
409 "Discarding extra byte on block read\n");
410
411 /* Set LAST_BYTE for last byte of read transaction */
412 if (priv->count == priv->len - 1)
413 outb_p(priv->cmd | SMBHSTCNT_LAST_BYTE,
414 SMBHSTCNT(priv));
415 } else if (priv->count < priv->len - 1) {
416 /* Write next byte, except for IRQ after last byte */
417 outb_p(priv->data[++priv->count], SMBBLKDAT(priv));
418 }
419
420 /* Clear BYTE_DONE to continue with next byte */
421 outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS(priv));
422}
423
376/* 424/*
377 * i801 signals transaction completion with one of these interrupts: 425 * There are two kinds of interrupts:
378 * INTR - Success 426 *
379 * DEV_ERR - Invalid command, NAK or communication timeout 427 * 1) i801 signals transaction completion with one of these interrupts:
380 * BUS_ERR - SMI# transaction collision 428 * INTR - Success
381 * FAILED - transaction was canceled due to a KILL request 429 * DEV_ERR - Invalid command, NAK or communication timeout
382 * When any of these occur, update ->status and wake up the waitq. 430 * BUS_ERR - SMI# transaction collision
383 * ->status must be cleared before kicking off the next transaction. 431 * FAILED - transaction was canceled due to a KILL request
432 * When any of these occur, update ->status and wake up the waitq.
433 * ->status must be cleared before kicking off the next transaction.
434 *
435 * 2) For byte-by-byte (I2C read/write) transactions, one BYTE_DONE interrupt
436 * occurs for each byte of a byte-by-byte to prepare the next byte.
384 */ 437 */
385static irqreturn_t i801_isr(int irq, void *dev_id) 438static irqreturn_t i801_isr(int irq, void *dev_id)
386{ 439{
@@ -397,6 +450,9 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
397 if (status != 0x42) 450 if (status != 0x42)
398 dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status); 451 dev_dbg(&priv->pci_dev->dev, "irq: status = %02x\n", status);
399 452
453 if (status & SMBHSTSTS_BYTE_DONE)
454 i801_isr_byte_done(priv);
455
400 /* 456 /*
401 * Clear irq sources and report transaction result. 457 * Clear irq sources and report transaction result.
402 * ->status must be cleared before the next transaction is started. 458 * ->status must be cleared before the next transaction is started.
@@ -443,6 +499,21 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
443 else 499 else
444 smbcmd = I801_BLOCK_DATA; 500 smbcmd = I801_BLOCK_DATA;
445 501
502 if (priv->features & FEATURE_IRQ) {
503 priv->is_read = (read_write == I2C_SMBUS_READ);
504 if (len == 1 && priv->is_read)
505 smbcmd |= SMBHSTCNT_LAST_BYTE;
506 priv->cmd = smbcmd | SMBHSTCNT_INTREN;
507 priv->len = len;
508 priv->count = 0;
509 priv->data = &data->block[1];
510
511 outb_p(priv->cmd | SMBHSTCNT_START, SMBHSTCNT(priv));
512 wait_event(priv->waitq, (status = priv->status));
513 priv->status = 0;
514 return i801_check_post(priv, status);
515 }
516
446 for (i = 1; i <= len; i++) { 517 for (i = 1; i <= len; i++) {
447 if (i == len && read_write == I2C_SMBUS_READ) 518 if (i == len && read_write == I2C_SMBUS_READ)
448 smbcmd |= SMBHSTCNT_LAST_BYTE; 519 smbcmd |= SMBHSTCNT_LAST_BYTE;