diff options
author | Shinya Kuribayashi <shinya.kuribayashi@necel.com> | 2009-11-06 07:51:57 -0500 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2009-12-08 19:19:13 -0500 |
commit | ce6eb574a1d9bbde72998ed9c95e9bf35c8f4131 (patch) | |
tree | 8d4d10f65061ac39b1d48103dc2e2d23a4b10b63 /drivers/i2c | |
parent | 597fe310f16d8246eec856326aa497bfa1b5bfa3 (diff) |
i2c-designware: Tx abort cleanups
* ABRT_MASTER_DIS: Fix a typo.
* i2c_dw_handle_tx_abort: Return an appropriate error number
depending on abort_source.
* i2c_dw_xfer: Add a missing abort_source initialization.
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi@necel.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware.c | 47 |
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 | |||
129 | static char *abort_sources[] = { | 147 | static 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 | ||
493 | static 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 | ||