/* start the transaction by setting bit 4 and size */
sis630_write(SMBHOST_CNT, SMB_START | (size & 0x07));
return 0;
}
staticint sis630_transaction_wait(struct i2c_adapter *adap, int size)
{ int temp, result = 0, timeout = 0;
/* We will always wait for a fraction of a second! */ do {
msleep(1);
temp = sis630_read(SMB_STS); /* check if block transmitted */ if (size == SIS630_BLOCK_DATA && (temp & BYTE_DONE_STS)) break;
} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
if (temp & SMBERR_STS) {
dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
result = -ENXIO;
}
if (temp & SMBCOL_STS) {
dev_err(&adap->dev, "Bus collision!\n");
result = -EAGAIN;
}
return result;
}
staticvoid sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
{ /* clear all status "sticky" bits */
sis630_write(SMB_STS, 0xFF);
dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
/* * restore old Host Master Clock if high_clock is set * and oldclock was not 56KHz
*/ if (high_clock && !(oldclock & SMBCLK_SEL))
sis630_write(SMB_CNT, sis630_read(SMB_CNT) & ~SMBCLK_SEL);
dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
}
staticint sis630_transaction(struct i2c_adapter *adap, int size)
{ int result = 0;
u8 oldclock = 0;
result = sis630_transaction_start(adap, size, &oldclock); if (!result) {
result = sis630_transaction_wait(adap, size);
sis630_transaction_end(adap, oldclock);
}
return result;
}
staticint sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write)
{ int i, len = 0, rc = 0;
u8 oldclock = 0;
if (read_write == I2C_SMBUS_WRITE) {
len = data->block[0]; if (len < 0)
len = 0; elseif (len > 32)
len = 32;
sis630_write(SMB_COUNT, len); for (i = 1; i <= len; i++) {
dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]); /* set data */
sis630_write(SMB_BYTE + (i - 1) % 8, data->block[i]); if (i == 8 || (len < 8 && i == len)) {
dev_dbg(&adap->dev, "start trans len=%d i=%d\n", len, i); /* first transaction */
rc = sis630_transaction_start(adap,
SIS630_BLOCK_DATA, &oldclock); if (rc) return rc;
} elseif ((i - 1) % 8 == 7 || i == len) {
dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n", len, i); if (i > 8) {
dev_dbg(&adap->dev, "clear smbary_sts" " len=%d i=%d\n", len, i); /* If this is not first transaction, we must clear sticky bit. clear SMBARY_STS
*/
sis630_write(SMB_STS, BYTE_DONE_STS);
}
rc = sis630_transaction_wait(adap,
SIS630_BLOCK_DATA); if (rc) {
dev_dbg(&adap->dev, "trans_wait failed\n"); break;
}
}
}
} else { /* read request */
data->block[0] = len = 0;
rc = sis630_transaction_start(adap,
SIS630_BLOCK_DATA, &oldclock); if (rc) return rc; do {
rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA); if (rc) {
dev_dbg(&adap->dev, "trans_wait failed\n"); break;
} /* if this first transaction then read byte count */ if (len == 0)
data->block[0] = sis630_read(SMB_COUNT);
/* just to be sure */ if (data->block[0] > 32)
data->block[0] = 32;
dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
for (i = 0; i < 8 && len < data->block[0]; i++, len++) {
dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
data->block[len + 1] = sis630_read(SMB_BYTE +
i);
}
dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);
retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name); if (retval) gotoexit;
/* Everything is happy, let's grab the memory and set things up. */ if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
sis630_driver.name)) {
dev_err(&sis630_dev->dev, "I/O Region 0x%04x-0x%04x for SMBus already in use.\n",
smbus_base + SMB_STS,
smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
retval = -EBUSY; gotoexit;
}
retval = 0;
exit: if (retval)
smbus_base = 0; return retval;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.