@@ -1476,19 +1476,75 @@ 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 ;
1492+ uint32_t chan_flags_all ;
1493+ uint32_t busy_channels ;
14841494 struct dma_chan * dchan ;
1495+ dma_cap_mask_t mask ;
1496+ uint32_t chan_mask ;
1497+ uint32_t chan_sel ;
1498+ int max_score ;
1499+ int score ;
1500+ int i ;
14851501
1486- dchan = dma_get_any_slave_channel (& dw -> dma );
1487- if (!dchan )
1488- return NULL ;
1502+ for (i = 0 ; i < dw -> hdata -> nr_channels ; i ++ )
1503+ chan_flags_all |= dw -> chan_flags [i ];
1504+
1505+ dma_cap_zero (mask );
1506+ dma_cap_set (DMA_SLAVE , mask );
1507+
1508+ chan_sel = dma_spec -> args [0 ];
1509+ busy_channels = 0 ;
1510+ dchan = NULL ;
1511+
1512+ while (1 ) {
1513+ max_score = 0 ;
1514+ chan_mask = 0 ;
1515+
1516+ for (i = 0 ; i < dw -> hdata -> nr_channels ; i ++ ) {
1517+ if (busy_channels & (1 << i ))
1518+ continue ;
1519+ /*
1520+ * Positive matches (wanted flags that match) score twice that of
1521+ * negetive matches (not wanted flags that are not present).
1522+ */
1523+ score = 2 * hweight32 (chan_sel & dw -> chan_flags [i ]) +
1524+ 1 * hweight32 (~chan_sel & ~dw -> chan_flags [i ] & chan_flags_all );
1525+ if (score > max_score ) {
1526+ max_score = score ;
1527+ chan_mask = (1 << i );
1528+ } else if (score == max_score ) {
1529+ chan_mask |= (1 << i );
1530+ }
1531+ }
1532+
1533+ if (!chan_mask )
1534+ return NULL ;
1535+
1536+ dchan = __dma_request_channel (& mask , dw_axi_dma_filter_fn ,
1537+ & chan_mask , ofdma -> of_node );
1538+ if (dchan )
1539+ break ;
1540+
1541+ /* Repeat, after first marking this group of channels as busy */
1542+ busy_channels |= chan_mask ;
1543+ }
14891544
14901545 chan = dchan_to_axi_dma_chan (dchan );
1491- chan -> hw_handshake_num = dma_spec -> args [0 ];
1546+ chan -> hw_handshake_num = (u8 )chan_sel ;
1547+
14921548 return dchan ;
14931549}
14941550
@@ -1570,6 +1626,15 @@ static int parse_device_properties(struct axi_dma_chip *chip)
15701626 }
15711627 }
15721628
1629+ /* snps,chan-flags is optional */
1630+ memset (chip -> dw -> chan_flags , 0 , sizeof (chip -> dw -> chan_flags ));
1631+ if (device_property_read_u32_array (dev , "snps,chan-flags" ,
1632+ chip -> dw -> chan_flags ,
1633+ chip -> dw -> hdata -> nr_channels ) < 0 )
1634+ device_property_read_u32_array (dev , "snps,sel-require" ,
1635+ chip -> dw -> chan_flags ,
1636+ chip -> dw -> hdata -> nr_channels );
1637+
15731638 return 0 ;
15741639}
15751640
0 commit comments