Commit 315cd67c authored by Alexander Sverdlin's avatar Alexander Sverdlin Committed by Wolfram Sang

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

Add SMBUS 2.0 Block Write-Block Read Process Call command support.
Signed-off-by: default avatarAlexander Sverdlin <alexander.sverdlin@nokia.com>
Reviewed-by: default avatarJean Delvare <jdelvare@suse.de>
Signed-off-by: default avatarWolfram Sang <wsa@the-dreams.de>
parent 79b44995
...@@ -88,7 +88,7 @@ SMBus controller. ...@@ -88,7 +88,7 @@ SMBus controller.
Process Call Support Process Call Support
-------------------- --------------------
Not supported. Block process call is supported on the 82801EB (ICH5) and later chips.
I2C Block Read Support I2C Block Read Support
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
* Software PEC no * Software PEC no
* Hardware PEC yes * Hardware PEC yes
* Block buffer 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) * I2C block read transaction yes (doesn't use the block buffer)
* Slave mode no * Slave mode no
* SMBus Host Notify yes * SMBus Host Notify yes
...@@ -178,6 +178,7 @@ ...@@ -178,6 +178,7 @@
#define I801_PROC_CALL 0x10 /* unimplemented */ #define I801_PROC_CALL 0x10 /* unimplemented */
#define I801_BLOCK_DATA 0x14 #define I801_BLOCK_DATA 0x14
#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ #define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */
#define I801_BLOCK_PROC_CALL 0x1C
/* I801 Host Control register bits */ /* I801 Host Control register bits */
#define SMBHSTCNT_INTREN BIT(0) #define SMBHSTCNT_INTREN BIT(0)
...@@ -518,10 +519,23 @@ static int i801_transaction(struct i801_priv *priv, int xact) ...@@ -518,10 +519,23 @@ static int i801_transaction(struct i801_priv *priv, int xact)
static int i801_block_transaction_by_block(struct i801_priv *priv, static int i801_block_transaction_by_block(struct i801_priv *priv,
union i2c_smbus_data *data, union i2c_smbus_data *data,
char read_write, int hwpec) char read_write, int command,
int hwpec)
{ {
int i, len; int i, len;
int status; 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 */ inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
...@@ -533,12 +547,12 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, ...@@ -533,12 +547,12 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
outb_p(data->block[i+1], SMBBLKDAT(priv)); outb_p(data->block[i+1], SMBBLKDAT(priv));
} }
status = i801_transaction(priv, I801_BLOCK_DATA | status = i801_transaction(priv, xact);
(hwpec ? SMBHSTCNT_PEC_EN : 0));
if (status) if (status)
return 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)); len = inb_p(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
return -EPROTO; return -EPROTO;
...@@ -676,6 +690,9 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, ...@@ -676,6 +690,9 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
int result; int result;
const struct i2c_adapter *adap = &priv->adapter; const struct i2c_adapter *adap = &priv->adapter;
if (command == I2C_SMBUS_BLOCK_PROC_CALL)
return -EOPNOTSUPP;
result = i801_check_pre(priv); result = i801_check_pre(priv);
if (result < 0) if (result < 0)
return result; return result;
...@@ -807,7 +824,8 @@ static int i801_block_transaction(struct i801_priv *priv, ...@@ -807,7 +824,8 @@ static int i801_block_transaction(struct i801_priv *priv,
&& command != I2C_SMBUS_I2C_BLOCK_DATA && command != I2C_SMBUS_I2C_BLOCK_DATA
&& i801_set_block_buffer_mode(priv) == 0) && i801_set_block_buffer_mode(priv) == 0)
result = i801_block_transaction_by_block(priv, data, result = i801_block_transaction_by_block(priv, data,
read_write, hwpec); read_write,
command, hwpec);
else else
result = i801_block_transaction_byte_by_byte(priv, data, result = i801_block_transaction_byte_by_byte(priv, data,
read_write, read_write,
...@@ -899,6 +917,15 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, ...@@ -899,6 +917,15 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
outb_p(command, SMBHSTCMD(priv)); outb_p(command, SMBHSTCMD(priv));
block = 1; block = 1;
break; 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: default:
dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
size); size);
...@@ -959,6 +986,8 @@ static u32 i801_func(struct i2c_adapter *adapter) ...@@ -959,6 +986,8 @@ static u32 i801_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | ((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) ? ((priv->features & FEATURE_I2C_BLOCK_READ) ?
I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) | I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0) |
((priv->features & FEATURE_HOST_NOTIFY) ? ((priv->features & FEATURE_HOST_NOTIFY) ?
...@@ -1654,6 +1683,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1654,6 +1683,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS:
priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
priv->features |= FEATURE_SMBUS_PEC; priv->features |= FEATURE_SMBUS_PEC;
...@@ -1673,6 +1703,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1673,6 +1703,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
priv->features |= FEATURE_IDF; priv->features |= FEATURE_IDF;
/* fall through */ /* fall through */
default: default:
priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
/* fall through */ /* fall through */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment