summaryrefslogtreecommitdiff
path: root/drivers/i2c
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2024-02-02 08:04:06 +0100
committerAndi Shyti <andi.shyti@kernel.org>2024-02-08 18:06:46 +0100
commit29dae4572efb676e4831eee68bc423b9f32c05d0 (patch)
tree2e7bd3b494a758a662a12772bf995ddabe73368f /drivers/i2c
parent6ff9d46cd36fbd004b1cd7c9173af5cdfbcd1df1 (diff)
i2c: i801: Add SMBUS_LEN_SENTINEL
Add a sentinel length value that is used to check whether we should read and use the length value provided by the slave device. This simplifies the currently used checks. 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>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-i801.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 24eb187dbc1f..15d251288317 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -205,6 +205,8 @@
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
STATUS_ERROR_FLAGS)
+#define SMBUS_LEN_SENTINEL (I2C_SMBUS_BLOCK_MAX + 1)
+
/* Older devices have their ID defined in <linux/pci_ids.h> */
#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3
#define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3
@@ -541,9 +543,12 @@ out:
static void i801_isr_byte_done(struct i801_priv *priv)
{
if (priv->is_read) {
- /* For SMBus block reads, length is received with first byte */
- if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
- (priv->count == 0)) {
+ /*
+ * At transfer start i801_smbus_block_transaction() marks
+ * the block length as invalid. Check for this sentinel value
+ * and read the block length from SMBHSTDAT0.
+ */
+ if (priv->len == SMBUS_LEN_SENTINEL) {
priv->len = inb_p(SMBHSTDAT0(priv));
if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
dev_err(&priv->pci_dev->dev,
@@ -698,8 +703,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
if (status)
return status;
- if (i == 1 && read_write == I2C_SMBUS_READ
- && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+ /*
+ * At transfer start i801_smbus_block_transaction() marks
+ * the block length as invalid. Check for this sentinel value
+ * and read the block length from SMBHSTDAT0.
+ */
+ if (len == SMBUS_LEN_SENTINEL) {
len = inb_p(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
dev_err(&priv->pci_dev->dev,
@@ -806,7 +815,8 @@ static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_
u8 addr, u8 hstcmd, char read_write, int command)
{
if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA)
- data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ /* Mark block length as invalid */
+ data->block[0] = SMBUS_LEN_SENTINEL;
else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;