68
68
69
69
/* SPRD_DMA_CHN_CFG register definition */
70
70
#define SPRD_DMA_CHN_EN BIT(0)
71
+ #define SPRD_DMA_LINKLIST_EN BIT(4)
71
72
#define SPRD_DMA_WAIT_BDONE_OFFSET 24
72
73
#define SPRD_DMA_DONOT_WAIT_BDONE 1
73
74
103
104
#define SPRD_DMA_REQ_MODE_MASK GENMASK(1, 0)
104
105
#define SPRD_DMA_FIX_SEL_OFFSET 21
105
106
#define SPRD_DMA_FIX_EN_OFFSET 20
106
- #define SPRD_DMA_LLIST_END_OFFSET 19
107
+ #define SPRD_DMA_LLIST_END BIT(19)
107
108
#define SPRD_DMA_FRG_LEN_MASK GENMASK(16, 0)
108
109
109
110
/* SPRD_DMA_CHN_BLK_LEN register definition */
@@ -164,6 +165,7 @@ struct sprd_dma_desc {
164
165
struct sprd_dma_chn {
165
166
struct virt_dma_chan vc ;
166
167
void __iomem * chn_base ;
168
+ struct sprd_dma_linklist linklist ;
167
169
struct dma_slave_config slave_cfg ;
168
170
u32 chn_num ;
169
171
u32 dev_id ;
@@ -582,15 +584,15 @@ static int sprd_dma_get_step(enum dma_slave_buswidth buswidth)
582
584
}
583
585
584
586
static int sprd_dma_fill_desc (struct dma_chan * chan ,
585
- struct sprd_dma_desc * sdesc ,
587
+ struct sprd_dma_chn_hw * hw ,
588
+ unsigned int sglen , int sg_index ,
586
589
dma_addr_t src , dma_addr_t dst , u32 len ,
587
590
enum dma_transfer_direction dir ,
588
591
unsigned long flags ,
589
592
struct dma_slave_config * slave_cfg )
590
593
{
591
594
struct sprd_dma_dev * sdev = to_sprd_dma_dev (chan );
592
595
struct sprd_dma_chn * schan = to_sprd_dma_chan (chan );
593
- struct sprd_dma_chn_hw * hw = & sdesc -> chn_hw ;
594
596
u32 req_mode = (flags >> SPRD_DMA_REQ_SHIFT ) & SPRD_DMA_REQ_MODE_MASK ;
595
597
u32 int_mode = flags & SPRD_DMA_INT_MASK ;
596
598
int src_datawidth , dst_datawidth , src_step , dst_step ;
@@ -670,12 +672,52 @@ static int sprd_dma_fill_desc(struct dma_chan *chan,
670
672
temp |= (src_step & SPRD_DMA_TRSF_STEP_MASK ) << SPRD_DMA_SRC_TRSF_STEP_OFFSET ;
671
673
hw -> trsf_step = temp ;
672
674
675
+ /* link-list configuration */
676
+ if (schan -> linklist .phy_addr ) {
677
+ if (sg_index == sglen - 1 )
678
+ hw -> frg_len |= SPRD_DMA_LLIST_END ;
679
+
680
+ hw -> cfg |= SPRD_DMA_LINKLIST_EN ;
681
+
682
+ /* link-list index */
683
+ temp = (sg_index + 1 ) % sglen ;
684
+ /* Next link-list configuration's physical address offset */
685
+ temp = temp * sizeof (* hw ) + SPRD_DMA_CHN_SRC_ADDR ;
686
+ /*
687
+ * Set the link-list pointer point to next link-list
688
+ * configuration's physical address.
689
+ */
690
+ hw -> llist_ptr = schan -> linklist .phy_addr + temp ;
691
+ } else {
692
+ hw -> llist_ptr = 0 ;
693
+ }
694
+
673
695
hw -> frg_step = 0 ;
674
696
hw -> src_blk_step = 0 ;
675
697
hw -> des_blk_step = 0 ;
676
698
return 0 ;
677
699
}
678
700
701
+ static int sprd_dma_fill_linklist_desc (struct dma_chan * chan ,
702
+ unsigned int sglen , int sg_index ,
703
+ dma_addr_t src , dma_addr_t dst , u32 len ,
704
+ enum dma_transfer_direction dir ,
705
+ unsigned long flags ,
706
+ struct dma_slave_config * slave_cfg )
707
+ {
708
+ struct sprd_dma_chn * schan = to_sprd_dma_chan (chan );
709
+ struct sprd_dma_chn_hw * hw ;
710
+
711
+ if (!schan -> linklist .virt_addr )
712
+ return - EINVAL ;
713
+
714
+ hw = (struct sprd_dma_chn_hw * )(schan -> linklist .virt_addr +
715
+ sg_index * sizeof (* hw ));
716
+
717
+ return sprd_dma_fill_desc (chan , hw , sglen , sg_index , src , dst , len ,
718
+ dir , flags , slave_cfg );
719
+ }
720
+
679
721
static struct dma_async_tx_descriptor *
680
722
sprd_dma_prep_dma_memcpy (struct dma_chan * chan , dma_addr_t dest , dma_addr_t src ,
681
723
size_t len , unsigned long flags )
@@ -744,10 +786,20 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
744
786
u32 len = 0 ;
745
787
int ret , i ;
746
788
747
- /* TODO: now we only support one sg for each DMA configuration. */
748
- if (!is_slave_direction (dir ) || sglen > 1 )
789
+ if (!is_slave_direction (dir ))
749
790
return NULL ;
750
791
792
+ if (context ) {
793
+ struct sprd_dma_linklist * ll_cfg =
794
+ (struct sprd_dma_linklist * )context ;
795
+
796
+ schan -> linklist .phy_addr = ll_cfg -> phy_addr ;
797
+ schan -> linklist .virt_addr = ll_cfg -> virt_addr ;
798
+ } else {
799
+ schan -> linklist .phy_addr = 0 ;
800
+ schan -> linklist .virt_addr = 0 ;
801
+ }
802
+
751
803
sdesc = kzalloc (sizeof (* sdesc ), GFP_NOWAIT );
752
804
if (!sdesc )
753
805
return NULL ;
@@ -762,10 +814,25 @@ sprd_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
762
814
src = slave_cfg -> src_addr ;
763
815
dst = sg_dma_address (sg );
764
816
}
817
+
818
+ /*
819
+ * The link-list mode needs at least 2 link-list
820
+ * configurations. If there is only one sg, it doesn't
821
+ * need to fill the link-list configuration.
822
+ */
823
+ if (sglen < 2 )
824
+ break ;
825
+
826
+ ret = sprd_dma_fill_linklist_desc (chan , sglen , i , src , dst , len ,
827
+ dir , flags , slave_cfg );
828
+ if (ret ) {
829
+ kfree (sdesc );
830
+ return NULL ;
831
+ }
765
832
}
766
833
767
- ret = sprd_dma_fill_desc (chan , sdesc , src , dst , len , dir , flags ,
768
- slave_cfg );
834
+ ret = sprd_dma_fill_desc (chan , & sdesc -> chn_hw , 0 , 0 , src , dst , len ,
835
+ dir , flags , slave_cfg );
769
836
if (ret ) {
770
837
kfree (sdesc );
771
838
return NULL ;
0 commit comments