Skip to contentSkip to conversation

i2c: improve RECV_LEN documentation & usage

PATCH Applied Wolfram Sang 2 participants 12 messages Jan 9, 2021 – Jan 22, 2021

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover i2c: improve RECV_LEN documentation & usage

Because I want to clarify I2C_M_RECV len usage, this series updates the documentation and some of its users. Patch 1 refactors the whole documentation of 'i2c_msg', so all usage of I2C_M_* flags and their conditions hopefully become clearer. Patch 2+3 remove some obvious boilerplate in the UAPI headers while here. Patch 4 is a driver fix I found while working on this series. Patch 5 introduces a new convenience macro to enable SMBus transfers which need I2C_M_RECV_LEN. Then, some drivers use the new macro, sometimes to remove boilerplate, sometimes because these SMBus transfers have been forgotten before.

This series is the first part of a larger work to extend I2C_M_RECV_LEN to allow larger transfer sizes (as specified in the SMBus 3.0 standard) and to enable this on Renesas R-Car hardware.

Looking forward to comments and/or reviews; the driver patches are only build-tested.

Happy hacking,

Wolfram

Wolfram Sang (8):
i2c: refactor documentation of struct i2c_msg
i2c: remove licence boilerplate from main UAPI header
i2c: remove licence boilerplate from i2c-dev UAPI header
i2c: octeon: check correct size of maximum RECV_LEN packet
i2c: uapi: add macro to describe support for all SMBus transfers
i2c: algo: bit: use new macro to specifiy capabilities
i2c: qup: advertise SMBus transfers using RECV_LEN
i2c: s3c2410: advertise SMBus transfers using RECV_LEN

 drivers/i2c/algos/i2c-algo-bit.c     |   4 +-
 drivers/i2c/busses/i2c-octeon-core.c |   2 +-
 drivers/i2c/busses/i2c-qup.c         |   2 +-
 drivers/i2c/busses/i2c-s3c2410.c     |   2 +-
 include/uapi/linux/i2c-dev.h         |  25 ++----
 include/uapi/linux/i2c.h             | 128 ++++++++++++++-------------
 6 files changed, 76 insertions(+), 87 deletions(-)
Signature · 1 line
2.29.2
#1 lore raw

PATCH 1/8 i2c: refactor documentation of struct i2c_msg

The information about 'i2c_msg' was spread between kdoc and comments. Move all the explanations to kdoc and duplicate only the requirements for the flags in the comments. Also, add some redundancy and fix some typos while here.

---
 include/uapi/linux/i2c.h | 91 ++++++++++++++++++++++++----------------
 1 file changed, 55 insertions(+), 36 deletions(-)
