diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-ali1563.c')
-rw-r--r-- | drivers/i2c/busses/i2c-ali1563.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 6b68074e518..fc3e5b02642 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -21,6 +21,7 @@ #include <linux/i2c.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/acpi.h> #define ALI1563_MAX_TIMEOUT 500 #define ALI1563_SMBBA 0x80 @@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) { u32 data; int timeout; + int status = -EIO; dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) /* Issue 'kill' to host controller */ outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); data = inb_p(SMB_HST_STS); + status = -ETIMEDOUT; } /* device error - no response, ignore the autodetection case */ - if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) { - dev_err(&a->dev, "Device error!\n"); + if (data & HST_STS_DEVERR) { + if (size != HST_CNTL2_QUICK) + dev_err(&a->dev, "Device error!\n"); + status = -ENXIO; } - /* bus collision */ if (data & HST_STS_BUSERR) { dev_err(&a->dev, "Bus collision!\n"); @@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) outb_p(0x0,SMB_HST_CNTL2); } - return -1; + return status; } static int ali1563_block_start(struct i2c_adapter * a) { u32 data; int timeout; + int status = -EIO; dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", @@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a) if (timeout && !(data & HST_STS_BAD)) return 0; + + if (timeout == 0) + status = -ETIMEDOUT; + + if (data & HST_STS_DEVERR) + status = -ENXIO; + dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", - timeout ? "Timeout " : "", + timeout ? "" : "Timeout ", data & HST_STS_FAIL ? "Transaction Failed " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "", data & HST_STS_DEVERR ? "Device Error " : "", !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); - return -1; + return status; } static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) @@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, /* Map the size to what the chip understands */ switch (size) { - case I2C_SMBUS_PROC_CALL: - dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); - error = -EINVAL; - break; case I2C_SMBUS_QUICK: size = HST_CNTL2_QUICK; break; @@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, case I2C_SMBUS_BLOCK_DATA: size = HST_CNTL2_BLOCK; break; + default: + dev_warn(&a->dev, "Unsupported transaction %d\n", size); + error = -EOPNOTSUPP; + goto Done; } outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); @@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev) } } + if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE, + ali1563_pci_driver.name)) + goto Err; + if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, ali1563_pci_driver.name)) { dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n", @@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = { static struct i2c_adapter ali1563_adapter = { .owner = THIS_MODULE, .id = I2C_HW_SMBUS_ALI1563, - .class = I2C_CLASS_HWMON, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &ali1563_algorithm, }; |