diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-mxs.c')
-rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 0ec1f1502def..c67d89fc6254 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #define MXS_I2C_CTRL1_SET (0x44) | 56 | #define MXS_I2C_CTRL1_SET (0x44) |
57 | #define MXS_I2C_CTRL1_CLR (0x48) | 57 | #define MXS_I2C_CTRL1_CLR (0x48) |
58 | 58 | ||
59 | #define MXS_I2C_CTRL1_CLR_GOT_A_NAK 0x10000000 | ||
59 | #define MXS_I2C_CTRL1_BUS_FREE_IRQ 0x80 | 60 | #define MXS_I2C_CTRL1_BUS_FREE_IRQ 0x80 |
60 | #define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ 0x40 | 61 | #define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ 0x40 |
61 | #define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ 0x20 | 62 | #define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ 0x20 |
@@ -340,6 +341,23 @@ static int mxs_i2c_pio_wait_cplt(struct mxs_i2c_dev *i2c, int last) | |||
340 | return 0; | 341 | return 0; |
341 | } | 342 | } |
342 | 343 | ||
344 | static int mxs_i2c_pio_check_error_state(struct mxs_i2c_dev *i2c) | ||
345 | { | ||
346 | u32 state; | ||
347 | |||
348 | state = readl(i2c->regs + MXS_I2C_CTRL1_CLR) & MXS_I2C_IRQ_MASK; | ||
349 | |||
350 | if (state & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ) | ||
351 | i2c->cmd_err = -ENXIO; | ||
352 | else if (state & (MXS_I2C_CTRL1_EARLY_TERM_IRQ | | ||
353 | MXS_I2C_CTRL1_MASTER_LOSS_IRQ | | ||
354 | MXS_I2C_CTRL1_SLAVE_STOP_IRQ | | ||
355 | MXS_I2C_CTRL1_SLAVE_IRQ)) | ||
356 | i2c->cmd_err = -EIO; | ||
357 | |||
358 | return i2c->cmd_err; | ||
359 | } | ||
360 | |||
343 | static void mxs_i2c_pio_trigger_cmd(struct mxs_i2c_dev *i2c, u32 cmd) | 361 | static void mxs_i2c_pio_trigger_cmd(struct mxs_i2c_dev *i2c, u32 cmd) |
344 | { | 362 | { |
345 | u32 reg; | 363 | u32 reg; |
@@ -380,6 +398,9 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap, | |||
380 | if (ret) | 398 | if (ret) |
381 | return ret; | 399 | return ret; |
382 | 400 | ||
401 | if (mxs_i2c_pio_check_error_state(i2c)) | ||
402 | goto cleanup; | ||
403 | |||
383 | /* READ command. */ | 404 | /* READ command. */ |
384 | mxs_i2c_pio_trigger_cmd(i2c, | 405 | mxs_i2c_pio_trigger_cmd(i2c, |
385 | MXS_CMD_I2C_READ | flags | | 406 | MXS_CMD_I2C_READ | flags | |
@@ -440,6 +461,10 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap, | |||
440 | if (ret) | 461 | if (ret) |
441 | return ret; | 462 | return ret; |
442 | 463 | ||
464 | /* make sure we capture any occurred error into cmd_err */ | ||
465 | mxs_i2c_pio_check_error_state(i2c); | ||
466 | |||
467 | cleanup: | ||
443 | /* Clear any dangling IRQs and re-enable interrupts. */ | 468 | /* Clear any dangling IRQs and re-enable interrupts. */ |
444 | writel(MXS_I2C_IRQ_MASK, i2c->regs + MXS_I2C_CTRL1_CLR); | 469 | writel(MXS_I2C_IRQ_MASK, i2c->regs + MXS_I2C_CTRL1_CLR); |
445 | writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); | 470 | writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); |
@@ -471,12 +496,12 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
471 | * using PIO mode while longer transfers use DMA. The 8 byte border is | 496 | * using PIO mode while longer transfers use DMA. The 8 byte border is |
472 | * based on this empirical measurement and a lot of previous frobbing. | 497 | * based on this empirical measurement and a lot of previous frobbing. |
473 | */ | 498 | */ |
499 | i2c->cmd_err = 0; | ||
474 | if (msg->len < 8) { | 500 | if (msg->len < 8) { |
475 | ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); | 501 | ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); |
476 | if (ret) | 502 | if (ret) |
477 | mxs_i2c_reset(i2c); | 503 | mxs_i2c_reset(i2c); |
478 | } else { | 504 | } else { |
479 | i2c->cmd_err = 0; | ||
480 | INIT_COMPLETION(i2c->cmd_complete); | 505 | INIT_COMPLETION(i2c->cmd_complete); |
481 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); | 506 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); |
482 | if (ret) | 507 | if (ret) |
@@ -486,13 +511,19 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
486 | msecs_to_jiffies(1000)); | 511 | msecs_to_jiffies(1000)); |
487 | if (ret == 0) | 512 | if (ret == 0) |
488 | goto timeout; | 513 | goto timeout; |
514 | } | ||
489 | 515 | ||
490 | if (i2c->cmd_err == -ENXIO) | 516 | if (i2c->cmd_err == -ENXIO) { |
491 | mxs_i2c_reset(i2c); | 517 | /* |
492 | 518 | * If the transfer fails with a NAK from the slave the | |
493 | ret = i2c->cmd_err; | 519 | * controller halts until it gets told to return to idle state. |
520 | */ | ||
521 | writel(MXS_I2C_CTRL1_CLR_GOT_A_NAK, | ||
522 | i2c->regs + MXS_I2C_CTRL1_SET); | ||
494 | } | 523 | } |
495 | 524 | ||
525 | ret = i2c->cmd_err; | ||
526 | |||
496 | dev_dbg(i2c->dev, "Done with err=%d\n", ret); | 527 | dev_dbg(i2c->dev, "Done with err=%d\n", ret); |
497 | 528 | ||
498 | return ret; | 529 | return ret; |