include/uapi/linux/i2c.h +55 -36
index f71a1751cacf..8d2f59f53324 100644
@@ -32,18 +32,41 @@
 
 /**
  * struct i2c_msg - an I2C transaction segment beginning with START
- * @addr: Slave address, either seven or ten bits.  When this is a ten
- *	bit address, I2C_M_TEN must be set in @flags and the adapter
- *	must support I2C_FUNC_10BIT_ADDR.
- * @flags: I2C_M_RD is handled by all adapters.  No other flags may be
- *	provided unless the adapter exported the relevant I2C_FUNC_*
- *	flags through i2c_check_functionality().
- * @len: Number of data bytes in @buf being read from or written to the
- *	I2C slave address.  For read transactions where I2C_M_RECV_LEN
- *	is set, the caller guarantees that this buffer can hold up to
- *	32 bytes in addition to the initial length byte sent by the
- *	slave (plus, if used, the SMBus PEC); and this value will be
- *	incremented by the number of block data bytes received.
+ *
+ * @addr: Slave address, either 7 or 10 bits. When this is a 10 bit address,
+ *   %I2C_M_TEN must be set in @flags and the adapter must support
+ *   %I2C_FUNC_10BIT_ADDR.
+ *
+ * @flags:
+ *   Supported by all adapters:
+ *   %I2C_M_RD: read data (from slave to master). Guaranteed to be 0x0001!
+ *
+ *   Optional:
+ *   %I2C_M_DMA_SAFE: the buffer of this message is DMA safe. Makes only sense
+ *     in kernelspace, because userspace buffers are copied anyway
+ *
+ *   Only if I2C_FUNC_10BIT_ADDR is set:
+ *   %I2C_M_TEN: this is a 10 bit chip address
+ *
+ *   Only if I2C_FUNC_SMBUS_READ_BLOCK_DATA is set:
+ *   %I2C_M_RECV_LEN: message length will be first received byte
+ *
+ *   Only if I2C_FUNC_NOSTART is set:
+ *   %I2C_M_NOSTART: skip repeated start sequence
+
+ *   Only if I2C_FUNC_PROTOCOL_MANGLING is set:
+ *   %I2C_M_NO_RD_ACK: in a read message, master ACK/NACK bit is skipped
+ *   %I2C_M_IGNORE_NAK: treat NACK from client as ACK
+ *   %I2C_M_REV_DIR_ADDR: toggles the Rd/Wr bit
+ *   %I2C_M_STOP: force a STOP condition after the message
+ *
+ * @len: Number of data bytes in @buf being read from or written to the I2C
+ *   slave address. For read transactions where %I2C_M_RECV_LEN is set, the
+ *   caller guarantees that this buffer can hold up to %I2C_SMBUS_BLOCK_MAX
+ *   bytes in addition to the initial length byte sent by the slave (plus,
+ *   if used, the SMBus PEC); and this value will be incremented by the number
+ *   of block data bytes received.
+ *
  * @buf: The buffer into which data is read, or from which it's written.
  *
  * An i2c_msg is the low level representation of one segment of an I2C
@@ -60,40 +83,36 @@
  * group, it is followed by a STOP.  Otherwise it is followed by the next
  * @i2c_msg transaction segment, beginning with a (repeated) START.
  *
- * Alternatively, when the adapter supports I2C_FUNC_PROTOCOL_MANGLING then
+ * Alternatively, when the adapter supports %I2C_FUNC_PROTOCOL_MANGLING then
  * passing certain @flags may have changed those standard protocol behaviors.
  * Those flags are only for use with broken/nonconforming slaves, and with
- * adapters which are known to support the specific mangling options they
- * need (one or more of IGNORE_NAK, NO_RD_ACK, NOSTART, and REV_DIR_ADDR).
+ * adapters which are known to support the specific mangling options they need.
  */
 struct i2c_msg {
-	__u16 addr;	/* slave address			*/
+	__u16 addr;
 	__u16 flags;
-#define I2C_M_RD		0x0001	/* read data, from slave to master */
-					/* I2C_M_RD is guaranteed to be 0x0001! */
-#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
-#define I2C_M_DMA_SAFE		0x0200	/* the buffer of this message is DMA safe */
-					/* makes only sense in kernelspace */
-					/* userspace buffers are copied anyway */
-#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
-#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
-#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
-#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
-	__u16 len;		/* msg length				*/
-	__u8 *buf;		/* pointer to msg data			*/
+#define I2C_M_RD		0x0001	/* guaranteed to be 0x0001! */
+#define I2C_M_TEN		0x0010	/* use only if I2C_FUNC_10BIT_ADDR */
+#define I2C_M_DMA_SAFE		0x0200	/* use only in kernel space */
+#define I2C_M_RECV_LEN		0x0400	/* use only if I2C_FUNC_SMBUS_READ_BLOCK_DATA */
+#define I2C_M_NO_RD_ACK		0x0800	/* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK	0x1000	/* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR	0x2000	/* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART		0x4000	/* use only if I2C_FUNC_NOSTART */
+#define I2C_M_STOP		0x8000	/* use only if I2C_FUNC_PROTOCOL_MANGLING */
+	__u16 len;
+	__u8 *buf;
 };
 
 /* To determine what functionality is present */
 
 #define I2C_FUNC_I2C			0x00000001
-#define I2C_FUNC_10BIT_ADDR		0x00000002
-#define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* I2C_M_IGNORE_NAK etc. */
+#define I2C_FUNC_10BIT_ADDR		0x00000002 /* required for I2C_M_TEN */
+#define I2C_FUNC_PROTOCOL_MANGLING	0x00000004 /* required for I2C_M_IGNORE_NAK etc. */
 #define I2C_FUNC_SMBUS_PEC		0x00000008
-#define I2C_FUNC_NOSTART		0x00000010 /* I2C_M_NOSTART */
+#define I2C_FUNC_NOSTART		0x00000010 /* required for I2C_M_NOSTART */
 #define I2C_FUNC_SLAVE			0x00000020
-#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 */
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL	0x00008000 /* SMBus 2.0 or later */
 #define I2C_FUNC_SMBUS_QUICK		0x00010000
 #define I2C_FUNC_SMBUS_READ_BYTE	0x00020000
 #define I2C_FUNC_SMBUS_WRITE_BYTE	0x00040000
@@ -102,11 +121,11 @@ struct i2c_msg {
 #define I2C_FUNC_SMBUS_READ_WORD_DATA	0x00200000
 #define I2C_FUNC_SMBUS_WRITE_WORD_DATA	0x00400000
 #define I2C_FUNC_SMBUS_PROC_CALL	0x00800000
-#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA	0x01000000 /* required for I2C_M_RECV_LEN */
 #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
 #define I2C_FUNC_SMBUS_READ_I2C_BLOCK	0x04000000 /* I2C-like block xfer  */
 #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK	0x08000000 /* w/ 1-byte reg. addr. */
-#define I2C_FUNC_SMBUS_HOST_NOTIFY	0x10000000
+#define I2C_FUNC_SMBUS_HOST_NOTIFY	0x10000000 /* SMBus 2.0 or later */
 
 #define I2C_FUNC_SMBUS_BYTE		(I2C_FUNC_SMBUS_READ_BYTE | \
 					 I2C_FUNC_SMBUS_WRITE_BYTE)
