Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+43 -11
+3 -2
drivers/i2c/busses/i2c-cbus-gpio.c
··· 195 195 } 196 196 197 197 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, 200 201 }; 201 202 202 203 static int cbus_i2c_remove(struct platform_device *pdev)
+2 -2
drivers/i2c/busses/i2c-rk3x.c
··· 423 423 if (!(ipd & REG_INT_MBRF)) 424 424 return; 425 425 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); 428 428 429 429 /* Can only handle a maximum of 32 bytes at a time */ 430 430 if (len > 32)
+38 -7
drivers/i2c/busses/i2c-stm32f7.c
··· 1493 1493 { 1494 1494 struct stm32f7_i2c_dev *i2c_dev = data; 1495 1495 struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg; 1496 + struct stm32_i2c_dma *dma = i2c_dev->dma; 1496 1497 void __iomem *base = i2c_dev->base; 1497 1498 u32 status, mask; 1498 1499 int ret = IRQ_HANDLED; ··· 1519 1518 dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", 1520 1519 __func__, f7_msg->addr); 1521 1520 writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); 1521 + if (i2c_dev->use_dma) { 1522 + stm32f7_i2c_disable_dma_req(i2c_dev); 1523 + dmaengine_terminate_async(dma->chan_using); 1524 + } 1522 1525 f7_msg->result = -ENXIO; 1523 1526 } 1524 1527 ··· 1538 1533 /* Clear STOP flag */ 1539 1534 writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR); 1540 1535 1541 - if (i2c_dev->use_dma) { 1536 + if (i2c_dev->use_dma && !f7_msg->result) { 1542 1537 ret = IRQ_WAKE_THREAD; 1543 1538 } else { 1544 1539 i2c_dev->master_mode = false; ··· 1551 1546 if (f7_msg->stop) { 1552 1547 mask = STM32F7_I2C_CR2_STOP; 1553 1548 stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask); 1554 - } else if (i2c_dev->use_dma) { 1549 + } else if (i2c_dev->use_dma && !f7_msg->result) { 1555 1550 ret = IRQ_WAKE_THREAD; 1556 1551 } else if (f7_msg->smbus) { 1557 1552 stm32f7_i2c_smbus_rep_start(i2c_dev); ··· 1588 1583 if (!ret) { 1589 1584 dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__); 1590 1585 stm32f7_i2c_disable_dma_req(i2c_dev); 1591 - dmaengine_terminate_all(dma->chan_using); 1586 + dmaengine_terminate_async(dma->chan_using); 1592 1587 f7_msg->result = -ETIMEDOUT; 1593 1588 } 1594 1589 ··· 1665 1660 /* Disable dma */ 1666 1661 if (i2c_dev->use_dma) { 1667 1662 stm32f7_i2c_disable_dma_req(i2c_dev); 1668 - dmaengine_terminate_all(dma->chan_using); 1663 + dmaengine_terminate_async(dma->chan_using); 1669 1664 } 1670 1665 1671 1666 i2c_dev->master_mode = false; ··· 1701 1696 time_left = wait_for_completion_timeout(&i2c_dev->complete, 1702 1697 i2c_dev->adap.timeout); 1703 1698 ret = f7_msg->result; 1699 + if (ret) { 1700 + if (i2c_dev->use_dma) 1701 + dmaengine_synchronize(dma->chan_using); 1702 + 1703 + /* 1704 + * It is possible that some unsent data have already been 1705 + * written into TXDR. To avoid sending old data in a 1706 + * further transfer, flush TXDR in case of any error 1707 + */ 1708 + writel_relaxed(STM32F7_I2C_ISR_TXE, 1709 + i2c_dev->base + STM32F7_I2C_ISR); 1710 + goto pm_free; 1711 + } 1704 1712 1705 1713 if (!time_left) { 1706 1714 dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n", 1707 1715 i2c_dev->msg->addr); 1708 1716 if (i2c_dev->use_dma) 1709 - dmaengine_terminate_all(dma->chan_using); 1717 + dmaengine_terminate_sync(dma->chan_using); 1718 + stm32f7_i2c_wait_free_bus(i2c_dev); 1710 1719 ret = -ETIMEDOUT; 1711 1720 } 1712 1721 ··· 1763 1744 timeout = wait_for_completion_timeout(&i2c_dev->complete, 1764 1745 i2c_dev->adap.timeout); 1765 1746 ret = f7_msg->result; 1766 - if (ret) 1747 + if (ret) { 1748 + if (i2c_dev->use_dma) 1749 + dmaengine_synchronize(dma->chan_using); 1750 + 1751 + /* 1752 + * It is possible that some unsent data have already been 1753 + * written into TXDR. To avoid sending old data in a 1754 + * further transfer, flush TXDR in case of any error 1755 + */ 1756 + writel_relaxed(STM32F7_I2C_ISR_TXE, 1757 + i2c_dev->base + STM32F7_I2C_ISR); 1767 1758 goto pm_free; 1759 + } 1768 1760 1769 1761 if (!timeout) { 1770 1762 dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr); 1771 1763 if (i2c_dev->use_dma) 1772 - dmaengine_terminate_all(dma->chan_using); 1764 + dmaengine_terminate_sync(dma->chan_using); 1765 + stm32f7_i2c_wait_free_bus(i2c_dev); 1773 1766 ret = -ETIMEDOUT; 1774 1767 goto pm_free; 1775 1768 }