Commit 80d75202 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "I2C has an interrupt storm fix for the i801, better timeout handling
  for the new virtio driver, and some documentation fixes this time"

* 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  docs: i2c: smbus-protocol: mention the repeated start condition
  i2c: virtio: disable timeout handling
  i2c: i801: Fix interrupt storm from SMB_ALERT signal
  i2c: i801: Restore INTREN on unload
  dt-bindings: i2c: imx-lpi2c: Fix i.MX 8QM compatible matching
parents 6b54698a bed68f4f
...@@ -17,9 +17,10 @@ properties: ...@@ -17,9 +17,10 @@ properties:
oneOf: oneOf:
- enum: - enum:
- fsl,imx7ulp-lpi2c - fsl,imx7ulp-lpi2c
- fsl,imx8qm-lpi2c
- items: - items:
- const: fsl,imx8qxp-lpi2c - enum:
- fsl,imx8qxp-lpi2c
- fsl,imx8qm-lpi2c
- const: fsl,imx7ulp-lpi2c - const: fsl,imx7ulp-lpi2c
reg: reg:
......
...@@ -36,6 +36,8 @@ Key to symbols ...@@ -36,6 +36,8 @@ Key to symbols
=============== ============================================================= =============== =============================================================
S Start condition S Start condition
Sr Repeated start condition, used to switch from write to
read mode.
P Stop condition P Stop condition
Rd/Wr (1 bit) Read/Write bit. Rd equals 1, Wr equals 0. Rd/Wr (1 bit) Read/Write bit. Rd equals 1, Wr equals 0.
A, NA (1 bit) Acknowledge (ACK) and Not Acknowledge (NACK) bit A, NA (1 bit) Acknowledge (ACK) and Not Acknowledge (NACK) bit
...@@ -100,7 +102,7 @@ Implemented by i2c_smbus_read_byte_data() ...@@ -100,7 +102,7 @@ Implemented by i2c_smbus_read_byte_data()
This reads a single byte from a device, from a designated register. This reads a single byte from a device, from a designated register.
The register is specified through the Comm byte:: The register is specified through the Comm byte::
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Data] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA Functionality flag: I2C_FUNC_SMBUS_READ_BYTE_DATA
...@@ -114,7 +116,7 @@ This operation is very like Read Byte; again, data is read from a ...@@ -114,7 +116,7 @@ This operation is very like Read Byte; again, data is read from a
device, from a designated register that is specified through the Comm device, from a designated register that is specified through the Comm
byte. But this time, the data is a complete word (16 bits):: byte. But this time, the data is a complete word (16 bits)::
S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P S Addr Wr [A] Comm [A] Sr Addr Rd [A] [DataLow] A [DataHigh] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA Functionality flag: I2C_FUNC_SMBUS_READ_WORD_DATA
...@@ -164,7 +166,7 @@ This command selects a device register (through the Comm byte), sends ...@@ -164,7 +166,7 @@ This command selects a device register (through the Comm byte), sends
16 bits of data to it, and reads 16 bits of data in return:: 16 bits of data to it, and reads 16 bits of data in return::
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
S Addr Rd [A] [DataLow] A [DataHigh] NA P Sr Addr Rd [A] [DataLow] A [DataHigh] NA P
Functionality flag: I2C_FUNC_SMBUS_PROC_CALL Functionality flag: I2C_FUNC_SMBUS_PROC_CALL
...@@ -181,7 +183,7 @@ of data is specified by the device in the Count byte. ...@@ -181,7 +183,7 @@ of data is specified by the device in the Count byte.
:: ::
S Addr Wr [A] Comm [A] S Addr Wr [A] Comm [A]
S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P Sr Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA Functionality flag: I2C_FUNC_SMBUS_READ_BLOCK_DATA
...@@ -212,7 +214,7 @@ This command selects a device register (through the Comm byte), sends ...@@ -212,7 +214,7 @@ This command selects a device register (through the Comm byte), sends
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return:: 1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return::
S Addr Wr [A] Comm [A] Count [A] Data [A] ... S Addr Wr [A] Comm [A] Count [A] Data [A] ...
S Addr Rd [A] [Count] A [Data] ... A P Sr Addr Rd [A] [Count] A [Data] ... A P
Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL Functionality flag: I2C_FUNC_SMBUS_BLOCK_PROC_CALL
...@@ -300,7 +302,7 @@ This command reads a block of bytes from a device, from a ...@@ -300,7 +302,7 @@ This command reads a block of bytes from a device, from a
designated register that is specified through the Comm byte:: designated register that is specified through the Comm byte::
S Addr Wr [A] Comm [A] S Addr Wr [A] Comm [A]
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P Sr Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK Functionality flag: I2C_FUNC_SMBUS_READ_I2C_BLOCK
......
...@@ -191,6 +191,7 @@ ...@@ -191,6 +191,7 @@
#define SMBSLVSTS_HST_NTFY_STS BIT(0) #define SMBSLVSTS_HST_NTFY_STS BIT(0)
/* Host Notify Command register bits */ /* Host Notify Command register bits */
#define SMBSLVCMD_SMBALERT_DISABLE BIT(2)
#define SMBSLVCMD_HST_NTFY_INTREN BIT(0) #define SMBSLVCMD_HST_NTFY_INTREN BIT(0)
#define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \ #define STATUS_ERROR_FLAGS (SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
...@@ -259,6 +260,7 @@ struct i801_priv { ...@@ -259,6 +260,7 @@ struct i801_priv {
struct i2c_adapter adapter; struct i2c_adapter adapter;
unsigned long smba; unsigned long smba;
unsigned char original_hstcfg; unsigned char original_hstcfg;
unsigned char original_hstcnt;
unsigned char original_slvcmd; unsigned char original_slvcmd;
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
unsigned int features; unsigned int features;
...@@ -641,12 +643,20 @@ static irqreturn_t i801_isr(int irq, void *dev_id) ...@@ -641,12 +643,20 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
i801_isr_byte_done(priv); i801_isr_byte_done(priv);
/* /*
* Clear irq sources and report transaction result. * Clear remaining IRQ sources: Completion of last command, errors
* and the SMB_ALERT signal. SMB_ALERT status is set after signal
* assertion independently of the interrupt generation being blocked
* or not so clear it always when the status is set.
*/
status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS | SMBHSTSTS_SMBALERT_STS;
if (status)
outb_p(status, SMBHSTSTS(priv));
status &= ~SMBHSTSTS_SMBALERT_STS; /* SMB_ALERT not reported */
/*
* Report transaction result.
* ->status must be cleared before the next transaction is started. * ->status must be cleared before the next transaction is started.
*/ */
status &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
if (status) { if (status) {
outb_p(status, SMBHSTSTS(priv));
priv->status = status; priv->status = status;
complete(&priv->done); complete(&priv->done);
} }
...@@ -974,9 +984,13 @@ static void i801_enable_host_notify(struct i2c_adapter *adapter) ...@@ -974,9 +984,13 @@ static void i801_enable_host_notify(struct i2c_adapter *adapter)
if (!(priv->features & FEATURE_HOST_NOTIFY)) if (!(priv->features & FEATURE_HOST_NOTIFY))
return; return;
if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd)) /*
outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd, * Enable host notify interrupt and block the generation of interrupt
SMBSLVCMD(priv)); * from the SMB_ALERT signal because the driver does not support
* SMBus Alert.
*/
outb_p(SMBSLVCMD_HST_NTFY_INTREN | SMBSLVCMD_SMBALERT_DISABLE |
priv->original_slvcmd, SMBSLVCMD(priv));
/* clear Host Notify bit to allow a new notification */ /* clear Host Notify bit to allow a new notification */
outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv)); outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
...@@ -1805,7 +1819,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1805,7 +1819,8 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
outb_p(inb_p(SMBAUXCTL(priv)) & outb_p(inb_p(SMBAUXCTL(priv)) &
~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
/* Remember original Host Notify setting */ /* Remember original Interrupt and Host Notify settings */
priv->original_hstcnt = inb_p(SMBHSTCNT(priv)) & ~SMBHSTCNT_KILL;
if (priv->features & FEATURE_HOST_NOTIFY) if (priv->features & FEATURE_HOST_NOTIFY)
priv->original_slvcmd = inb_p(SMBSLVCMD(priv)); priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
...@@ -1869,6 +1884,7 @@ static void i801_remove(struct pci_dev *dev) ...@@ -1869,6 +1884,7 @@ static void i801_remove(struct pci_dev *dev)
{ {
struct i801_priv *priv = pci_get_drvdata(dev); struct i801_priv *priv = pci_get_drvdata(dev);
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
i801_disable_host_notify(priv); i801_disable_host_notify(priv);
i801_del_mux(priv); i801_del_mux(priv);
i2c_del_adapter(&priv->adapter); i2c_del_adapter(&priv->adapter);
...@@ -1892,6 +1908,7 @@ static void i801_shutdown(struct pci_dev *dev) ...@@ -1892,6 +1908,7 @@ static void i801_shutdown(struct pci_dev *dev)
struct i801_priv *priv = pci_get_drvdata(dev); struct i801_priv *priv = pci_get_drvdata(dev);
/* Restore config registers to avoid hard hang on some systems */ /* Restore config registers to avoid hard hang on some systems */
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
i801_disable_host_notify(priv); i801_disable_host_notify(priv);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
} }
...@@ -1901,6 +1918,7 @@ static int i801_suspend(struct device *dev) ...@@ -1901,6 +1918,7 @@ static int i801_suspend(struct device *dev)
{ {
struct i801_priv *priv = dev_get_drvdata(dev); struct i801_priv *priv = dev_get_drvdata(dev);
outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg);
return 0; return 0;
} }
......
...@@ -104,11 +104,10 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq, ...@@ -104,11 +104,10 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
static int virtio_i2c_complete_reqs(struct virtqueue *vq, static int virtio_i2c_complete_reqs(struct virtqueue *vq,
struct virtio_i2c_req *reqs, struct virtio_i2c_req *reqs,
struct i2c_msg *msgs, int num, struct i2c_msg *msgs, int num)
bool timedout)
{ {
struct virtio_i2c_req *req; struct virtio_i2c_req *req;
bool failed = timedout; bool failed = false;
unsigned int len; unsigned int len;
int i, j = 0; int i, j = 0;
...@@ -130,7 +129,7 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq, ...@@ -130,7 +129,7 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
j++; j++;
} }
return timedout ? -ETIMEDOUT : j; return j;
} }
static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
...@@ -139,7 +138,6 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -139,7 +138,6 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
struct virtio_i2c *vi = i2c_get_adapdata(adap); struct virtio_i2c *vi = i2c_get_adapdata(adap);
struct virtqueue *vq = vi->vq; struct virtqueue *vq = vi->vq;
struct virtio_i2c_req *reqs; struct virtio_i2c_req *reqs;
unsigned long time_left;
int count; int count;
reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL); reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
...@@ -162,11 +160,9 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -162,11 +160,9 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
reinit_completion(&vi->completion); reinit_completion(&vi->completion);
virtqueue_kick(vq); virtqueue_kick(vq);
time_left = wait_for_completion_timeout(&vi->completion, adap->timeout); wait_for_completion(&vi->completion);
if (!time_left)
dev_err(&adap->dev, "virtio i2c backend timeout.\n");
count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left); count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);
err_free: err_free:
kfree(reqs); kfree(reqs);
......
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