8181#define AXI_DMAC_REG_CURRENT_DEST_ADDR 0x438
8282#define AXI_DMAC_REG_PARTIAL_XFER_LEN 0x44c
8383#define AXI_DMAC_REG_PARTIAL_XFER_ID 0x450
84+ #define AXI_DMAC_REG_CURRENT_SG_ID 0x454
85+ #define AXI_DMAC_REG_SG_ADDRESS 0x47c
86+ #define AXI_DMAC_REG_SG_ADDRESS_HIGH 0x4bc
8487
8588#define AXI_DMAC_CTRL_ENABLE BIT(0)
8689#define AXI_DMAC_CTRL_PAUSE BIT(1)
90+ #define AXI_DMAC_CTRL_ENABLE_SG BIT(2)
8791
8892#define AXI_DMAC_IRQ_SOT BIT(0)
8993#define AXI_DMAC_IRQ_EOT BIT(1)
97101/* The maximum ID allocated by the hardware is 31 */
98102#define AXI_DMAC_SG_UNUSED 32U
99103
104+ /* Flags for axi_dmac_hw_desc.flags */
105+ #define AXI_DMAC_HW_FLAG_LAST BIT(0)
106+ #define AXI_DMAC_HW_FLAG_IRQ BIT(1)
107+
100108struct axi_dmac_hw_desc {
101109 u32 flags ;
102110 u32 id ;
103111 u64 dest_addr ;
104112 u64 src_addr ;
105- u64 __unused ;
113+ u64 next_sg_addr ;
106114 u32 y_len ;
107115 u32 x_len ;
108116 u32 src_stride ;
@@ -150,6 +158,7 @@ struct axi_dmac_chan {
150158 bool hw_partial_xfer ;
151159 bool hw_cyclic ;
152160 bool hw_2d ;
161+ bool hw_sg ;
153162};
154163
155164struct axi_dmac {
@@ -224,9 +233,11 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
224233 unsigned int flags = 0 ;
225234 unsigned int val ;
226235
227- val = axi_dmac_read (dmac , AXI_DMAC_REG_START_TRANSFER );
228- if (val ) /* Queue is full, wait for the next SOT IRQ */
229- return ;
236+ if (!chan -> hw_sg ) {
237+ val = axi_dmac_read (dmac , AXI_DMAC_REG_START_TRANSFER );
238+ if (val ) /* Queue is full, wait for the next SOT IRQ */
239+ return ;
240+ }
230241
231242 desc = chan -> next_desc ;
232243
@@ -245,9 +256,10 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
245256 return ;
246257 }
247258
248- desc -> num_submitted ++ ;
249- if (desc -> num_submitted == desc -> num_sgs ||
250- desc -> have_partial_xfer ) {
259+ if (chan -> hw_sg ) {
260+ chan -> next_desc = NULL ;
261+ } else if (++ desc -> num_submitted == desc -> num_sgs ||
262+ desc -> have_partial_xfer ) {
251263 if (desc -> cyclic )
252264 desc -> num_submitted = 0 ; /* Start again */
253265 else
@@ -259,14 +271,16 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
259271
260272 sg -> hw -> id = axi_dmac_read (dmac , AXI_DMAC_REG_TRANSFER_ID );
261273
262- if (axi_dmac_dest_is_mem (chan )) {
263- axi_dmac_write (dmac , AXI_DMAC_REG_DEST_ADDRESS , sg -> hw -> dest_addr );
264- axi_dmac_write (dmac , AXI_DMAC_REG_DEST_STRIDE , sg -> hw -> dst_stride );
265- }
274+ if (!chan -> hw_sg ) {
275+ if (axi_dmac_dest_is_mem (chan )) {
276+ axi_dmac_write (dmac , AXI_DMAC_REG_DEST_ADDRESS , sg -> hw -> dest_addr );
277+ axi_dmac_write (dmac , AXI_DMAC_REG_DEST_STRIDE , sg -> hw -> dst_stride );
278+ }
266279
267- if (axi_dmac_src_is_mem (chan )) {
268- axi_dmac_write (dmac , AXI_DMAC_REG_SRC_ADDRESS , sg -> hw -> src_addr );
269- axi_dmac_write (dmac , AXI_DMAC_REG_SRC_STRIDE , sg -> hw -> src_stride );
280+ if (axi_dmac_src_is_mem (chan )) {
281+ axi_dmac_write (dmac , AXI_DMAC_REG_SRC_ADDRESS , sg -> hw -> src_addr );
282+ axi_dmac_write (dmac , AXI_DMAC_REG_SRC_STRIDE , sg -> hw -> src_stride );
283+ }
270284 }
271285
272286 /*
@@ -281,8 +295,14 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
281295 if (chan -> hw_partial_xfer )
282296 flags |= AXI_DMAC_FLAG_PARTIAL_REPORT ;
283297
284- axi_dmac_write (dmac , AXI_DMAC_REG_X_LENGTH , sg -> hw -> x_len );
285- axi_dmac_write (dmac , AXI_DMAC_REG_Y_LENGTH , sg -> hw -> y_len );
298+ if (chan -> hw_sg ) {
299+ axi_dmac_write (dmac , AXI_DMAC_REG_SG_ADDRESS , (u32 )sg -> hw_phys );
300+ axi_dmac_write (dmac , AXI_DMAC_REG_SG_ADDRESS_HIGH ,
301+ (u64 )sg -> hw_phys >> 32 );
302+ } else {
303+ axi_dmac_write (dmac , AXI_DMAC_REG_X_LENGTH , sg -> hw -> x_len );
304+ axi_dmac_write (dmac , AXI_DMAC_REG_Y_LENGTH , sg -> hw -> y_len );
305+ }
286306 axi_dmac_write (dmac , AXI_DMAC_REG_FLAGS , flags );
287307 axi_dmac_write (dmac , AXI_DMAC_REG_START_TRANSFER , 1 );
288308}
@@ -359,6 +379,9 @@ static void axi_dmac_compute_residue(struct axi_dmac_chan *chan,
359379 rslt -> result = DMA_TRANS_NOERROR ;
360380 rslt -> residue = 0 ;
361381
382+ if (chan -> hw_sg )
383+ return ;
384+
362385 /*
363386 * We get here if the last completed segment is partial, which
364387 * means we can compute the residue from that segment onwards
@@ -385,36 +408,46 @@ static bool axi_dmac_transfer_done(struct axi_dmac_chan *chan,
385408 (completed_transfers & AXI_DMAC_FLAG_PARTIAL_XFER_DONE ))
386409 axi_dmac_dequeue_partial_xfers (chan );
387410
388- do {
389- sg = & active -> sg [active -> num_completed ];
390- if (sg -> hw -> id == AXI_DMAC_SG_UNUSED ) /* Not yet submitted */
391- break ;
392- if (!(BIT (sg -> hw -> id ) & completed_transfers ))
393- break ;
394- active -> num_completed ++ ;
395- sg -> hw -> id = AXI_DMAC_SG_UNUSED ;
396- if (sg -> schedule_when_free ) {
397- sg -> schedule_when_free = false;
398- start_next = true;
411+ if (chan -> hw_sg ) {
412+ if (active -> cyclic ) {
413+ vchan_cyclic_callback (& active -> vdesc );
414+ } else {
415+ list_del (& active -> vdesc .node );
416+ vchan_cookie_complete (& active -> vdesc );
417+ active = axi_dmac_active_desc (chan );
399418 }
419+ } else {
420+ do {
421+ sg = & active -> sg [active -> num_completed ];
422+ if (sg -> hw -> id == AXI_DMAC_SG_UNUSED ) /* Not yet submitted */
423+ break ;
424+ if (!(BIT (sg -> hw -> id ) & completed_transfers ))
425+ break ;
426+ active -> num_completed ++ ;
427+ sg -> hw -> id = AXI_DMAC_SG_UNUSED ;
428+ if (sg -> schedule_when_free ) {
429+ sg -> schedule_when_free = false;
430+ start_next = true;
431+ }
400432
401- if (sg -> partial_len )
402- axi_dmac_compute_residue (chan , active );
433+ if (sg -> partial_len )
434+ axi_dmac_compute_residue (chan , active );
403435
404- if (active -> cyclic )
405- vchan_cyclic_callback (& active -> vdesc );
436+ if (active -> cyclic )
437+ vchan_cyclic_callback (& active -> vdesc );
406438
407- if (active -> num_completed == active -> num_sgs ||
408- sg -> partial_len ) {
409- if (active -> cyclic ) {
410- active -> num_completed = 0 ; /* wrap around */
411- } else {
412- list_del (& active -> vdesc .node );
413- vchan_cookie_complete (& active -> vdesc );
414- active = axi_dmac_active_desc (chan );
439+ if (active -> num_completed == active -> num_sgs ||
440+ sg -> partial_len ) {
441+ if (active -> cyclic ) {
442+ active -> num_completed = 0 ; /* wrap around */
443+ } else {
444+ list_del (& active -> vdesc .node );
445+ vchan_cookie_complete (& active -> vdesc );
446+ active = axi_dmac_active_desc (chan );
447+ }
415448 }
416- }
417- } while ( active );
449+ } while ( active );
450+ }
418451
419452 return start_next ;
420453}
@@ -478,8 +511,12 @@ static void axi_dmac_issue_pending(struct dma_chan *c)
478511 struct axi_dmac_chan * chan = to_axi_dmac_chan (c );
479512 struct axi_dmac * dmac = chan_to_axi_dmac (chan );
480513 unsigned long flags ;
514+ u32 ctrl = AXI_DMAC_CTRL_ENABLE ;
515+
516+ if (chan -> hw_sg )
517+ ctrl |= AXI_DMAC_CTRL_ENABLE_SG ;
481518
482- axi_dmac_write (dmac , AXI_DMAC_REG_CTRL , AXI_DMAC_CTRL_ENABLE );
519+ axi_dmac_write (dmac , AXI_DMAC_REG_CTRL , ctrl );
483520
484521 spin_lock_irqsave (& chan -> vchan .lock , flags );
485522 if (vchan_issue_pending (& chan -> vchan ))
@@ -516,8 +553,14 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
516553
517554 hws [i ].id = AXI_DMAC_SG_UNUSED ;
518555 hws [i ].flags = 0 ;
556+
557+ /* Link hardware descriptors */
558+ hws [i ].next_sg_addr = hw_phys + (i + 1 ) * sizeof (* hws );
519559 }
520560
561+ /* The last hardware descriptor will trigger an interrupt */
562+ desc -> sg [num_sgs - 1 ].hw -> flags = AXI_DMAC_HW_FLAG_LAST | AXI_DMAC_HW_FLAG_IRQ ;
563+
521564 return desc ;
522565}
523566
@@ -753,6 +796,9 @@ static bool axi_dmac_regmap_rdwr(struct device *dev, unsigned int reg)
753796 case AXI_DMAC_REG_CURRENT_DEST_ADDR :
754797 case AXI_DMAC_REG_PARTIAL_XFER_LEN :
755798 case AXI_DMAC_REG_PARTIAL_XFER_ID :
799+ case AXI_DMAC_REG_CURRENT_SG_ID :
800+ case AXI_DMAC_REG_SG_ADDRESS :
801+ case AXI_DMAC_REG_SG_ADDRESS_HIGH :
756802 return true;
757803 default :
758804 return false;
@@ -905,6 +951,10 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
905951 if (axi_dmac_read (dmac , AXI_DMAC_REG_FLAGS ) == AXI_DMAC_FLAG_CYCLIC )
906952 chan -> hw_cyclic = true;
907953
954+ axi_dmac_write (dmac , AXI_DMAC_REG_SG_ADDRESS , 0xffffffff );
955+ if (axi_dmac_read (dmac , AXI_DMAC_REG_SG_ADDRESS ))
956+ chan -> hw_sg = true;
957+
908958 axi_dmac_write (dmac , AXI_DMAC_REG_Y_LENGTH , 1 );
909959 if (axi_dmac_read (dmac , AXI_DMAC_REG_Y_LENGTH ) == 1 )
910960 chan -> hw_2d = true;
@@ -1005,6 +1055,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
10051055 dma_dev -> dst_addr_widths = BIT (dmac -> chan .dest_width );
10061056 dma_dev -> directions = BIT (dmac -> chan .direction );
10071057 dma_dev -> residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR ;
1058+ dma_dev -> max_sg_burst = 31 ; /* 31 SGs maximum in one burst */
10081059 INIT_LIST_HEAD (& dma_dev -> channels );
10091060
10101061 dmac -> chan .vchan .desc_free = axi_dmac_desc_free ;
0 commit comments