diff options
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index a54685bb7e53..9ca6454cfadc 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -660,13 +660,25 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) | |||
660 | return IRQ_NONE; | 660 | return IRQ_NONE; |
661 | } | 661 | } |
662 | 662 | ||
663 | static void reset_sccr1(struct driver_data *drv_data) | ||
664 | { | ||
665 | void __iomem *reg = drv_data->ioaddr; | ||
666 | struct chip_data *chip = drv_data->cur_chip; | ||
667 | u32 sccr1_reg; | ||
668 | |||
669 | sccr1_reg = read_SSCR1(reg) & ~drv_data->int_cr1; | ||
670 | sccr1_reg &= ~SSCR1_RFT; | ||
671 | sccr1_reg |= chip->threshold; | ||
672 | write_SSCR1(sccr1_reg, reg); | ||
673 | } | ||
674 | |||
663 | static void int_error_stop(struct driver_data *drv_data, const char* msg) | 675 | static void int_error_stop(struct driver_data *drv_data, const char* msg) |
664 | { | 676 | { |
665 | void __iomem *reg = drv_data->ioaddr; | 677 | void __iomem *reg = drv_data->ioaddr; |
666 | 678 | ||
667 | /* Stop and reset SSP */ | 679 | /* Stop and reset SSP */ |
668 | write_SSSR_CS(drv_data, drv_data->clear_sr); | 680 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
669 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 681 | reset_sccr1(drv_data); |
670 | if (!pxa25x_ssp_comp(drv_data)) | 682 | if (!pxa25x_ssp_comp(drv_data)) |
671 | write_SSTO(0, reg); | 683 | write_SSTO(0, reg); |
672 | flush(drv_data); | 684 | flush(drv_data); |
@@ -684,7 +696,7 @@ static void int_transfer_complete(struct driver_data *drv_data) | |||
684 | 696 | ||
685 | /* Stop SSP */ | 697 | /* Stop SSP */ |
686 | write_SSSR_CS(drv_data, drv_data->clear_sr); | 698 | write_SSSR_CS(drv_data, drv_data->clear_sr); |
687 | write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); | 699 | reset_sccr1(drv_data); |
688 | if (!pxa25x_ssp_comp(drv_data)) | 700 | if (!pxa25x_ssp_comp(drv_data)) |
689 | write_SSTO(0, reg); | 701 | write_SSTO(0, reg); |
690 | 702 | ||
@@ -739,24 +751,34 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) | |||
739 | } | 751 | } |
740 | 752 | ||
741 | if (drv_data->tx == drv_data->tx_end) { | 753 | if (drv_data->tx == drv_data->tx_end) { |
742 | write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); | 754 | u32 bytes_left; |
743 | /* PXA25x_SSP has no timeout, read trailing bytes */ | 755 | u32 sccr1_reg; |
756 | |||
757 | sccr1_reg = read_SSCR1(reg); | ||
758 | sccr1_reg &= ~SSCR1_TIE; | ||
759 | |||
760 | /* | ||
761 | * PXA25x_SSP has no timeout, set up rx threshould for the | ||
762 | * remaing RX bytes. | ||
763 | */ | ||
744 | if (pxa25x_ssp_comp(drv_data)) { | 764 | if (pxa25x_ssp_comp(drv_data)) { |
745 | if (!wait_ssp_rx_stall(reg)) | 765 | |
746 | { | 766 | sccr1_reg &= ~SSCR1_RFT; |
747 | int_error_stop(drv_data, "interrupt_transfer: " | 767 | |
748 | "rx stall failed"); | 768 | bytes_left = drv_data->rx_end - drv_data->rx; |
749 | return IRQ_HANDLED; | 769 | switch (drv_data->n_bytes) { |
750 | } | 770 | case 4: |
751 | if (!drv_data->read(drv_data)) | 771 | bytes_left >>= 1; |
752 | { | 772 | case 2: |
753 | int_error_stop(drv_data, | 773 | bytes_left >>= 1; |
754 | "interrupt_transfer: " | ||
755 | "trailing byte read failed"); | ||
756 | return IRQ_HANDLED; | ||
757 | } | 774 | } |
758 | int_transfer_complete(drv_data); | 775 | |
776 | if (bytes_left > RX_THRESH_DFLT) | ||
777 | bytes_left = RX_THRESH_DFLT; | ||
778 | |||
779 | sccr1_reg |= SSCR1_RxTresh(bytes_left); | ||
759 | } | 780 | } |
781 | write_SSCR1(sccr1_reg, reg); | ||
760 | } | 782 | } |
761 | 783 | ||
762 | /* We did something */ | 784 | /* We did something */ |