]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dmaengine: dw: Simplify max-burst calculation procedure
authorSerge Semin <fancer.lancer@gmail.com>
Fri, 2 Aug 2024 07:50:50 +0000 (10:50 +0300)
committerVinod Koul <vkoul@kernel.org>
Mon, 5 Aug 2024 16:37:47 +0000 (22:07 +0530)
In order to have a more coherent DW AHB DMA slave configuration method -
dwc_config() - let's simplify the source and destination channel max-burst
calculation procedure:

1. Create the max-burst verification method as it has been just done for
the memory and peripheral address widths. Thus the dwc_config() method
will turn to a set of the verification methods execution.

2. Since both the generic DW AHB DMA and Intel iDMA 32-bit engines support
the power-of-2 bursts only, then the specified by the client driver
max-burst values can be converted to being power-of-2 right in the
max-burst verification method.

3. Since max-burst encoded value is required on the CTL_LO fields
calculation stage, the encode_maxburst() callback can be easily dropped
from the dw_dma structure meanwhile the encoding procedure will be
executed right in the CTL_LO register value calculation.

Thus the update will provide the next positive effects: the internal
DMA-slave config structure will contain only the real DMA-transfer config
values, which will be encoded to the DMA-controller register fields only
when it's required on the buffer mapping; the redundant encode_maxburst()
callback will be dropped simplifying the internal HW-abstraction API;
dwc_config() will look more readable executing the verification functions
one-by-one.

Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
Acked-by: Andy Shevchenko <andy@kernel.org>
Link: https://lore.kernel.org/r/20240802075100.6475-6-fancer.lancer@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dw/core.c
drivers/dma/dw/dw.c
drivers/dma/dw/idma32.c
drivers/dma/dw/regs.h

index b341a6f1b043836c4e06a4664229810b88d0e5d4..32a66f9effd9cc832d7de9925d4f5200efb45c5d 100644 (file)
@@ -779,6 +779,23 @@ bool dw_dma_filter(struct dma_chan *chan, void *param)
 }
 EXPORT_SYMBOL_GPL(dw_dma_filter);
 
+static int dwc_verify_maxburst(struct dma_chan *chan)
+{
+       struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
+
+       dwc->dma_sconfig.src_maxburst =
+               clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst);
+       dwc->dma_sconfig.dst_maxburst =
+               clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst);
+
+       dwc->dma_sconfig.src_maxburst =
+               rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst);
+       dwc->dma_sconfig.dst_maxburst =
+               rounddown_pow_of_two(dwc->dma_sconfig.dst_maxburst);
+
+       return 0;
+}
+
 static int dwc_verify_p_buswidth(struct dma_chan *chan)
 {
        struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
@@ -838,7 +855,7 @@ static int dwc_verify_m_buswidth(struct dma_chan *chan)
                dwc->dma_sconfig.src_addr_width = mem_width;
        } else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) {
                reg_width = dwc->dma_sconfig.src_addr_width;
-               reg_burst = rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst);
+               reg_burst = dwc->dma_sconfig.src_maxburst;
 
                dwc->dma_sconfig.dst_addr_width = min(mem_width, reg_width * reg_burst);
        }
@@ -849,15 +866,13 @@ static int dwc_verify_m_buswidth(struct dma_chan *chan)
 static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 {
        struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
-       struct dw_dma *dw = to_dw_dma(chan->device);
        int ret;
 
        memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
 
-       dwc->dma_sconfig.src_maxburst =
-               clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst);
-       dwc->dma_sconfig.dst_maxburst =
-               clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst);
+       ret = dwc_verify_maxburst(chan);
+       if (ret)
+               return ret;
 
        ret = dwc_verify_p_buswidth(chan);
        if (ret)
@@ -867,9 +882,6 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
        if (ret)
                return ret;
 
-       dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
-       dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
-
        return 0;
 }
 
index 628ee1e77505d76067342840882da6a8ae2797cc..6766142884b66ea6222ad6dfc1ef33e249a39ae5 100644 (file)
@@ -64,13 +64,13 @@ static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width)
        return DWC_CTLH_BLOCK_TS(block) << width;
 }
 
