summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorAdamski, Krzysztof (Nokia - PL/Wroclaw) <krzysztof.adamski@nokia.com>2018-12-10 10:01:27 -0500
committerWolfram Sang <wsa@the-dreams.de>2018-12-11 14:59:17 -0500
commit4f5c85fe3a60ace555d09898166af372547f97fc (patch)
tree8da99d012d410a87b2784ef071d03f5b37dc84f6 /drivers/i2c
parenteb9907789ac373fc122c4b3a3c2d3f061d9ee922 (diff)
i2c-axxia: check for error conditions first
It was observed that when using seqentional mode contrary to the documentation, the SS bit (which is supposed to only be set if automatic/sequence command completed normally), is sometimes set together with NA (NAK in address phase) causing transfer to falsely be considered successful. My assumption is that this does not happen during manual mode since the controller is stopping its work the moment it sets NA/ND bit in status register. This is not the case in Automatic/Sequentional mode where it is still working to send STOP condition and the actual status we get depends on the time when the ISR is run. This patch changes the order of checking status bits in ISR - error conditions are checked first and only if none of them occurred, the transfer may be considered successful. This is required to introduce using of sequentional mode in next patch. Signed-off-by: Krzysztof Adamski <krzysztof.adamski@nokia.com> Reviewed-by: Alexander Sverdlin <alexander.sverdlin@nokia.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-axxia.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index d37caf694fbf..35258321e81b 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -296,22 +296,7 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
296 i2c_int_disable(idev, MST_STATUS_TFL); 296 i2c_int_disable(idev, MST_STATUS_TFL);
297 } 297 }
298 298
299 if (status & MST_STATUS_SCC) { 299 if (unlikely(status & MST_STATUS_ERR)) {
300 /* Stop completed */
301 i2c_int_disable(idev, ~MST_STATUS_TSS);
302 complete(&idev->msg_complete);
303 } else if (status & MST_STATUS_SNS) {
304 /* Transfer done */
305 i2c_int_disable(idev, ~MST_STATUS_TSS);
306 if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
307 axxia_i2c_empty_rx_fifo(idev);
308 complete(&idev->msg_complete);
309 } else if (status & MST_STATUS_TSS) {
310 /* Transfer timeout */
311 idev->msg_err = -ETIMEDOUT;
312 i2c_int_disable(idev, ~MST_STATUS_TSS);
313 complete(&idev->msg_complete);
314 } else if (unlikely(status & MST_STATUS_ERR)) {
315 /* Transfer error */ 300 /* Transfer error */
316 i2c_int_disable(idev, ~0); 301 i2c_int_disable(idev, ~0);
317 if (status & MST_STATUS_AL) 302 if (status & MST_STATUS_AL)
@@ -328,6 +313,21 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
328 readl(idev->base + MST_TX_BYTES_XFRD), 313 readl(idev->base + MST_TX_BYTES_XFRD),
329 readl(idev->base + MST_TX_XFER)); 314 readl(idev->base + MST_TX_XFER));
330 complete(&idev->msg_complete); 315 complete(&idev->msg_complete);
316 } else if (status & MST_STATUS_SCC) {
317 /* Stop completed */
318 i2c_int_disable(idev, ~MST_STATUS_TSS);
319 complete(&idev->msg_complete);
320 } else if (status & MST_STATUS_SNS) {
321 /* Transfer done */
322 i2c_int_disable(idev, ~MST_STATUS_TSS);
323 if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
324 axxia_i2c_empty_rx_fifo(idev);
325 complete(&idev->msg_complete);
326 } else if (status & MST_STATUS_TSS) {
327 /* Transfer timeout */
328 idev->msg_err = -ETIMEDOUT;
329 i2c_int_disable(idev, ~MST_STATUS_TSS);
330 complete(&idev->msg_complete);
331 } 331 }
332 332
333out: 333out: