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: 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>
This commit is contained in:
Родитель
5eea6c9712
Коммит
32286e2793
|
@ -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, ®_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];
|
||||
|
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче