Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a340ba10 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
parents c10fccdd 4a4e5787
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -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
+31 −15
Original line number Original line Diff line number Diff line
@@ -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 @@
#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)


	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)


	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)


	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,
	}
	}


	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,
		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))