mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-02-02 09:05:51 +00:00
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: Alexander Sverdlin <alexander.sverdlin@nokia.com> Reviewed-by: Jean Delvare <jdelvare@suse.de> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
79b4499524
commit
315cd67c94
@ -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 @@
|
|||||||
* 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 @@
|
|||||||
#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)
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
&& 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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user