Skip to content

Commit f66062c

Browse files
committed
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 another set of driver bugfixes, mostly for the stm32f7 driver" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: i2c: rk3x: Handle a spurious start completion interrupt flag i2c: stm32f7: use proper DMAENGINE API for termination i2c: stm32f7: stop dma transfer in case of NACK i2c: stm32f7: recover the bus on access timeout i2c: stm32f7: flush TX FIFO upon transfer errors i2c: cbus-gpio: set atomic transfer callback
2 parents a44f27e + 02fe0fb commit f66062c

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

drivers/i2c/busses/i2c-cbus-gpio.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,9 @@ static u32 cbus_i2c_func(struct i2c_adapter *adapter)
195195
}
196196

197197
static const struct i2c_algorithm cbus_i2c_algo = {
198-
.smbus_xfer = cbus_i2c_smbus_xfer,
199-
.functionality = cbus_i2c_func,
198+
.smbus_xfer = cbus_i2c_smbus_xfer,
199+
.smbus_xfer_atomic = cbus_i2c_smbus_xfer,
200+
.functionality = cbus_i2c_func,
200201
};
201202

202203
static int cbus_i2c_remove(struct platform_device *pdev)

drivers/i2c/busses/i2c-rk3x.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,8 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd)
423423
if (!(ipd & REG_INT_MBRF))
424424
return;
425425

426-
/* ack interrupt */
427-
i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
426+
/* ack interrupt (read also produces a spurious START flag, clear it too) */
427+
i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD);
428428

429429
/* Can only handle a maximum of 32 bytes at a time */
430430
if (len > 32)

drivers/i2c/busses/i2c-stm32f7.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
14931493
{
14941494
struct stm32f7_i2c_dev *i2c_dev = data;
14951495
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
1496+
struct stm32_i2c_dma *dma = i2c_dev->dma;
14961497
void __iomem *base = i2c_dev->base;
14971498
u32 status, mask;
14981499
int ret = IRQ_HANDLED;
@@ -1518,6 +1519,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15181519
dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n",
15191520
__func__, f7_msg->addr);
15201521
writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
1522+
if (i2c_dev->use_dma) {
1523+
stm32f7_i2c_disable_dma_req(i2c_dev);
1524+
dmaengine_terminate_async(dma->chan_using);
1525+
}
15211526
f7_msg->result = -ENXIO;
15221527
}
15231528

@@ -1533,7 +1538,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15331538
/* Clear STOP flag */
15341539
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
15351540

1536-
if (i2c_dev->use_dma) {
1541+
if (i2c_dev->use_dma && !f7_msg->result) {
15371542
ret = IRQ_WAKE_THREAD;
15381543
} else {
15391544
i2c_dev->master_mode = false;
@@ -1546,7 +1551,7 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
15461551
if (f7_msg->stop) {
15471552
mask = STM32F7_I2C_CR2_STOP;
15481553
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
1549-
} else if (i2c_dev->use_dma) {
1554+
} else if (i2c_dev->use_dma && !f7_msg->result) {
15501555
ret = IRQ_WAKE_THREAD;
15511556
} else if (f7_msg->smbus) {
15521557
stm32f7_i2c_smbus_rep_start(i2c_dev);
@@ -1583,7 +1588,7 @@ static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
15831588
if (!ret) {
15841589
dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
15851590
stm32f7_i2c_disable_dma_req(i2c_dev);
1586-
dmaengine_terminate_all(dma->chan_using);
1591+
dmaengine_terminate_async(dma->chan_using);
15871592
f7_msg->result = -ETIMEDOUT;
15881593
}
15891594

@@ -1660,7 +1665,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
16601665
/* Disable dma */
16611666
if (i2c_dev->use_dma) {
16621667
stm32f7_i2c_disable_dma_req(i2c_dev);
1663-
dmaengine_terminate_all(dma->chan_using);
1668+
dmaengine_terminate_async(dma->chan_using);
16641669
}
16651670

16661671
i2c_dev->master_mode = false;
@@ -1696,12 +1701,26 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
16961701
time_left = wait_for_completion_timeout(&i2c_dev->complete,
16971702
i2c_dev->adap.timeout);
16981703
ret = f7_msg->result;
1704+
if (ret) {
1705+
if (i2c_dev->use_dma)
1706+
dmaengine_synchronize(dma->chan_using);
1707+
1708+
/*
1709+
* It is possible that some unsent data have already been
1710+
* written into TXDR. To avoid sending old data in a
1711+
* further transfer, flush TXDR in case of any error
1712+
*/
1713+
writel_relaxed(STM32F7_I2C_ISR_TXE,
1714+
i2c_dev->base + STM32F7_I2C_ISR);
1715+
goto pm_free;
1716+
}
16991717

17001718
if (!time_left) {
17011719
dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
17021720
i2c_dev->msg->addr);
17031721
if (i2c_dev->use_dma)
1704-
dmaengine_terminate_all(dma->chan_using);
1722+
dmaengine_terminate_sync(dma->chan_using);
1723+
stm32f7_i2c_wait_free_bus(i2c_dev);
17051724
ret = -ETIMEDOUT;
17061725
}
17071726

@@ -1744,13 +1763,25 @@ static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
17441763
timeout = wait_for_completion_timeout(&i2c_dev->complete,
17451764
i2c_dev->adap.timeout);
17461765
ret = f7_msg->result;
1747-
if (ret)
1766+
if (ret) {
1767+
if (i2c_dev->use_dma)
1768+
dmaengine_synchronize(dma->chan_using);
1769+
1770+
/*
1771+
* It is possible that some unsent data have already been
1772+
* written into TXDR. To avoid sending old data in a
1773+
* further transfer, flush TXDR in case of any error
1774+
*/
1775+
writel_relaxed(STM32F7_I2C_ISR_TXE,
1776+
i2c_dev->base + STM32F7_I2C_ISR);
17481777
goto pm_free;
1778+
}
17491779

17501780
if (!timeout) {
17511781
dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
17521782
if (i2c_dev->use_dma)
1753-
dmaengine_terminate_all(dma->chan_using);
1783+
dmaengine_terminate_sync(dma->chan_using);
1784+
stm32f7_i2c_wait_free_bus(i2c_dev);
17541785
ret = -ETIMEDOUT;
17551786
goto pm_free;
17561787
}

0 commit comments

Comments
 (0)