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

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.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 5eea6c97
...@@ -470,18 +470,13 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan) ...@@ -470,18 +470,13 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan)
pm_runtime_put(chan->chip->dev); pm_runtime_put(chan->chip->dev);
} }
static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip, static void dw_axi_dma_set_hw_channel(struct axi_dma_chan *chan, bool set)
u32 handshake_num, bool set)
{ {
unsigned long start = 0; struct axi_dma_chip *chip = chan->chip;
unsigned long reg_value; unsigned long reg_value, val;
unsigned long reg_mask;
unsigned long reg_set;
unsigned long mask;
unsigned long val;
if (!chip->apb_regs) { if (!chip->apb_regs) {
dev_dbg(chip->dev, "apb_regs not initialized\n"); dev_err(chip->dev, "apb_regs not initialized\n");
return; return;
} }
...@@ -490,26 +485,22 @@ static void dw_axi_dma_set_hw_channel(struct axi_dma_chip *chip, ...@@ -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. * Lock the DMA channel by assign a handshake number to the channel.
* Unlock the DMA channel by assign 0x3F to the channel. * Unlock the DMA channel by assign 0x3F to the channel.
*/ */
if (set) { if (set)
reg_set = UNUSED_CHANNEL; val = chan->hw_handshake_num;
val = handshake_num; else
} else {
reg_set = handshake_num;
val = UNUSED_CHANNEL; val = UNUSED_CHANNEL;
}
reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0); reg_value = lo_hi_readq(chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
for_each_set_clump8(start, reg_mask, &reg_value, 64) { /* Channel is already allocated, set handshake as per channel ID */
if (reg_mask == reg_set) { /* 64 bit write should handle for 8 channels */
mask = GENMASK_ULL(start + 7, start);
reg_value &= ~mask; reg_value &= ~(DMA_APB_HS_SEL_MASK <<
reg_value |= rol64(val, start); (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
lo_hi_writeq(reg_value, reg_value |= (val << (chan->id * DMA_APB_HS_SEL_BIT_SIZE));
chip->apb_regs + DMAC_APB_HW_HS_SEL_0); lo_hi_writeq(reg_value, chip->apb_regs + DMAC_APB_HW_HS_SEL_0);
break;
} return;
}
} }
/* /*
...@@ -742,7 +733,7 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr, ...@@ -742,7 +733,7 @@ dw_axi_dma_chan_prep_cyclic(struct dma_chan *dchan, dma_addr_t dma_addr,
llp = hw_desc->llp; llp = hw_desc->llp;
} while (total_segments); } 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); 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, ...@@ -822,7 +813,7 @@ dw_axi_dma_chan_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
llp = hw_desc->llp; llp = hw_desc->llp;
} while (num_sgs); } 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); return vchan_tx_prep(&chan->vc, &desc->vd, flags);
...@@ -1098,8 +1089,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan) ...@@ -1098,8 +1089,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan)
"%s failed to stop\n", axi_chan_name(chan)); "%s failed to stop\n", axi_chan_name(chan));
if (chan->direction != DMA_MEM_TO_MEM) if (chan->direction != DMA_MEM_TO_MEM)
dw_axi_dma_set_hw_channel(chan->chip, dw_axi_dma_set_hw_channel(chan, false);
chan->hw_handshake_num, false);
if (chan->direction == DMA_MEM_TO_DEV) if (chan->direction == DMA_MEM_TO_DEV)
dw_axi_dma_set_byte_halfword(chan, false); dw_axi_dma_set_byte_halfword(chan, false);
...@@ -1365,7 +1355,6 @@ static int dw_probe(struct platform_device *pdev) ...@@ -1365,7 +1355,6 @@ static int dw_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
INIT_LIST_HEAD(&dw->dma.channels); INIT_LIST_HEAD(&dw->dma.channels);
for (i = 0; i < hdata->nr_channels; i++) { for (i = 0; i < hdata->nr_channels; i++) {
struct axi_dma_chan *chan = &dw->chan[i]; struct axi_dma_chan *chan = &dw->chan[i];
......
...@@ -184,6 +184,8 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan) ...@@ -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 DMAC_APB_HALFWORD_WR_CH_EN 0x020 /* DMAC Halfword write enables */
#define UNUSED_CHANNEL 0x3F /* Set unused DMA channel to 0x3F */ #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 */ #define MAX_BLOCK_SIZE 0x1000 /* 1024 blocks * 4 bytes data width */
/* DMAC_CFG */ /* DMAC_CFG */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment