Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: sprd: Add wrap address support for link-list mode

The Spreadtrum Audio compress offload mode will use 2-stage DMA transfer
to save power. That means we can request 2 dma channels, one for source
channel, and another one for destination channel. Once the source channel's
transaction is done, it will trigger the destination channel's transaction
automatically by hardware signal.

In this case, the source channel will transfer data from IRAM buffer to
the DSP fifo to decoding/encoding, once IRAM buffer is empty by transferring
done, the destination channel will start to transfer data from DDR buffer
to IRAM buffer. Since the destination channel will use link-list mode to
fill the IRAM data, and IRAM buffer is allocated by 32K, and DDR buffer
is larger to 2M, that means we need lots of link-list nodes to do a cyclic
transfer, instead wasting lots of link-list memory, we can use wrap address
support to reduce link-list node number, which means when the transfer
address reaches the wrap address, the transfer address will jump to the
wrap_to address specified by wrap_to register, and only 2 link-list nodes
can do a cyclic transfer to transfer data from DDR to IRAM.

Thus this patch adds wrap address to support this case.

[Baolin Wang changes the commit message]
Signed-off-by: Eric Long <eric.long@unisoc.com>
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Link: https://lore.kernel.org/r/85a5484bc1f3dd53ce6f92700ad8b35f30a0b096.1571812029.git.baolin.wang@linaro.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Eric Long and committed by
Vinod Koul
a7e335de bb5a471d

+17
+13
drivers/dma/sprd-dma.c
··· 99 99 /* DMA_CHN_WARP_* register definition */ 100 100 #define SPRD_DMA_HIGH_ADDR_MASK GENMASK(31, 28) 101 101 #define SPRD_DMA_LOW_ADDR_MASK GENMASK(31, 0) 102 + #define SPRD_DMA_WRAP_ADDR_MASK GENMASK(27, 0) 102 103 #define SPRD_DMA_HIGH_ADDR_OFFSET 4 103 104 104 105 /* SPRD_DMA_CHN_INTC register definition */ ··· 119 118 #define SPRD_DMA_SWT_MODE_OFFSET 26 120 119 #define SPRD_DMA_REQ_MODE_OFFSET 24 121 120 #define SPRD_DMA_REQ_MODE_MASK GENMASK(1, 0) 121 + #define SPRD_DMA_WRAP_SEL_DEST BIT(23) 122 + #define SPRD_DMA_WRAP_EN BIT(22) 122 123 #define SPRD_DMA_FIX_SEL_OFFSET 21 123 124 #define SPRD_DMA_FIX_EN_OFFSET 20 124 125 #define SPRD_DMA_LLIST_END BIT(19) ··· 807 804 temp |= req_mode << SPRD_DMA_REQ_MODE_OFFSET; 808 805 temp |= fix_mode << SPRD_DMA_FIX_SEL_OFFSET; 809 806 temp |= fix_en << SPRD_DMA_FIX_EN_OFFSET; 807 + temp |= schan->linklist.wrap_addr ? 808 + SPRD_DMA_WRAP_EN | SPRD_DMA_WRAP_SEL_DEST : 0; 810 809 temp |= slave_cfg->src_maxburst & SPRD_DMA_FRG_LEN_MASK; 811 810 hw->frg_len = temp; 812 811 ··· 836 831 hw->llist_ptr = lower_32_bits(llist_ptr); 837 832 hw->src_blk_step = (upper_32_bits(llist_ptr) << SPRD_DMA_LLIST_HIGH_SHIFT) & 838 833 SPRD_DMA_LLIST_HIGH_MASK; 834 + 835 + if (schan->linklist.wrap_addr) { 836 + hw->wrap_ptr |= schan->linklist.wrap_addr & 837 + SPRD_DMA_WRAP_ADDR_MASK; 838 + hw->wrap_to |= dst & SPRD_DMA_WRAP_ADDR_MASK; 839 + } 839 840 } else { 840 841 hw->llist_ptr = 0; 841 842 hw->src_blk_step = 0; ··· 950 939 951 940 schan->linklist.phy_addr = ll_cfg->phy_addr; 952 941 schan->linklist.virt_addr = ll_cfg->virt_addr; 942 + schan->linklist.wrap_addr = ll_cfg->wrap_addr; 953 943 } else { 954 944 schan->linklist.phy_addr = 0; 955 945 schan->linklist.virt_addr = 0; 946 + schan->linklist.wrap_addr = 0; 956 947 } 957 948 958 949 /*
+4
include/linux/dma/sprd-dma.h
··· 118 118 * struct sprd_dma_linklist - DMA link-list address structure 119 119 * @virt_addr: link-list virtual address to configure link-list node 120 120 * @phy_addr: link-list physical address to link DMA transfer 121 + * @wrap_addr: the wrap address for link-list mode, which means once the 122 + * transfer address reaches the wrap address, the next transfer address 123 + * will jump to the address specified by wrap_to register. 121 124 * 122 125 * The Spreadtrum DMA controller supports the link-list mode, that means slaves 123 126 * can supply several groups configurations (each configuration represents one ··· 184 181 struct sprd_dma_linklist { 185 182 unsigned long virt_addr; 186 183 phys_addr_t phy_addr; 184 + phys_addr_t wrap_addr; 187 185 }; 188 186 189 187 #endif