diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-20 16:52:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-20 16:52:52 -0500 |
commit | a4e1328a9d20ccf4a9e5a19fce172e6deb2a33e2 (patch) | |
tree | 6dca79d197408609608a1d3ac732dbbc94587f6f /drivers/i2c | |
parent | cdce6ac277a4a1aa5316cd0cdf30fff927433917 (diff) | |
parent | fe07adec730d271c91f4160f96a0f24fe7553c63 (diff) |
Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull more i2c updates from Wolfram Sang:
"Included are two bugfixes needing some bigger refactoring (sh_mobile:
deferred probe with DMA, mv64xxx: fix offload support) and one
deprecated driver removal I thought would go in via ppc but I
misunderstood. It has a proper ack from BenH"
* 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
i2c: sh_mobile: fix uninitialized var when debug is enabled
macintosh: therm_pm72: delete deprecated driver
i2c: sh_mobile: I2C_SH_MOBILE should depend on HAS_DMA
i2c: sh_mobile: rework deferred probing
i2c: sh_mobile: refactor DMA setup
i2c: mv64xxx: rework offload support to fix several problems
i2c: mv64xxx: use BIT() macro for register value definitions
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 328 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 112 |
3 files changed, 252 insertions, 189 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 91a488c7cc44..31e8308ba899 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -753,6 +753,7 @@ config I2C_SH7760 | |||
753 | 753 | ||
754 | config I2C_SH_MOBILE | 754 | config I2C_SH_MOBILE |
755 | tristate "SuperH Mobile I2C Controller" | 755 | tristate "SuperH Mobile I2C Controller" |
756 | depends on HAS_DMA | ||
756 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST | 757 | depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST |
757 | help | 758 | help |
758 | If you say yes to this option, support will be included for the | 759 | If you say yes to this option, support will be included for the |
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 | ||
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index d7efaf44868b..440d5dbc8b5f 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -140,6 +140,7 @@ struct sh_mobile_i2c_data { | |||
140 | int sr; | 140 | int sr; |
141 | bool send_stop; | 141 | bool send_stop; |
142 | 142 | ||
143 | struct resource *res; | ||
143 | struct dma_chan *dma_tx; | 144 | struct dma_chan *dma_tx; |
144 | struct dma_chan *dma_rx; | 145 | struct dma_chan *dma_rx; |
145 | struct scatterlist sg; | 146 | struct scatterlist sg; |
@@ -539,6 +540,42 @@ static void sh_mobile_i2c_dma_callback(void *data) | |||
539 | iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); | 540 | iic_set_clr(pd, ICIC, 0, ICIC_TDMAE | ICIC_RDMAE); |
540 | } | 541 | } |
541 | 542 | ||
543 | static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev, | ||
544 | enum dma_transfer_direction dir, dma_addr_t port_addr) | ||
545 | { | ||
546 | struct dma_chan *chan; | ||
547 | struct dma_slave_config cfg; | ||
548 | char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx"; | ||
549 | int ret; | ||
550 | |||
551 | chan = dma_request_slave_channel_reason(dev, chan_name); | ||
552 | if (IS_ERR(chan)) { | ||
553 | ret = PTR_ERR(chan); | ||
554 | dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret); | ||
555 | return chan; | ||
556 | } | ||
557 | |||
558 | memset(&cfg, 0, sizeof(cfg)); | ||
559 | cfg.direction = dir; | ||
560 | if (dir == DMA_MEM_TO_DEV) { | ||
561 | cfg.dst_addr = port_addr; | ||
562 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
563 | } else { | ||
564 | cfg.src_addr = port_addr; | ||
565 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
566 | } | ||
567 | |||
568 | ret = dmaengine_slave_config(chan, &cfg); | ||
569 | if (ret) { | ||
570 | dev_dbg(dev, "slave_config failed for %s (%d)\n", chan_name, ret); | ||
571 | dma_release_channel(chan); | ||
572 | return ERR_PTR(ret); | ||
573 | } | ||
574 | |||
575 | dev_dbg(dev, "got DMA channel for %s\n", chan_name); | ||
576 | return chan; | ||
577 | } | ||
578 | |||
542 | static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) | 579 | static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) |
543 | { | 580 | { |
544 | bool read = pd->msg->flags & I2C_M_RD; | 581 | bool read = pd->msg->flags & I2C_M_RD; |
@@ -548,7 +585,16 @@ static void sh_mobile_i2c_xfer_dma(struct sh_mobile_i2c_data *pd) | |||
548 | dma_addr_t dma_addr; | 585 | dma_addr_t dma_addr; |
549 | dma_cookie_t cookie; | 586 | dma_cookie_t cookie; |
550 | 587 | ||
551 | if (!chan) | 588 | if (PTR_ERR(chan) == -EPROBE_DEFER) { |
589 | if (read) | ||
590 | chan = pd->dma_rx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_DEV_TO_MEM, | ||
591 | pd->res->start + ICDR); | ||
592 | else | ||
593 | chan = pd->dma_tx = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_MEM_TO_DEV, | ||
594 | pd->res->start + ICDR); | ||
595 | } | ||
596 | |||
597 | if (IS_ERR(chan)) | ||
552 | return; | 598 | return; |
553 | 599 | ||
554 | dma_addr = dma_map_single(chan->device->dev, pd->msg->buf, pd->msg->len, dir); | 600 | dma_addr = dma_map_single(chan->device->dev, pd->msg->buf, pd->msg->len, dir); |
@@ -747,56 +793,16 @@ static const struct of_device_id sh_mobile_i2c_dt_ids[] = { | |||
747 | }; | 793 | }; |
748 | MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); | 794 | MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); |
749 | 795 | ||
750 | static int sh_mobile_i2c_request_dma_chan(struct device *dev, enum dma_transfer_direction dir, | ||
751 | dma_addr_t port_addr, struct dma_chan **chan_ptr) | ||
752 | { | ||
753 | struct dma_chan *chan; | ||
754 | struct dma_slave_config cfg; | ||
755 | char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx"; | ||
756 | int ret; | ||
757 | |||
758 | *chan_ptr = NULL; | ||
759 | |||
760 | chan = dma_request_slave_channel_reason(dev, chan_name); | ||
761 | if (IS_ERR(chan)) { | ||
762 | ret = PTR_ERR(chan); | ||
763 | dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret); | ||
764 | return ret; | ||
765 | } | ||
766 | |||
767 | memset(&cfg, 0, sizeof(cfg)); | ||
768 | cfg.direction = dir; | ||
769 | if (dir == DMA_MEM_TO_DEV) { | ||
770 | cfg.dst_addr = port_addr; | ||
771 | cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
772 | } else { | ||
773 | cfg.src_addr = port_addr; | ||
774 | cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; | ||
775 | } | ||
776 | |||
777 | ret = dmaengine_slave_config(chan, &cfg); | ||
778 | if (ret) { | ||
779 | dev_dbg(dev, "slave_config failed for %s (%d)\n", chan_name, ret); | ||
780 | dma_release_channel(chan); | ||
781 | return ret; | ||
782 | } | ||
783 | |||
784 | *chan_ptr = chan; | ||
785 | |||
786 | dev_dbg(dev, "got DMA channel for %s\n", chan_name); | ||
787 | return 0; | ||
788 | } | ||
789 | |||
790 | static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd) | 796 | static void sh_mobile_i2c_release_dma(struct sh_mobile_i2c_data *pd) |
791 | { | 797 | { |
792 | if (pd->dma_tx) { | 798 | if (!IS_ERR(pd->dma_tx)) { |
793 | dma_release_channel(pd->dma_tx); | 799 | dma_release_channel(pd->dma_tx); |
794 | pd->dma_tx = NULL; | 800 | pd->dma_tx = ERR_PTR(-EPROBE_DEFER); |
795 | } | 801 | } |
796 | 802 | ||
797 | if (pd->dma_rx) { | 803 | if (!IS_ERR(pd->dma_rx)) { |
798 | dma_release_channel(pd->dma_rx); | 804 | dma_release_channel(pd->dma_rx); |
799 | pd->dma_rx = NULL; | 805 | pd->dma_rx = ERR_PTR(-EPROBE_DEFER); |
800 | } | 806 | } |
801 | } | 807 | } |
802 | 808 | ||
@@ -849,6 +855,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
849 | 855 | ||
850 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 856 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
851 | 857 | ||
858 | pd->res = res; | ||
852 | pd->reg = devm_ioremap_resource(&dev->dev, res); | 859 | pd->reg = devm_ioremap_resource(&dev->dev, res); |
853 | if (IS_ERR(pd->reg)) | 860 | if (IS_ERR(pd->reg)) |
854 | return PTR_ERR(pd->reg); | 861 | return PTR_ERR(pd->reg); |
@@ -889,17 +896,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
889 | /* Init DMA */ | 896 | /* Init DMA */ |
890 | sg_init_table(&pd->sg, 1); | 897 | sg_init_table(&pd->sg, 1); |
891 | pd->dma_direction = DMA_NONE; | 898 | pd->dma_direction = DMA_NONE; |
892 | ret = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_DEV_TO_MEM, | 899 | pd->dma_rx = pd->dma_tx = ERR_PTR(-EPROBE_DEFER); |
893 | res->start + ICDR, &pd->dma_rx); | ||
894 | if (ret == -EPROBE_DEFER) | ||
895 | return ret; | ||
896 | |||
897 | ret = sh_mobile_i2c_request_dma_chan(pd->dev, DMA_MEM_TO_DEV, | ||
898 | res->start + ICDR, &pd->dma_tx); | ||
899 | if (ret == -EPROBE_DEFER) { | ||
900 | sh_mobile_i2c_release_dma(pd); | ||
901 | return ret; | ||
902 | } | ||
903 | 900 | ||
904 | /* Enable Runtime PM for this device. | 901 | /* Enable Runtime PM for this device. |
905 | * | 902 | * |
@@ -937,8 +934,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
937 | return ret; | 934 | return ret; |
938 | } | 935 | } |
939 | 936 | ||
940 | dev_info(&dev->dev, "I2C adapter %d, bus speed %lu Hz, DMA=%c\n", | 937 | dev_info(&dev->dev, "I2C adapter %d, bus speed %lu Hz\n", adap->nr, pd->bus_speed); |
941 | adap->nr, pd->bus_speed, (pd->dma_rx || pd->dma_tx) ? 'y' : 'n'); | ||
942 | 938 | ||
943 | return 0; | 939 | return 0; |
944 | } | 940 | } |