@@ -173,6 +173,7 @@ struct pl08x_sg {
173
173
* @ccfg: config reg values for current txd
174
174
* @done: this marks completed descriptors, which should not have their
175
175
* mux released.
176
+ * @cyclic: indicate cyclic transfers
176
177
*/
177
178
struct pl08x_txd {
178
179
struct virt_dma_desc vd ;
@@ -187,6 +188,7 @@ struct pl08x_txd {
187
188
*/
188
189
u32 ccfg ;
189
190
bool done ;
191
+ bool cyclic ;
190
192
};
191
193
192
194
/**
@@ -574,9 +576,9 @@ static u32 pl08x_getbytes_chan(struct pl08x_dma_chan *plchan)
574
576
bytes += get_bytes_in_cctl (llis_va [PL080_LLI_CCTL ]);
575
577
576
578
/*
577
- * A LLI pointer of 0 terminates the LLI list
579
+ * A LLI pointer going backward terminates the LLI list
578
580
*/
579
- if (! llis_va [PL080_LLI_LLI ])
581
+ if (llis_va [PL080_LLI_LLI ] <= clli )
580
582
break ;
581
583
}
582
584
@@ -1125,10 +1127,16 @@ static int pl08x_fill_llis_for_desc(struct pl08x_driver_data *pl08x,
1125
1127
1126
1128
llis_va = txd -> llis_va ;
1127
1129
last_lli = llis_va + (num_llis - 1 ) * pl08x -> lli_words ;
1128
- /* The final LLI terminates the LLI. */
1129
- last_lli [PL080_LLI_LLI ] = 0 ;
1130
- /* The final LLI element shall also fire an interrupt. */
1131
- last_lli [PL080_LLI_CCTL ] |= PL080_CONTROL_TC_IRQ_EN ;
1130
+
1131
+ if (txd -> cyclic ) {
1132
+ /* Link back to the first LLI. */
1133
+ last_lli [PL080_LLI_LLI ] = txd -> llis_bus | bd .lli_bus ;
1134
+ } else {
1135
+ /* The final LLI terminates the LLI. */
1136
+ last_lli [PL080_LLI_LLI ] = 0 ;
1137
+ /* The final LLI element shall also fire an interrupt. */
1138
+ last_lli [PL080_LLI_CCTL ] |= PL080_CONTROL_TC_IRQ_EN ;
1139
+ }
1132
1140
1133
1141
pl08x_dump_lli (pl08x , llis_va , num_llis );
1134
1142
@@ -1513,25 +1521,19 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_memcpy(
1513
1521
return vchan_tx_prep (& plchan -> vc , & txd -> vd , flags );
1514
1522
}
1515
1523
1516
- static struct dma_async_tx_descriptor * pl08x_prep_slave_sg (
1517
- struct dma_chan * chan , struct scatterlist * sgl ,
1518
- unsigned int sg_len , enum dma_transfer_direction direction ,
1519
- unsigned long flags , void * context )
1524
+ static struct pl08x_txd * pl08x_init_txd (
1525
+ struct dma_chan * chan ,
1526
+ enum dma_transfer_direction direction ,
1527
+ dma_addr_t * slave_addr )
1520
1528
{
1521
1529
struct pl08x_dma_chan * plchan = to_pl08x_chan (chan );
1522
1530
struct pl08x_driver_data * pl08x = plchan -> host ;
1523
1531
struct pl08x_txd * txd ;
1524
- struct pl08x_sg * dsg ;
1525
- struct scatterlist * sg ;
1526
1532
enum dma_slave_buswidth addr_width ;
1527
- dma_addr_t slave_addr ;
1528
1533
int ret , tmp ;
1529
1534
u8 src_buses , dst_buses ;
1530
1535
u32 maxburst , cctl ;
1531
1536
1532
- dev_dbg (& pl08x -> adev -> dev , "%s prepare transaction of %d bytes from %s\n" ,
1533
- __func__ , sg_dma_len (sgl ), plchan -> name );
1534
-
1535
1537
txd = pl08x_get_txd (plchan );
1536
1538
if (!txd ) {
1537
1539
dev_err (& pl08x -> adev -> dev , "%s no txd\n" , __func__ );
@@ -1545,14 +1547,14 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1545
1547
*/
1546
1548
if (direction == DMA_MEM_TO_DEV ) {
1547
1549
cctl = PL080_CONTROL_SRC_INCR ;
1548
- slave_addr = plchan -> cfg .dst_addr ;
1550
+ * slave_addr = plchan -> cfg .dst_addr ;
1549
1551
addr_width = plchan -> cfg .dst_addr_width ;
1550
1552
maxburst = plchan -> cfg .dst_maxburst ;
1551
1553
src_buses = pl08x -> mem_buses ;
1552
1554
dst_buses = plchan -> cd -> periph_buses ;
1553
1555
} else if (direction == DMA_DEV_TO_MEM ) {
1554
1556
cctl = PL080_CONTROL_DST_INCR ;
1555
- slave_addr = plchan -> cfg .src_addr ;
1557
+ * slave_addr = plchan -> cfg .src_addr ;
1556
1558
addr_width = plchan -> cfg .src_addr_width ;
1557
1559
maxburst = plchan -> cfg .src_maxburst ;
1558
1560
src_buses = plchan -> cd -> periph_buses ;
@@ -1601,24 +1603,107 @@ static struct dma_async_tx_descriptor *pl08x_prep_slave_sg(
1601
1603
else
1602
1604
txd -> ccfg |= plchan -> signal << PL080_CONFIG_SRC_SEL_SHIFT ;
1603
1605
1606
+ return txd ;
1607
+ }
1608
+
1609
+ static int pl08x_tx_add_sg (struct pl08x_txd * txd ,
1610
+ enum dma_transfer_direction direction ,
1611
+ dma_addr_t slave_addr ,
1612
+ dma_addr_t buf_addr ,
1613
+ unsigned int len )
1614
+ {
1615
+ struct pl08x_sg * dsg ;
1616
+
1617
+ dsg = kzalloc (sizeof (struct pl08x_sg ), GFP_NOWAIT );
1618
+ if (!dsg )
1619
+ return - ENOMEM ;
1620
+
1621
+ list_add_tail (& dsg -> node , & txd -> dsg_list );
1622
+
1623
+ dsg -> len = len ;
1624
+ if (direction == DMA_MEM_TO_DEV ) {
1625
+ dsg -> src_addr = buf_addr ;
1626
+ dsg -> dst_addr = slave_addr ;
1627
+ } else {
1628
+ dsg -> src_addr = slave_addr ;
1629
+ dsg -> dst_addr = buf_addr ;
1630
+ }
1631
+
1632
+ return 0 ;
1633
+ }
1634
+
1635
+ static struct dma_async_tx_descriptor * pl08x_prep_slave_sg (
1636
+ struct dma_chan * chan , struct scatterlist * sgl ,
1637
+ unsigned int sg_len , enum dma_transfer_direction direction ,
1638
+ unsigned long flags , void * context )
1639
+ {
1640
+ struct pl08x_dma_chan * plchan = to_pl08x_chan (chan );
1641
+ struct pl08x_driver_data * pl08x = plchan -> host ;
1642
+ struct pl08x_txd * txd ;
1643
+ struct scatterlist * sg ;
1644
+ int ret , tmp ;
1645
+ dma_addr_t slave_addr ;
1646
+
1647
+ dev_dbg (& pl08x -> adev -> dev , "%s prepare transaction of %d bytes from %s\n" ,
1648
+ __func__ , sg_dma_len (sgl ), plchan -> name );
1649
+
1650
+ txd = pl08x_init_txd (chan , direction , & slave_addr );
1651
+ if (!txd )
1652
+ return NULL ;
1653
+
1604
1654
for_each_sg (sgl , sg , sg_len , tmp ) {
1605
- dsg = kzalloc (sizeof (struct pl08x_sg ), GFP_NOWAIT );
1606
- if (!dsg ) {
1655
+ ret = pl08x_tx_add_sg (txd , direction , slave_addr ,
1656
+ sg_dma_address (sg ),
1657
+ sg_dma_len (sg ));
1658
+ if (ret ) {
1607
1659
pl08x_release_mux (plchan );
1608
1660
pl08x_free_txd (pl08x , txd );
1609
1661
dev_err (& pl08x -> adev -> dev , "%s no mem for pl080 sg\n" ,
1610
1662
__func__ );
1611
1663
return NULL ;
1612
1664
}
1613
- list_add_tail ( & dsg -> node , & txd -> dsg_list );
1665
+ }
1614
1666
1615
- dsg -> len = sg_dma_len (sg );
1616
- if (direction == DMA_MEM_TO_DEV ) {
1617
- dsg -> src_addr = sg_dma_address (sg );
1618
- dsg -> dst_addr = slave_addr ;
1619
- } else {
1620
- dsg -> src_addr = slave_addr ;
1621
- dsg -> dst_addr = sg_dma_address (sg );
1667
+ ret = pl08x_fill_llis_for_desc (plchan -> host , txd );
1668
+ if (!ret ) {
1669
+ pl08x_release_mux (plchan );
1670
+ pl08x_free_txd (pl08x , txd );
1671
+ return NULL ;
1672
+ }
1673
+
1674
+ return vchan_tx_prep (& plchan -> vc , & txd -> vd , flags );
1675
+ }
1676
+
1677
+ static struct dma_async_tx_descriptor * pl08x_prep_dma_cyclic (
1678
+ struct dma_chan * chan , dma_addr_t buf_addr , size_t buf_len ,
1679
+ size_t period_len , enum dma_transfer_direction direction ,
1680
+ unsigned long flags , void * context )
1681
+ {
1682
+ struct pl08x_dma_chan * plchan = to_pl08x_chan (chan );
1683
+ struct pl08x_driver_data * pl08x = plchan -> host ;
1684
+ struct pl08x_txd * txd ;
1685
+ int ret , tmp ;
1686
+ dma_addr_t slave_addr ;
1687
+
1688
+ dev_dbg (& pl08x -> adev -> dev ,
1689
+ "%s prepare cyclic transaction of %d/%d bytes %s %s\n" ,
1690
+ __func__ , period_len , buf_len ,
1691
+ direction == DMA_MEM_TO_DEV ? "to" : "from" ,
1692
+ plchan -> name );
1693
+
1694
+ txd = pl08x_init_txd (chan , direction , & slave_addr );
1695
+ if (!txd )
1696
+ return NULL ;
1697
+
1698
+ txd -> cyclic = true;
1699
+ txd -> cctl |= PL080_CONTROL_TC_IRQ_EN ;
1700
+ for (tmp = 0 ; tmp < buf_len ; tmp += period_len ) {
1701
+ ret = pl08x_tx_add_sg (txd , direction , slave_addr ,
1702
+ buf_addr + tmp , period_len );
1703
+ if (ret ) {
1704
+ pl08x_release_mux (plchan );
1705
+ pl08x_free_txd (pl08x , txd );
1706
+ return NULL ;
1622
1707
}
1623
1708
}
1624
1709
@@ -1761,7 +1846,9 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
1761
1846
1762
1847
spin_lock (& plchan -> vc .lock );
1763
1848
tx = plchan -> at ;
1764
- if (tx ) {
1849
+ if (tx && tx -> cyclic ) {
1850
+ vchan_cyclic_callback (& tx -> vd );
1851
+ } else if (tx ) {
1765
1852
plchan -> at = NULL ;
1766
1853
/*
1767
1854
* This descriptor is done, release its mux
@@ -1983,13 +2070,15 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
1983
2070
1984
2071
/* Initialize slave engine */
1985
2072
dma_cap_set (DMA_SLAVE , pl08x -> slave .cap_mask );
2073
+ dma_cap_set (DMA_CYCLIC , pl08x -> slave .cap_mask );
1986
2074
pl08x -> slave .dev = & adev -> dev ;
1987
2075
pl08x -> slave .device_alloc_chan_resources = pl08x_alloc_chan_resources ;
1988
2076
pl08x -> slave .device_free_chan_resources = pl08x_free_chan_resources ;
1989
2077
pl08x -> slave .device_prep_dma_interrupt = pl08x_prep_dma_interrupt ;
1990
2078
pl08x -> slave .device_tx_status = pl08x_dma_tx_status ;
1991
2079
pl08x -> slave .device_issue_pending = pl08x_issue_pending ;
1992
2080
pl08x -> slave .device_prep_slave_sg = pl08x_prep_slave_sg ;
2081
+ pl08x -> slave .device_prep_dma_cyclic = pl08x_prep_dma_cyclic ;
1993
2082
pl08x -> slave .device_control = pl08x_control ;
1994
2083
1995
2084
/* Get the platform data */
0 commit comments