Commit 80d75202 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -17,9 +17,10 @@ properties:
    oneOf:
      - enum:
          - fsl,imx7ulp-lpi2c
          - fsl,imx8qm-lpi2c
      - items:
          - const: fsl,imx8qxp-lpi2c
          - enum:
              - fsl,imx8qxp-lpi2c
              - fsl,imx8qm-lpi2c
          - const: fsl,imx7ulp-lpi2c

  reg:
+8 −6
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ Key to symbols

=============== =============================================================
S               Start condition
Sr              Repeated start condition, used to switch from write to
                read mode.
P               Stop condition
Rd/Wr (1 bit)   Read/Write bit. Rd equals 1, Wr equals 0.
A, NA (1 bit)   Acknowledge (ACK) and Not Acknowledge (NACK) bit
@@ -100,7 +102,7 @@ Implemented by i2c_smbus_read_byte_data()
This reads a single byte from a device, from a designated register.
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

@@ -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
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

@@ -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::

  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

@@ -181,7 +183,7 @@ of data is specified by the device in the Count byte.
::

  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

@@ -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::

  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

@@ -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::

  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

+25 −7
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@
#define SMBSLVSTS_HST_NTFY_STS	BIT(0)

/* Host Notify Command register bits */
#define SMBSLVCMD_SMBALERT_DISABLE	BIT(2)
#define SMBSLVCMD_HST_NTFY_INTREN	BIT(0)

#define STATUS_ERROR_FLAGS	(SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
@@ -259,6 +260,7 @@ struct i801_priv {
	struct i2c_adapter adapter;
	unsigned long smba;
	unsigned char original_hstcfg;
	unsigned char original_hstcnt;
	unsigned char original_slvcmd;
	struct pci_dev *pci_dev;
	unsigned int features;
@@ -641,12 +643,20 @@ static irqreturn_t i801_isr(int irq, void *dev_id)
		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 &= SMBHSTSTS_INTR | STATUS_ERROR_FLAGS;
	if (status) {
		outb_p(status, SMBHSTSTS(priv));
		priv->status = status;
		complete(&priv->done);
	}
@@ -974,9 +984,13 @@ static void i801_enable_host_notify(struct i2c_adapter *adapter)
	if (!(priv->features & FEATURE_HOST_NOTIFY))
		return;

	if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd))
		outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd,
		       SMBSLVCMD(priv));
	/*
	 * Enable host notify interrupt and block the generation of interrupt
	 * 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 */
	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)
		outb_p(inb_p(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)
		priv->original_slvcmd = inb_p(SMBSLVCMD(priv));

@@ -1869,6 +1884,7 @@ static void i801_remove(struct pci_dev *dev)
{
	struct i801_priv *priv = pci_get_drvdata(dev);

	outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
	i801_disable_host_notify(priv);
	i801_del_mux(priv);
	i2c_del_adapter(&priv->adapter);
@@ -1892,6 +1908,7 @@ static void i801_shutdown(struct pci_dev *dev)
	struct i801_priv *priv = pci_get_drvdata(dev);

	/* Restore config registers to avoid hard hang on some systems */
	outb_p(priv->original_hstcnt, SMBHSTCNT(priv));
	i801_disable_host_notify(priv);
	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
}
@@ -1901,6 +1918,7 @@ static int i801_suspend(struct device *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);
	return 0;
}
+5 −9
Original line number Diff line number Diff line
@@ -104,11 +104,10 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq,

static int virtio_i2c_complete_reqs(struct virtqueue *vq,
				    struct virtio_i2c_req *reqs,
				    struct i2c_msg *msgs, int num,
				    bool timedout)
				    struct i2c_msg *msgs, int num)
{
	struct virtio_i2c_req *req;
	bool failed = timedout;
	bool failed = false;
	unsigned int len;
	int i, j = 0;

@@ -130,7 +129,7 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
			j++;
	}

	return timedout ? -ETIMEDOUT : j;
	return j;
}

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 virtqueue *vq = vi->vq;
	struct virtio_i2c_req *reqs;
	unsigned long time_left;
	int count;

	reqs = kcalloc(num, sizeof(*reqs), GFP_KERNEL);
@@ -162,11 +160,9 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
	reinit_completion(&vi->completion);
	virtqueue_kick(vq);

	time_left = wait_for_completion_timeout(&vi->completion, adap->timeout);
	if (!time_left)
		dev_err(&adap->dev, "virtio i2c backend timeout.\n");
	wait_for_completion(&vi->completion);

	count = virtio_i2c_complete_reqs(vq, reqs, msgs, count, !time_left);
	count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);

err_free:
	kfree(reqs);