dmaengine: dw-axi-dmac: Remove free slot check algorithm in dw_axi_dma_set_hw_channel
authorPandith N <pandith.n@intel.com>
Mon, 2 Aug 2021 05:54:52 +0000 (11:24 +0530)
committerVinod Koul <vkoul@kernel.org>
Mon, 2 Aug 2021 06:49:51 +0000 (12:19 +0530)
Removed free slot check algorithm in dw_axi_dma_set_hw_channel. For 8
DMA channels, use respective handshake slot in DMA_HS_SEL APB register.

For every channel, an dedicated slot is provided in  hardware handshake
register AXIDMA_CTRL_DMA_HS_SEL_n. Peripheral source number is
programmed in respective channel slots.

Signed-off-by: Pandith N <pandith.n@intel.com>
Tested-by: Pan Kris <kris.pan@intel.com>
Link: https://lore.kernel.org/r/20210802055454.15192-2-pandith.n@intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
drivers/dma/dw-axi-dmac/dw-axi-dmac.h

index d9e4ac3..c3bb2b4 100644 (file)
@@ -470,18 +470,13 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan)
        pm_runtime_put(chan->chip->dev);
 }
 
-static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip,
-                                     u32 handshake_num, bool set)
+static void dw_axi_dma_set_hw_channel(struct axi_dma_chan *chan, bool set)
 {
-       unsigned long start = 0;
-       unsigned long reg_value;
-       unsigned long reg_mask;
-       unsigned long reg_set;
-       unsigned long mask;
-       unsigned long val;
+       struct axi_dma_chip *chip = chan->chip;
+       unsigned long reg_value, val;
 
        if (!chip->apb_regs) {
-               dev_dbg(chip->dev, "apb_regs not initialized\n");
+               dev_err(chip->dev, "apb_regs not initialized\n");
                return;
        }
 
@@ -490,26 +485,22 @@ static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip,
         * Lock the DMA channel by assign a handshake number to the channel.
         * Unlock the DMA channel by assign 0x3F to the channel.
         */
-       if (set) {
-               reg_set = UNUSED_CHANNEL;
-               val = handshake_num;
-       } else {
-               reg_set = handshake_num;
+       if (set)
+               val = chan->hw_handshake_num;
+       else
                val = UNUSED_CHANNEL;
-       }
 
        reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
 
-       for_each_set_clump8(start, reg_mask, &reg_value, 64) {
-               if (reg_mask == reg_set) {
-                       mask = GENMASK_ULL(start + 7, start);
-                       reg_value &= ~mask;
-                       reg_value |= rol64(val, start);
-                       lo_hi_writeq(reg_value,
-                                    chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
-                       break;
-               }
-       }
+       /* Channel is already allocated, set handshake as per channel ID */
+       /* 64 bit write should handle for 8 channels */
+
+       reg_value &= ~(DMA_APB_HS_SEL_MASK <<
+                       (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
+       reg_value |= (val << (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
+       lo_hi_writeq(reg_value, chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
+
+       return;
 }
 
 /*
@@ -742,7 +733,7 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr,
                llp = hw_desc->llp;
        } while (total_segments);
 
-       dw_axi_dma_set_hw_channel(chan->chip, chan->hw_handshake_num, true);
+       dw_axi_dma_set_hw_channel(chan, true);
 
        return vchan_tx_prep(&chan->vc, &desc->vd, flags);
 
@@ -822,7 +813,7 @@ dw_axi_dma_chan_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
                llp = hw_desc->llp;
        } while (num_sgs);
 
-       dw_axi_dma_set_hw_channel(chan->chip, chan->hw_handshake_num, true);
+       dw_axi_dma_set_hw_channel(chan, true);
 
        return vchan_tx_prep(&chan->vc, &desc->vd, flags);
 
@@ -1098,8 +1089,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
                         "%s failed to stop\n", axi_chan_name(chan));
 
        if (chan->direction != DMA_MEM_TO_MEM)
-               dw_axi_dma_set_hw_channel(chan->chip,
-                                         chan->hw_handshake_num, false);
+               dw_axi_dma_set_hw_channel(chan, false);
        if (chan->direction == DMA_MEM_TO_DEV)
                dw_axi_dma_set_byte_halfword(chan, false);
 
@@ -1365,7 +1355,6 @@ static int dw_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-
        INIT_LIST_HEAD(&dw->dma.channels);
        for (i = 0; i < hdata->nr_channels; i++) {
                struct axi_dma_chan *chan = &dw->chan[i];
index b698978..358f553 100644 (file)
@@ -184,6 +184,8 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan)
 #define DMAC_APB_HALFWORD_WR_CH_EN     0x020 /* DMAC Halfword write enables */
 
 #define UNUSED_CHANNEL         0x3F /* Set unused DMA channel to 0x3F */
+#define DMA_APB_HS_SEL_BIT_SIZE        0x08 /* HW handshake bits per channel */
+#define DMA_APB_HS_SEL_MASK    0xFF /* HW handshake select masks */
 #define MAX_BLOCK_SIZE         0x1000 /* 1024 blocks * 4 bytes data width */
 
 /* DMAC_CFG */