Commit a340ba10 authored by Linus Torvalds's avatar Linus Torvalds
parents c10fccdd 4a4e5787
...@@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net ...@@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org/SpeedTouch/ W: http://www.linux-usb.org/SpeedTouch/
S: Maintained S: Maintained
ALI1563 I2C DRIVER
P: Rudolf Marek
M: r.marek@sh.cvut.cz
L: sensors@stimpy.netroedge.com
S: Maintained
ALPHA PORT ALPHA PORT
P: Richard Henderson P: Richard Henderson
M: rth@twiddle.net M: rth@twiddle.net
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge * i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
* *
* Copyright (C) 2004 Patrick Mochel * Copyright (C) 2004 Patrick Mochel
* 2005 Rudolf Marek <r.marek@sh.cvut.cz>
* *
* The 1563 southbridge is deceptively similar to the 1533, with a * The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they * few notable exceptions. One of those happens to be the fact they
...@@ -57,10 +58,11 @@ ...@@ -57,10 +58,11 @@
#define HST_CNTL2_BLOCK 0x05 #define HST_CNTL2_BLOCK 0x05
#define HST_CNTL2_SIZEMASK 0x38
static unsigned short ali1563_smba; static unsigned short ali1563_smba;
static int ali1563_transaction(struct i2c_adapter * a) static int ali1563_transaction(struct i2c_adapter * a, int size)
{ {
u32 data; u32 data;
int timeout; int timeout;
...@@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a) ...@@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a)
data = inb_p(SMB_HST_STS); data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) { if (data & HST_STS_BAD) {
dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
outb_p(data | HST_STS_BAD,SMB_HST_STS); outb_p(data | HST_STS_BAD,SMB_HST_STS);
data = inb_p(SMB_HST_STS); data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) if (data & HST_STS_BAD)
...@@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a) ...@@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD)) if (timeout && !(data & HST_STS_BAD))
return 0; return 0;
dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
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 " : "");
if (!(data & HST_STS_DONE)) if (!timeout) {
dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
/* Issue 'kill' to host controller */ /* Issue 'kill' to host controller */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
else data = inb_p(SMB_HST_STS);
/* Issue timeout to reset all devices on bus */ }
/* device error - no response, ignore the autodetection case */
if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
dev_err(&a->dev, "Device error!\n");
}
/* bus collision */
if (data & HST_STS_BUSERR) {
dev_err(&a->dev, "Bus collision!\n");
/* Issue timeout, hoping it helps */
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
}
if (data & HST_STS_FAIL) {
dev_err(&a->dev, "Cleaning fail after KILL!\n");
outb_p(0x0,SMB_HST_CNTL2);
}
return -1; return -1;
} }
...@@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a) ...@@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD)) if (timeout && !(data & HST_STS_BAD))
return 0; return 0;
dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n", 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_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "", data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
...@@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, ...@@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
} }
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2); outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
/* Write the command register */ /* Write the command register */
switch(size) { switch(size) {
case HST_CNTL2_BYTE: case HST_CNTL2_BYTE:
if (rw== I2C_SMBUS_WRITE) if (rw== I2C_SMBUS_WRITE)
outb_p(cmd, SMB_HST_CMD); /* Beware it uses DAT0 register and not CMD! */
outb_p(cmd, SMB_HST_DAT0);
break; break;
case HST_CNTL2_BYTE_DATA: case HST_CNTL2_BYTE_DATA:
outb_p(cmd, SMB_HST_CMD); outb_p(cmd, SMB_HST_CMD);
...@@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, ...@@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
goto Done; goto Done;
} }
if ((error = ali1563_transaction(a))) if ((error = ali1563_transaction(a, size)))
goto Done; goto Done;
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)) if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment