Skip to content

Commit 562de4f

Browse files
stmordretWolfram Sang
authored andcommitted
i2c: i2c-stm32f7: Implement I2C release mechanism
Feature prevents I2C lock-ups. Mechanism resets I2C state machine and releases SCL/SDA signals but preserves I2C registers. Signed-off-by: Pierre-Yves MORDRET <pierre-yves.mordret@st.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
1 parent 7ecc8cf commit 562de4f

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

drivers/i2c/busses/i2c-stm32f7.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,20 @@ static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)
718718
writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
719719
}
720720

721+
static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)
722+
{
723+
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
724+
725+
dev_info(i2c_dev->dev, "Trying to recover bus\n");
726+
727+
stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
728+
STM32F7_I2C_CR1_PE);
729+
730+
stm32f7_i2c_hw_config(i2c_dev);
731+
732+
return 0;
733+
}
734+
721735
static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
722736
{
723737
u32 status;
@@ -727,12 +741,18 @@ static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
727741
status,
728742
!(status & STM32F7_I2C_ISR_BUSY),
729743
10, 1000);
744+
if (!ret)
745+
return 0;
746+
747+
dev_info(i2c_dev->dev, "bus busy\n");
748+
749+
ret = stm32f7_i2c_release_bus(&i2c_dev->adap);
730750
if (ret) {
731-
dev_dbg(i2c_dev->dev, "bus busy\n");
732-
ret = -EBUSY;
751+
dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
752+
return ret;
733753
}
734754

735-
return ret;
755+
return -EBUSY;
736756
}
737757

738758
static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
@@ -1474,6 +1494,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
14741494
if (status & STM32F7_I2C_ISR_BERR) {
14751495
dev_err(dev, "<%s>: Bus error\n", __func__);
14761496
writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
1497+
stm32f7_i2c_release_bus(&i2c_dev->adap);
14771498
f7_msg->result = -EIO;
14781499
}
14791500

0 commit comments

Comments
 (0)