@@ -1476,19 +1476,46 @@ static int __maybe_unused axi_dma_runtime_resume(struct device *dev)
14761476 return axi_dma_resume (chip );
14771477}
14781478
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+
14791487static struct dma_chan * dw_axi_dma_of_xlate (struct of_phandle_args * dma_spec ,
14801488 struct of_dma * ofdma )
14811489{
14821490 struct dw_axi_dma * dw = ofdma -> of_dma_data ;
14831491 struct axi_dma_chan * chan ;
14841492 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 ];
14851503
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 );
14871514 if (!dchan )
14881515 return NULL ;
14891516
14901517 chan = dchan_to_axi_dma_chan (dchan );
1491- chan -> hw_handshake_num = dma_spec -> args [ 0 ] ;
1518+ chan -> hw_handshake_num = ( u8 ) chan_sel ;
14921519 return dchan ;
14931520}
14941521
@@ -1570,6 +1597,18 @@ static int parse_device_properties(struct axi_dma_chip *chip)
15701597 }
15711598 }
15721599
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+
15731612 return 0 ;
15741613}
15751614
0 commit comments