@@ -140,6 +140,7 @@ struct pci1xxxx_spi_internal {
140140 int irq [NUM_VEC_PER_INST ];
141141 int mode ;
142142 bool spi_xfer_in_progress ;
143+ atomic_t dma_completion_count ;
143144 void * rx_buf ;
144145 bool dma_aborted_rd ;
145146 u32 bytes_recvd ;
@@ -163,8 +164,10 @@ struct pci1xxxx_spi {
163164 u8 dev_rev ;
164165 void __iomem * reg_base ;
165166 void __iomem * dma_offset_bar ;
166- /* lock to safely access the DMA registers in isr */
167- spinlock_t dma_reg_lock ;
167+ /* lock to safely access the DMA RD registers in isr */
168+ spinlock_t dma_rd_reg_lock ;
169+ /* lock to safely access the DMA RD registers in isr */
170+ spinlock_t dma_wr_reg_lock ;
168171 bool can_dma ;
169172 struct pci1xxxx_spi_internal * spi_int [] __counted_by (total_hw_instances );
170173};
@@ -330,7 +333,8 @@ static int pci1xxxx_spi_dma_init(struct pci1xxxx_spi *spi_bus, int hw_inst, int
330333 if (ret )
331334 return ret ;
332335
333- spin_lock_init (& spi_bus -> dma_reg_lock );
336+ spin_lock_init (& spi_bus -> dma_rd_reg_lock );
337+ spin_lock_init (& spi_bus -> dma_wr_reg_lock );
334338 writel (SPI_DMA_ENGINE_EN , spi_bus -> dma_offset_bar + SPI_DMA_GLOBAL_WR_ENGINE_EN );
335339 writel (SPI_DMA_ENGINE_EN , spi_bus -> dma_offset_bar + SPI_DMA_GLOBAL_RD_ENGINE_EN );
336340
@@ -464,6 +468,7 @@ static void pci1xxxx_start_spi_xfer(struct pci1xxxx_spi_internal *p)
464468{
465469 u32 regval ;
466470
471+ atomic_set (& p -> dma_completion_count , 0 );
467472 regval = readl (p -> parent -> reg_base + SPI_MST_CTL_REG_OFFSET (p -> hw_inst ));
468473 regval |= SPI_MST_CTL_GO ;
469474 writel (regval , p -> parent -> reg_base + SPI_MST_CTL_REG_OFFSET (p -> hw_inst ));
@@ -536,7 +541,6 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
536541{
537542 struct pci1xxxx_spi_internal * p = spi_controller_get_devdata (spi_ctlr );
538543 struct pci1xxxx_spi * par = p -> parent ;
539- dma_addr_t rx_dma_addr = 0 ;
540544 dma_addr_t tx_dma_addr = 0 ;
541545 int ret = 0 ;
542546 u32 regval ;
@@ -545,6 +549,7 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
545549 p -> tx_sgl = xfer -> tx_sg .sgl ;
546550 p -> rx_sgl = xfer -> rx_sg .sgl ;
547551 p -> rx_buf = xfer -> rx_buf ;
552+ atomic_set (& p -> dma_completion_count , 1 );
548553 regval = readl (par -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
549554 writel (regval , par -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
550555
@@ -561,13 +566,9 @@ static int pci1xxxx_spi_transfer_with_dma(struct spi_controller *spi_ctlr,
561566 writel (regval , par -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
562567
563568 tx_dma_addr = sg_dma_address (p -> tx_sgl );
564- rx_dma_addr = sg_dma_address (p -> rx_sgl );
565569 p -> tx_sgl_len = sg_dma_len (p -> tx_sgl );
566- p -> rx_sgl_len = sg_dma_len (p -> rx_sgl );
567570 pci1xxxx_spi_setup (par , p -> hw_inst , p -> mode , p -> clkdiv , p -> tx_sgl_len );
568571 pci1xxxx_spi_setup_dma_to_io (p , (tx_dma_addr ), p -> tx_sgl_len );
569- if (rx_dma_addr )
570- pci1xxxx_spi_setup_dma_from_io (p , rx_dma_addr , p -> rx_sgl_len );
571572 writel (p -> hw_inst , par -> dma_offset_bar + SPI_DMA_RD_DOORBELL_REG );
572573
573574 reinit_completion (& p -> spi_xfer_done );
@@ -657,32 +658,33 @@ static irqreturn_t pci1xxxx_spi_isr_io(int irq, void *dev)
657658 return spi_int_fired ;
658659}
659660
660- static void pci1xxxx_spi_setup_next_dma_transfer (struct pci1xxxx_spi_internal * p )
661+ static void pci1xxxx_spi_setup_next_dma_to_io_transfer (struct pci1xxxx_spi_internal * p )
661662{
662663 dma_addr_t tx_dma_addr = 0 ;
663- dma_addr_t rx_dma_addr = 0 ;
664664 u32 prev_len ;
665665
666666 p -> tx_sgl = sg_next (p -> tx_sgl );
667- if (p -> rx_sgl )
668- p -> rx_sgl = sg_next (p -> rx_sgl );
669- if (!p -> tx_sgl ) {
670- /* Clear xfer_done */
671- complete (& p -> spi_xfer_done );
672- } else {
667+ if (p -> tx_sgl ) {
673668 tx_dma_addr = sg_dma_address (p -> tx_sgl );
674669 prev_len = p -> tx_sgl_len ;
675670 p -> tx_sgl_len = sg_dma_len (p -> tx_sgl );
671+ pci1xxxx_spi_setup_dma_to_io (p , tx_dma_addr , p -> tx_sgl_len );
672+ writel (p -> hw_inst , p -> parent -> dma_offset_bar + SPI_DMA_RD_DOORBELL_REG );
676673 if (prev_len != p -> tx_sgl_len )
677674 pci1xxxx_spi_setup (p -> parent ,
678675 p -> hw_inst , p -> mode , p -> clkdiv , p -> tx_sgl_len );
679- pci1xxxx_spi_setup_dma_to_io (p , tx_dma_addr , p -> tx_sgl_len );
680- if (p -> rx_sgl ) {
681- rx_dma_addr = sg_dma_address (p -> rx_sgl );
682- p -> rx_sgl_len = sg_dma_len (p -> rx_sgl );
683- pci1xxxx_spi_setup_dma_from_io (p , rx_dma_addr , p -> rx_sgl_len );
684- }
685- writel (p -> hw_inst , p -> parent -> dma_offset_bar + SPI_DMA_RD_DOORBELL_REG );
676+ }
677+ }
678+
679+ static void pci1xxxx_spi_setup_next_dma_from_io_transfer (struct pci1xxxx_spi_internal * p )
680+ {
681+ dma_addr_t rx_dma_addr = 0 ;
682+
683+ if (p -> rx_sgl ) {
684+ rx_dma_addr = sg_dma_address (p -> rx_sgl );
685+ p -> rx_sgl_len = sg_dma_len (p -> rx_sgl );
686+ pci1xxxx_spi_setup_dma_from_io (p , rx_dma_addr , p -> rx_sgl_len );
687+ writel (p -> hw_inst , p -> parent -> dma_offset_bar + SPI_DMA_WR_DOORBELL_REG );
686688 }
687689}
688690
@@ -693,22 +695,24 @@ static irqreturn_t pci1xxxx_spi_isr_dma_rd(int irq, void *dev)
693695 unsigned long flags ;
694696 u32 regval ;
695697
696- spin_lock_irqsave (& p -> parent -> dma_reg_lock , flags );
697698 /* Clear the DMA RD INT and start spi xfer*/
698699 regval = readl (p -> parent -> dma_offset_bar + SPI_DMA_INTR_RD_STS );
699700 if (regval ) {
700701 if (regval & SPI_DMA_DONE_INT_MASK (p -> hw_inst )) {
701- pci1xxxx_start_spi_xfer (p );
702+ /* Start the SPI transfer only if both DMA read and write are completed */
703+ if (atomic_inc_return (& p -> dma_completion_count ) == 2 )
704+ pci1xxxx_start_spi_xfer (p );
702705 spi_int_fired = IRQ_HANDLED ;
703706 }
704707 if (regval & SPI_DMA_ABORT_INT_MASK (p -> hw_inst )) {
705708 p -> dma_aborted_rd = true;
706709 spi_int_fired = IRQ_HANDLED ;
707710 }
711+ spin_lock_irqsave (& p -> parent -> dma_rd_reg_lock , flags );
712+ writel ((SPI_DMA_DONE_INT_MASK (p -> hw_inst ) | SPI_DMA_ABORT_INT_MASK (p -> hw_inst )),
713+ p -> parent -> dma_offset_bar + SPI_DMA_INTR_RD_CLR );
714+ spin_unlock_irqrestore (& p -> parent -> dma_rd_reg_lock , flags );
708715 }
709- writel ((SPI_DMA_DONE_INT_MASK (p -> hw_inst ) | SPI_DMA_ABORT_INT_MASK (p -> hw_inst )),
710- p -> parent -> dma_offset_bar + SPI_DMA_INTR_RD_CLR );
711- spin_unlock_irqrestore (& p -> parent -> dma_reg_lock , flags );
712716 return spi_int_fired ;
713717}
714718
@@ -719,22 +723,29 @@ static irqreturn_t pci1xxxx_spi_isr_dma_wr(int irq, void *dev)
719723 unsigned long flags ;
720724 u32 regval ;
721725
722- spin_lock_irqsave (& p -> parent -> dma_reg_lock , flags );
723726 /* Clear the DMA WR INT */
724727 regval = readl (p -> parent -> dma_offset_bar + SPI_DMA_INTR_WR_STS );
725728 if (regval ) {
726729 if (regval & SPI_DMA_DONE_INT_MASK (p -> hw_inst )) {
727- pci1xxxx_spi_setup_next_dma_transfer (p );
728730 spi_int_fired = IRQ_HANDLED ;
731+ if (sg_is_last (p -> rx_sgl )) {
732+ complete (& p -> spi_xfer_done );
733+ } else {
734+ p -> rx_sgl = sg_next (p -> rx_sgl );
735+ if (atomic_inc_return (& p -> dma_completion_count ) == 2 )
736+ pci1xxxx_start_spi_xfer (p );
737+ }
738+
729739 }
730740 if (regval & SPI_DMA_ABORT_INT_MASK (p -> hw_inst )) {
731741 p -> dma_aborted_wr = true;
732742 spi_int_fired = IRQ_HANDLED ;
733743 }
744+ spin_lock_irqsave (& p -> parent -> dma_wr_reg_lock , flags );
745+ writel ((SPI_DMA_DONE_INT_MASK (p -> hw_inst ) | SPI_DMA_ABORT_INT_MASK (p -> hw_inst )),
746+ p -> parent -> dma_offset_bar + SPI_DMA_INTR_WR_CLR );
747+ spin_unlock_irqrestore (& p -> parent -> dma_wr_reg_lock , flags );
734748 }
735- writel ((SPI_DMA_DONE_INT_MASK (p -> hw_inst ) | SPI_DMA_ABORT_INT_MASK (p -> hw_inst )),
736- p -> parent -> dma_offset_bar + SPI_DMA_INTR_WR_CLR );
737- spin_unlock_irqrestore (& p -> parent -> dma_reg_lock , flags );
738749 return spi_int_fired ;
739750}
740751
@@ -747,10 +758,11 @@ static irqreturn_t pci1xxxx_spi_isr_dma(int irq, void *dev)
747758 /* Clear the SPI GO_BIT Interrupt */
748759 regval = readl (p -> parent -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
749760 if (regval & SPI_INTR ) {
750- writel (p -> hw_inst , p -> parent -> dma_offset_bar + SPI_DMA_WR_DOORBELL_REG );
761+ pci1xxxx_spi_setup_next_dma_from_io_transfer (p );
762+ pci1xxxx_spi_setup_next_dma_to_io_transfer (p );
751763 spi_int_fired = IRQ_HANDLED ;
764+ writel (regval , p -> parent -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
752765 }
753- writel (regval , p -> parent -> reg_base + SPI_MST_EVENT_REG_OFFSET (p -> hw_inst ));
754766 return spi_int_fired ;
755767}
756768
0 commit comments