Loading MAINTAINERS +6 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading drivers/i2c/busses/i2c-ali1563.c +31 −15 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; } } Loading Loading @@ -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 " : "", Loading Loading @@ -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); Loading @@ -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)) Loading Loading
MAINTAINERS +6 −0 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
drivers/i2c/busses/i2c-ali1563.c +31 −15 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading @@ -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) Loading @@ -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; } } Loading Loading @@ -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 " : "", Loading Loading @@ -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); Loading @@ -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)) Loading