[RFC V3 PATCH 8/8] dmaengine: xilinx_dma: Add device_config support

From: Sarath Babu Naidu Gaddam
Date: Tue Sep 20 2022 - 01:53:43 EST


DMA clients (ethernet driver) can use this interface to pass get/set
coalesce information.

Signed-off-by: Sarath Babu Naidu Gaddam <sarath.babu.naidu.gaddam@xxxxxxx>
---
At present device_config support to program coalesce is only for AXIDMA
and once the RFC is accepted it will extended to other IP variants.

Changes in V3:
- New patch.
---
drivers/dma/xilinx/xilinx_dma.c | 37 ++++++++++++++++++++++++++++++++-
include/linux/dma/xilinx_dma.h | 16 ++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index bd8f09837141..0a994c5f3ae0 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -414,6 +414,7 @@ struct xilinx_dma_tx_descriptor {
* @tdest: TDEST value for mcdma
* @has_vflip: S2MM vertical flip
* @irq_delay: Interrupt delay timeout
+ * @has_static_coalesce: Used to check static/dynamic coalesce selection
*/
struct xilinx_dma_chan {
struct xilinx_dma_device *xdev;
@@ -453,6 +454,7 @@ struct xilinx_dma_chan {
u16 tdest;
bool has_vflip;
u8 irq_delay;
+ u8 has_static_coalesce;
};

/**
@@ -1555,7 +1557,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)

reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);

- if (chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
+ if (!(chan->has_static_coalesce) && chan->desc_pendingcount <= XILINX_DMA_COALESCE_MAX) {
reg &= ~XILINX_DMA_CR_COALESCE_MAX;
reg |= chan->desc_pendingcount <<
XILINX_DMA_CR_COALESCE_SHIFT;
@@ -1696,6 +1698,39 @@ static void xilinx_dma_issue_pending(struct dma_chan *dchan)
static int xilinx_dma_device_config(struct dma_chan *dchan,
struct dma_slave_config *config)
{
+ struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+ u32 regval;
+
+ if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
+ struct xilinx_peri_config *pconfig = config->peripheral_config;
+
+ if (!pconfig || config->peripheral_size != sizeof(*pconfig))
+ return -EINVAL;
+
+ switch (pconfig->cmd) {
+ case XILINX_DMA_GET_COALESCE:
+ regval = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+ regval &= XILINX_DMA_CR_COALESCE_MAX;
+ *((int *)pconfig->data) = regval >> XILINX_DMA_CR_COALESCE_SHIFT;
+
+ break;
+ case XILINX_DMA_SET_COALESCE:
+ if ((*(int *)pconfig->data) <= XILINX_DMA_COALESCE_MAX) {
+ regval = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
+ regval &= ~XILINX_DMA_CR_COALESCE_MAX;
+ regval |= ((*(int *)pconfig->data) <<
+ XILINX_DMA_CR_COALESCE_SHIFT);
+
+ dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, regval);
+ chan->has_static_coalesce = 1;
+ }
+
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
return 0;
}

diff --git a/include/linux/dma/xilinx_dma.h b/include/linux/dma/xilinx_dma.h
index 0dde1a46ab75..ce0267baf5eb 100644
--- a/include/linux/dma/xilinx_dma.h
+++ b/include/linux/dma/xilinx_dma.h
@@ -41,5 +41,21 @@ struct xilinx_vdma_config {

int xilinx_vdma_channel_set_config(struct dma_chan *dchan,
struct xilinx_vdma_config *cfg);
+/**
+ * struct xilinx_peri_config -Configuration structure for user
+ * configurable commands and associated data.
+ *cmd: cmd for passing any slave info. Example: ethtool get/set coalesce
+ *data: data for cmd argument
+ */
+struct xilinx_peri_config {
+ int cmd;
+ void *data;
+};
+
+/**
+ * XILINX_DMA_GET/SET COALSCE -setting IP coalesce parameters
+ */
+#define XILINX_DMA_GET_COALESCE 1
+#define XILINX_DMA_SET_COALESCE 2

#endif
--
2.25.1