diff options
| -rw-r--r-- | drivers/spi/spi-sh-msiof.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 2a4354dcd661..887c2084130f 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c | |||
| @@ -636,48 +636,38 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, | |||
| 636 | dma_cookie_t cookie; | 636 | dma_cookie_t cookie; |
| 637 | int ret; | 637 | int ret; |
| 638 | 638 | ||
| 639 | if (tx) { | 639 | /* First prepare and submit the DMA request(s), as this may fail */ |
| 640 | ier_bits |= IER_TDREQE | IER_TDMAE; | ||
| 641 | dma_sync_single_for_device(p->master->dma_tx->device->dev, | ||
| 642 | p->tx_dma_addr, len, DMA_TO_DEVICE); | ||
| 643 | desc_tx = dmaengine_prep_slave_single(p->master->dma_tx, | ||
| 644 | p->tx_dma_addr, len, DMA_TO_DEVICE, | ||
| 645 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 646 | if (!desc_tx) | ||
| 647 | return -EAGAIN; | ||
| 648 | } | ||
| 649 | |||
| 650 | if (rx) { | 640 | if (rx) { |
| 651 | ier_bits |= IER_RDREQE | IER_RDMAE; | 641 | ier_bits |= IER_RDREQE | IER_RDMAE; |
| 652 | desc_rx = dmaengine_prep_slave_single(p->master->dma_rx, | 642 | desc_rx = dmaengine_prep_slave_single(p->master->dma_rx, |
| 653 | p->rx_dma_addr, len, DMA_FROM_DEVICE, | 643 | p->rx_dma_addr, len, DMA_FROM_DEVICE, |
| 654 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 644 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
| 655 | if (!desc_rx) | 645 | if (!desc_rx) { |
| 656 | return -EAGAIN; | 646 | ret = -EAGAIN; |
| 657 | } | 647 | goto no_dma_rx; |
| 658 | 648 | } | |
| 659 | /* 1 stage FIFO watermarks for DMA */ | ||
| 660 | sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1); | ||
| 661 | |||
| 662 | /* setup msiof transfer mode registers (32-bit words) */ | ||
| 663 | sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4); | ||
| 664 | |||
| 665 | sh_msiof_write(p, IER, ier_bits); | ||
| 666 | |||
| 667 | reinit_completion(&p->done); | ||
| 668 | 649 | ||
| 669 | if (rx) { | ||
| 670 | desc_rx->callback = sh_msiof_dma_complete; | 650 | desc_rx->callback = sh_msiof_dma_complete; |
| 671 | desc_rx->callback_param = p; | 651 | desc_rx->callback_param = p; |
| 672 | cookie = dmaengine_submit(desc_rx); | 652 | cookie = dmaengine_submit(desc_rx); |
| 673 | if (dma_submit_error(cookie)) { | 653 | if (dma_submit_error(cookie)) { |
| 674 | ret = cookie; | 654 | ret = cookie; |
| 675 | goto stop_ier; | 655 | goto no_dma_rx; |
| 676 | } | 656 | } |
| 677 | dma_async_issue_pending(p->master->dma_rx); | ||
| 678 | } | 657 | } |
| 679 | 658 | ||
| 680 | if (tx) { | 659 | if (tx) { |
| 660 | ier_bits |= IER_TDREQE | IER_TDMAE; | ||
| 661 | dma_sync_single_for_device(p->master->dma_tx->device->dev, | ||
| 662 | p->tx_dma_addr, len, DMA_TO_DEVICE); | ||
| 663 | desc_tx = dmaengine_prep_slave_single(p->master->dma_tx, | ||
| 664 | p->tx_dma_addr, len, DMA_TO_DEVICE, | ||
| 665 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 666 | if (!desc_tx) { | ||
| 667 | ret = -EAGAIN; | ||
| 668 | goto no_dma_tx; | ||
| 669 | } | ||
| 670 | |||
| 681 | if (rx) { | 671 | if (rx) { |
| 682 | /* No callback */ | 672 | /* No callback */ |
| 683 | desc_tx->callback = NULL; | 673 | desc_tx->callback = NULL; |
| @@ -688,15 +678,30 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, | |||
| 688 | cookie = dmaengine_submit(desc_tx); | 678 | cookie = dmaengine_submit(desc_tx); |
| 689 | if (dma_submit_error(cookie)) { | 679 | if (dma_submit_error(cookie)) { |
| 690 | ret = cookie; | 680 | ret = cookie; |
| 691 | goto stop_rx; | 681 | goto no_dma_tx; |
| 692 | } | 682 | } |
| 693 | dma_async_issue_pending(p->master->dma_tx); | ||
| 694 | } | 683 | } |
| 695 | 684 | ||
| 685 | /* 1 stage FIFO watermarks for DMA */ | ||
| 686 | sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1); | ||
| 687 | |||
| 688 | /* setup msiof transfer mode registers (32-bit words) */ | ||
| 689 | sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4); | ||
| 690 | |||
| 691 | sh_msiof_write(p, IER, ier_bits); | ||
| 692 | |||
| 693 | reinit_completion(&p->done); | ||
| 694 | |||
| 695 | /* Now start DMA */ | ||
| 696 | if (tx) | ||
| 697 | dma_async_issue_pending(p->master->dma_rx); | ||
| 698 | if (rx) | ||
| 699 | dma_async_issue_pending(p->master->dma_tx); | ||
| 700 | |||
| 696 | ret = sh_msiof_spi_start(p, rx); | 701 | ret = sh_msiof_spi_start(p, rx); |
| 697 | if (ret) { | 702 | if (ret) { |
| 698 | dev_err(&p->pdev->dev, "failed to start hardware\n"); | 703 | dev_err(&p->pdev->dev, "failed to start hardware\n"); |
| 699 | goto stop_tx; | 704 | goto stop_dma; |
| 700 | } | 705 | } |
| 701 | 706 | ||
| 702 | /* wait for tx fifo to be emptied / rx fifo to be filled */ | 707 | /* wait for tx fifo to be emptied / rx fifo to be filled */ |
| @@ -726,14 +731,14 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, | |||
| 726 | stop_reset: | 731 | stop_reset: |
| 727 | sh_msiof_reset_str(p); | 732 | sh_msiof_reset_str(p); |
| 728 | sh_msiof_spi_stop(p, rx); | 733 | sh_msiof_spi_stop(p, rx); |
| 729 | stop_tx: | 734 | stop_dma: |
| 730 | if (tx) | 735 | if (tx) |
| 731 | dmaengine_terminate_all(p->master->dma_tx); | 736 | dmaengine_terminate_all(p->master->dma_tx); |
| 732 | stop_rx: | 737 | no_dma_tx: |
| 733 | if (rx) | 738 | if (rx) |
| 734 | dmaengine_terminate_all(p->master->dma_rx); | 739 | dmaengine_terminate_all(p->master->dma_rx); |
| 735 | stop_ier: | ||
| 736 | sh_msiof_write(p, IER, 0); | 740 | sh_msiof_write(p, IER, 0); |
| 741 | no_dma_rx: | ||
| 737 | return ret; | 742 | return ret; |
| 738 | } | 743 | } |
| 739 | 744 | ||
