Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[powerpc.git] / drivers / i2c / busses / i2c-viapro.c
index 3be476c..a2237d4 100644 (file)
@@ -104,34 +104,56 @@ static struct i2c_adapter vt596_adapter;
 #define FEATURE_I2CBLOCK       (1<<0)
 static unsigned int vt596_features;
 
+#ifdef DEBUG
+static void vt596_dump_regs(const char *msg, u8 size)
+{
+       dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x "
+               "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+               inb_p(SMBHSTDAT1));
+
+       if (size == VT596_BLOCK_DATA
+        || size == VT596_I2C_BLOCK_DATA) {
+               int i;
+
+               dev_dbg(&vt596_adapter.dev, "BLK=");
+               for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++)
+                       printk("%02x,", inb_p(SMBBLKDAT));
+               printk("\n");
+               dev_dbg(&vt596_adapter.dev, "    ");
+               for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++)
+                       printk("%02x,", inb_p(SMBBLKDAT));
+               printk("%02x\n", inb_p(SMBBLKDAT));
+       }
+}
+#else
+static inline void vt596_dump_regs(const char *msg, u8 size) { }
+#endif
+
 /* Return -1 on error, 0 on success */
-static int vt596_transaction(void)
+static int vt596_transaction(u8 size)
 {
        int temp;
        int result = 0;
        int timeout = 0;
 
-       dev_dbg(&vt596_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
-               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
-               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
-               inb_p(SMBHSTDAT1));
+       vt596_dump_regs("Transaction (pre)", size);
 
        /* Make sure the SMBus host is ready to start transmitting */
        if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
                dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
-                       "Resetting... ", temp);
+                       "Resetting...\n", temp);
 
                outb_p(temp, SMBHSTSTS);
                if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
-                       printk("Failed! (0x%02x)\n", temp);
+                       dev_err(&vt596_adapter.dev, "SMBus reset failed! "
+                               "(0x%02x)\n", temp);
                        return -1;
-               } else {
-                       printk("Successful!\n");
                }
        }
 
        /* Start the transaction by setting bit 6 */
-       outb_p(inb(SMBHSTCNT) | 0x40, SMBHSTCNT);
+       outb_p(0x40 | size, SMBHSTCNT);
 
        /* We will always wait for a fraction of a second */
        do {
@@ -148,7 +170,7 @@ static int vt596_transaction(void)
        if (temp & 0x10) {
                result = -1;
                dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
-                       inb_p(SMBHSTCNT) & 0x3C);
+                       size);
        }
 
        if (temp & 0x08) {
@@ -157,11 +179,13 @@ static int vt596_transaction(void)
        }
 
        if (temp & 0x04) {
+               int read = inb_p(SMBHSTADD) & 0x01;
                result = -1;
-               /* Quick commands are used to probe for chips, so
-                  errors are expected, and we don't want to frighten the
-                  user. */
-               if ((inb_p(SMBHSTCNT) & 0x3C) != VT596_QUICK)
+               /* The quick and receive byte commands are used to probe
+                  for chips, so errors are expected, and we don't want
+                  to frighten the user. */
+               if (!((size == VT596_QUICK && !read) ||
+                     (size == VT596_BYTE && read)))
                        dev_err(&vt596_adapter.dev, "Transaction error!\n");
        }
 
@@ -169,10 +193,7 @@ static int vt596_transaction(void)
        if (temp & 0x1F)
                outb_p(temp, SMBHSTSTS);
 
-       dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
-               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
-               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
-               inb_p(SMBHSTDAT1));
+       vt596_dump_regs("Transaction (post)", size);
 
        return result;
 }
@@ -232,9 +253,8 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
        }
 
        outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
-       outb_p((size & 0x3C), SMBHSTCNT);
 
-       if (vt596_transaction()) /* Error in transaction */
+       if (vt596_transaction(size)) /* Error in transaction */
                return -1;
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
@@ -420,6 +440,7 @@ static struct pci_device_id vt596_ids[] = {
 MODULE_DEVICE_TABLE(pci, vt596_ids);
 
 static struct pci_driver vt596_driver = {
+       .owner          = THIS_MODULE,
        .name           = "vt596_smbus",
        .id_table       = vt596_ids,
        .probe          = vt596_probe,
@@ -442,9 +463,9 @@ static void __exit i2c_vt596_exit(void)
        }
 }
 
-MODULE_AUTHOR(
-    "Frodo Looijaard <frodol@dds.nl> and "
-    "Philip Edelbrock <phil@netroedge.com>");
+MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, "
+             "Mark D. Studebaker <mdsxyz123@yahoo.com> and "
+             "Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("vt82c596 SMBus driver");
 MODULE_LICENSE("GPL");