Signature · 1 line
2.29.2
#2 lore raw

PATCH 2/8 i2c: remove licence boilerplate from main UAPI header

In reply to Wolfram Sang

Remove boilerplate because we now have the SPDX header.

---
 include/uapi/linux/i2c.h | 32 +++++++-------------------------
 1 file changed, 7 insertions(+), 25 deletions(-)
include/uapi/linux/i2c.h +7 -25
index 8d2f59f53324..7786551eb177 100644
@@ -1,29 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/* ------------------------------------------------------------------------- */
-/*									     */
-/* i2c.h - definitions for the i2c-bus interface			     */
-/*									     */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-2000 Simon G. Vogl
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-    MA 02110-1301 USA.							     */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <[email protected]> and
-   Frodo Looijaard <[email protected]> */
+/*
+ * i2c.h - definitions for the I2C bus interface
+ *
+ * Copyright (C) 1995-2000 Simon G. Vogl
+ * With some changes from Kyösti Mälkki <[email protected]> and
+ * Frodo Looijaard <[email protected]>
+ */
 
 #ifndef _UAPI_LINUX_I2C_H
 #define _UAPI_LINUX_I2C_H
Signature · 1 line
2.29.2
#3 lore raw

PATCH 3/8 i2c: remove licence boilerplate from i2c-dev UAPI header

In reply to Wolfram Sang

Remove boilerplate because we now have the SPDX header.

---
 include/uapi/linux/i2c-dev.h | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)
include/uapi/linux/i2c-dev.h +5 -20
index 85f8047afcf2..1c4cec4ddd84 100644
@@ -1,25 +1,10 @@
 /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
 /*
-    i2c-dev.h - i2c-bus driver, char device interface
-
-    Copyright (C) 1995-97 Simon G. Vogl
-    Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
-    MA 02110-1301 USA.
-*/
+ * i2c-dev.h - I2C bus char device interface
+ *
+ * Copyright (C) 1995-97 Simon G. Vogl
+ * Copyright (C) 1998-99 Frodo Looijaard <[email protected]>
+ */
 
 #ifndef _UAPI_LINUX_I2C_DEV_H
 #define _UAPI_LINUX_I2C_DEV_H
Signature · 1 line
2.29.2
#4 lore raw

PATCH 4/8 i2c: octeon: check correct size of maximum RECV_LEN packet

In reply to Wolfram Sang

I2C_SMBUS_BLOCK_MAX defines already the maximum number as defined in the SMBus 2.0 specs. No reason to add one to it.

Fixes 886f6f8337dd ("i2c: octeon: Support I2C_M_RECV_LEN")
---
 drivers/i2c/busses/i2c-octeon-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-octeon-core.c +1 -1
index d9607905dc2f..845eda70b8ca 100644
@@ -347,7 +347,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
 		if (result)
 			return result;
 		if (recv_len && i == 0) {
-			if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
+			if (data[i] > I2C_SMBUS_BLOCK_MAX)
 				return -EPROTO;
 			length += data[i];
 		}
Signature · 1 line
2.29.2
maintainer Reviewed-by on v1 4/8
#5 lore raw

Re: [PATCH 4/8] i2c: octeon: check correct size of maximum RECV_LEN packet

Quoted 5 lines · Wolfram Sang

I2C_SMBUS_BLOCK_MAX defines already the maximum number as defined in the SMBus 2.0 specs. No reason to add one to it.

Fixes 886f6f8337dd ("i2c: octeon: Support I2C_M_RECV_LEN")
author Applied
#6 lore raw

Re: [PATCH 4/8] i2c: octeon: check correct size of maximum RECV_LEN packet

In reply to Wolfram Sang
Quoted 5 lines · Wolfram Sang

I2C_SMBUS_BLOCK_MAX defines already the maximum number as defined in the SMBus 2.0 specs. No reason to add one to it.

Fixes 886f6f8337dd ("i2c: octeon: Support I2C_M_RECV_LEN")

Applied to for-current, thanks!

#7 lore raw

PATCH 5/8 i2c: uapi: add macro to describe support for all SMBus transfers

In reply to Wolfram Sang

Some I2C bus master drivers which support I2C_M_RECV_LEN do not set the functionality bits of the now supported SMBus transfers. Add a convenience macro to make this very simple.