-static void dw_dma_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst)
+static inline u8 dw_dma_encode_maxburst(u32 maxburst)
 {
        /*
         * Fix burst size according to dw_dmac. We need to convert them as:
         * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
         */
-       *maxburst = *maxburst > 1 ? fls(*maxburst) - 2 : 0;
+       return maxburst > 1 ? fls(maxburst) - 2 : 0;
 }
 
 static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc)
@@ -82,11 +82,11 @@ static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc)
        if (dwc->direction == DMA_MEM_TO_DEV) {
                sms = dwc->dws.m_master;
                dms = dwc->dws.p_master;
-               dmsize = sconfig->dst_maxburst;
+               dmsize = dw_dma_encode_maxburst(sconfig->dst_maxburst);
        } else if (dwc->direction == DMA_DEV_TO_MEM) {
                sms = dwc->dws.p_master;
                dms = dwc->dws.m_master;
-               smsize = sconfig->src_maxburst;
+               smsize = dw_dma_encode_maxburst(sconfig->src_maxburst);
        } else /* DMA_MEM_TO_MEM */ {
                sms = dwc->dws.m_master;
                dms = dwc->dws.m_master;
@@ -125,7 +125,6 @@ int dw_dma_probe(struct dw_dma_chip *chip)
        dw->suspend_chan = dw_dma_suspend_chan;
        dw->resume_chan = dw_dma_resume_chan;
        dw->prepare_ctllo = dw_dma_prepare_ctllo;
-       dw->encode_maxburst = dw_dma_encode_maxburst;
        dw->bytes2block = dw_dma_bytes2block;
        dw->block2bytes = dw_dma_block2bytes;
 
index 493fcbafa2b8edd2b00b1b08c052c5f5f75c6f09..dac617c183e6a564bc382d25fc8a00c3bc4874f9 100644 (file)
@@ -199,9 +199,9 @@ static size_t idma32_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width)
        return IDMA32C_CTLH_BLOCK_TS(block);
 }
 
-static void idma32_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst)
+static inline u8 idma32_encode_maxburst(u32 maxburst)
 {
-       *maxburst = *maxburst > 1 ? fls(*maxburst) - 1 : 0;
+       return maxburst > 1 ? fls(maxburst) - 1 : 0;
 }
 
 static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc)
@@ -210,9 +210,9 @@ static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc)
        u8 smsize = 0, dmsize = 0;
 
        if (dwc->direction == DMA_MEM_TO_DEV)
-               dmsize = sconfig->dst_maxburst;
+               dmsize = idma32_encode_maxburst(sconfig->dst_maxburst);
        else if (dwc->direction == DMA_DEV_TO_MEM)
-               smsize = sconfig->src_maxburst;
+               smsize = idma32_encode_maxburst(sconfig->src_maxburst);
 
        return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN |
               DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize);
@@ -274,7 +274,6 @@ int idma32_dma_probe(struct dw_dma_chip *chip)
        dw->suspend_chan = idma32_suspend_chan;
        dw->resume_chan = idma32_resume_chan;
        dw->prepare_ctllo = idma32_prepare_ctllo;
-       dw->encode_maxburst = idma32_encode_maxburst;
        dw->bytes2block = idma32_bytes2block;
        dw->block2bytes = idma32_block2bytes;
 
index 76654bd13c1abf723ca3707cc03c8bab89506721..5969d9cc8d7ae2da1e95f03c7805dc98818e5f7f 100644 (file)
@@ -327,7 +327,6 @@ struct dw_dma {
        void    (*suspend_chan)(struct dw_dma_chan *dwc, bool drain);
        void    (*resume_chan)(struct dw_dma_chan *dwc, bool drain);
        u32     (*prepare_ctllo)(struct dw_dma_chan *dwc);
-       void    (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst);
        u32     (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes,
                               unsigned int width, size_t *len);
        size_t  (*block2bytes)(struct dw_dma_chan *dwc, u32 block, u32 width);