public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v12 0/3] i2c: octeon: add block-mode r/w
@ 2025-03-11  2:34 Aryan Srivastava
  2025-03-11  2:34 ` [PATCH v12 1/3] i2c: octeon: fix return commenting Aryan Srivastava
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Aryan Srivastava @ 2025-03-11  2:34 UTC (permalink / raw)
  To: Andi Shyti, Andy Shevchenko, Markus Elfring
  Cc: linux-i2c, linux-kernel, Aryan Srivastava

Add support for block mode read/write operations on
Thunderx chips.

-Refactor common code for i2c transactions (merged in v11).
-Correct function docs.
-Remove 10-bit addressing considerations.
-Add block mode transaction functionality.

Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
---
Changes in v2:
- comment style and formatting.

Changes in v3:
- comment style and formatting.

Changes in v4:
- Refactoring common code.
- Additional comments.

Changes in v5:
- Further refactoring.
- Split refactoring into separate patch in series.
- Add more comments + details to comments.

Changes in v6:
- Reword/reformat commit messages

Changes in v7:
- Fix typo in commit message.
- Remove usage of r/w and hlc abbreviations from commits.

Changes in v8:
- Updated refactor commit msg with more information.
- Rebased patch

Changes in v9:
- Rebased patch against i2c-host

Changes in v10:
- Fixed unitialised variable

Changes in v11:
- Rebased patch against i2c-host

Changes in v12:
- Added fixes for function docs
- Removed considerations for 10-bit addressing
- Transition to using appropriate byte-swap operations, instead of custom code
- Refactor commit removed from this set, merged in:
  https://lore.kernel.org/linux-i2c/seom4yspcjnmdxxwn6wuyiqdy2ywpna6nw4rn36tsqinlncbca@jdehzfnznlsg/

Aryan Srivastava (3):
  i2c: octeon: fix return commenting
  i2c: octeon: remove 10-bit addressing support
  i2c: octeon: add block-mode i2c operations

 drivers/i2c/busses/i2c-octeon-core.c     | 195 +++++++++++++++++++----
 drivers/i2c/busses/i2c-octeon-core.h     |  13 +-
 drivers/i2c/busses/i2c-thunderx-pcidrv.c |   3 +
 3 files changed, 179 insertions(+), 32 deletions(-)

-- 
2.47.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v12 1/3] i2c: octeon: fix return commenting
  2025-03-11  2:34 [PATCH v12 0/3] i2c: octeon: add block-mode r/w Aryan Srivastava
@ 2025-03-11  2:34 ` Aryan Srivastava
  2025-03-19  0:13   ` Andi Shyti
  2025-03-11  2:34 ` [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support Aryan Srivastava
  2025-03-11  2:34 ` [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations Aryan Srivastava
  2 siblings, 1 reply; 8+ messages in thread
From: Aryan Srivastava @ 2025-03-11  2:34 UTC (permalink / raw)
  To: Andi Shyti, Andy Shevchenko, Markus Elfring
  Cc: linux-i2c, linux-kernel, Aryan Srivastava, Robert Richter

Kernel-docs require a ':' to signify the return behaviour of a function
with within the comment. Many functions in this file were missing ':'
after the "Returns" line, resulting in kernel-doc warnings.

Add the ':' to satisfy kernel-doc requirements.

Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
---
 drivers/i2c/busses/i2c-octeon-core.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
index 3fbc828508ab..0094fe5f7460 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -45,7 +45,7 @@ static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c)
  * octeon_i2c_wait - wait for the IFLG to be set
  * @i2c: The struct octeon_i2c
  *
- * Returns 0 on success, otherwise a negative errno.
+ * Returns: 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
@@ -139,7 +139,7 @@ static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
  * octeon_i2c_hlc_wait - wait for an HLC operation to complete
  * @i2c: The struct octeon_i2c
  *
- * Returns 0 on success, otherwise -ETIMEDOUT.
+ * Returns: 0 on success, otherwise -ETIMEDOUT.
  */
 static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
@@ -273,7 +273,7 @@ static int octeon_i2c_recovery(struct octeon_i2c *i2c)
  * octeon_i2c_start - send START to the bus
  * @i2c: The struct octeon_i2c
  *
- * Returns 0 on success, otherwise a negative errno.
+ * Returns: 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_start(struct octeon_i2c *i2c)
 {
@@ -314,7 +314,7 @@ static void octeon_i2c_stop(struct octeon_i2c *i2c)
  *
  * The address is sent over the bus, then the data is read.
  *
- * Returns 0 on success, otherwise a negative errno.
+ * Returns: 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 			   u8 *data, u16 *rlength, bool recv_len)
@@ -382,7 +382,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
  *
  * The address is sent over the bus, then the data.
  *
- * Returns 0 on success, otherwise a negative errno.
+ * Returns: 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_write(struct octeon_i2c *i2c, int target,
 			    const u8 *data, int length)
@@ -625,7 +625,7 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg
  * @msgs: Pointer to the messages to be processed
  * @num: Length of the MSGS array
  *
- * Returns the number of messages processed, or a negative errno on failure.
+ * Returns: the number of messages processed, or a negative errno on failure.
  */
 int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support
  2025-03-11  2:34 [PATCH v12 0/3] i2c: octeon: add block-mode r/w Aryan Srivastava
  2025-03-11  2:34 ` [PATCH v12 1/3] i2c: octeon: fix return commenting Aryan Srivastava
@ 2025-03-11  2:34 ` Aryan Srivastava
  2025-03-19  0:11   ` Andi Shyti
  2025-03-11  2:34 ` [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations Aryan Srivastava
  2 siblings, 1 reply; 8+ messages in thread
From: Aryan Srivastava @ 2025-03-11  2:34 UTC (permalink / raw)
  To: Andi Shyti, Andy Shevchenko, Markus Elfring
  Cc: linux-i2c, linux-kernel, Aryan Srivastava, Robert Richter

The driver gives the illusion of 10-bit address support, but the upper
3 bits of the given address are always thrown away. Remove unnecessary
considerations for 10 bit addressing and always complete 7 bit ops when
using the hlc methods.

Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
---
 drivers/i2c/busses/i2c-octeon-core.c | 23 ++++-------------------
 1 file changed, 4 insertions(+), 19 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
index 0094fe5f7460..baf6b27f3752 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -421,17 +421,12 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
 	octeon_i2c_hlc_enable(i2c);
 	octeon_i2c_hlc_int_clear(i2c);
 
-	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7;
 	/* SIZE */
 	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
 	/* A */
 	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
 
-	if (msgs[0].flags & I2C_M_TEN)
-		cmd |= SW_TWSI_OP_10;
-	else
-		cmd |= SW_TWSI_OP_7;
-
 	octeon_i2c_writeq_flush(cmd, i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
 	ret = octeon_i2c_hlc_wait(i2c);
 	if (ret)
@@ -463,17 +458,12 @@ static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
 	octeon_i2c_hlc_enable(i2c);
 	octeon_i2c_hlc_int_clear(i2c);
 
-	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7;
 	/* SIZE */
 	cmd |= (u64)(msgs[0].len - 1) << SW_TWSI_SIZE_SHIFT;
 	/* A */
 	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
 
-	if (msgs[0].flags & I2C_M_TEN)
-		cmd |= SW_TWSI_OP_10;
-	else
-		cmd |= SW_TWSI_OP_7;
-
 	for (i = 0, j = msgs[0].len - 1; i  < msgs[0].len && i < 4; i++, j--)
 		cmd |= (u64)msgs[0].buf[j] << (8 * i);
 
@@ -513,11 +503,6 @@ static bool octeon_i2c_hlc_ext(struct octeon_i2c *i2c, struct i2c_msg msg, u64 *
 	bool set_ext = false;
 	u64 cmd = 0;
 
-	if (msg.flags & I2C_M_TEN)
-		cmd |= SW_TWSI_OP_10_IA;
-	else
-		cmd |= SW_TWSI_OP_7_IA;
-
 	if (msg.len == 2) {
 		cmd |= SW_TWSI_EIA;
 		*ext = (u64)msg.buf[0] << SW_TWSI_IA_SHIFT;
@@ -550,7 +535,7 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs
 
 	octeon_i2c_hlc_enable(i2c);
 
-	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR;
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
 	/* SIZE */
 	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
 	/* A */
@@ -587,7 +572,7 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg
 
 	octeon_i2c_hlc_enable(i2c);
 
-	cmd = SW_TWSI_V | SW_TWSI_SOVR;
+	cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
 	/* SIZE */
 	cmd |= (u64)(msgs[1].len - 1) << SW_TWSI_SIZE_SHIFT;
 	/* A */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations
  2025-03-11  2:34 [PATCH v12 0/3] i2c: octeon: add block-mode r/w Aryan Srivastava
  2025-03-11  2:34 ` [PATCH v12 1/3] i2c: octeon: fix return commenting Aryan Srivastava
  2025-03-11  2:34 ` [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support Aryan Srivastava
@ 2025-03-11  2:34 ` Aryan Srivastava
  2025-03-11 19:45   ` Andy Shevchenko
  2025-03-12 23:12   ` kernel test robot
  2 siblings, 2 replies; 8+ messages in thread
From: Aryan Srivastava @ 2025-03-11  2:34 UTC (permalink / raw)
  To: Andi Shyti, Andy Shevchenko, Markus Elfring
  Cc: linux-i2c, linux-kernel, Aryan Srivastava, Robert Richter

Add functions to perform block read and write operations. This applies
for cases where the requested operation is for >8 bytes of data.

When not using the block mode transfer, the driver will attempt a series
of 8 byte i2c operations until it reaches the desired total. For
example, for a 40 byte request the driver will complete 5 separate
transactions. This results in large transactions taking a significant
amount of time to process.

Add block mode such that the driver can request larger transactions, up
to 1024 bytes per transfer.

Many aspects of the block mode transfer is common with the regular 8
byte operations. Use generic functions for parts of the message
construction and sending the message. The key difference for the block
mode is the usage of separate FIFO buffer to store data.

Write to this buffer in the case of a write (before command send).
Read from this buffer in the case of a read (after command send).

Data is written into this buffer by placing data into the MSB onwards.
This means the bottom 8 bits of the data will match the top 8 bits, and
so on and so forth.

Set specific bits in message for block mode, enable block mode transfers
from global i2c management registers, construct message, send message,
read or write from FIFO buffer as required.

The block-mode transactions result in a significant speed increase in
large i2c requests.

Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>
---
 drivers/i2c/busses/i2c-octeon-core.c     | 160 ++++++++++++++++++++++-
 drivers/i2c/busses/i2c-octeon-core.h     |  13 +-
 drivers/i2c/busses/i2c-thunderx-pcidrv.c |   3 +
 3 files changed, 169 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c
index baf6b27f3752..e92935d61b67 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -135,6 +135,32 @@ static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
 	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 }
 