---
 include/uapi/linux/i2c.h | 5 +++++
 1 file changed, 5 insertions(+)
include/uapi/linux/i2c.h +5 -0
index 7786551eb177..92326ebde350 100644
@@ -129,6 +129,11 @@ struct i2c_msg {
 					 I2C_FUNC_SMBUS_I2C_BLOCK | \
 					 I2C_FUNC_SMBUS_PEC)
 
+/* if I2C_M_RECV_LEN is also supported */
+#define I2C_FUNC_SMBUS_EMUL_ALL		(I2C_FUNC_SMBUS_EMUL | \
+					 I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+					 I2C_FUNC_SMBUS_BLOCK_PROC_CALL)
+
 /*
  * Data for SMBus Messages
  */
Signature · 1 line
2.29.2
#8 lore raw

PATCH 6/8 i2c: algo: bit: use new macro to specifiy capabilities

In reply to Wolfram Sang

Let's use the new macro for emulating SMBus with RECV_LEN support.

---
 drivers/i2c/algos/i2c-algo-bit.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/i2c/algos/i2c-algo-bit.c +1 -3
index 913db013fe90..fc90293afcbf 100644
@@ -622,9 +622,7 @@ static int bit_xfer_atomic(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL |
-	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
-	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+	return I2C_FUNC_I2C | I2C_FUNC_NOSTART | I2C_FUNC_SMBUS_EMUL_ALL |
 	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
Signature · 1 line
2.29.2
#9 lore raw

PATCH 7/8 i2c: qup: advertise SMBus transfers using RECV_LEN

In reply to Wolfram Sang

This driver implements I2C_M_RECV_LEN, so it can advertise the SMBus transfers needing it. This also enables client devices to check for the RECV_LEN capability.

---
 drivers/i2c/busses/i2c-qup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-qup.c +1 -1
index 5a47915869ae..61dc20fd1191 100644
@@ -1603,7 +1603,7 @@ static int qup_i2c_xfer_v2(struct i2c_adapter *adap,
 
 static u32 qup_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL_ALL & ~I2C_FUNC_SMBUS_QUICK);
 }
 
 static const struct i2c_algorithm qup_i2c_algo = {
Signature · 1 line
2.29.2
#10 lore raw

PATCH 8/8 i2c: s3c2410: advertise SMBus transfers using RECV_LEN

In reply to Wolfram Sang

This driver implements I2C_M_RECV_LEN, so it can advertise the SMBus transfers needing it. This also enables client devices to check for the RECV_LEN capability.

---
 drivers/i2c/busses/i2c-s3c2410.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-s3c2410.c +1 -1
index 3eafe0eb3e4c..62a903fbe912 100644
@@ -781,7 +781,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
 /* declare our i2c functionality */
 static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART |
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL_ALL | I2C_FUNC_NOSTART |
 		I2C_FUNC_PROTOCOL_MANGLING;
 }
 
Signature · 1 line
2.29.2
author Applied
#11 lore raw
In reply to Wolfram Sang
Quoted 32 lines · Wolfram Sang

Because I want to clarify I2C_M_RECV len usage, this series updates the documentation and some of its users. Patch 1 refactors the whole documentation of 'i2c_msg', so all usage of I2C_M_* flags and their conditions hopefully become clearer. Patch 2+3 remove some obvious boilerplate in the UAPI headers while here. Patch 4 is a driver fix I found while working on this series. Patch 5 introduces a new convenience macro to enable SMBus transfers which need I2C_M_RECV_LEN. Then, some drivers use the new macro, sometimes to remove boilerplate, sometimes because these SMBus transfers have been forgotten before.

This series is the first part of a larger work to extend I2C_M_RECV_LEN to allow larger transfer sizes (as specified in the SMBus 3.0 standard) and to enable this on Renesas R-Car hardware.

Looking forward to comments and/or reviews; the driver patches are only build-tested.

Happy hacking,

Wolfram

Wolfram Sang (8):
i2c: refactor documentation of struct i2c_msg
i2c: remove licence boilerplate from main UAPI header
i2c: remove licence boilerplate from i2c-dev UAPI header
i2c: octeon: check correct size of maximum RECV_LEN packet
i2c: uapi: add macro to describe support for all SMBus transfers
i2c: algo: bit: use new macro to specifiy capabilities
i2c: qup: advertise SMBus transfers using RECV_LEN
i2c: s3c2410: advertise SMBus transfers using RECV_LEN

Quoted 4 lines
 drivers/i2c/algos/i2c-algo-bit.c     |   4 +-
 drivers/i2c/busses/i2c-octeon-core.c |   2 +-
 drivers/i2c/busses/i2c-qup.c         |   2 +-
 drivers/i2c/busses/i2c-s3c2410.c     |   2 +-

Applied to for-next, thanks!

_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel