Skip to content

Commit a131169

Browse files
Jyothi Kumar Seerapuvinodkoul
authored andcommitted
dmaengine: qcom: gpi: Add GPI immediate DMA support for SPI protocol
The DMA TRE(Transfer ring element) buffer contains the DMA buffer address. Accessing data from this address can cause significant delays in SPI transfers, which can be mitigated to some extent by utilizing immediate DMA support. QCOM GPI DMA hardware supports an immediate DMA feature for data up to 8 bytes, storing the data directly in the DMA TRE buffer instead of the DMA buffer address. This enhancement enables faster SPI data transfers. This optimization reduces the average transfer time from 25 us to 16 us for a single SPI transfer of 8 bytes length, with a clock frequency of 50 MHz. Signed-off-by: Jyothi Kumar Seerapu <quic_jseerapu@quicinc.com> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Link: https://lore.kernel.org/r/20241209075033.16860-1-quic_jseerapu@quicinc.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 06d5363 commit a131169

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

drivers/dma/qcom/gpi.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "../virt-dma.h"
1919

2020
#define TRE_TYPE_DMA 0x10
21+
#define TRE_TYPE_IMMEDIATE_DMA 0x11
2122
#define TRE_TYPE_GO 0x20
2223
#define TRE_TYPE_CONFIG0 0x22
2324

@@ -64,6 +65,7 @@
6465

6566
/* DMA TRE */
6667
#define TRE_DMA_LEN GENMASK(23, 0)
68+
#define TRE_DMA_IMMEDIATE_LEN GENMASK(3, 0)
6769

6870
/* Register offsets from gpi-top */
6971
#define GPII_n_CH_k_CNTXT_0_OFFS(n, k) (0x20000 + (0x4000 * (n)) + (0x80 * (k)))
@@ -1711,6 +1713,7 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc,
17111713
dma_addr_t address;
17121714
struct gpi_tre *tre;
17131715
unsigned int i;
1716+
int len;
17141717

17151718
/* first create config tre if applicable */
17161719
if (direction == DMA_MEM_TO_DEV && spi->set_config) {
@@ -1763,14 +1766,30 @@ static int gpi_create_spi_tre(struct gchan *chan, struct gpi_desc *desc,
17631766
tre_idx++;
17641767

17651768
address = sg_dma_address(sgl);
1766-
tre->dword[0] = lower_32_bits(address);
1767-
tre->dword[1] = upper_32_bits(address);
1769+
len = sg_dma_len(sgl);
17681770

1769-
tre->dword[2] = u32_encode_bits(sg_dma_len(sgl), TRE_DMA_LEN);
1771+
/* Support Immediate dma for write transfers for data length up to 8 bytes */
1772+
if (direction == DMA_MEM_TO_DEV && len <= 2 * sizeof(tre->dword[0])) {
1773+
/*
1774+
* For Immediate dma, data length may not always be length of 8 bytes,
1775+
* it can be length less than 8, hence initialize both dword's with 0
1776+
*/
1777+
tre->dword[0] = 0;
1778+
tre->dword[1] = 0;
1779+
memcpy(&tre->dword[0], sg_virt(sgl), len);
17701780

1771-
tre->dword[3] = u32_encode_bits(TRE_TYPE_DMA, TRE_FLAGS_TYPE);
1772-
if (direction == DMA_MEM_TO_DEV)
1773-
tre->dword[3] |= u32_encode_bits(1, TRE_FLAGS_IEOT);
1781+
tre->dword[2] = u32_encode_bits(len, TRE_DMA_IMMEDIATE_LEN);
1782+
tre->dword[3] = u32_encode_bits(TRE_TYPE_IMMEDIATE_DMA, TRE_FLAGS_TYPE);
1783+
} else {
1784+
tre->dword[0] = lower_32_bits(address);
1785+
tre->dword[1] = upper_32_bits(address);
1786+
1787+
tre->dword[2] = u32_encode_bits(len, TRE_DMA_LEN);
1788+
tre->dword[3] = u32_encode_bits(TRE_TYPE_DMA, TRE_FLAGS_TYPE);
1789+
}
1790+
1791+
tre->dword[3] |= u32_encode_bits(direction == DMA_MEM_TO_DEV,
1792+
TRE_FLAGS_IEOT);
17741793

17751794
for (i = 0; i < tre_idx; i++)
17761795
dev_dbg(dev, "TRE:%d %x:%x:%x:%x\n", i, desc->tre[i].dword[0],

0 commit comments

Comments
 (0)