aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/pxa2xx_spi.c56
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
663static 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
663static void int_error_stop(struct driver_data *drv_data, const char* msg) 675static 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 */