lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <458484CD-01AC-4155-8687-D628A19D6493@cisco.com>
Date: Tue, 9 Dec 2025 03:30:31 +0000
From: "Qing Chang (qinchang)" <qinchang@...co.com>
CC: "Jean Delvare   (maintainer:I2C/SMBUS CONTROLLER DRIVERS FOR PC)"
	<jdelvare@...e.com>, "Andi Shyti   (maintainer:I2C SUBSYSTEM HOST DRIVERS)"
	<andi.shyti@...nel.org>, "open list:I2C/SMBUS CONTROLLER DRIVERS FOR PC"
	<linux-i2c@...r.kernel.org>, open list <linux-kernel@...r.kernel.org>
Subject: [PATCH] i2c: piix4: Add support for I2C block data transactions

>From 329a0f951071c03b75a92e6b3c5746d9ee002935 Mon Sep 17 00:00:00 2001

-
From: Qing Chang <qinchang@...co.com>
Date: Sun, 30 Nov 2025 19:30:36 -0800
Subject: [PATCH] i2c: piix4: Add support for I2C block data transactions

Add support for I2C_SMBUS_I2C_BLOCK_DATA protocol to the PIIX4 SMBus
driver. This enables I2C block read/write operations where the master
specifies the transfer length, unlike SMBus block data where the slave
provides the length.

Key changes:
- Add PIIX4_I2C_BLOCK_DATA protocol constant (0x18)
- Implement I2C block write: first data byte to SMBHSTDAT0, rest to SMBBLKDAT
- Implement I2C block read: pre-specify length, read first byte from
  SMBHSTDAT0, rest from SMBBLKDAT
- Update piix4_func() to advertise I2C_FUNC_SMBUS_I2C_BLOCK support
- Add IMC notification for SB800 series chips

Signed-off-by: Qing Chang <qinchang@...co.com>
---
 drivers/i2c/busses/i2c-piix4.c | 44 +++++++++++++++++++++++++++++++---
 drivers/i2c/busses/i2c-piix4.h |  3 ++-
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index ac3bb550303f..778ff169b138 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -649,6 +649,28 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                }
                size = PIIX4_BLOCK_DATA;
                break;
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               outb_p((addr << 1) | read_write,
+                      SMBHSTADD);
+               outb_p(command, SMBHSTCMD);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       len = data->block[0];
+                       if (len == 0 || len > I2C_SMBUS_BLOCK_MAX + 1)
+                               return -EINVAL;
+                       /* For I2C block write, first byte goes to SMBHSTDAT0 */
+                       outb_p(data->block[1], SMBHSTDAT0);
+                       inb_p(SMBHSTCNT);       /* Reset SMBBLKDAT */
+                       /* Write remaining bytes to SMBBLKDAT */
+                       for (i = 2; i <= len; i++)
+                               outb_p(data->block[i], SMBBLKDAT);
+               } else {
+                       /* For I2C block read, length is pre-specified by caller */
+                       len = data->block[0];
+                       if (len == 0 || len > I2C_SMBUS_BLOCK_MAX + 1)
+                               return -EINVAL;
+               }
+               size = PIIX4_I2C_BLOCK_DATA;
+               break;
        default:
                dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
                return -EOPNOTSUPP;
@@ -680,6 +702,18 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                for (i = 1; i <= data->block[0]; i++)
                        data->block[i] = inb_p(SMBBLKDAT);
                break;
+       case PIIX4_I2C_BLOCK_DATA:
+               /* For I2C block read, the length was pre-specified */
+               len = data->block[0];
+               if (len == 0 || len > I2C_SMBUS_BLOCK_MAX + 1)
+                       return -EPROTO;
+               /* First byte of data is in SMBHSTDAT0, not a count */
+               data->block[1] = inb_p(SMBHSTDAT0);
+               inb_p(SMBHSTCNT);       /* Reset SMBBLKDAT */
+               /* Read remaining bytes from SMBBLKDAT */
+               for (i = 2; i <= len; i++)
+                       data->block[i] = inb_p(SMBBLKDAT);
+               break;
        }
        return 0;
 }
@@ -819,7 +853,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
         * Therefore we need to request the ownership flag during those
         * transactions.
         */
-       if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) {
+       if ((size == I2C_SMBUS_BLOCK_DATA ||
+            size == I2C_SMBUS_I2C_BLOCK_DATA) &&
+           adapdata->notify_imc) {
                int ret;

                ret = piix4_imc_sleep();
@@ -855,7 +891,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr,
        /* Release the semaphore */
        outb_p(smbslvcnt | 0x20, SMBSLVCNT);

-       if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc)
+       if ((size == I2C_SMBUS_BLOCK_DATA ||
+            size == I2C_SMBUS_I2C_BLOCK_DATA) &&
+           adapdata->notify_imc)
                piix4_imc_wakeup();

 release:
@@ -867,7 +905,7 @@ static u32 piix4_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
-           I2C_FUNC_SMBUS_BLOCK_DATA;
+           I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;
 }

 static const struct i2c_algorithm smbus_algorithm = {
diff --git a/drivers/i2c/busses/i2c-piix4.h b/drivers/i2c/busses/i2c-piix4.h
index 36bc6ce82a27..6311af3ca661 100644
--- a/drivers/i2c/busses/i2c-piix4.h
+++ b/drivers/i2c/busses/i2c-piix4.h
@@ -29,7 +29,8 @@
 #define SMBSLVDAT      (0x0C + piix4_smba)

 /* PIIX4 constants */
-#define PIIX4_BLOCK_DATA       0x14
+#define PIIX4_BLOCK_DATA               0x14
+#define PIIX4_I2C_BLOCK_DATA   0x18

 struct sb800_mmio_cfg {
        void __iomem *addr;
--
2.35.6



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