示例#1
0
/* Return -1 on error. */
static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
			 unsigned short flags, char read_write,
			 u8 command, int size, union i2c_smbus_data * data)
{

	switch (size) {
	case I2C_SMBUS_QUICK:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		size = SIS96x_QUICK;
		break;

	case I2C_SMBUS_BYTE:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		if (read_write == I2C_SMBUS_WRITE)
			sis96x_write(SMB_CMD, command);
		size = SIS96x_BYTE;
		break;

	case I2C_SMBUS_BYTE_DATA:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		sis96x_write(SMB_CMD, command);
		if (read_write == I2C_SMBUS_WRITE)
			sis96x_write(SMB_BYTE, data->byte);
		size = SIS96x_BYTE_DATA;
		break;

	case I2C_SMBUS_PROC_CALL:
	case I2C_SMBUS_WORD_DATA:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		sis96x_write(SMB_CMD, command);
		if (read_write == I2C_SMBUS_WRITE) {
			sis96x_write(SMB_BYTE, data->word & 0xff);
			sis96x_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
		}
		size = (size == I2C_SMBUS_PROC_CALL ? 
			SIS96x_PROC_CALL : SIS96x_WORD_DATA);
		break;

	case I2C_SMBUS_BLOCK_DATA:
		/* TO DO: */
		dev_info(&adap->dev, "SMBus block not implemented!\n");
		return -1;
		break;

	default:
		dev_info(&adap->dev, "Unsupported I2C size\n");
		return -1;
		break;
	}
static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
			 unsigned short flags, char read_write,
			 u8 command, int size, union i2c_smbus_data * data)
{
	int status;

	switch (size) {
	case I2C_SMBUS_QUICK:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		size = SIS96x_QUICK;
		break;

	case I2C_SMBUS_BYTE:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		if (read_write == I2C_SMBUS_WRITE)
			sis96x_write(SMB_CMD, command);
		size = SIS96x_BYTE;
		break;

	case I2C_SMBUS_BYTE_DATA:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		sis96x_write(SMB_CMD, command);
		if (read_write == I2C_SMBUS_WRITE)
			sis96x_write(SMB_BYTE, data->byte);
		size = SIS96x_BYTE_DATA;
		break;

	case I2C_SMBUS_PROC_CALL:
	case I2C_SMBUS_WORD_DATA:
		sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
		sis96x_write(SMB_CMD, command);
		if (read_write == I2C_SMBUS_WRITE) {
			sis96x_write(SMB_BYTE, data->word & 0xff);
			sis96x_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
		}
		size = (size == I2C_SMBUS_PROC_CALL ? 
			SIS96x_PROC_CALL : SIS96x_WORD_DATA);
		break;

	default:
		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
		return -EOPNOTSUPP;
	}
static int sis96x_transaction(int size)
{
	int temp;
	int result = 0;
	int timeout = 0;

	dev_dbg(&sis96x_adapter.dev, "SMBus transaction %d\n", size);

	
	if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {

		dev_dbg(&sis96x_adapter.dev, "SMBus busy (0x%02x). "
			"Resetting...\n", temp);

		
		sis96x_write(SMB_HOST_CNT, 0x20);

		
		if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {
			dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp);
			return -EBUSY;
		} else {
			dev_dbg(&sis96x_adapter.dev, "Successful\n");
		}
	}

	
	sis96x_write(SMB_CNT, 0x20);

	
	temp = sis96x_read(SMB_STS);
	sis96x_write(SMB_STS, temp & 0x1e);

	
	sis96x_write(SMB_HOST_CNT, 0x10 | (size & 0x07));

	
	do {
		msleep(1);
		temp = sis96x_read(SMB_STS);
	} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));

	
	if (timeout > MAX_TIMEOUT) {
		dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
		result = -ETIMEDOUT;
	}

	
	if (temp & 0x02) {
		dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n");
		result = -ENXIO;
	}

	
	if (temp & 0x04) {
		dev_dbg(&sis96x_adapter.dev, "Bus collision!\n");
		result = -EIO;
	}

	
	sis96x_write(SMB_STS, temp);
	if ((temp = sis96x_read(SMB_STS))) {
		dev_dbg(&sis96x_adapter.dev, "Failed reset at "
			"end of transaction! (0x%02x)\n", temp);
	}

	return result;
}
示例#4
0
/* Execute a SMBus transaction.
   int size is from SIS96x_QUICK to SIS96x_BLOCK_DATA
 */
static int sis96x_transaction(int size)
{
	int temp;
	int result = 0;
	int timeout = 0;

	dev_dbg(&sis96x_adapter.dev, "SMBus transaction %d\n", size);

	/* Make sure the SMBus host is ready to start transmitting */
	if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {

		dev_dbg(&sis96x_adapter.dev, "SMBus busy (0x%02x). "
			"Resetting...\n", temp);

		/* kill the transaction */
		sis96x_write(SMB_HOST_CNT, 0x20);

		/* check it again */
		if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {
			dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp);
			return -EBUSY;
		} else {
			dev_dbg(&sis96x_adapter.dev, "Successful\n");
		}
	}

	/* Turn off timeout interrupts, set fast host clock */
	sis96x_write(SMB_CNT, 0x20);

	/* clear all (sticky) status flags */
	temp = sis96x_read(SMB_STS);
	sis96x_write(SMB_STS, temp & 0x1e);

	/* start the transaction by setting bit 4 and size bits */
	sis96x_write(SMB_HOST_CNT, 0x10 | (size & 0x07));

	/* We will always wait for a fraction of a second! */
	do {
		msleep(1);
		temp = sis96x_read(SMB_STS);
	} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));

	/* If the SMBus is still busy, we give up */
	if (timeout > MAX_TIMEOUT) {
		dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
		result = -ETIMEDOUT;
	}

	/* device error - probably missing ACK */
	if (temp & 0x02) {
		dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n");
		result = -ENXIO;
	}

	/* bus collision */
	if (temp & 0x04) {
		dev_dbg(&sis96x_adapter.dev, "Bus collision!\n");
		result = -EIO;
	}

	/* Finish up by resetting the bus */
	sis96x_write(SMB_STS, temp);
	if ((temp = sis96x_read(SMB_STS))) {
		dev_dbg(&sis96x_adapter.dev, "Failed reset at "
			"end of transaction! (0x%02x)\n", temp);
	}

	return result;
}