i2c: i801: Split i801_block_transaction

i2c and smbus block transaction handling have little in common,
therefore split this function to improve code readability.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
This commit is contained in:
Heiner Kallweit 2024-02-02 08:02:55 +01:00 committed by Andi Shyti
parent 03f9863b1a
commit 6ff9d46cd3

View file

@ -802,77 +802,65 @@ static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data
return 0;
}
/* Block transaction function */
static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
{
int result = 0;
unsigned char hostc;
if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA)
data->block[0] = I2C_SMBUS_BLOCK_MAX;
else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
switch (command) {
case I2C_SMBUS_BLOCK_DATA:
i801_set_hstadd(priv, addr, read_write);
outb_p(hstcmd, SMBHSTCMD(priv));
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/*
* NB: page 240 of ICH5 datasheet shows that the R/#W
* bit should be cleared here, even when reading.
* However if SPD Write Disable is set (Lynx Point and later),
* the read will fail if we don't set the R/#W bit.
*/
i801_set_hstadd(priv, addr,
priv->original_hstcfg & SMBHSTCFG_SPD_WD ?
read_write : I2C_SMBUS_WRITE);
if (read_write == I2C_SMBUS_READ) {
/* NB: page 240 of ICH5 datasheet also shows
* that DATA1 is the cmd field when reading
*/
outb_p(hstcmd, SMBHSTDAT1(priv));
} else
outb_p(hstcmd, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) {
/* set I2C_EN bit in configuration register */
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
hostc | SMBHSTCFG_I2C_EN);
} else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
dev_err(&priv->pci_dev->dev,
"I2C block read is unsupported!\n");
return -EOPNOTSUPP;
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
if (command == I2C_SMBUS_BLOCK_PROC_CALL)
/* Needs to be flagged as write transaction */
i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE);
outb_p(hstcmd, SMBHSTCMD(priv));
break;
}
/* Experience has shown that the block buffer can only be used for
SMBus (not I2C) block transactions, even though the datasheet
doesn't mention this limitation. */
if ((priv->features & FEATURE_BLOCK_BUFFER) &&
command != I2C_SMBUS_I2C_BLOCK_DATA)
result = i801_block_transaction_by_block(priv, data,
read_write,
command);
else
result = i801_block_transaction_byte_by_byte(priv, data,
read_write,
command);
i801_set_hstadd(priv, addr, read_write);
outb_p(hstcmd, SMBHSTCMD(priv));
if (command == I2C_SMBUS_I2C_BLOCK_DATA
&& read_write == I2C_SMBUS_WRITE) {
/* restore saved configuration register value */
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
if (priv->features & FEATURE_BLOCK_BUFFER)
return i801_block_transaction_by_block(priv, data, read_write, command);
else
return i801_block_transaction_byte_by_byte(priv, data, read_write, command);
}
static int i801_i2c_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
{
int result;
u8 hostc;
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
/*
* NB: page 240 of ICH5 datasheet shows that the R/#W bit should be cleared here,
* even when reading. However if SPD Write Disable is set (Lynx Point and later),
* the read will fail if we don't set the R/#W bit.
*/
i801_set_hstadd(priv, addr,
priv->original_hstcfg & SMBHSTCFG_SPD_WD ? read_write : I2C_SMBUS_WRITE);
/* NB: page 240 of ICH5 datasheet shows that DATA1 is the cmd field when reading */
if (read_write == I2C_SMBUS_READ)
outb_p(hstcmd, SMBHSTDAT1(priv));
else
outb_p(hstcmd, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) {
/* set I2C_EN bit in configuration register */
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
} else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
pci_err(priv->pci_dev, "I2C block read is unsupported!\n");
return -EOPNOTSUPP;
}
/* Block buffer isn't supported for I2C block transactions */
result = i801_block_transaction_byte_by_byte(priv, data, read_write, command);
/* restore saved configuration register value */
if (read_write == I2C_SMBUS_WRITE)
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
return result;
}
@ -903,10 +891,10 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
SMBAUXCTL(priv));
if (size == I2C_SMBUS_BLOCK_DATA ||
size == I2C_SMBUS_I2C_BLOCK_DATA ||
size == I2C_SMBUS_BLOCK_PROC_CALL)
ret = i801_block_transaction(priv, data, addr, command, read_write, size);
if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_BLOCK_PROC_CALL)
ret = i801_smbus_block_transaction(priv, data, addr, command, read_write, size);
else if (size == I2C_SMBUS_I2C_BLOCK_DATA)
ret = i801_i2c_block_transaction(priv, data, addr, command, read_write, size);
else
ret = i801_simple_transaction(priv, data, addr, command, read_write, size);