+static void octeon_i2c_block_enable(struct octeon_i2c *i2c)
+{
+	u64 mode;
+
+	if (i2c->block_enabled || !OCTEON_REG_BLOCK_CTL(i2c))
+		return;
+
+	i2c->block_enabled = true;
+	mode = __raw_readq(i2c->twsi_base + OCTEON_REG_MODE(i2c));
+	mode |= TWSX_MODE_BLOCK_MODE;
+	octeon_i2c_writeq_flush(mode, i2c->twsi_base + OCTEON_REG_MODE(i2c));
+}
+
+static void octeon_i2c_block_disable(struct octeon_i2c *i2c)
+{
+	u64 mode;
+
+	if (!i2c->block_enabled || !OCTEON_REG_BLOCK_CTL(i2c))
+		return;
+
+	i2c->block_enabled = false;
+	mode = __raw_readq(i2c->twsi_base + OCTEON_REG_MODE(i2c));
+	mode &= ~TWSX_MODE_BLOCK_MODE;
+	octeon_i2c_writeq_flush(mode, i2c->twsi_base + OCTEON_REG_MODE(i2c));
+}
+
 /**
  * octeon_i2c_hlc_wait - wait for an HLC operation to complete
  * @i2c: The struct octeon_i2c
@@ -281,6 +307,7 @@ static int octeon_i2c_start(struct octeon_i2c *i2c)
 	u8 stat;
 
 	octeon_i2c_hlc_disable(i2c);
+	octeon_i2c_block_disable(i2c);
 
 	octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB | TWSI_CTL_STA);
 	ret = octeon_i2c_wait(i2c);
@@ -604,6 +631,119 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msg
 	return ret;
 }
 
+/**
+ * octeon_i2c_hlc_block_comp_read - high-level-controller composite block read
+ * @i2c: The struct octeon_i2c
+ * @msgs: msg[0] contains address, place read data into msg[1]
+ *
+ * i2c core command is constructed and written into the SW_TWSI register.
+ * The execution of the command will result in requested data being
+ * placed into a FIFO buffer, ready to be read.
+ * Used in the case where the i2c xfer is for greater than 8 bytes of read data.
+ *
+ * Returns: 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_hlc_block_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	int ret = 0;
+	u16 len;
+	u64 cmd;
+
+	octeon_i2c_hlc_enable(i2c);
+	octeon_i2c_block_enable(i2c);
+
+	/* Write (size - 1) into block control register */
+	len = msgs[1].len - 1;
+	octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));
+
+	/* Prepare core command */
+	cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	/* Send core command */
+	ret = octeon_i2c_hlc_read_cmd(i2c, msgs[0], cmd);
+	if (ret)
+		return ret;
+
+	cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
+	if ((cmd & SW_TWSI_R) == 0)
+		return octeon_i2c_check_status(i2c, false);
+
+	/* read data in FIFO */
+	octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
+				i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
+	for (u16 i = 0; i <= len; i += 8) {
+		/* Byte-swap FIFO data and copy into msg buffer */
+		u64 rd = cpu_to_be64(__raw_readq(i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c)));
+
+		memcpy(&msgs[1].buf[i], &rd, MIN_T(u16, 8, msgs[1].len - i));
+	}
+
+	octeon_i2c_block_disable(i2c);
+	return ret;
+}
+
+/**
+ * octeon_i2c_hlc_block_comp_write - high-level-controller composite block write
+ * @i2c: The struct octeon_i2c
+ * @msgs: msg[0] contains address, msg[1] contains data to be written
+ *
+ * i2c core command is constructed and write data is written into the FIFO buffer.
+ * The execution of the command will result in HW write, using the data in FIFO.
+ * Used in the case where the i2c xfer is for greater than 8 bytes of write data.
+ *
+ * Returns: 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_hlc_block_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
+{
+	bool set_ext = false;
+	int ret = 0;
+	u16 len;
+	u64 cmd, ext = 0;
+
+	octeon_i2c_hlc_enable(i2c);
+	octeon_i2c_block_enable(i2c);
+
+	/* Write (size - 1) into block control register */
+	len = msgs[1].len - 1;
+	octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));
+
+	/* Prepare core command */
+	cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
+	cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
+
+	/* Set parameters for extended message (if required) */
+	set_ext = octeon_i2c_hlc_ext(i2c, msgs[0], &cmd, &ext);
+
+	/* Write msg into FIFO buffer */
+	octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
+				i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
+	for (u16 i = 0; i <= len; i += 8) {
+		u64 buf = 0;
+
+		/* Copy 8 bytes or remaining bytes from message buffer */
+		memcpy(&buf, &msgs[1].buf[i], MIN_T(u16, 8, msgs[1].len - i));
+
+		/* Byte-swap message data and write into FIFO */
+		buf = cpu_to_be64(buf);
+		octeon_i2c_writeq_flush(buf, i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c));
+	}
+	if (set_ext)
+		octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c));
+
+	/* Send command to core (send data in FIFO) */
+	ret = octeon_i2c_hlc_cmd_send(i2c, cmd);
+	if (ret)
+		return ret;
+
+	cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
+	if ((cmd & SW_TWSI_R) == 0)
+		return octeon_i2c_check_status(i2c, false);
+
+	octeon_i2c_block_disable(i2c);
+	return ret;
+}
+
 /**
  * octeon_i2c_xfer - The driver's xfer function
  * @adap: Pointer to the i2c_adapter structure
@@ -630,13 +770,21 @@ int octeon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 			if ((msgs[0].flags & I2C_M_RD) == 0 &&
 			    (msgs[1].flags & I2C_M_RECV_LEN) == 0 &&
 			    msgs[0].len > 0 && msgs[0].len <= 2 &&
-			    msgs[1].len > 0 && msgs[1].len <= 8 &&
+			    msgs[1].len > 0 &&
 			    msgs[0].addr == msgs[1].addr) {
-				if (msgs[1].flags & I2C_M_RD)
-					ret = octeon_i2c_hlc_comp_read(i2c, msgs);
-				else
-					ret = octeon_i2c_hlc_comp_write(i2c, msgs);
-				goto out;
+				if (msgs[1].len <= 8) {
+					if (msgs[1].flags & I2C_M_RD)
+						ret = octeon_i2c_hlc_comp_read(i2c, msgs);
+					else
+						ret = octeon_i2c_hlc_comp_write(i2c, msgs);
+					goto out;
+				} else if (msgs[1].len <= 1024 && OCTEON_REG_BLOCK_CTL(i2c)) {
+					if (msgs[1].flags & I2C_M_RD)
+						ret = octeon_i2c_hlc_block_comp_read(i2c, msgs);
+					else
+						ret = octeon_i2c_hlc_block_comp_write(i2c, msgs);
+					goto out;
+				}
 			}
 		}
 	}
diff --git a/drivers/i2c/busses/i2c-octeon-core.h b/drivers/i2c/busses/i2c-octeon-core.h
index b265e21189a1..fecaf7388182 100644
--- a/drivers/i2c/busses/i2c-octeon-core.h
+++ b/drivers/i2c/busses/i2c-octeon-core.h
@@ -96,18 +96,28 @@ struct octeon_i2c_reg_offset {
 	unsigned int twsi_int;
 	unsigned int sw_twsi_ext;
 	unsigned int mode;
+	unsigned int block_ctl;
+	unsigned int block_sts;
+	unsigned int block_fifo;
 };
 
 #define OCTEON_REG_SW_TWSI(x)		((x)->roff.sw_twsi)
 #define OCTEON_REG_TWSI_INT(x)		((x)->roff.twsi_int)
 #define OCTEON_REG_SW_TWSI_EXT(x)	((x)->roff.sw_twsi_ext)
 #define OCTEON_REG_MODE(x)		((x)->roff.mode)
+#define OCTEON_REG_BLOCK_CTL(x)	(x->roff.block_ctl)
+#define OCTEON_REG_BLOCK_STS(x)	(x->roff.block_sts)
+#define OCTEON_REG_BLOCK_FIFO(x)	(x->roff.block_fifo)
 
-/* Set REFCLK_SRC and HS_MODE in TWSX_MODE register */
+/* TWSX_MODE register */
 #define TWSX_MODE_REFCLK_SRC	BIT(4)
