aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-designware.c47
1 files changed, 40 insertions, 7 deletions
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c
index e6b1e6ece5d7..887aed6601fb 100644
--- a/drivers/i2c/busses/i2c-designware.c
+++ b/drivers/i2c/busses/i2c-designware.c
@@ -123,9 +123,27 @@
123#define ABRT_SBYTE_ACKDET 7 123#define ABRT_SBYTE_ACKDET 7
124#define ABRT_SBYTE_NORSTRT 9 124#define ABRT_SBYTE_NORSTRT 9
125#define ABRT_10B_RD_NORSTRT 10 125#define ABRT_10B_RD_NORSTRT 10
126#define ARB_MASTER_DIS 11 126#define ABRT_MASTER_DIS 11
127#define ARB_LOST 12 127#define ARB_LOST 12
128 128
129#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK)
130#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK)
131#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK)
132#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK)
133#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK)
134#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ)
135#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET)
136#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT)
137#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT)
138#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS)
139#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST)
140
141#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \
142 DW_IC_TX_ABRT_10ADDR1_NOACK | \
143 DW_IC_TX_ABRT_10ADDR2_NOACK | \
144 DW_IC_TX_ABRT_TXDATA_NOACK | \
145 DW_IC_TX_ABRT_GCALL_NOACK)
146
129static char *abort_sources[] = { 147static char *abort_sources[] = {
130 [ABRT_7B_ADDR_NOACK] = 148 [ABRT_7B_ADDR_NOACK] =
131 "slave address not acknowledged (7bit mode)", 149 "slave address not acknowledged (7bit mode)",
@@ -472,6 +490,24 @@ i2c_dw_read(struct dw_i2c_dev *dev)
472 } 490 }
473} 491}
474 492
493static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
494{
495 unsigned long abort_source = dev->abort_source;
496 int i;
497
498 for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
499 dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
500
501 if (abort_source & DW_IC_TX_ARB_LOST)
502 return -EAGAIN;
503 else if (abort_source & DW_IC_TX_ABRT_NOACK)
504 return -EREMOTEIO;
505 else if (abort_source & DW_IC_TX_ABRT_GCALL_READ)
506 return -EINVAL; /* wrong msgs[] data */
507 else
508 return -EIO;
509}
510
475/* 511/*
476 * Prepare controller for a transaction and call i2c_dw_xfer_msg 512 * Prepare controller for a transaction and call i2c_dw_xfer_msg
477 */ 513 */
@@ -493,6 +529,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
493 dev->msg_read_idx = 0; 529 dev->msg_read_idx = 0;
494 dev->msg_err = 0; 530 dev->msg_err = 0;
495 dev->status = STATUS_IDLE; 531 dev->status = STATUS_IDLE;
532 dev->abort_source = 0;
496 533
497 ret = i2c_dw_wait_bus_not_busy(dev); 534 ret = i2c_dw_wait_bus_not_busy(dev);
498 if (ret < 0) 535 if (ret < 0)
@@ -526,12 +563,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
526 563
527 /* We have an error */ 564 /* We have an error */
528 if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { 565 if (dev->cmd_err == DW_IC_ERR_TX_ABRT) {
529 unsigned long abort_source = dev->abort_source; 566 ret = i2c_dw_handle_tx_abort(dev);
530 int i; 567 goto done;
531
532 for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) {
533 dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
534 }
535 } 568 }
536 ret = -EIO; 569 ret = -EIO;
537 570