@@ -230,6 +230,7 @@ struct i801_priv {
/* isr processing */
wait_queue_head_t waitq;
u8 status;
+ u8 xact_extra; /* Used to set INTREN if irqs enabled, and HWPEC */
/* Command state used by isr for byte-by-byte block transactions */
u8 cmd;
@@ -401,13 +402,13 @@ static int i801_transaction(struct i801_priv *priv, int xact)
int result;
const struct i2c_adapter *adap = &priv->adapter;
- result = i801_check_pre(priv);
- if (result < 0)
- return result;
+ /*
+ * the current contents of SMBHSTCNT can be overwritten, since PEC,
+ * SMBSCMD are passed in xact
+ */
+ outb_p(xact | priv->xact_extra | SMBHSTCNT_START, SMBHSTCNT(priv));
if (priv->features & FEATURE_IRQ) {
- outb_p(xact | SMBHSTCNT_INTREN | SMBHSTCNT_START,
- SMBHSTCNT(priv));
result = wait_event_timeout(priv->waitq,
(status = priv->status),
adap->timeout);
@@ -420,17 +421,13 @@ static int i801_transaction(struct i801_priv *priv, int xact)
return i801_check_post(priv, status);
}
- /* the current contents of SMBHSTCNT can be overwritten, since PEC,
- * SMBSCMD are passed in xact */
- outb_p(xact | SMBHSTCNT_START, SMBHSTCNT(priv));
-
status = i801_wait_intr(priv);
return i801_check_post(priv, status);
}
static int i801_block_transaction_by_block(struct i801_priv *priv,
union i2c_smbus_data *data,
- char read_write, int hwpec)
+ char read_write)
{
int i, len;
int status;
@@ -445,8 +442,7 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
outb_p(data->block[i+1], SMBBLKDAT(priv));
}
- status = i801_transaction(priv, I801_BLOCK_DATA |
- (hwpec ? SMBHSTCNT_PEC_EN : 0));
+ status = i801_transaction(priv, I801_BLOCK_DATA);
if (status)
return status;
@@ -553,8 +549,7 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
*/
static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
union i2c_smbus_data *data,
- char read_write, int command,
- int hwpec)
+ char read_write, int command)
{
int i, len;
int smbcmd;
@@ -562,10 +557,6 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
int result;
const struct i2c_adapter *adap = &priv->adapter;
- result = i801_check_pre(priv);
- if (result < 0)
- return result;
-
len = data->block[0];
if (read_write == I2C_SMBUS_WRITE) {
@@ -583,7 +574,7 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
priv->is_read = (read_write == I2C_SMBUS_READ);
if (len == 1 && priv->is_read)
smbcmd |= SMBHSTCNT_LAST_BYTE;
- priv->cmd = smbcmd | SMBHSTCNT_INTREN;
+ priv->cmd = smbcmd | priv->xact_extra;
priv->len = len;
priv->count = 0;
priv->data = &data->block[1];
@@ -691,13 +682,15 @@ static int i801_block_transaction(struct i801_priv *priv,
doesn't mention this limitation. */
if ((priv->features & FEATURE_BLOCK_BUFFER)
&& command != I2C_SMBUS_I2C_BLOCK_DATA
- && i801_set_block_buffer_mode(priv) == 0)
+ && i801_set_block_buffer_mode(priv) == 0) {
+ if (hwpec)
+ priv->xact_extra |= SMBHSTCNT_PEC_EN;
result = i801_block_transaction_by_block(priv, data,
- read_write, hwpec);
- else
+ read_write);
+ } else
result = i801_block_transaction_byte_by_byte(priv, data,
read_write,
- command, hwpec);
+ command);
if (command == I2C_SMBUS_I2C_BLOCK_DATA
&& read_write == I2C_SMBUS_WRITE) {
@@ -716,6 +709,7 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
int block = 0;
int ret, xact = 0;
struct i801_priv *priv = i2c_get_adapdata(adap);
+ int result;
hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
&& size != I2C_SMBUS_QUICK
@@ -776,11 +770,17 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
return -EOPNOTSUPP;
}
- if (hwpec) /* enable/disable hardware PEC */
+ result = i801_check_pre(priv);
+ if (result < 0)
+ return result;
+
+ if (hwpec) { /* enable/disable hardware PEC */
outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv));
- else
+ } else {
outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
SMBAUXCTL(priv));
+ priv->xact_extra &= ~SMBHSTCNT_PEC_EN;
+ }
if (block)
ret = i801_block_transaction(priv, data, read_write, size,
@@ -1381,6 +1381,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
}
if (priv->features & FEATURE_IRQ) {
+ priv->xact_extra |= SMBHSTCNT_INTREN;
init_waitqueue_head(&priv->waitq);
err = devm_request_irq(&dev->dev, dev->irq, i801_isr,