+#define TWSX_MODE_BLOCK_MODE	BIT(2)
 #define TWSX_MODE_HS_MODE	BIT(0)
 #define TWSX_MODE_HS_MASK	(TWSX_MODE_REFCLK_SRC | TWSX_MODE_HS_MODE)
 
+/* TWSX_BLOCK_STS register */
+#define TWSX_BLOCK_STS_RESET_PTR	BIT(0)
+
 /* Set BUS_MON_RST to reset bus monitor */
 #define BUS_MON_RST_MASK	BIT(3)
 
@@ -123,6 +133,7 @@ struct octeon_i2c {
 	void __iomem *twsi_base;
 	struct device *dev;
 	bool hlc_enabled;
+	bool block_enabled;
 	bool broken_irq_mode;
 	bool broken_irq_check;
 	void (*int_enable)(struct octeon_i2c *);
diff --git a/drivers/i2c/busses/i2c-thunderx-pcidrv.c b/drivers/i2c/busses/i2c-thunderx-pcidrv.c
index 143d012fa43e..0dc08cd97e8a 100644
--- a/drivers/i2c/busses/i2c-thunderx-pcidrv.c
+++ b/drivers/i2c/busses/i2c-thunderx-pcidrv.c
@@ -168,6 +168,9 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
 	i2c->roff.twsi_int = 0x1010;
 	i2c->roff.sw_twsi_ext = 0x1018;
 	i2c->roff.mode = 0x1038;
+	i2c->roff.block_ctl = 0x1048;
+	i2c->roff.block_sts = 0x1050;
+	i2c->roff.block_fifo = 0x1058;
 
 	i2c->dev = dev;
 	pci_set_drvdata(pdev, i2c);
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations
  2025-03-11  2:34 ` [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations Aryan Srivastava
@ 2025-03-11 19:45   ` Andy Shevchenko
  2025-03-12 23:12   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: Andy Shevchenko @ 2025-03-11 19:45 UTC (permalink / raw)
  To: Aryan Srivastava
  Cc: Andi Shyti, Markus Elfring, linux-i2c, linux-kernel,
	Robert Richter

On Tue, Mar 11, 2025 at 4:34 AM Aryan Srivastava
<aryan.srivastava@alliedtelesis.co.nz> wrote:
>
> Add functions to perform block read and write operations. This applies
> for cases where the requested operation is for >8 bytes of data.
>
> When not using the block mode transfer, the driver will attempt a series
> of 8 byte i2c operations until it reaches the desired total. For
> example, for a 40 byte request the driver will complete 5 separate
> transactions. This results in large transactions taking a significant
> amount of time to process.
>
> Add block mode such that the driver can request larger transactions, up
> to 1024 bytes per transfer.
>
> Many aspects of the block mode transfer is common with the regular 8
> byte operations. Use generic functions for parts of the message
> construction and sending the message. The key difference for the block
> mode is the usage of separate FIFO buffer to store data.
>
> Write to this buffer in the case of a write (before command send).
> Read from this buffer in the case of a read (after command send).
>
> Data is written into this buffer by placing data into the MSB onwards.
> This means the bottom 8 bits of the data will match the top 8 bits, and
> so on and so forth.
>
> Set specific bits in message for block mode, enable block mode transfers
> from global i2c management registers, construct message, send message,
> read or write from FIFO buffer as required.
>
> The block-mode transactions result in a significant speed increase in
> large i2c requests.

...

> +static int octeon_i2c_hlc_block_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
> +{

> +       int ret = 0;

Why the useless assignment?

> +       u16 len;
> +       u64 cmd;
> +
> +       octeon_i2c_hlc_enable(i2c);
> +       octeon_i2c_block_enable(i2c);
> +
> +       /* Write (size - 1) into block control register */
> +       len = msgs[1].len - 1;
> +       octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));

