diff mbox series

i2c: i801: Add Block Write-Block Read Process Call support

Message ID 20180829161810.2147-1-alexander.sverdlin@nokia.com
State Superseded
Headers show
Series i2c: i801: Add Block Write-Block Read Process Call support | expand

Commit Message

Alexander A Sverdlin Aug. 29, 2018, 4:18 p.m. UTC
Add SMBUS 2.0 Block Write-Block Read Process Call command support.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
---
 drivers/i2c/busses/i2c-i801.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

Comments

Jean Delvare June 13, 2019, 9:13 a.m. UTC | #1
Hi Alexander,

Sorry for the very late reply.

On Wed, 29 Aug 2018 18:18:10 +0200, Alexander Sverdlin wrote:
> Add SMBUS 2.0 Block Write-Block Read Process Call command support.

I have never seen any SMBus device using this command. Which device do
you need it for?

> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> ---
>  drivers/i2c/busses/i2c-i801.c | 43 +++++++++++++++++++++++++++++++++++++------
>  1 file changed, 37 insertions(+), 6 deletions(-)
> (...)

Looks good overall, except for missing an update to the documentation
file (Documentation/i2c/busses/i2c-i801). However I will only consider
applying the patch if it has a real use case.
Alexander A Sverdlin June 17, 2019, 8:40 a.m. UTC | #2
Hi Jean,

On 13/06/2019 11:13, Jean Delvare wrote:
>> Add SMBUS 2.0 Block Write-Block Read Process Call command support.
> I have never seen any SMBus device using this command. Which device do
> you need it for?

That's our in-house FPGA design. This device is not otherwise publicly available.

>> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
>> ---
>>  drivers/i2c/busses/i2c-i801.c | 43 +++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 37 insertions(+), 6 deletions(-)
>> (...)
> Looks good overall, except for missing an update to the documentation
> file (Documentation/i2c/busses/i2c-i801). However I will only consider
> applying the patch if it has a real use case.

But the support for the new command is long-time tested and reported to work fine,
that's why I thought it can be of interest for the community.

Please let me know if I should update the documentation and re-spin or this is
not of the maintainer's interest at all.
Wolfram Sang June 17, 2019, 10:05 a.m. UTC | #3
> Please let me know if I should update the documentation and re-spin or this is
> not of the maintainer's interest at all. 

Despite your device being non-public, it exists so I think it is a valid user.

I have a vague memory of seeing a TPM device using a block process call
a few years ago, yet I couldn't find it again right now.
Jean Delvare June 17, 2019, 2:19 p.m. UTC | #4
Hi Alexander,

On Mon, 17 Jun 2019 08:40:27 +0000, Sverdlin, Alexander (Nokia - DE/Ulm) wrote:
> On 13/06/2019 11:13, Jean Delvare wrote:
> >> Add SMBUS 2.0 Block Write-Block Read Process Call command support.  
> > I have never seen any SMBus device using this command. Which device do
> > you need it for?  
> 
> That's our in-house FPGA design. This device is not otherwise publicly available.

OK.

> >> Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
> >> ---
> >>  drivers/i2c/busses/i2c-i801.c | 43 +++++++++++++++++++++++++++++++++++++------
> >>  1 file changed, 37 insertions(+), 6 deletions(-)
> >> (...)  
> > Looks good overall, except for missing an update to the documentation
> > file (Documentation/i2c/busses/i2c-i801). However I will only consider
> > applying the patch if it has a real use case.  
> 
> But the support for the new command is long-time tested and reported to work fine,
> that's why I thought it can be of interest for the community.
> 
> Please let me know if I should update the documentation and re-spin or this is
> not of the maintainer's interest at all. 

It is of interest. I just wanted to make sure you had implemented it
because the need exists and not just because the controller happens to
support it. Now that this is clarified, I'll be happy to review and
approve the patch, if you submit it again based on a recent code base
and with the missing documentation update included.

Thanks,
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 941c223..b02e798 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -76,7 +76,7 @@ 
  * Software PEC				no
  * Hardware PEC				yes
  * Block buffer				yes
