i2c: i801: Split i801_block_transaction
authorHeiner Kallweit <hkallweit1@gmail.com>
Fri, 2 Feb 2024 07:02:55 +0000 (08:02 +0100)
committerAndi Shyti <andi.shyti@kernel.org>
Thu, 8 Feb 2024 17:06:45 +0000 (18:06 +0100)
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>
drivers/i2c/busses/i2c-i801.c

index 156bace92ad3ba3d0d2cb76fbe56b69bf404fe97..24eb187dbc1f540c270fa850f6922be290e99165 100644 (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);
+       else
+               i801_set_hstadd(priv, addr, read_write);
+       outb_p(hstcmd, SMBHSTCMD(priv));
+
+       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));
-               break;
+
+       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;
        }
 
-       /* 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);
+       /* Block buffer isn't supported for I2C block transactions */
+       result = i801_block_transaction_byte_by_byte(priv, data, read_write, command);
 
-       if (command == I2C_SMBUS_I2C_BLOCK_DATA
-        && read_write == I2C_SMBUS_WRITE) {
-               /* restore saved configuration register value */
+       /* 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);