Why explicit casting? (And no need to have parentheses for simple
cases like this)

> +       /* Prepare core command */
> +       cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
> +       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
> +
> +       /* Send core command */
> +       ret = octeon_i2c_hlc_read_cmd(i2c, msgs[0], cmd);
> +       if (ret)
> +               return ret;
> +
> +       cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
> +       if ((cmd & SW_TWSI_R) == 0)
> +               return octeon_i2c_check_status(i2c, false);
> +
> +       /* read data in FIFO */
> +       octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
> +                               i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
> +       for (u16 i = 0; i <= len; i += 8) {
> +               /* Byte-swap FIFO data and copy into msg buffer */
> +               u64 rd = cpu_to_be64(__raw_readq(i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c)));
> +
> +               memcpy(&msgs[1].buf[i], &rd, MIN_T(u16, 8, msgs[1].len - i));

Why MIN_T()?! umin() or min() should work.

> +       }
> +
> +       octeon_i2c_block_disable(i2c);
> +       return ret;
> +}

...

> +static int octeon_i2c_hlc_block_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
> +{

Same comments as per above.

> +       bool set_ext = false;
> +       int ret = 0;

Why do you need these assignments? What for?

> +       u16 len;
> +       u64 cmd, ext = 0;
> +
> +       octeon_i2c_hlc_enable(i2c);
> +       octeon_i2c_block_enable(i2c);
> +
> +       /* Write (size - 1) into block control register */
> +       len = msgs[1].len - 1;
> +       octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));
> +
> +       /* Prepare core command */
> +       cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
> +       cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
> +
> +       /* Set parameters for extended message (if required) */
> +       set_ext = octeon_i2c_hlc_ext(i2c, msgs[0], &cmd, &ext);
> +
> +       /* Write msg into FIFO buffer */
> +       octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
> +                               i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
> +       for (u16 i = 0; i <= len; i += 8) {
> +               u64 buf = 0;
> +
> +               /* Copy 8 bytes or remaining bytes from message buffer */
> +               memcpy(&buf, &msgs[1].buf[i], MIN_T(u16, 8, msgs[1].len - i));
> +
> +               /* Byte-swap message data and write into FIFO */
> +               buf = cpu_to_be64(buf);
> +               octeon_i2c_writeq_flush(buf, i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c));
> +       }
> +       if (set_ext)
> +               octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c));
> +
> +       /* Send command to core (send data in FIFO) */
> +       ret = octeon_i2c_hlc_cmd_send(i2c, cmd);
> +       if (ret)
> +               return ret;
> +
> +       cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
> +       if ((cmd & SW_TWSI_R) == 0)
> +               return octeon_i2c_check_status(i2c, false);
> +
> +       octeon_i2c_block_disable(i2c);
> +       return ret;
> +}

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations
  2025-03-11  2:34 ` [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations Aryan Srivastava
  2025-03-11 19:45   ` Andy Shevchenko