- * Block process call transaction	no
+ * Block process call transaction	yes
  * I2C block read transaction		yes (doesn't use the block buffer)
  * Slave mode				no
  * SMBus Host Notify			yes
@@ -175,6 +175,7 @@ 
 #define I801_PROC_CALL		0x10	/* unimplemented */
 #define I801_BLOCK_DATA		0x14
 #define I801_I2C_BLOCK_DATA	0x18	/* ICH5 and later */
+#define I801_BLOCK_PROC_CALL	0x1C
 
 /* I801 Host Control register bits */
 #define SMBHSTCNT_INTREN	BIT(0)
@@ -514,10 +515,23 @@  static int i801_transaction(struct i801_priv *priv, int xact)
 
 static int i801_block_transaction_by_block(struct i801_priv *priv,
 					   union i2c_smbus_data *data,
-					   char read_write, int hwpec)
+					   char read_write, int command,
+					   int hwpec)
 {
 	int i, len;
 	int status;
+	int xact = hwpec ? SMBHSTCNT_PEC_EN : 0;
+
+	switch (command) {
+	case I2C_SMBUS_BLOCK_PROC_CALL:
+		xact |= I801_BLOCK_PROC_CALL;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		xact |= I801_BLOCK_DATA;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
 
 	inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
 
@@ -529,12 +543,12 @@  static int i801_block_transaction_by_block(struct i801_priv *priv,
 			outb_p(data->block[i+1], SMBBLKDAT(priv));
 	}
 
-	status = i801_transaction(priv, I801_BLOCK_DATA |
-				  (hwpec ? SMBHSTCNT_PEC_EN : 0));
+	status = i801_transaction(priv, xact);
 	if (status)
 		return status;
 
-	if (read_write == I2C_SMBUS_READ) {
+	if (read_write == I2C_SMBUS_READ ||
+	    command == I2C_SMBUS_BLOCK_PROC_CALL) {
 		len = inb_p(SMBHSTDAT0(priv));
 		if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
 			return -EPROTO;
@@ -672,6 +686,9 @@  static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
 	int result;
 	const struct i2c_adapter *adap = &priv->adapter;
 
+	if (command == I2C_SMBUS_BLOCK_PROC_CALL)
+		return -EOPNOTSUPP;
+
 	result = i801_check_pre(priv);
 	if (result < 0)
 		return result;
@@ -803,7 +820,8 @@  static int i801_block_transaction(struct i801_priv *priv,
 	 && command != I2C_SMBUS_I2C_BLOCK_DATA
 	 && i801_set_block_buffer_mode(priv) == 0)
 		result = i801_block_transaction_by_block(priv, data,
-							 read_write, hwpec);
+							 read_write,
+							 command, hwpec);
 	else
 		result = i801_block_transaction_byte_by_byte(priv, data,
 							     read_write,
@@ -895,6 +913,15 @@  static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 			outb_p(command, SMBHSTCMD(priv));
 		block = 1;
 		break;
+	case I2C_SMBUS_BLOCK_PROC_CALL:
+		/*
+		 * Bit 0 of the slave address register always indicate a write
+		 * command.
+		 */
+		outb_p((addr & 0x7f) << 1, SMBHSTADD(priv));
+		outb_p(command, SMBHSTCMD(priv));
+		block = 1;
+		break;
 	default:
 		dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
 			size);
@@ -955,6 +982,8 @@  static u32 i801_func(struct i2c_adapter *adapter)
 	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
 	       ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
+	       ((priv->features & FEATURE_BLOCK_PROC) ?
+		I2C_FUNC_SMBUS_BLOCK_PROC_CALL : 0) |
 	       ((priv->features & FEATURE_I2C_BLOCK_READ) ?
 		I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) |
 	       ((priv->features & FEATURE_HOST_NOTIFY) ?
@@ -1522,6 +1551,7 @@  static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
 	case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
 	case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
+		priv->features |= FEATURE_BLOCK_PROC;
 		priv->features |= FEATURE_I2C_BLOCK_READ;
 		priv->features |= FEATURE_IRQ;
 		priv->features |= FEATURE_SMBUS_PEC;
@@ -1541,6 +1571,7 @@  static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		priv->features |= FEATURE_IDF;
 		/* fall through */
 	default:
+		priv->features |= FEATURE_BLOCK_PROC;
 		priv->features |= FEATURE_I2C_BLOCK_READ;
 		priv->features |= FEATURE_IRQ;
 		/* fall through */