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 | } |
