@@ -1476,19 +1476,46 @@ static int __maybe_unused axi_dma_runtime_resume(struct device *dev)
1476
1476
return axi_dma_resume (chip );
1477
1477
}
1478
1478
1479
+ static bool dw_axi_dma_filter_fn (struct dma_chan * dchan , void * filter_param )
1480
+ {
1481
+ struct axi_dma_chan * chan = dchan_to_axi_dma_chan (dchan );
1482
+ uint32_t selector = * (const uint32_t * )filter_param ;
1483
+
1484
+ return !!(selector & (1 << chan -> id ));
1485
+ }
1486
+
1479
1487
static struct dma_chan * dw_axi_dma_of_xlate (struct of_phandle_args * dma_spec ,
1480
1488
struct of_dma * ofdma )
1481
1489
{
1482
1490
struct dw_axi_dma * dw = ofdma -> of_dma_data ;
1483
1491
struct axi_dma_chan * chan ;
1484
1492
struct dma_chan * dchan ;
1493
+ uint32_t chan_mask = 0 ;
1494
+ uint32_t chan_sel ;
1495
+ dma_cap_mask_t mask ;
1496
+ int i ;
1497
+
1498
+ /*
1499
+ * Walk through all channels looking for the best match.
1500
+ * Starting from 0, choose the first available slave channel which isn't precluded.
1501
+ */
1502
+ chan_sel = dma_spec -> args [0 ];
1485
1503
1486
- dchan = dma_get_any_slave_channel (& dw -> dma );
1504
+ for (i = 0 ; i < dw -> hdata -> nr_channels ; i ++ ) {
1505
+ if (((dw -> sel_precluded [i ] & chan_sel ) == 0 ) &&
1506
+ ((dw -> sel_required [i ] & chan_sel ) == dw -> sel_required [i ]))
1507
+ chan_mask |= (1 << i );
1508
+ }
1509
+
1510
+ dma_cap_zero (mask );
1511
+ dma_cap_set (DMA_SLAVE , mask );
1512
+
1513
+ dchan = __dma_request_channel (& mask , dw_axi_dma_filter_fn , & chan_mask , ofdma -> of_node );
1487
1514
if (!dchan )
1488
1515
return NULL ;
1489
1516
1490
1517
chan = dchan_to_axi_dma_chan (dchan );
1491
- chan -> hw_handshake_num = dma_spec -> args [ 0 ] ;
1518
+ chan -> hw_handshake_num = ( u8 ) chan_sel ;
1492
1519
return dchan ;
1493
1520
}
1494
1521
@@ -1570,6 +1597,18 @@ static int parse_device_properties(struct axi_dma_chip *chip)
1570
1597
}
1571
1598
}
1572
1599
1600
+ /* sel-require is optional */
1601
+ memset (chip -> dw -> sel_required , 0 , sizeof (chip -> dw -> sel_required ));
1602
+ device_property_read_u32_array (dev , "snps,sel-require" ,
1603
+ chip -> dw -> sel_required ,
1604
+ chip -> dw -> hdata -> nr_channels );
1605
+
1606
+ /* sel-preclude is optional */
1607
+ memset (chip -> dw -> sel_precluded , 0 , sizeof (chip -> dw -> sel_precluded ));
1608
+ device_property_read_u32_array (dev , "snps,sel-preclude" ,
1609
+ chip -> dw -> sel_precluded ,
1610
+ chip -> dw -> hdata -> nr_channels );
1611
+
1573
1612
return 0 ;
1574
1613
}
1575
1614
0 commit comments