diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-mv64xxx.c')
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 328 |
1 files changed, 197 insertions, 131 deletions
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 373f6d4e4080..30059c1df2a3 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c | |||
@@ -30,12 +30,12 @@ | |||
30 | #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) | 30 | #define MV64XXX_I2C_BAUD_DIV_N(val) (val & 0x7) |
31 | #define MV64XXX_I2C_BAUD_DIV_M(val) ((val & 0xf) << 3) | 31 | #define MV64XXX_I2C_BAUD_DIV_M(val) ((val & 0xf) << 3) |
32 | 32 | ||
33 | #define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 | 33 | #define MV64XXX_I2C_REG_CONTROL_ACK BIT(2) |
34 | #define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 | 34 | #define MV64XXX_I2C_REG_CONTROL_IFLG BIT(3) |
35 | #define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010 | 35 | #define MV64XXX_I2C_REG_CONTROL_STOP BIT(4) |
36 | #define MV64XXX_I2C_REG_CONTROL_START 0x00000020 | 36 | #define MV64XXX_I2C_REG_CONTROL_START BIT(5) |
37 | #define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040 | 37 | #define MV64XXX_I2C_REG_CONTROL_TWSIEN BIT(6) |
38 | #define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080 | 38 | #define MV64XXX_I2C_REG_CONTROL_INTEN BIT(7) |
39 | 39 | ||
40 | /* Ctlr status values */ | 40 | /* Ctlr status values */ |
41 | #define MV64XXX_I2C_STATUS_BUS_ERR 0x00 | 41 | #define MV64XXX_I2C_STATUS_BUS_ERR 0x00 |
@@ -68,19 +68,17 @@ | |||
68 | #define MV64XXX_I2C_REG_BRIDGE_TIMING 0xe0 | 68 | #define MV64XXX_I2C_REG_BRIDGE_TIMING 0xe0 |
69 | 69 | ||
70 | /* Bridge Control values */ | 70 | /* Bridge Control values */ |
71 | #define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x00000001 | 71 | #define MV64XXX_I2C_BRIDGE_CONTROL_WR BIT(0) |
72 | #define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x00000002 | 72 | #define MV64XXX_I2C_BRIDGE_CONTROL_RD BIT(1) |
73 | #define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 | 73 | #define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 |
74 | #define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x00001000 | 74 | #define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT BIT(12) |
75 | #define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT 13 | 75 | #define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT 13 |
76 | #define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT 16 | 76 | #define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT 16 |
77 | #define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x00080000 | 77 | #define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE BIT(19) |
78 | #define MV64XXX_I2C_BRIDGE_CONTROL_REPEATED_START BIT(20) | ||
78 | 79 | ||
79 | /* Bridge Status values */ | 80 | /* Bridge Status values */ |
80 | #define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x00000001 | 81 | #define MV64XXX_I2C_BRIDGE_STATUS_ERROR BIT(0) |
81 | #define MV64XXX_I2C_STATUS_OFFLOAD_ERROR 0xf0000001 | ||
82 | #define MV64XXX_I2C_STATUS_OFFLOAD_OK 0xf0000000 | ||
83 | |||
84 | 82 | ||
85 | /* Driver states */ | 83 | /* Driver states */ |
86 | enum { | 84 | enum { |
@@ -99,14 +97,12 @@ enum { | |||
99 | MV64XXX_I2C_ACTION_INVALID, | 97 | MV64XXX_I2C_ACTION_INVALID, |
100 | MV64XXX_I2C_ACTION_CONTINUE, | 98 | MV64XXX_I2C_ACTION_CONTINUE, |
101 | MV64XXX_I2C_ACTION_SEND_RESTART, | 99 | MV64XXX_I2C_ACTION_SEND_RESTART, |
102 | MV64XXX_I2C_ACTION_OFFLOAD_RESTART, | ||
103 | MV64XXX_I2C_ACTION_SEND_ADDR_1, | 100 | MV64XXX_I2C_ACTION_SEND_ADDR_1, |
104 | MV64XXX_I2C_ACTION_SEND_ADDR_2, | 101 | MV64XXX_I2C_ACTION_SEND_ADDR_2, |
105 | MV64XXX_I2C_ACTION_SEND_DATA, | 102 | MV64XXX_I2C_ACTION_SEND_DATA, |
106 | MV64XXX_I2C_ACTION_RCV_DATA, | 103 | MV64XXX_I2C_ACTION_RCV_DATA, |
107 | MV64XXX_I2C_ACTION_RCV_DATA_STOP, | 104 | MV64XXX_I2C_ACTION_RCV_DATA_STOP, |
108 | MV64XXX_I2C_ACTION_SEND_STOP, | 105 | MV64XXX_I2C_ACTION_SEND_STOP, |
109 | MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP, | ||
110 | }; | 106 | }; |
111 | 107 | ||
112 | struct mv64xxx_i2c_regs { | 108 | struct mv64xxx_i2c_regs { |
@@ -193,75 +189,6 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, | |||
193 | } | 189 | } |
194 | } | 190 | } |
195 | 191 | ||
196 | static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data) | ||
197 | { | ||
198 | unsigned long data_reg_hi = 0; | ||
199 | unsigned long data_reg_lo = 0; | ||
200 | unsigned long ctrl_reg; | ||
201 | struct i2c_msg *msg = drv_data->msgs; | ||
202 | |||
203 | if (!drv_data->offload_enabled) | ||
204 | return -EOPNOTSUPP; | ||
205 | |||
206 | /* Only regular transactions can be offloaded */ | ||
207 | if ((msg->flags & ~(I2C_M_TEN | I2C_M_RD)) != 0) | ||
208 | return -EINVAL; | ||
209 | |||
210 | /* Only 1-8 byte transfers can be offloaded */ | ||
211 | if (msg->len < 1 || msg->len > 8) | ||
212 | return -EINVAL; | ||
213 | |||
214 | /* Build transaction */ | ||
215 | ctrl_reg = MV64XXX_I2C_BRIDGE_CONTROL_ENABLE | | ||
216 | (msg->addr << MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT); | ||
217 | |||
218 | if ((msg->flags & I2C_M_TEN) != 0) | ||
219 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT; | ||
220 | |||
221 | if ((msg->flags & I2C_M_RD) == 0) { | ||
222 | u8 local_buf[8] = { 0 }; | ||
223 | |||
224 | memcpy(local_buf, msg->buf, msg->len); | ||
225 | data_reg_lo = cpu_to_le32(*((u32 *)local_buf)); | ||
226 | data_reg_hi = cpu_to_le32(*((u32 *)(local_buf+4))); | ||
227 | |||
228 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR | | ||
229 | (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT; | ||
230 | |||
231 | writel(data_reg_lo, | ||
232 | drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO); | ||
233 | writel(data_reg_hi, | ||
234 | drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI); | ||
235 | |||
236 | } else { | ||
237 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_RD | | ||
238 | (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT; | ||
239 | } | ||
240 | |||
241 | /* Execute transaction */ | ||
242 | writel(ctrl_reg, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static void | ||
248 | mv64xxx_i2c_update_offload_data(struct mv64xxx_i2c_data *drv_data) | ||
249 | { | ||
250 | struct i2c_msg *msg = drv_data->msg; | ||
251 | |||
252 | if (msg->flags & I2C_M_RD) { | ||
253 | u32 data_reg_lo = readl(drv_data->reg_base + | ||
254 | MV64XXX_I2C_REG_RX_DATA_LO); | ||
255 | u32 data_reg_hi = readl(drv_data->reg_base + | ||
256 | MV64XXX_I2C_REG_RX_DATA_HI); | ||
257 | u8 local_buf[8] = { 0 }; | ||
258 | |||
259 | *((u32 *)local_buf) = le32_to_cpu(data_reg_lo); | ||
260 | *((u32 *)(local_buf+4)) = le32_to_cpu(data_reg_hi); | ||
261 | memcpy(msg->buf, local_buf, msg->len); | ||
262 | } | ||
263 | |||
264 | } | ||
265 | /* | 192 | /* |
266 | ***************************************************************************** | 193 | ***************************************************************************** |
267 | * | 194 | * |
@@ -389,16 +316,6 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) | |||
389 | drv_data->rc = -ENXIO; | 316 | drv_data->rc = -ENXIO; |
390 | break; | 317 | break; |
391 | 318 | ||
392 | case MV64XXX_I2C_STATUS_OFFLOAD_OK: | ||
393 | if (drv_data->send_stop || drv_data->aborting) { | ||
394 | drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP; | ||
395 | drv_data->state = MV64XXX_I2C_STATE_IDLE; | ||
396 | } else { | ||
397 | drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_RESTART; | ||
398 | drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_RESTART; | ||
399 | } | ||
400 | break; | ||
401 | |||
402 | default: | 319 | default: |
403 | dev_err(&drv_data->adapter.dev, | 320 | dev_err(&drv_data->adapter.dev, |
404 | "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " | 321 | "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " |
@@ -419,25 +336,15 @@ static void mv64xxx_i2c_send_start(struct mv64xxx_i2c_data *drv_data) | |||
419 | drv_data->aborting = 0; | 336 | drv_data->aborting = 0; |
420 | drv_data->rc = 0; | 337 | drv_data->rc = 0; |
421 | 338 | ||
422 | /* Can we offload this msg ? */ | 339 | mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); |
423 | if (mv64xxx_i2c_offload_msg(drv_data) < 0) { | 340 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, |
424 | /* No, switch to standard path */ | 341 | drv_data->reg_base + drv_data->reg_offsets.control); |
425 | mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); | ||
426 | writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, | ||
427 | drv_data->reg_base + drv_data->reg_offsets.control); | ||
428 | } | ||
429 | } | 342 | } |
430 | 343 | ||
431 | static void | 344 | static void |
432 | mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | 345 | mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) |
433 | { | 346 | { |
434 | switch(drv_data->action) { | 347 | switch(drv_data->action) { |
435 | case MV64XXX_I2C_ACTION_OFFLOAD_RESTART: | ||
436 | mv64xxx_i2c_update_offload_data(drv_data); | ||
437 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); | ||
438 | writel(0, drv_data->reg_base + | ||
439 | MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); | ||
440 | /* FALLTHRU */ | ||
441 | case MV64XXX_I2C_ACTION_SEND_RESTART: | 348 | case MV64XXX_I2C_ACTION_SEND_RESTART: |
442 | /* We should only get here if we have further messages */ | 349 | /* We should only get here if we have further messages */ |
443 | BUG_ON(drv_data->num_msgs == 0); | 350 | BUG_ON(drv_data->num_msgs == 0); |
@@ -518,16 +425,71 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) | |||
518 | drv_data->block = 0; | 425 | drv_data->block = 0; |
519 | wake_up(&drv_data->waitq); | 426 | wake_up(&drv_data->waitq); |
520 | break; | 427 | break; |
428 | } | ||
429 | } | ||
521 | 430 | ||
522 | case MV64XXX_I2C_ACTION_OFFLOAD_SEND_STOP: | 431 | static void |
523 | mv64xxx_i2c_update_offload_data(drv_data); | 432 | mv64xxx_i2c_read_offload_rx_data(struct mv64xxx_i2c_data *drv_data, |
524 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); | 433 | struct i2c_msg *msg) |
525 | writel(0, drv_data->reg_base + | 434 | { |
526 | MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); | 435 | u32 buf[2]; |
527 | drv_data->block = 0; | 436 | |
528 | wake_up(&drv_data->waitq); | 437 | buf[0] = readl(drv_data->reg_base + MV64XXX_I2C_REG_RX_DATA_LO); |
529 | break; | 438 | buf[1] = readl(drv_data->reg_base + MV64XXX_I2C_REG_RX_DATA_HI); |
439 | |||
440 | memcpy(msg->buf, buf, msg->len); | ||
441 | } | ||
442 | |||
443 | static int | ||
444 | mv64xxx_i2c_intr_offload(struct mv64xxx_i2c_data *drv_data) | ||
445 | { | ||
446 | u32 cause, status; | ||
447 | |||
448 | cause = readl(drv_data->reg_base + | ||
449 | MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); | ||
450 | if (!cause) | ||
451 | return IRQ_NONE; | ||
452 | |||
453 | status = readl(drv_data->reg_base + | ||
454 | MV64XXX_I2C_REG_BRIDGE_STATUS); | ||
455 | |||
456 | if (status & MV64XXX_I2C_BRIDGE_STATUS_ERROR) { | ||
457 | drv_data->rc = -EIO; | ||
458 | goto out; | ||
459 | } | ||
460 | |||
461 | drv_data->rc = 0; | ||
462 | |||
463 | /* | ||
464 | * Transaction is a one message read transaction, read data | ||
465 | * for this message. | ||
466 | */ | ||
467 | if (drv_data->num_msgs == 1 && drv_data->msgs[0].flags & I2C_M_RD) { | ||
468 | mv64xxx_i2c_read_offload_rx_data(drv_data, drv_data->msgs); | ||
469 | drv_data->msgs++; | ||
470 | drv_data->num_msgs--; | ||
471 | } | ||
472 | /* | ||
473 | * Transaction is a two messages write/read transaction, read | ||
474 | * data for the second (read) message. | ||
475 | */ | ||
476 | else if (drv_data->num_msgs == 2 && | ||
477 | !(drv_data->msgs[0].flags & I2C_M_RD) && | ||
478 | drv_data->msgs[1].flags & I2C_M_RD) { | ||
479 | mv64xxx_i2c_read_offload_rx_data(drv_data, drv_data->msgs + 1); | ||
480 | drv_data->msgs += 2; | ||
481 | drv_data->num_msgs -= 2; | ||
530 | } | 482 | } |
483 | |||
484 | out: | ||
485 | writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); | ||
486 | writel(0, drv_data->reg_base + | ||
487 | MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); | ||
488 | drv_data->block = 0; | ||
489 | |||
490 | wake_up(&drv_data->waitq); | ||
491 | |||
492 | return IRQ_HANDLED; | ||
531 | } | 493 | } |
532 | 494 | ||
533 | static irqreturn_t | 495 | static irqreturn_t |
@@ -540,20 +502,9 @@ mv64xxx_i2c_intr(int irq, void *dev_id) | |||
540 | 502 | ||
541 | spin_lock_irqsave(&drv_data->lock, flags); | 503 | spin_lock_irqsave(&drv_data->lock, flags); |
542 | 504 | ||
543 | if (drv_data->offload_enabled) { | 505 | if (drv_data->offload_enabled) |
544 | while (readl(drv_data->reg_base + | 506 | rc = mv64xxx_i2c_intr_offload(drv_data); |
545 | MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { | 507 | |
546 | int reg_status = readl(drv_data->reg_base + | ||
547 | MV64XXX_I2C_REG_BRIDGE_STATUS); | ||
548 | if (reg_status & MV64XXX_I2C_BRIDGE_STATUS_ERROR) | ||
549 | status = MV64XXX_I2C_STATUS_OFFLOAD_ERROR; | ||
550 | else | ||
551 | status = MV64XXX_I2C_STATUS_OFFLOAD_OK; | ||
552 | mv64xxx_i2c_fsm(drv_data, status); | ||
553 | mv64xxx_i2c_do_action(drv_data); | ||
554 | rc = IRQ_HANDLED; | ||
555 | } | ||
556 | } | ||
557 | while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & | 508 | while (readl(drv_data->reg_base + drv_data->reg_offsets.control) & |
558 | MV64XXX_I2C_REG_CONTROL_IFLG) { | 509 | MV64XXX_I2C_REG_CONTROL_IFLG) { |
559 | status = readl(drv_data->reg_base + drv_data->reg_offsets.status); | 510 | status = readl(drv_data->reg_base + drv_data->reg_offsets.status); |
@@ -635,6 +586,117 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, | |||
635 | return drv_data->rc; | 586 | return drv_data->rc; |
636 | } | 587 | } |
637 | 588 | ||
589 | static void | ||
590 | mv64xxx_i2c_prepare_tx(struct mv64xxx_i2c_data *drv_data) | ||
591 | { | ||
592 | struct i2c_msg *msg = drv_data->msgs; | ||
593 | u32 buf[2]; | ||
594 | |||
595 | memcpy(buf, msg->buf, msg->len); | ||
596 | |||
597 | writel(buf[0], drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO); | ||
598 | writel(buf[1], drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI); | ||
599 | } | ||
600 | |||
601 | static int | ||
602 | mv64xxx_i2c_offload_xfer(struct mv64xxx_i2c_data *drv_data) | ||
603 | { | ||
604 | struct i2c_msg *msgs = drv_data->msgs; | ||
605 | int num = drv_data->num_msgs; | ||
606 | unsigned long ctrl_reg; | ||
607 | unsigned long flags; | ||
608 | |||
609 | spin_lock_irqsave(&drv_data->lock, flags); | ||
610 | |||
611 | /* Build transaction */ | ||
612 | ctrl_reg = MV64XXX_I2C_BRIDGE_CONTROL_ENABLE | | ||
613 | (msgs[0].addr << MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT); | ||
614 | |||
615 | if (msgs[0].flags & I2C_M_TEN) | ||
616 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT; | ||
617 | |||
618 | /* Single write message transaction */ | ||
619 | if (num == 1 && !(msgs[0].flags & I2C_M_RD)) { | ||
620 | size_t len = msgs[0].len - 1; | ||
621 | |||
622 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR | | ||
623 | (len << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT); | ||
624 | mv64xxx_i2c_prepare_tx(drv_data); | ||
625 | } | ||
626 | /* Single read message transaction */ | ||
627 | else if (num == 1 && msgs[0].flags & I2C_M_RD) { | ||
628 | size_t len = msgs[0].len - 1; | ||
629 | |||
630 | ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_RD | | ||
631 | (len << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT); | ||
632 | } | ||
633 | /* | ||
634 | * Transaction with one write and one read message. This is | ||
635 | * guaranteed by the mv64xx_i2c_can_offload() checks. | ||
636 | */ | ||
637 | else if (num == 2) { | ||
638 | size_t lentx = msgs[0].len - 1; | ||
639 | size_t lenrx = msgs[1].len - 1; | ||
640 | |||
641 | ctrl_reg |= | ||
642 | MV64XXX_I2C_BRIDGE_CONTROL_RD | | ||
643 | MV64XXX_I2C_BRIDGE_CONTROL_WR | | ||
644 | (lentx << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT) | | ||
645 | (lenrx << MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT) | | ||
646 | MV64XXX_I2C_BRIDGE_CONTROL_REPEATED_START; | ||
647 | mv64xxx_i2c_prepare_tx(drv_data); | ||
648 | } | ||
649 | |||
650 | /* Execute transaction */ | ||
651 | drv_data->block = 1; | ||
652 | writel(ctrl_reg, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); | ||
653 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
654 | |||
655 | mv64xxx_i2c_wait_for_completion(drv_data); | ||
656 | |||
657 | return drv_data->rc; | ||
658 | } | ||
659 | |||
660 | static bool | ||
661 | mv64xxx_i2c_valid_offload_sz(struct i2c_msg *msg) | ||
662 | { | ||
663 | return msg->len <= 8 && msg->len >= 1; | ||
664 | } | ||
665 | |||
666 | static bool | ||
667 | mv64xxx_i2c_can_offload(struct mv64xxx_i2c_data *drv_data) | ||
668 | { | ||
669 | struct i2c_msg *msgs = drv_data->msgs; | ||
670 | int num = drv_data->num_msgs; | ||
671 | |||
672 | return false; | ||
673 | |||
674 | if (!drv_data->offload_enabled) | ||
675 | return false; | ||
676 | |||
677 | /* | ||
678 | * We can offload a transaction consisting of a single | ||
679 | * message, as long as the message has a length between 1 and | ||
680 | * 8 bytes. | ||
681 | */ | ||
682 | if (num == 1 && mv64xxx_i2c_valid_offload_sz(msgs)) | ||
683 | return true; | ||
684 | |||
685 | /* | ||
686 | * We can offload a transaction consisting of two messages, if | ||
687 | * the first is a write and a second is a read, and both have | ||
688 | * a length between 1 and 8 bytes. | ||
689 | */ | ||
690 | if (num == 2 && | ||
691 | mv64xxx_i2c_valid_offload_sz(msgs) && | ||
692 | mv64xxx_i2c_valid_offload_sz(msgs + 1) && | ||
693 | !(msgs[0].flags & I2C_M_RD) && | ||
694 | msgs[1].flags & I2C_M_RD) | ||
695 | return true; | ||
696 | |||
697 | return false; | ||
698 | } | ||
699 | |||
638 | /* | 700 | /* |
639 | ***************************************************************************** | 701 | ***************************************************************************** |
640 | * | 702 | * |
@@ -658,7 +720,11 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | |||
658 | drv_data->msgs = msgs; | 720 | drv_data->msgs = msgs; |
659 | drv_data->num_msgs = num; | 721 | drv_data->num_msgs = num; |
660 | 722 | ||
661 | rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); | 723 | if (mv64xxx_i2c_can_offload(drv_data)) |
724 | rc = mv64xxx_i2c_offload_xfer(drv_data); | ||
725 | else | ||
726 | rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[0], num == 1); | ||
727 | |||
662 | if (rc < 0) | 728 | if (rc < 0) |
663 | ret = rc; | 729 | ret = rc; |
664 | 730 | ||