@ 2025-03-12 23:12   ` kernel test robot
  1 sibling, 0 replies; 8+ messages in thread
From: kernel test robot @ 2025-03-12 23:12 UTC (permalink / raw)
  To: Aryan Srivastava, Andi Shyti, Andy Shevchenko, Markus Elfring
  Cc: oe-kbuild-all, linux-i2c, linux-kernel, Aryan Srivastava,
	Robert Richter

Hi Aryan,

kernel test robot noticed the following build warnings:

[auto build test WARNING on andi-shyti/i2c/i2c-host]
[also build test WARNING on next-20250312]
[cannot apply to linus/master v6.14-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Aryan-Srivastava/i2c-octeon-fix-return-commenting/20250311-103714
base:   https://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git i2c/i2c-host
patch link:    https://lore.kernel.org/r/20250311023435.3962466-4-aryan.srivastava%40alliedtelesis.co.nz
patch subject: [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations
config: alpha-randconfig-r132-20250312 (https://download.01.org/0day-ci/archive/20250313/202503130610.rUb3f7P4-lkp@intel.com/config)
compiler: alpha-linux-gcc (GCC) 14.2.0
reproduce: (https://download.01.org/0day-ci/archive/20250313/202503130610.rUb3f7P4-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202503130610.rUb3f7P4-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/i2c/busses/i2c-octeon-core.c:677:26: sparse: sparse: incorrect type in initializer (different base types) @@     expected unsigned long long [usertype] rd @@     got restricted __be64 [usertype] @@
   drivers/i2c/busses/i2c-octeon-core.c:677:26: sparse:     expected unsigned long long [usertype] rd
   drivers/i2c/busses/i2c-octeon-core.c:677:26: sparse:     got restricted __be64 [usertype]
>> drivers/i2c/busses/i2c-octeon-core.c:728:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned long long [addressable] [usertype] buf @@     got restricted __be64 [usertype] @@
   drivers/i2c/busses/i2c-octeon-core.c:728:21: sparse:     expected unsigned long long [addressable] [usertype] buf
   drivers/i2c/busses/i2c-octeon-core.c:728:21: sparse:     got restricted __be64 [usertype]

vim +677 drivers/i2c/busses/i2c-octeon-core.c

   633	
   634	/**
   635	 * octeon_i2c_hlc_block_comp_read - high-level-controller composite block read
   636	 * @i2c: The struct octeon_i2c
   637	 * @msgs: msg[0] contains address, place read data into msg[1]
   638	 *
   639	 * i2c core command is constructed and written into the SW_TWSI register.
   640	 * The execution of the command will result in requested data being
   641	 * placed into a FIFO buffer, ready to be read.
   642	 * Used in the case where the i2c xfer is for greater than 8 bytes of read data.
   643	 *
   644	 * Returns: 0 on success, otherwise a negative errno.
   645	 */
   646	static int octeon_i2c_hlc_block_comp_read(struct octeon_i2c *i2c, struct i2c_msg *msgs)
   647	{
   648		int ret = 0;
   649		u16 len;
   650		u64 cmd;
   651	
   652		octeon_i2c_hlc_enable(i2c);
   653		octeon_i2c_block_enable(i2c);
   654	
   655		/* Write (size - 1) into block control register */
   656		len = msgs[1].len - 1;
   657		octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));
   658	
   659		/* Prepare core command */
   660		cmd = SW_TWSI_V | SW_TWSI_R | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
   661		cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
   662	
   663		/* Send core command */
   664		ret = octeon_i2c_hlc_read_cmd(i2c, msgs[0], cmd);
   665		if (ret)
   666			return ret;
   667	
   668		cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
   669		if ((cmd & SW_TWSI_R) == 0)
   670			return octeon_i2c_check_status(i2c, false);
   671	
   672		/* read data in FIFO */
   673		octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
   674					i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
   675		for (u16 i = 0; i <= len; i += 8) {
   676			/* Byte-swap FIFO data and copy into msg buffer */
 > 677			u64 rd = cpu_to_be64(__raw_readq(i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c)));
   678	
   679			memcpy(&msgs[1].buf[i], &rd, MIN_T(u16, 8, msgs[1].len - i));
   680		}
   681	
   682		octeon_i2c_block_disable(i2c);
   683		return ret;
   684	}
   685	
   686	/**
   687	 * octeon_i2c_hlc_block_comp_write - high-level-controller composite block write
   688	 * @i2c: The struct octeon_i2c
   689	 * @msgs: msg[0] contains address, msg[1] contains data to be written
   690	 *
   691	 * i2c core command is constructed and write data is written into the FIFO buffer.
   692	 * The execution of the command will result in HW write, using the data in FIFO.
   693	 * Used in the case where the i2c xfer is for greater than 8 bytes of write data.
   694	 *
   695	 * Returns: 0 on success, otherwise a negative errno.
   696	 */
   697	static int octeon_i2c_hlc_block_comp_write(struct octeon_i2c *i2c, struct i2c_msg *msgs)
   698	{
   699		bool set_ext = false;
   700		int ret = 0;
   701		u16 len;
   702		u64 cmd, ext = 0;
   703	
   704		octeon_i2c_hlc_enable(i2c);
   705		octeon_i2c_block_enable(i2c);
   706	
   707		/* Write (size - 1) into block control register */
   708		len = msgs[1].len - 1;
   709		octeon_i2c_writeq_flush((u64)(len), i2c->twsi_base + OCTEON_REG_BLOCK_CTL(i2c));
   710	
   711		/* Prepare core command */
   712		cmd = SW_TWSI_V | SW_TWSI_SOVR | SW_TWSI_OP_7_IA;
   713		cmd |= (u64)(msgs[0].addr & 0x7full) << SW_TWSI_ADDR_SHIFT;
   714	
   715		/* Set parameters for extended message (if required) */
   716		set_ext = octeon_i2c_hlc_ext(i2c, msgs[0], &cmd, &ext);
   717	
   718		/* Write msg into FIFO buffer */
   719		octeon_i2c_writeq_flush(TWSX_BLOCK_STS_RESET_PTR,
   720					i2c->twsi_base + OCTEON_REG_BLOCK_STS(i2c));
   721		for (u16 i = 0; i <= len; i += 8) {
   722			u64 buf = 0;
   723	
   724			/* Copy 8 bytes or remaining bytes from message buffer */
   725			memcpy(&buf, &msgs[1].buf[i], MIN_T(u16, 8, msgs[1].len - i));
   726	
   727			/* Byte-swap message data and write into FIFO */
 > 728			buf = cpu_to_be64(buf);
   729			octeon_i2c_writeq_flush(buf, i2c->twsi_base + OCTEON_REG_BLOCK_FIFO(i2c));
   730		}
   731		if (set_ext)
   732			octeon_i2c_writeq_flush(ext, i2c->twsi_base + OCTEON_REG_SW_TWSI_EXT(i2c));
   733	
   734		/* Send command to core (send data in FIFO) */
   735		ret = octeon_i2c_hlc_cmd_send(i2c, cmd);
   736		if (ret)
   737			return ret;
   738	
   739		cmd = __raw_readq(i2c->twsi_base + OCTEON_REG_SW_TWSI(i2c));
   740		if ((cmd & SW_TWSI_R) == 0)
   741			return octeon_i2c_check_status(i2c, false);
   742	
   743		octeon_i2c_block_disable(i2c);
   744		return ret;
   745	}
   746	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support
  2025-03-11  2:34 ` [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support Aryan Srivastava
@ 2025-03-19  0:11   ` Andi Shyti
  0 siblings, 0 replies; 8+ messages in thread
From: Andi Shyti @ 2025-03-19  0:11 UTC (permalink / raw)
  To: Aryan Srivastava
  Cc: Andy Shevchenko, Markus Elfring, linux-i2c, linux-kernel,
	Robert Richter

Hi Aryan,

On Tue, Mar 11, 2025 at 03:34:33PM +1300, Aryan Srivastava wrote:
> The driver gives the illusion of 10-bit address support, but the upper
> 3 bits of the given address are always thrown away. Remove unnecessary
> considerations for 10 bit addressing and always complete 7 bit ops when
> using the hlc methods.

Can someone from Marvell comment here?

The datasheet I have isn't very clear on this part. Also, I'd
like to know if there's any product line that could be negatively
impacted by this patch.

Andi

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v12 1/3] i2c: octeon: fix return commenting
  2025-03-11  2:34 ` [PATCH v12 1/3] i2c: octeon: fix return commenting Aryan Srivastava
@ 2025-03-19  0:13   ` Andi Shyti
  0 siblings, 0 replies; 8+ messages in thread
From: Andi Shyti @ 2025-03-19  0:13 UTC (permalink / raw)
  To: Aryan Srivastava
  Cc: Andy Shevchenko, Markus Elfring, linux-i2c, linux-kernel,
	Robert Richter

Hi Aryan,

On Tue, Mar 11, 2025 at 03:34:32PM +1300, Aryan Srivastava wrote:
> Kernel-docs require a ':' to signify the return behaviour of a function
> with within the comment. Many functions in this file were missing ':'
> after the "Returns" line, resulting in kernel-doc warnings.
> 
> Add the ':' to satisfy kernel-doc requirements.
> 
> Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz>

I merged just this patch in i2c/i2c-host.

Thanks,
Andi

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-03-19  0:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-11  2:34 [PATCH v12 0/3] i2c: octeon: add block-mode r/w Aryan Srivastava
2025-03-11  2:34 ` [PATCH v12 1/3] i2c: octeon: fix return commenting Aryan Srivastava
2025-03-19  0:13   ` Andi Shyti
2025-03-11  2:34 ` [PATCH v12 2/3] i2c: octeon: remove 10-bit addressing support Aryan Srivastava
2025-03-19  0:11   ` Andi Shyti
2025-03-11  2:34 ` [PATCH v12 3/3] i2c: octeon: add block-mode i2c operations Aryan Srivastava
2025-03-11 19:45   ` Andy Shevchenko
2025-03-12 23:12   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox