Commit 7f52bb9d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'i2c-for-6.11-final-but-missed-it' of...

Merge tag 'i2c-for-6.11-final-but-missed-it' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c fixes from Wolfram Sang:
 "The Aspeed driver tracks the controller's state (stop, pending, start,
  etc.). Previously, when the stop command was sent, the state was not
  updated. The fix ensures the driver's state is aligned with the device
  status.

  The Intel SCH driver receives a new look, and among the cleanups,
  there is a fix where, due to an oversight, an if/else statement was
  missing the else, causing it to move forward instead of exiting the
  function in case of an error.

  The Qualcomm GENI I2C driver adds the IRQF_NO_AUTOEN flag to the IRQ
  setup to prevent unwanted interrupts during probe.

  The Xilinx XPS controller fixes TX FIFO handling to avoid missed NAKs.
  Another fix ensures the controller is reinitialized when the bus
  appears busy"

* tag 'i2c-for-6.11-final-but-missed-it' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: qcom-geni: Use IRQF_NO_AUTOEN flag in request_irq()
  i2c: isch: Add missed 'else'
  i2c: xiic: Try re-initialization on bus busy timeout
  i2c: xiic: Wait for TX empty to avoid missed TX NAKs
  i2c: aspeed: Update the stop sw state when the bus recovery occurs
parents 839c4f59 e03ad65c
......@@ -170,6 +170,13 @@ struct aspeed_i2c_bus {
static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
/* precondition: bus.lock has been acquired. */
static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
{
bus->master_state = ASPEED_I2C_MASTER_STOP;
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
}
static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
{
unsigned long time_left, flags;
......@@ -187,7 +194,7 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
command);
reinit_completion(&bus->cmd_complete);
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
aspeed_i2c_do_stop(bus);
spin_unlock_irqrestore(&bus->lock, flags);
time_left = wait_for_completion_timeout(
......@@ -390,13 +397,6 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
writel(command, bus->base + ASPEED_I2C_CMD_REG);
}
/* precondition: bus.lock has been acquired. */
static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
{
bus->master_state = ASPEED_I2C_MASTER_STOP;
writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
}
/* precondition: bus.lock has been acquired. */
static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
{
......
......@@ -99,8 +99,7 @@ static int sch_transaction(void)
if (retries > MAX_RETRIES) {
dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
if (temp & 0x04) {
} else if (temp & 0x04) {
result = -EIO;
dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n");
......
......@@ -818,15 +818,13 @@ static int geni_i2c_probe(struct platform_device *pdev)
init_completion(&gi2c->done);
spin_lock_init(&gi2c->lock);
platform_set_drvdata(pdev, gi2c);
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, 0,
ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
dev_name(dev), gi2c);
if (ret) {
dev_err(dev, "Request_irq failed:%d: err:%d\n",
gi2c->irq, ret);
return ret;
}
/* Disable the interrupt so that the system can enter low-power mode */
disable_irq(gi2c->irq);
i2c_set_adapdata(&gi2c->adap, gi2c);
gi2c->adap.dev.parent = dev;
gi2c->adap.dev.of_node = dev->of_node;
......
......@@ -772,14 +772,17 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
goto out;
}
if (xiic_tx_space(i2c)) {
xiic_fill_tx_fifo(i2c);
/* current message sent and there is space in the fifo */
if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) {
} else {
/* current message fully written */
dev_dbg(i2c->adap.dev.parent,
"%s end of message sent, nmsgs: %d\n",
__func__, i2c->nmsgs);
if (i2c->nmsgs > 1) {
/* Don't move onto the next message until the TX FIFO empties,
* to ensure that a NAK is not missed.
*/
if (i2c->nmsgs > 1 && (pend & XIIC_INTR_TX_EMPTY_MASK)) {
i2c->nmsgs--;
i2c->tx_msg++;
xfer_more = 1;
......@@ -790,11 +793,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
"%s Got TX IRQ but no more to do...\n",
__func__);
}
} else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1))
/* current frame is sent and is last,
* make sure to disable tx half
*/
xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
}
}
if (pend & XIIC_INTR_BNB_MASK) {
......@@ -844,23 +843,11 @@ static int xiic_bus_busy(struct xiic_i2c *i2c)
return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0;
}
static int xiic_busy(struct xiic_i2c *i2c)
static int xiic_wait_not_busy(struct xiic_i2c *i2c)
{
int tries = 3;
int err;
if (i2c->tx_msg || i2c->rx_msg)
return -EBUSY;
/* In single master mode bus can only be busy, when in use by this
* driver. If the register indicates bus being busy for some reason we
* should ignore it, since bus will never be released and i2c will be
* stuck forever.
*/
if (i2c->singlemaster) {
return 0;
}
/* for instance if previous transfer was terminated due to TX error
* it might be that the bus is on it's way to become available
* give it at most 3 ms to wake
......@@ -1104,12 +1091,35 @@ static int xiic_start_xfer(struct xiic_i2c *i2c, struct i2c_msg *msgs, int num)
mutex_lock(&i2c->lock);
ret = xiic_busy(i2c);
if (ret) {
if (i2c->tx_msg || i2c->rx_msg) {
dev_err(i2c->adap.dev.parent,
"cannot start a transfer while busy\n");
ret = -EBUSY;
goto out;
}
/* In single master mode bus can only be busy, when in use by this
* driver. If the register indicates bus being busy for some reason we
* should ignore it, since bus will never be released and i2c will be
* stuck forever.
*/
if (!i2c->singlemaster) {
ret = xiic_wait_not_busy(i2c);
if (ret) {
/* If the bus is stuck in a busy state, such as due to spurious low
* pulses on the bus causing a false start condition to be detected,
* then try to recover by re-initializing the controller and check
* again if the bus is still busy.
*/
dev_warn(i2c->adap.dev.parent, "I2C bus busy timeout, reinitializing\n");
ret = xiic_reinit(i2c);
if (ret)
goto out;
ret = xiic_wait_not_busy(i2c);
if (ret)
goto out;
}
}
i2c->tx_msg = msgs;
i2c->rx_msg = NULL;
......
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