Commit 32286e27 authored by Pandith N's avatar Pandith N Committed by Vinod Koul
Browse files

dmaengine: dw-axi-dmac: Remove free slot check algorithm in dw_axi_dma_set_hw_channel



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: default avatarPandith N <pandith.n@intel.com>
Tested-by: default avatarPan Kris <kris.pan@intel.com>
Link: https://lore.kernel.org/r/20210802055454.15192-2-pandith.n@intel.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 5eea6c97
Loading
Loading
Loading
Loading
+19 −30
Original line number Diff line number Diff line
@@ -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];
+2 −0
Original line number Diff line number Diff line
@@ -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 */