Skip to contentSkip to conversation

new Atmel DMA controller (XDMAC)

PATCH Superseded Ludovic Desroches 2 participants 14 messages Oct 1, 2014 – Oct 21, 2014

Subsystems (4)

v6 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

v6 cover new Atmel DMA controller (XDMAC)

Hi,

This set of patches introduces support for the new Atmel DMA controller know as XDMAC and available on SAMA5D4.

Since there were no feedback about v5, could you give your ack if you agree with this new version.

Changes from:
- v5
- fix a bug when doing memcpy, condition to set the NDE was inverted
- replace irqsave locks by bh variant
- unmasked channel errors
- v4
- compile the driver if COMPILE_TEST is selected
- merge header file into at_xdmac.c
- use write memory barriers before starting the channel
- init active_xfer to false when taking a descriptor from the free descriptors list
- remove dma capabilities mask
- use CONFIG_PM instead of CONFIG_PM_SLEEP for prepare function
- style fixes
- update documentation to add the <chip> compatible description
- add maintener entry
- v3
- use dma_get_any_slave_channel instead of dma_request_channel
- fix tx_status behavior for non active transfers
- rename at_xdmac_terminate_xfer
- replace suspend/resume no irq variants by late/early variants
- no more use dev res to request the irq, use the legacy way
- add slave capabilities
- v2
- documentation updated
- fix locking issues
- v1
- add power management stuff
- check maxburst value
- revert subsys_initcall remove, EPROBE_DEFER not yet available on the kernel version I use to do the tests, moreover other devices are not ready to use it
- RFC:
- DMA_SUCCESS replaced by DMA_COMPLETE
- fix memcpy issue caused by a mistake in interfaces used
- add filter function
- remove some parameters from device tree since we can get them through the dma slave configuration
- use readl/writel relaxed
- remove subsys_initcall
- synchronize irq before killing tasklets
- use BIT macro
- misc cleanup

Ludovic Desroches (3):
dma: at_xdmac: creation of the atmel eXtended DMA Controller driver
ARM: dts: at_xdmac: add bindings documentation
MAINTAINERS: add entry for Atmel XDMA driver

 .../devicetree/bindings/dma/atmel-xdma.txt         |   50 +
 MAINTAINERS                                        |    7 +
 drivers/dma/Kconfig                                |    7 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/at_xdmac.c                             | 1493 ++++++++++++++++++++
 include/dt-bindings/dma/at91.h                     |   25 +
 6 files changed, 1583 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-xdma.txt
 create mode 100644 drivers/dma/at_xdmac.c
Signature · 1 line
2.0.3
#1 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

New atmel DMA controller known as XDMAC, introduced with SAMA5D4 devices.

---
 drivers/dma/Kconfig            |    7 +
 drivers/dma/Makefile           |    1 +
 drivers/dma/at_xdmac.c         | 1493 ++++++++++++++++++++++++++++++++++++++++
 include/dt-bindings/dma/at91.h |   25 +
 4 files changed, 1526 insertions(+)
 create mode 100644 drivers/dma/at_xdmac.c
drivers/dma/Kconfig +7 -0
index 9b1ea0e..042ebb1 100644
@@ -107,6 +107,13 @@ config AT_HDMAC
 	help
 	  Support the Atmel AHB DMA controller.
 
+config AT_XDMAC
+	tristate "Atmel XDMA support"
+	depends on (ARCH_AT91 || COMPILE_TEST)
+	select DMA_ENGINE
+	help
+	  Support the Atmel XDMA controller.
+
 config FSL_DMA
 	tristate "Freescale Elo series DMA support"
 	depends on FSL_SOC
drivers/dma/Makefile +1 -0
index c6adb92..f32bfe1 100644
@@ -17,6 +17,7 @@ obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC_CORE) += dw/
 obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
+obj-$(CONFIG_AT_XDMAC) += at_xdmac.o
 obj-$(CONFIG_MX3_IPU) += ipu/
 obj-$(CONFIG_TXX9_DMAC) += txx9dmac.o
 obj-$(CONFIG_SH_DMAE_BASE) += sh/
drivers/dma/at_xdmac.c new file +1493 -0

1,493 lines not on this page · raw message

include/dt-bindings/dma/at91.h +25 -0
index e835037..4875a50 100644
@@ -9,6 +9,8 @@
 #ifndef __DT_BINDINGS_AT91_DMA_H__
 #define __DT_BINDINGS_AT91_DMA_H__
 
+/* ---------- HDMAC ---------- */
+
 /*
  * Source and/or destination peripheral ID
  */
@@ -24,4 +26,27 @@
 #define AT91_DMA_CFG_FIFOCFG_ALAP	(0x1 << AT91_DMA_CFG_FIFOCFG_OFFSET)	/* largest defined AHB burst */
 #define AT91_DMA_CFG_FIFOCFG_ASAP	(0x2 << AT91_DMA_CFG_FIFOCFG_OFFSET)	/* single AHB access */
 
+
+/* ---------- XDMAC ---------- */
+#define AT91_XDMAC_DT_MEM_IF_MASK	(0x1)
+#define AT91_XDMAC_DT_MEM_IF_OFFSET	(16)
+#define AT91_XDMAC_DT_MEM_IF(mem_if)	(((mem_if) & AT91_XDMAC_DT_MEM_IF_MASK) \
+					<< AT91_XDMAC_DT_MEM_IF_OFFSET)
+#define AT91_XDMAC_DT_GET_MEM_IF(cfg)	(((cfg) >> AT91_XDMAC_DT_MEM_IF_OFFSET) \
+					& AT91_XDMAC_DT_MEM_IF_MASK)
+
+#define AT91_XDMAC_DT_PER_IF_MASK	(0x1)
+#define AT91_XDMAC_DT_PER_IF_OFFSET	(0)
+#define AT91_XDMAC_DT_PER_IF(per_if)	(((per_if) & AT91_XDMAC_DT_PER_IF_MASK) \
+					<< AT91_XDMAC_DT_PER_IF_OFFSET)
+#define AT91_XDMAC_DT_GET_PER_IF(cfg)	(((cfg) >> AT91_XDMAC_DT_PER_IF_OFFSET) \
+					& AT91_XDMAC_DT_PER_IF_MASK)
+
+#define AT91_XDMAC_DT_PERID_MASK	(0x7f)
+#define AT91_XDMAC_DT_PERID_OFFSET	(24)
+#define AT91_XDMAC_DT_PERID(perid)	(((perid) & AT91_XDMAC_DT_PERID_MASK) \
+					<< AT91_XDMAC_DT_PERID_OFFSET)
+#define AT91_XDMAC_DT_GET_PERID(cfg)	(((cfg) >> AT91_XDMAC_DT_PERID_OFFSET) \
+					& AT91_XDMAC_DT_PERID_MASK)
+
 #endif /* __DT_BINDINGS_AT91_DMA_H__ */
Signature · 1 line
2.0.3
#2 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

drivers/dma/at_xdmac.c line 292

Quoted 9 lines · Ludovic Desroches

New atmel DMA controller known as XDMAC, introduced with SAMA5D4 devices.

drivers/dma/at_xdmac.c new file +6 -0
+
+static inline u32 at_xdmac_csize(u32 maxburst)
+{
+	u32 csize;
+
+	switch (ffs(maxburst) - 1) {

This is pretty odd, I dont see a reason why we can have proper case values and converted ones. It would have made sense if we use this for conversion but in case values in quite puzzling

drivers/dma/at_xdmac.c line 294

Quoted 2 lines
drivers/dma/at_xdmac.c new file +2 -0
+	case 1:
+		csize = AT_XDMAC_CC_CSIZE_CHK_2;

and looking at values this can be ffs(maxburst) - 1 for valid cases

drivers/dma/at_xdmac.c line 306

Quoted 12 lines
drivers/dma/at_xdmac.c new file +12 -0
+		break;
+	case 2:
+		csize = AT_XDMAC_CC_CSIZE_CHK_4;
+		break;
+	case 3:
+		csize = AT_XDMAC_CC_CSIZE_CHK_8;
+		break;
+	case 4:
+		csize = AT_XDMAC_CC_CSIZE_CHK_16;
+		break;
+	default:
+		csize = AT_XDMAC_CC_CSIZE_CHK_1;

why?

Quoted 57 lines
drivers/dma/at_xdmac.c new file +57 -0
+	}
+
+	return csize;
+};
+
+static unsigned int init_nr_desc_per_channel = 64;
+module_param(init_nr_desc_per_channel, uint, 0644);
+MODULE_PARM_DESC(init_nr_desc_per_channel,
+		 "initial descriptors per channel (default: 64)");
+
+
+static bool at_xdmac_chan_is_enabled(struct at_xdmac_chan *atchan)
+{
+	return at_xdmac_chan_read(atchan, AT_XDMAC_GS) & atchan->mask;
+}
+
+static void at_xdmac_off(struct at_xdmac *atxdmac)
+{
+	at_xdmac_write(atxdmac, AT_XDMAC_GD, -1L);
+
+	/* Wait that all chans are disabled. */
+	while (at_xdmac_read(atxdmac, AT_XDMAC_GS))
+		cpu_relax();
+
+	at_xdmac_write(atxdmac, AT_XDMAC_GID, -1L);
+}
+
+/* Call with lock hold. */
+static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
+				struct at_xdmac_desc *first)
+{
+	struct at_xdmac	*atxdmac = to_at_xdmac(atchan->chan.device);
+	u32		reg;
+
+	dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first);
+
+	if (at_xdmac_chan_is_enabled(atchan))
+		return;
+
+	/* Set transfer as active to not try to start it again. */
+	first->active_xfer = true;
+
+	/* Tell xdmac where to get the first descriptor. */
+	reg = AT_XDMAC_CNDA_NDA(first->tx_dma_desc.phys)
+	      | AT_XDMAC_CNDA_NDAIF(atchan->memif);
+	at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, reg);
+
+	/*
+	 * When doing memory to memory transfer we need to use the next
+	 * descriptor view 2 since some fields of the configuration register
+	 * depend on transfer size and src/dest addresses.
+	 */
+	if (atchan->cfg & AT_XDMAC_CC_TYPE_PER_TRAN) {
+		reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
+		at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->cfg);
+	} else {
+		reg = AT_XDMAC_CNDC_NDVIEW_NDV2;

drivers/dma/at_xdmac.c line 373

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+	}
+
+	reg |= AT_XDMAC_CNDC_NDDUP
+	       | AT_XDMAC_CNDC_NDSUP
+	       | AT_XDMAC_CNDC_NDE;
+	at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, reg);
+
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: XDMAC_CC=0x%08x XDMAC_CNDA=0x%08x, XDMAC_CNDC=0x%08x, "
+		 "XDMAC_CSA=0x%08x, XDMAC_CDA=0x%08x, XDMAC_CUBC=0x%08x\n",

multi line prints are not encouraged. You could perhpas do XDMAC CC, CNDC... and reduce your text size and ignore 80char limit.

Quoted 55 lines
drivers/dma/at_xdmac.c new file +54 -0
+		 __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CSA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
+
+	at_xdmac_chan_write(atchan, AT_XDMAC_CID, 0xffffffff);
+	reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE | AT_XDMAC_CIE_ROIE;
+	/*
+	 * There is no end of list when doing cyclic dma, we need to get
+	 * an interrupt after each periods.
+	 */
+	if (at_xdmac_chan_is_cyclic(atchan))
+		at_xdmac_chan_write(atchan, AT_XDMAC_CIE,
+				    reg | AT_XDMAC_CIE_BIE);
+	else
+		at_xdmac_chan_write(atchan, AT_XDMAC_CIE,
+				    reg | AT_XDMAC_CIE_LIE);
+	at_xdmac_write(atxdmac, AT_XDMAC_GIE, atchan->mask);
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: enable channel (0x%08x)\n", __func__, atchan->mask);
+	wmb();
+	at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask);
+
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: XDMAC_CC=0x%08x XDMAC_CNDA=0x%08x, XDMAC_CNDC=0x%08x, "
+		 "XDMAC_CSA=0x%08x, XDMAC_CDA=0x%08x, XDMAC_CUBC=0x%08x\n",
+		 __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CSA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
+
+}
 
+static int at_xdmac_set_slave_config(struct dma_chan *chan,
+				      struct dma_slave_config *sconfig)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+
+	atchan->cfg = AT91_XDMAC_DT_PERID(atchan->perid)
+		      |	AT_XDMAC_CC_SWREQ_HWR_CONNECTED
+		      | AT_XDMAC_CC_MBSIZE_SIXTEEN
+		      | AT_XDMAC_CC_TYPE_PER_TRAN;
+
+	if (sconfig->direction == DMA_DEV_TO_MEM) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_INCREMENTED_AM
+			       | AT_XDMAC_CC_SAM_FIXED_AM
+			       | AT_XDMAC_CC_DIF(atchan->memif)
+			       | AT_XDMAC_CC_SIF(atchan->perif)
+			       | AT_XDMAC_CC_DSYNC_PER2MEM;
+		atchan->dwidth = ffs(sconfig->src_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);

drivers/dma/at_xdmac.c

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+		atchan->cfg |= at_xdmac_csize(sconfig->src_maxburst);
+	} else if (sconfig->direction == DMA_MEM_TO_DEV) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_FIXED_AM
+			       | AT_XDMAC_CC_SAM_INCREMENTED_AM
+			       | AT_XDMAC_CC_DIF(atchan->perif)
+			       | AT_XDMAC_CC_SIF(atchan->memif)
+			       | AT_XDMAC_CC_DSYNC_MEM2PER;
+		atchan->dwidth = ffs(sconfig->dst_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->dst_maxburst);

please store both direction configs and use them based on direction in prep_xxx calls. We will remove the direction here.

Quoted 93 lines
drivers/dma/at_xdmac.c new file +93 -0
+	} else {
+		return -EINVAL;
+	}
+
+	/*
+	 * Src address and dest addr are needed to configure the link list
+	 * descriptor so keep the slave configuration.
+	 */
+	memcpy(&atchan->dma_sconfig, sconfig, sizeof(struct dma_slave_config));
+
+	dev_dbg(chan2dev(chan), "%s: atchan->cfg=0x%08x\n", __func__, atchan->cfg);
+
+	return 0;
+}
+
+static struct dma_async_tx_descriptor *
+at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+		       unsigned int sg_len, enum dma_transfer_direction direction,
+		       unsigned long flags, void *context)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+	struct dma_slave_config	*sconfig = &atchan->dma_sconfig;
+	struct at_xdmac_desc	*first = NULL, *prev = NULL;
+	struct scatterlist	*sg;
+	int 			i;
+
+	if (!sgl)
+		return NULL;
+
+	if (!is_slave_direction(direction)) {
+		dev_err(chan2dev(chan), "invalid DMA direction\n");
+		return NULL;
+	}
+
+	dev_dbg(chan2dev(chan), "%s: sg_len=%d, dir=%s, flags=0x%lx\n",
+		 __func__, sg_len,
+		 direction == DMA_MEM_TO_DEV ? "to device" : "from device",
+		 flags);
+
+	/* Protect dma_sconfig field that can be modified by set_slave_conf. */
+	spin_lock_bh(&atchan->lock);
+
+	/* Prepare descriptors. */
+	for_each_sg(sgl, sg, sg_len, i) {
+		struct at_xdmac_desc	*desc = NULL;
+		u32			len, mem;
+
+		len = sg_dma_len(sg);
+		mem = sg_dma_address(sg);
+		if (unlikely(!len)) {
+			dev_err(chan2dev(chan), "sg data length is zero\n");
+			spin_unlock_bh(&atchan->lock);
+			return NULL;
+		}
+		dev_dbg(chan2dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n",
+			 __func__, i, len, mem);
+
+		desc = at_xdmac_get_desc(atchan);
+		if (!desc) {
+			dev_err(chan2dev(chan), "can't get descriptor\n");
+			if (first)
+				list_splice_init(&first->descs_list, &atchan->free_descs_list);
+			spin_unlock_bh(&atchan->lock);
+			return NULL;
+		}
+
+		/* Linked list descriptor setup. */
+		if (direction == DMA_DEV_TO_MEM) {
+			desc->lld.mbr_sa = sconfig->src_addr;
+			desc->lld.mbr_da = mem;
+		} else {
+			desc->lld.mbr_sa = mem;
+			desc->lld.mbr_da = sconfig->dst_addr;
+		}
+		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1		/* next descriptor view */
+			| AT_XDMAC_MBR_UBC_NDEN				/* next descriptor dst parameter update */
+			| AT_XDMAC_MBR_UBC_NSEN				/* next descriptor src parameter update */
+			| (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE)	/* descriptor fetch */
+			| len / (1 << atchan->dwidth);			/* microblock length */
+		dev_dbg(chan2dev(chan),
+			 "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x\n",
+			 __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc);
+
+		/* Chain lld. */
+		if (prev) {
+			prev->lld.mbr_nda = desc->tx_dma_desc.phys;
+			dev_dbg(chan2dev(chan),
+				 "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n",
+				 __func__, prev, prev->lld.mbr_nda);
+		}
+
+		prev = desc;
+		if (!first)

drivers/dma/at_xdmac.c line 625

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+			first = desc;
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	spin_unlock_bh(&atchan->lock);
+
+	first->tx_dma_desc.cookie = -EBUSY;

why are you init cookie here

Quoted 14 lines
drivers/dma/at_xdmac.c new file +13 -0
+	first->tx_dma_desc.flags = flags;
+	first->xfer_size = sg_len;
+
+	return &first->tx_dma_desc;
+}
+
 
+static struct dma_async_tx_descriptor *
+at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+			 size_t len, unsigned long flags)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+	struct at_xdmac_desc	*first = NULL, *prev = NULL;
+	size_t			remaining_size = len, xfer_size = 0, ublen;

drivers/dma/at_xdmac.c line 737

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+	dma_addr_t		src_addr = src, dst_addr = dest;
+	u32			dwidth;
+	/*
+	 * WARNING: The channel configuration is set here since there is no
+	 * dmaengine_slave_config call in this case. Moreover we don't know the
+	 * direction, it involves we can't dynamically set the source and dest
+	 * interface so we have to use the same one. Only interface 0 allows EBI
+	 * access. Hopefully we can access DDR through both ports (at least on
+	 * SAMA5D4x), so we can use the same interface for source and dest,
+	 * that solves the fact we don't know the direction.

For memcpy why should we need slave_config. The system memory source and destination width could be assumed to relastic values and then burst sizes maxed for performance. These values make more sense for periphral where we have to match up with the periphral

Quoted 102 lines
drivers/dma/at_xdmac.c new file +102 -0
+	 */
+	u32			chan_cc = AT_XDMAC_CC_DAM_INCREMENTED_AM
+					| AT_XDMAC_CC_SAM_INCREMENTED_AM
+					| AT_XDMAC_CC_DIF(0)
+					| AT_XDMAC_CC_SIF(0)
+					| AT_XDMAC_CC_MBSIZE_SIXTEEN
+					| AT_XDMAC_CC_TYPE_MEM_TRAN;
+
+	dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, len=%d, flags=0x%lx\n",
+		__func__, src, dest, len, flags);
+
+	if (unlikely(!len))
+		return NULL;
+
+	/*
+	 * Check address alignment to select the greater data width we can use.
+	 * Some XDMAC implementations don't provide dword transfer, in this
+	 * case selecting dword has the same behavior as selecting word transfers.
+	 */
+	if (!((src_addr | dst_addr) & 7)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
+	} else if (!((src_addr | dst_addr)  & 3)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_WORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
+	} else if (!((src_addr | dst_addr) & 1)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
+	} else {
+		dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
+		dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
+	}
+
+	atchan->cfg = chan_cc | AT_XDMAC_CC_DWIDTH(dwidth);
+
+	/* Prepare descriptors. */
+	while (remaining_size) {
+		struct at_xdmac_desc	*desc = NULL;
+
+		dev_dbg(chan2dev(chan), "%s: remaining_size=%u\n", __func__, remaining_size);
+
+		spin_lock_bh(&atchan->lock);
+		desc = at_xdmac_get_desc(atchan);
+		spin_unlock_bh(&atchan->lock);
+		if (!desc) {
+			dev_err(chan2dev(chan), "can't get descriptor\n");
+			if (first)
+				list_splice_init(&first->descs_list, &atchan->free_descs_list);
+			return NULL;
+		}
+
+		/* Update src and dest addresses. */
+		src_addr += xfer_size;
+		dst_addr += xfer_size;
+
+		if (remaining_size >= AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth)
+			xfer_size = AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth;
+		else
+			xfer_size = remaining_size;
+
+		dev_dbg(chan2dev(chan), "%s: xfer_size=%u\n", __func__, xfer_size);
+
+		/* Check remaining length and change data width if needed. */
+		if (!((src_addr | dst_addr | xfer_size) & 7)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
+		} else if (!((src_addr | dst_addr | xfer_size)  & 3)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_WORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
+		} else if (!((src_addr | dst_addr | xfer_size) & 1)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
+		} else if ((src_addr | dst_addr | xfer_size) & 1) {
+			dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
+			dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
+		}
+		chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
+
+		ublen = xfer_size >> dwidth;
+		remaining_size -= xfer_size;
+
+		desc->lld.mbr_sa = src_addr;
+		desc->lld.mbr_da = dst_addr;
+		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2
+			| AT_XDMAC_MBR_UBC_NDEN
+			| AT_XDMAC_MBR_UBC_NSEN
+			| (remaining_size ? AT_XDMAC_MBR_UBC_NDE : 0)
+			| ublen;
+		desc->lld.mbr_cfg = chan_cc;
+
+		dev_dbg(chan2dev(chan),
+			 "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+			 __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg);
+
+		/* Chain lld. */
+		if (prev) {
+			prev->lld.mbr_nda = desc->tx_dma_desc.phys;
+			dev_dbg(chan2dev(chan),
+				 "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n",
+				 __func__, prev, prev->lld.mbr_nda);
+		}
+

drivers/dma/at_xdmac.c line 849

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+		prev = desc;
+		if (!first)
+			first = desc;
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	first->tx_dma_desc.cookie = -EBUSY;

again..

Signature · 1 line
~Vinod
#3 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

Quoted 14 lines · Vinod Koul

drivers/dma/at_xdmac.c line 292

Quoted 9 lines · Ludovic Desroches

New atmel DMA controller known as XDMAC, introduced with SAMA5D4 devices.

drivers/dma/at_xdmac.c new file +6 -0
+
+static inline u32 at_xdmac_csize(u32 maxburst)
+{
+	u32 csize;
+
+	switch (ffs(maxburst) - 1) {

This is pretty odd, I dont see a reason why we can have proper case values and converted ones. It would have made sense if we use this for conversion but in case values in quite puzzling

Quoted 3 lines

drivers/dma/at_xdmac.c line 294

Quoted 2 lines
drivers/dma/at_xdmac.c new file +2 -0
+	case 1:
+		csize = AT_XDMAC_CC_CSIZE_CHK_2;

and looking at values this can be ffs(maxburst) - 1 for valid cases

Yes I can return ffs(maxburst) - 1 for valid cases.

Quoted 5 lines
Quoted 5 lines
drivers/dma/at_xdmac.c new file +5 -0
+		break;
+	case 2:
+		csize = AT_XDMAC_CC_CSIZE_CHK_4;
+		break;
+	case 3:
Quoted 8 lines

drivers/dma/at_xdmac.c line 306

Quoted 7 lines
drivers/dma/at_xdmac.c new file +7 -0
+		csize = AT_XDMAC_CC_CSIZE_CHK_8;
+		break;
+	case 4:
+		csize = AT_XDMAC_CC_CSIZE_CHK_16;
+		break;
+	default:
+		csize = AT_XDMAC_CC_CSIZE_CHK_1;

why?

Because some devices don't set maxburst, for example, our serial driver.

Quoted 62 lines
Quoted 62 lines
drivers/dma/at_xdmac.c new file +61 -0
+	}
+
+	return csize;
+};
+
+static unsigned int init_nr_desc_per_channel = 64;
+module_param(init_nr_desc_per_channel, uint, 0644);
+MODULE_PARM_DESC(init_nr_desc_per_channel,
+		 "initial descriptors per channel (default: 64)");
+
+
+static bool at_xdmac_chan_is_enabled(struct at_xdmac_chan *atchan)
+{
+	return at_xdmac_chan_read(atchan, AT_XDMAC_GS) & atchan->mask;
+}
+
+static void at_xdmac_off(struct at_xdmac *atxdmac)
+{
+	at_xdmac_write(atxdmac, AT_XDMAC_GD, -1L);
+
+	/* Wait that all chans are disabled. */
+	while (at_xdmac_read(atxdmac, AT_XDMAC_GS))
+		cpu_relax();
+
+	at_xdmac_write(atxdmac, AT_XDMAC_GID, -1L);
+}
+
+/* Call with lock hold. */
+static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan,
+				struct at_xdmac_desc *first)
+{
+	struct at_xdmac	*atxdmac = to_at_xdmac(atchan->chan.device);
+	u32		reg;
+
+	dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first);
+
+	if (at_xdmac_chan_is_enabled(atchan))
+		return;
+
+	/* Set transfer as active to not try to start it again. */
+	first->active_xfer = true;
+
+	/* Tell xdmac where to get the first descriptor. */
+	reg = AT_XDMAC_CNDA_NDA(first->tx_dma_desc.phys)
+	      | AT_XDMAC_CNDA_NDAIF(atchan->memif);
+	at_xdmac_chan_write(atchan, AT_XDMAC_CNDA, reg);
+
+	/*
+	 * When doing memory to memory transfer we need to use the next
+	 * descriptor view 2 since some fields of the configuration register
+	 * depend on transfer size and src/dest addresses.
+	 */
+	if (atchan->cfg & AT_XDMAC_CC_TYPE_PER_TRAN) {
+		reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
+		at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->cfg);
+	} else {
+		reg = AT_XDMAC_CNDC_NDVIEW_NDV2;
+	}
+
+	reg |= AT_XDMAC_CNDC_NDDUP
+	       | AT_XDMAC_CNDC_NDSUP
Quoted 8 lines

drivers/dma/at_xdmac.c line 373

Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+	       | AT_XDMAC_CNDC_NDE;
+	at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, reg);
+
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: XDMAC_CC=0x%08x XDMAC_CNDA=0x%08x, XDMAC_CNDC=0x%08x, "
+		 "XDMAC_CSA=0x%08x, XDMAC_CDA=0x%08x, XDMAC_CUBC=0x%08x\n",

multi line prints are not encouraged. You could perhpas do XDMAC CC, CNDC... and reduce your text size and ignore 80char limit.

Ok

Quoted 60 lines
Quoted 60 lines
drivers/dma/at_xdmac.c new file +58 -0
+		 __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CSA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
+
+	at_xdmac_chan_write(atchan, AT_XDMAC_CID, 0xffffffff);
+	reg = AT_XDMAC_CIE_RBEIE | AT_XDMAC_CIE_WBEIE | AT_XDMAC_CIE_ROIE;
+	/*
+	 * There is no end of list when doing cyclic dma, we need to get
+	 * an interrupt after each periods.
+	 */
+	if (at_xdmac_chan_is_cyclic(atchan))
+		at_xdmac_chan_write(atchan, AT_XDMAC_CIE,
+				    reg | AT_XDMAC_CIE_BIE);
+	else
+		at_xdmac_chan_write(atchan, AT_XDMAC_CIE,
+				    reg | AT_XDMAC_CIE_LIE);
+	at_xdmac_write(atxdmac, AT_XDMAC_GIE, atchan->mask);
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: enable channel (0x%08x)\n", __func__, atchan->mask);
+	wmb();
+	at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask);
+
+	dev_vdbg(chan2dev(&atchan->chan),
+		 "%s: XDMAC_CC=0x%08x XDMAC_CNDA=0x%08x, XDMAC_CNDC=0x%08x, "
+		 "XDMAC_CSA=0x%08x, XDMAC_CDA=0x%08x, XDMAC_CUBC=0x%08x\n",
+		 __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CNDC),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CSA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
+		 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
+
+}
 
+static int at_xdmac_set_slave_config(struct dma_chan *chan,
+				      struct dma_slave_config *sconfig)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+
+	atchan->cfg = AT91_XDMAC_DT_PERID(atchan->perid)
+		      |	AT_XDMAC_CC_SWREQ_HWR_CONNECTED
+		      | AT_XDMAC_CC_MBSIZE_SIXTEEN
+		      | AT_XDMAC_CC_TYPE_PER_TRAN;
+
+	if (sconfig->direction == DMA_DEV_TO_MEM) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_INCREMENTED_AM
+			       | AT_XDMAC_CC_SAM_FIXED_AM
+			       | AT_XDMAC_CC_DIF(atchan->memif)
+			       | AT_XDMAC_CC_SIF(atchan->perif)
+			       | AT_XDMAC_CC_DSYNC_PER2MEM;
+		atchan->dwidth = ffs(sconfig->src_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->src_maxburst);
+	} else if (sconfig->direction == DMA_MEM_TO_DEV) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_FIXED_AM
+			       | AT_XDMAC_CC_SAM_INCREMENTED_AM
Quoted 8 lines

drivers/dma/at_xdmac.c line 522

Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+			       | AT_XDMAC_CC_DIF(atchan->perif)
+			       | AT_XDMAC_CC_SIF(atchan->memif)
+			       | AT_XDMAC_CC_DSYNC_MEM2PER;
+		atchan->dwidth = ffs(sconfig->dst_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->dst_maxburst);

please store both direction configs and use them based on direction in prep_xxx calls. We will remove the direction here.

Ok, I'll do this update.

Quoted 97 lines
Quoted 97 lines
drivers/dma/at_xdmac.c new file +96 -0
+	} else {
+		return -EINVAL;
+	}
+
+	/*
+	 * Src address and dest addr are needed to configure the link list
+	 * descriptor so keep the slave configuration.
+	 */
+	memcpy(&atchan->dma_sconfig, sconfig, sizeof(struct dma_slave_config));
+
+	dev_dbg(chan2dev(chan), "%s: atchan->cfg=0x%08x\n", __func__, atchan->cfg);
+
+	return 0;
+}
+
+static struct dma_async_tx_descriptor *
+at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+		       unsigned int sg_len, enum dma_transfer_direction direction,
+		       unsigned long flags, void *context)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+	struct dma_slave_config	*sconfig = &atchan->dma_sconfig;
+	struct at_xdmac_desc	*first = NULL, *prev = NULL;
+	struct scatterlist	*sg;
+	int 			i;
+
+	if (!sgl)
+		return NULL;
+
+	if (!is_slave_direction(direction)) {
+		dev_err(chan2dev(chan), "invalid DMA direction\n");
+		return NULL;
+	}
+
+	dev_dbg(chan2dev(chan), "%s: sg_len=%d, dir=%s, flags=0x%lx\n",
+		 __func__, sg_len,
+		 direction == DMA_MEM_TO_DEV ? "to device" : "from device",
+		 flags);
+
+	/* Protect dma_sconfig field that can be modified by set_slave_conf. */
+	spin_lock_bh(&atchan->lock);
+
+	/* Prepare descriptors. */
+	for_each_sg(sgl, sg, sg_len, i) {
+		struct at_xdmac_desc	*desc = NULL;
+		u32			len, mem;
+
+		len = sg_dma_len(sg);
+		mem = sg_dma_address(sg);
+		if (unlikely(!len)) {
+			dev_err(chan2dev(chan), "sg data length is zero\n");
+			spin_unlock_bh(&atchan->lock);
+			return NULL;
+		}
+		dev_dbg(chan2dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n",
+			 __func__, i, len, mem);
+
+		desc = at_xdmac_get_desc(atchan);
+		if (!desc) {
+			dev_err(chan2dev(chan), "can't get descriptor\n");
+			if (first)
+				list_splice_init(&first->descs_list, &atchan->free_descs_list);
+			spin_unlock_bh(&atchan->lock);
+			return NULL;
+		}
+
+		/* Linked list descriptor setup. */
+		if (direction == DMA_DEV_TO_MEM) {
+			desc->lld.mbr_sa = sconfig->src_addr;
+			desc->lld.mbr_da = mem;
+		} else {
+			desc->lld.mbr_sa = mem;
+			desc->lld.mbr_da = sconfig->dst_addr;
+		}
+		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV1		/* next descriptor view */
+			| AT_XDMAC_MBR_UBC_NDEN				/* next descriptor dst parameter update */
+			| AT_XDMAC_MBR_UBC_NSEN				/* next descriptor src parameter update */
+			| (i == sg_len - 1 ? 0 : AT_XDMAC_MBR_UBC_NDE)	/* descriptor fetch */
+			| len / (1 << atchan->dwidth);			/* microblock length */
+		dev_dbg(chan2dev(chan),
+			 "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x\n",
+			 __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc);
+
+		/* Chain lld. */
+		if (prev) {
+			prev->lld.mbr_nda = desc->tx_dma_desc.phys;
+			dev_dbg(chan2dev(chan),
+				 "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n",
+				 __func__, prev, prev->lld.mbr_nda);
+		}
+
+		prev = desc;
+		if (!first)
+			first = desc;
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
Quoted 8 lines

drivers/dma/at_xdmac.c line 625

Quoted 7 lines
drivers/dma/at_xdmac.c new file +7 -0
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	spin_unlock_bh(&atchan->lock);
+
+	first->tx_dma_desc.cookie = -EBUSY;

why are you init cookie here

Inspired by other driver. What is the right place so?

Quoted 20 lines
Quoted 20 lines
drivers/dma/at_xdmac.c new file +19 -0
+	first->tx_dma_desc.flags = flags;
+	first->xfer_size = sg_len;
+
+	return &first->tx_dma_desc;
+}
+
 
+static struct dma_async_tx_descriptor *
+at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+			 size_t len, unsigned long flags)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+	struct at_xdmac_desc	*first = NULL, *prev = NULL;
+	size_t			remaining_size = len, xfer_size = 0, ublen;
+	dma_addr_t		src_addr = src, dst_addr = dest;
+	u32			dwidth;
+	/*
+	 * WARNING: The channel configuration is set here since there is no
+	 * dmaengine_slave_config call in this case. Moreover we don't know the
+	 * direction, it involves we can't dynamically set the source and dest
Quoted 8 lines

drivers/dma/at_xdmac.c line 737

Quoted 4 lines
drivers/dma/at_xdmac.c new file +4 -0
+	 * interface so we have to use the same one. Only interface 0 allows EBI
+	 * access. Hopefully we can access DDR through both ports (at least on
+	 * SAMA5D4x), so we can use the same interface for source and dest,
+	 * that solves the fact we don't know the direction.

For memcpy why should we need slave_config. The system memory source and destination width could be assumed to relastic values and then burst sizes maxed for performance. These values make more sense for periphral where we have to match up with the periphral

I don't tell I need slave_config. We have already talked about this. I don't see the problem. It is only a comment, a reminder. The only information I may need, one day, is the direction because we have to set src and dst interfaces. At the moment, all our products are done in a way nand flash and DDR are on the same interface so we don't have to care about direction.
Since we don't have the direction, two solutions:
- remember this limitation for next products, that's why there is this reminder,
- change our nand driver in order to see nand as a peripheral instead of a memory.

Quoted 106 lines
Quoted 106 lines
drivers/dma/at_xdmac.c new file +105 -0
+	 */
+	u32			chan_cc = AT_XDMAC_CC_DAM_INCREMENTED_AM
+					| AT_XDMAC_CC_SAM_INCREMENTED_AM
+					| AT_XDMAC_CC_DIF(0)
+					| AT_XDMAC_CC_SIF(0)
+					| AT_XDMAC_CC_MBSIZE_SIXTEEN
+					| AT_XDMAC_CC_TYPE_MEM_TRAN;
+
+	dev_dbg(chan2dev(chan), "%s: src=0x%08x, dest=0x%08x, len=%d, flags=0x%lx\n",
+		__func__, src, dest, len, flags);
+
+	if (unlikely(!len))
+		return NULL;
+
+	/*
+	 * Check address alignment to select the greater data width we can use.
+	 * Some XDMAC implementations don't provide dword transfer, in this
+	 * case selecting dword has the same behavior as selecting word transfers.
+	 */
+	if (!((src_addr | dst_addr) & 7)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
+	} else if (!((src_addr | dst_addr)  & 3)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_WORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
+	} else if (!((src_addr | dst_addr) & 1)) {
+		dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
+		dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
+	} else {
+		dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
+		dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
+	}
+
+	atchan->cfg = chan_cc | AT_XDMAC_CC_DWIDTH(dwidth);
+
+	/* Prepare descriptors. */
+	while (remaining_size) {
+		struct at_xdmac_desc	*desc = NULL;
+
+		dev_dbg(chan2dev(chan), "%s: remaining_size=%u\n", __func__, remaining_size);
+
+		spin_lock_bh(&atchan->lock);
+		desc = at_xdmac_get_desc(atchan);
+		spin_unlock_bh(&atchan->lock);
+		if (!desc) {
+			dev_err(chan2dev(chan), "can't get descriptor\n");
+			if (first)
+				list_splice_init(&first->descs_list, &atchan->free_descs_list);
+			return NULL;
+		}
+
+		/* Update src and dest addresses. */
+		src_addr += xfer_size;
+		dst_addr += xfer_size;
+
+		if (remaining_size >= AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth)
+			xfer_size = AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth;
+		else
+			xfer_size = remaining_size;
+
+		dev_dbg(chan2dev(chan), "%s: xfer_size=%u\n", __func__, xfer_size);
+
+		/* Check remaining length and change data width if needed. */
+		if (!((src_addr | dst_addr | xfer_size) & 7)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_DWORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__);
+		} else if (!((src_addr | dst_addr | xfer_size)  & 3)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_WORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__);
+		} else if (!((src_addr | dst_addr | xfer_size) & 1)) {
+			dwidth = AT_XDMAC_CC_DWIDTH_HALFWORD;
+			dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__);
+		} else if ((src_addr | dst_addr | xfer_size) & 1) {
+			dwidth = AT_XDMAC_CC_DWIDTH_BYTE;
+			dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__);
+		}
+		chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
+
+		ublen = xfer_size >> dwidth;
+		remaining_size -= xfer_size;
+
+		desc->lld.mbr_sa = src_addr;
+		desc->lld.mbr_da = dst_addr;
+		desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2
+			| AT_XDMAC_MBR_UBC_NDEN
+			| AT_XDMAC_MBR_UBC_NSEN
+			| (remaining_size ? AT_XDMAC_MBR_UBC_NDE : 0)
+			| ublen;
+		desc->lld.mbr_cfg = chan_cc;
+
+		dev_dbg(chan2dev(chan),
+			 "%s: lld: mbr_sa=0x%08x, mbr_da=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n",
+			 __func__, desc->lld.mbr_sa, desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg);
+
+		/* Chain lld. */
+		if (prev) {
+			prev->lld.mbr_nda = desc->tx_dma_desc.phys;
+			dev_dbg(chan2dev(chan),
+				 "%s: chain lld: prev=0x%p, mbr_nda=0x%08x\n",
+				 __func__, prev, prev->lld.mbr_nda);
+		}
+
+		prev = desc;
+		if (!first)
+			first = desc;
Quoted 11 lines

drivers/dma/at_xdmac.c line 625

Quoted 7 lines
drivers/dma/at_xdmac.c new file +7 -0
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	first->tx_dma_desc.cookie = -EBUSY;

again..

Signature · 1 line
~Vinod

Ludovic

#4 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

Quoted 24 lines · Ludovic Desroches
Quoted 7 lines

This is pretty odd, I dont see a reason why we can have proper case values and converted ones. It would have made sense if we use this for conversion but in case values in quite puzzling

drivers/dma/at_xdmac.c line 294

Quoted 2 lines
drivers/dma/at_xdmac.c new file +2 -0
+	case 1:
+		csize = AT_XDMAC_CC_CSIZE_CHK_2;

and looking at values this can be ffs(maxburst) - 1 for valid cases

Yes I can return ffs(maxburst) - 1 for valid cases.

Quoted 5 lines
Quoted 5 lines
drivers/dma/at_xdmac.c new file +5 -0
+		break;
+	case 2:
+		csize = AT_XDMAC_CC_CSIZE_CHK_4;
+		break;
+	case 3:
Quoted 8 lines

drivers/dma/at_xdmac.c line 306

Quoted 7 lines
drivers/dma/at_xdmac.c new file +7 -0
+		csize = AT_XDMAC_CC_CSIZE_CHK_8;
+		break;
+	case 4:
+		csize = AT_XDMAC_CC_CSIZE_CHK_16;
+		break;
+	default:
+		csize = AT_XDMAC_CC_CSIZE_CHK_1;

why?

Quoted 1 line

Because some devices don't set maxburst, for example, our serial driver.

Then pls send a patch against that as well. returniung error here will ensure that they fix that as well

Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+
+		prev = desc;
+		if (!first)
+			first = desc;
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
Quoted 8 lines

drivers/dma/at_xdmac.c line 625

Quoted 7 lines
drivers/dma/at_xdmac.c new file +7 -0
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	spin_unlock_bh(&atchan->lock);
+
+	first->tx_dma_desc.cookie = -EBUSY;

why are you init cookie here

Quoted 1 line

Inspired by other driver. What is the right place so?

You dont. Cookie will be set to correct value when the descriptor is submitted

Quoted 5 lines
Quoted 4 lines

For memcpy why should we need slave_config. The system memory source and destination width could be assumed to relastic values and then burst sizes maxed for performance. These values make more sense for periphral where we have to match up with the periphral

Quoted 10 lines

I don't tell I need slave_config. We have already talked about this. I don't see the problem. It is only a comment, a reminder. The only information I may need, one day, is the direction because we have to set src and dst interfaces. At the moment, all our products are done in a way nand flash and DDR are on the same interface so we don't have to care about direction.
Since we don't have the direction, two solutions:
- remember this limitation for next products, that's why there is this reminder,
- change our nand driver in order to see nand as a peripheral instead of a memory.

I think treating NAND as memory may not be a right model. It should be treated as periphral with incrementing and decrementing address value. That way you should be able to set the right properties for it.

The system memory copy is right model for memcpy.

Signature · 1 line
~Vinod
#5 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

Quoted 25 lines · Vinod Koul
Quoted 24 lines · Ludovic Desroches
Quoted 7 lines

This is pretty odd, I dont see a reason why we can have proper case values and converted ones. It would have made sense if we use this for conversion but in case values in quite puzzling

drivers/dma/at_xdmac.c line 294

Quoted 2 lines
drivers/dma/at_xdmac.c new file +2 -0
+	case 1:
+		csize = AT_XDMAC_CC_CSIZE_CHK_2;

and looking at values this can be ffs(maxburst) - 1 for valid cases

Yes I can return ffs(maxburst) - 1 for valid cases.

Quoted 13 lines

drivers/dma/at_xdmac.c line 306

Quoted 12 lines
drivers/dma/at_xdmac.c new file +12 -0
+		break;
+	case 2:
+		csize = AT_XDMAC_CC_CSIZE_CHK_4;
+		break;
+	case 3:
+		csize = AT_XDMAC_CC_CSIZE_CHK_8;
+		break;
+	case 4:
+		csize = AT_XDMAC_CC_CSIZE_CHK_16;
+		break;
+	default:
+		csize = AT_XDMAC_CC_CSIZE_CHK_1;

why?

Quoted 3 lines
Quoted 1 line

Because some devices don't set maxburst, for example, our serial driver.

Then pls send a patch against that as well. returniung error here will ensure that they fix that as well

Ok, I'll return an error and have a look to fix our serial driver.

Quoted 35 lines
Quoted 16 lines
Quoted 15 lines
Quoted 4 lines
drivers/dma/at_xdmac.c new file +3 -0
+
+		prev = desc;
+		if (!first)

drivers/dma/at_xdmac.c line 625

Quoted 10 lines
drivers/dma/at_xdmac.c new file +10 -0
+			first = desc;
+
+		dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
+			 __func__, desc, first);
+		list_add_tail(&desc->desc_node, &first->descs_list);
+	}
+
+	spin_unlock_bh(&atchan->lock);
+
+	first->tx_dma_desc.cookie = -EBUSY;

why are you init cookie here

Quoted 1 line

Inspired by other driver. What is the right place so?

You dont. Cookie will be set to correct value when the descriptor is submitted

Quoted 5 lines
Quoted 4 lines

For memcpy why should we need slave_config. The system memory source and destination width could be assumed to relastic values and then burst sizes maxed for performance. These values make more sense for periphral where we have to match up with the periphral

Quoted 10 lines

I don't tell I need slave_config. We have already talked about this. I don't see the problem. It is only a comment, a reminder. The only information I may need, one day, is the direction because we have to set src and dst interfaces. At the moment, all our products are done in a way nand flash and DDR are on the same interface so we don't have to care about direction.
Since we don't have the direction, two solutions:
- remember this limitation for next products, that's why there is this reminder,
- change our nand driver in order to see nand as a peripheral instead of a memory.

Quoted 5 lines

I think treating NAND as memory may not be a right model. It should be treated as periphral with incrementing and decrementing address value. That way you should be able to set the right properties for it.

The system memory copy is right model for memcpy.

Ok, I'll discuss of it with the atmel nand maintener. Even if there is something to improve here, I hope it is not considered as a blocking point to get the xdmac driver included into 3.19 because at the moment we have no DMA on the SAMA5D4 recently introduced.

Ludovic

#6 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

Quoted 20 lines · Ludovic Desroches
Quoted 20 lines
Quoted 6 lines
Quoted 5 lines

For memcpy why should we need slave_config. The system memory source and destination width could be assumed to relastic values and then burst sizes maxed for performance. These values make more sense for periphral where we have to match up with the periphral

Quoted 10 lines

I don't tell I need slave_config. We have already talked about this. I don't see the problem. It is only a comment, a reminder. The only information I may need, one day, is the direction because we have to set src and dst interfaces. At the moment, all our products are done in a way nand flash and DDR are on the same interface so we don't have to care about direction.
Since we don't have the direction, two solutions:
- remember this limitation for next products, that's why there is this reminder,
- change our nand driver in order to see nand as a peripheral instead of a memory.

I think treating NAND as memory may not be a right model. It should be treated as periphral with incrementing and decrementing address value. That way you should be able to set the right properties for it.

Quoted 6 lines
Quoted 1 line

The system memory copy is right model for memcpy.

Ok, I'll discuss of it with the atmel nand maintener. Even if there is something to improve here, I hope it is not considered as a blocking point to get the xdmac driver included into 3.19 because at the moment we have no DMA on the SAMA5D4 recently introduced.

That sounds good to me, no this is non blocker here

And yes keeping the comment here is fine to warn folks.

Signature · 1 line
~Vinod
#7 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

In reply to Vinod Koul

Hi Vinod,

Quoted 26 lines · Vinod Koul
Quoted 25 lines · Ludovic Desroches

New atmel DMA controller known as XDMAC, introduced with SAMA5D4 devices.

drivers/dma/at_xdmac.c new file +22 -0
+static int at_xdmac_set_slave_config(struct dma_chan *chan,
+				      struct dma_slave_config *sconfig)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+
+	atchan->cfg = AT91_XDMAC_DT_PERID(atchan->perid)
+		      |	AT_XDMAC_CC_SWREQ_HWR_CONNECTED
+		      | AT_XDMAC_CC_MBSIZE_SIXTEEN
+		      | AT_XDMAC_CC_TYPE_PER_TRAN;
+
+	if (sconfig->direction == DMA_DEV_TO_MEM) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_INCREMENTED_AM
+			       | AT_XDMAC_CC_SAM_FIXED_AM
+			       | AT_XDMAC_CC_DIF(atchan->memif)
+			       | AT_XDMAC_CC_SIF(atchan->perif)
+			       | AT_XDMAC_CC_DSYNC_PER2MEM;
+		atchan->dwidth = ffs(sconfig->src_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->src_maxburst);
+	} else if (sconfig->direction == DMA_MEM_TO_DEV) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_FIXED_AM
+			       | AT_XDMAC_CC_SAM_INCREMENTED_AM
Quoted 9 lines

drivers/dma/at_xdmac.c line 522

Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+			       | AT_XDMAC_CC_DIF(atchan->perif)
+			       | AT_XDMAC_CC_SIF(atchan->memif)
+			       | AT_XDMAC_CC_DSYNC_MEM2PER;
+		atchan->dwidth = ffs(sconfig->dst_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->dst_maxburst);

please store both direction configs and use them based on direction in prep_xxx calls. We will remove the direction here.

Ok so direction will disappear the dma_slave_config structure I assume but what is planned for src/dst_addr_width and src/dst_maxburst. If slave config looses the direction, there is no sense to have some src and dst fields. So where should I get them?

Quoted 6 lines
Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+	} else {
+		return -EINVAL;
+	}
+
+	/*
+	 * Src address and dest addr are needed to configure the link list
Quoted 8 lines

drivers/dma/at_xdmac.c line 536

Quoted 8 lines
drivers/dma/at_xdmac.c new file +8 -0
+	 * descriptor so keep the slave configuration.
+	 */
+	memcpy(&atchan->dma_sconfig, sconfig, sizeof(struct dma_slave_config));
+
+	dev_dbg(chan2dev(chan), "%s: atchan->cfg=0x%08x\n", __func__, atchan->cfg);
+
+	return 0;
+}

Ludovic

#8 lore raw

PATCH v6 1/3 dma: at_xdmac: creation of the atmel eXtended DMA Controller driver

Quoted 39 lines · Ludovic Desroches

Hi Vinod,

Quoted 26 lines · Vinod Koul
Quoted 25 lines · Ludovic Desroches

New atmel DMA controller known as XDMAC, introduced with SAMA5D4 devices.

drivers/dma/at_xdmac.c new file +22 -0
+static int at_xdmac_set_slave_config(struct dma_chan *chan,
+				      struct dma_slave_config *sconfig)
+{
+	struct at_xdmac_chan 	*atchan = to_at_xdmac_chan(chan);
+
+	atchan->cfg = AT91_XDMAC_DT_PERID(atchan->perid)
+		      |	AT_XDMAC_CC_SWREQ_HWR_CONNECTED
+		      | AT_XDMAC_CC_MBSIZE_SIXTEEN
+		      | AT_XDMAC_CC_TYPE_PER_TRAN;
+
+	if (sconfig->direction == DMA_DEV_TO_MEM) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_INCREMENTED_AM
+			       | AT_XDMAC_CC_SAM_FIXED_AM
+			       | AT_XDMAC_CC_DIF(atchan->memif)
+			       | AT_XDMAC_CC_SIF(atchan->perif)
+			       | AT_XDMAC_CC_DSYNC_PER2MEM;
+		atchan->dwidth = ffs(sconfig->src_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->src_maxburst);
+	} else if (sconfig->direction == DMA_MEM_TO_DEV) {
+		atchan->cfg |= AT_XDMAC_CC_DAM_FIXED_AM
+			       | AT_XDMAC_CC_SAM_INCREMENTED_AM
Quoted 9 lines

drivers/dma/at_xdmac.c line 522

Quoted 6 lines
drivers/dma/at_xdmac.c new file +6 -0
+			       | AT_XDMAC_CC_DIF(atchan->perif)
+			       | AT_XDMAC_CC_SIF(atchan->memif)
+			       | AT_XDMAC_CC_DSYNC_MEM2PER;
+		atchan->dwidth = ffs(sconfig->dst_addr_width) - 1;
+		atchan->cfg |= AT_XDMAC_CC_DWIDTH(atchan->dwidth);
+		atchan->cfg |= at_xdmac_csize(sconfig->dst_maxburst);

please store both direction configs and use them based on direction in prep_xxx calls. We will remove the direction here.

Quoted 4 lines

Ok so direction will disappear the dma_slave_config structure I assume but what is planned for src/dst_addr_width and src/dst_maxburst. If slave config looses the direction, there is no sense to have some src and dst fields. So where should I get them?

No there is!

So you get both src and dstn fields programmed by client. Then in prep_xxx calls, based on the direction (which is arg for prep_xxx) we need to to use either src or dstn fields

HTH

Signature · 1 line
~Vinod
#9 lore raw

PATCH v6 2/3 ARM: dts: at_xdmac: add bindings documentation

In reply to Ludovic Desroches

Add bindings documentation for the new Atmel DMA controller (XDMAC) introduced with SAMA5D4.

---
 .../devicetree/bindings/dma/atmel-xdma.txt         | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-xdma.txt
Documentation/devicetree/bindings/dma/atmel-xdma.txt new file +50 -0
new file mode 100644
index 0000000..ae587ad
@@ -0,0 +1,50 @@
+* Atmel Extensible Direct Memory Access Controller (XDMAC)
+
+* XDMA Controller
+Required properties:
+- compatible: Should be "atmel,<chip>-dma".
+  <chip> compatible description:
+  - sama5d4: first SoC adding the XDMAC
+- reg: Should contain DMA registers location and length.
+- interrupts: Should contain DMA interrupt.
+- #dma-cells: Must be <2>, used to represent the number of integer cells in
+the dmas property of client devices.
+  - The 1st cell specifies the memory interface (16 most significant bits) and
+  the peripheral interface (16 less significant bits) to use.
+  - The 2nd cell specifies the channel configuration register:
+    - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+dma1: dma-controller at f0004000 {
+	compatible = "atmel,sama5d4-dma";
+	reg = <0xf0004000 0x200>;
+	interrupts = <50 4 0>;
+	#dma-cells = <2>;
+};
+
+
+* DMA clients
+DMA clients connected to the Atmel XDMA controller must use the format
+described in the dma.txt file, using a two-cell specifier for each channel.
+The three cells in order are:
+1. A phandle pointing to the DMA controller.
+2. The memory interface (16 most significant bits), the peripheral interface
+(16 less significant bits).
+3. Channel configuration register. Configurable fields are:
+  - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+i2c2: i2c at f8024000 {
+	compatible = "atmel,at91sam9x5-i2c";
+	reg = <0xf8024000 0x4000>;
+	interrupts = <34 4 6>;
+	dmas = <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(6)>,
+	       <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(7)>;
+	dma-names = "tx", "rx";
+};
Signature · 1 line
2.0.3
#10 lore raw

PATCH v6 2/3 ARM: dts: at_xdmac: add bindings documentation

Quoted 2 lines · Ludovic Desroches

Add bindings documentation for the new Atmel DMA controller (XDMAC) introduced with SAMA5D4.

Seeing the example below, it doesnt seem to me that we cant reuse existing atmel binding, can you explain why we cnat reuse

Signature · 1 line
~Vinod
Quoted 67 lines
---
 .../devicetree/bindings/dma/atmel-xdma.txt         | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-xdma.txt
Documentation/devicetree/bindings/dma/atmel-xdma.txt new file +50 -0
new file mode 100644
index 0000000..ae587ad
@@ -0,0 +1,50 @@
+* Atmel Extensible Direct Memory Access Controller (XDMAC)
+
+* XDMA Controller
+Required properties:
+- compatible: Should be "atmel,<chip>-dma".
+  <chip> compatible description:
+  - sama5d4: first SoC adding the XDMAC
+- reg: Should contain DMA registers location and length.
+- interrupts: Should contain DMA interrupt.
+- #dma-cells: Must be <2>, used to represent the number of integer cells in
+the dmas property of client devices.
+  - The 1st cell specifies the memory interface (16 most significant bits) and
+  the peripheral interface (16 less significant bits) to use.
+  - The 2nd cell specifies the channel configuration register:
+    - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+dma1: dma-controller at f0004000 {
+	compatible = "atmel,sama5d4-dma";
+	reg = <0xf0004000 0x200>;
+	interrupts = <50 4 0>;
+	#dma-cells = <2>;
+};
+
+
+* DMA clients
+DMA clients connected to the Atmel XDMA controller must use the format
+described in the dma.txt file, using a two-cell specifier for each channel.
+The three cells in order are:
+1. A phandle pointing to the DMA controller.
+2. The memory interface (16 most significant bits), the peripheral interface
+(16 less significant bits).
+3. Channel configuration register. Configurable fields are:
+  - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+i2c2: i2c at f8024000 {
+	compatible = "atmel,at91sam9x5-i2c";
+	reg = <0xf8024000 0x4000>;
+	interrupts = <34 4 6>;
+	dmas = <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(6)>,
+	       <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(7)>;
+	dma-names = "tx", "rx";
+};
Signature · 1 line
2.0.3
#11 lore raw

PATCH v6 2/3 ARM: dts: at_xdmac: add bindings documentation

Quoted 5 lines · Vinod Koul
Quoted 2 lines · Ludovic Desroches

Add bindings documentation for the new Atmel DMA controller (XDMAC) introduced with SAMA5D4.

Seeing the example below, it doesnt seem to me that we cant reuse existing atmel binding, can you explain why we cnat reuse

We have discussed this in v3 but I didn't get answer:

"
Bindings have changed through the revisions, I didn't notice they were so close to the hdmac bindings. The only difference is the content of the second cell.

I don't know if it's a sufficient reason to add a new binding. "

It makes me thinking that I should merge the two cells since the memory and peripheral interface have been moved to the configuration register in xdmac. So the number of cells won't be the same.

Ludovic

Quoted 73 lines
Signature · 2 lines
-- 
~Vinod
Quoted 67 lines
---
 .../devicetree/bindings/dma/atmel-xdma.txt         | 50 ++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-xdma.txt
Documentation/devicetree/bindings/dma/atmel-xdma.txt new file +50 -0
new file mode 100644
index 0000000..ae587ad
@@ -0,0 +1,50 @@
+* Atmel Extensible Direct Memory Access Controller (XDMAC)
+
+* XDMA Controller
+Required properties:
+- compatible: Should be "atmel,<chip>-dma".
+  <chip> compatible description:
+  - sama5d4: first SoC adding the XDMAC
+- reg: Should contain DMA registers location and length.
+- interrupts: Should contain DMA interrupt.
+- #dma-cells: Must be <2>, used to represent the number of integer cells in
+the dmas property of client devices.
+  - The 1st cell specifies the memory interface (16 most significant bits) and
+  the peripheral interface (16 less significant bits) to use.
+  - The 2nd cell specifies the channel configuration register:
+    - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+dma1: dma-controller at f0004000 {
+	compatible = "atmel,sama5d4-dma";
+	reg = <0xf0004000 0x200>;
+	interrupts = <50 4 0>;
+	#dma-cells = <2>;
+};
+
+
+* DMA clients
+DMA clients connected to the Atmel XDMA controller must use the format
+described in the dma.txt file, using a two-cell specifier for each channel.
+The three cells in order are:
+1. A phandle pointing to the DMA controller.
+2. The memory interface (16 most significant bits), the peripheral interface
+(16 less significant bits).
+3. Channel configuration register. Configurable fields are:
+  - bit 30-24: PERID, peripheral identifier.
+
+Example:
+
+i2c2: i2c at f8024000 {
+	compatible = "atmel,at91sam9x5-i2c";
+	reg = <0xf8024000 0x4000>;
+	interrupts = <34 4 6>;
+	dmas = <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(6)>,
+	       <&dma1
+		(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1))
+		AT91_XDMAC_DT_PERID(7)>;
+	dma-names = "tx", "rx";
+};
Signature · 1 line
2.0.3
#12 lore raw

PATCH v6 3/3 MAINTAINERS: add entry for Atmel XDMA driver

In reply to Ludovic Desroches
---
 MAINTAINERS | 7 +++++++
 1 file changed, 7 insertions(+)
MAINTAINERS +7 -0
index 65cc66d..5f0849d 100644
@@ -1684,6 +1684,13 @@ F:	drivers/dma/at_hdmac.c
 F:	drivers/dma/at_hdmac_regs.h
 F:	include/linux/platform_data/dma-atmel.h
 
+ATMEL XDMA DRIVER
+M:	Ludovic Desroches <[email protected]>
+L:	linux-arm-kernel at lists.infradead.org
+L:	dmaengine at vger.kernel.org
+S:	Supported
+F:	drivers/dma/at_xdmac.c
+
 ATMEL I2C DRIVER
 M:	Ludovic Desroches <[email protected]>
 L:	linux-i2c at vger.kernel.org
Signature · 1 line
2.0.3
#13 lore raw

v6 cover new Atmel DMA controller (XDMAC)

In reply to Ludovic Desroches

Hi Vinod,

Could you take these patches since there are no new comments since v5?

Thanks

Ludovic

Quoted 69 lines · Ludovic Desroches

Hi,

This set of patches introduces support for the new Atmel DMA controller know as XDMAC and available on SAMA5D4.

Since there were no feedback about v5, could you give your ack if you agree with this new version.

Changes from:
- v5
- fix a bug when doing memcpy, condition to set the NDE was inverted
- replace irqsave locks by bh variant
- unmasked channel errors
- v4
- compile the driver if COMPILE_TEST is selected
- merge header file into at_xdmac.c
- use write memory barriers before starting the channel
- init active_xfer to false when taking a descriptor from the free descriptors list
- remove dma capabilities mask
- use CONFIG_PM instead of CONFIG_PM_SLEEP for prepare function
- style fixes
- update documentation to add the <chip> compatible description
- add maintener entry
- v3
- use dma_get_any_slave_channel instead of dma_request_channel
- fix tx_status behavior for non active transfers
- rename at_xdmac_terminate_xfer
- replace suspend/resume no irq variants by late/early variants
- no more use dev res to request the irq, use the legacy way
- add slave capabilities
- v2
- documentation updated
- fix locking issues
- v1
- add power management stuff
- check maxburst value
- revert subsys_initcall remove, EPROBE_DEFER not yet available on the kernel version I use to do the tests, moreover other devices are not ready to use it
- RFC:
- DMA_SUCCESS replaced by DMA_COMPLETE
- fix memcpy issue caused by a mistake in interfaces used
- add filter function
- remove some parameters from device tree since we can get them through the dma slave configuration
- use readl/writel relaxed
- remove subsys_initcall
- synchronize irq before killing tasklets
- use BIT macro
- misc cleanup

Ludovic Desroches (3):
dma: at_xdmac: creation of the atmel eXtended DMA Controller driver
ARM: dts: at_xdmac: add bindings documentation
MAINTAINERS: add entry for Atmel XDMA driver

 .../devicetree/bindings/dma/atmel-xdma.txt         |   50 +
 MAINTAINERS                                        |    7 +
 drivers/dma/Kconfig                                |    7 +
 drivers/dma/Makefile                               |    1 +
 drivers/dma/at_xdmac.c                             | 1493 ++++++++++++++++++++
 include/dt-bindings/dma/at91.h                     |   25 +
 6 files changed, 1583 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/dma/atmel-xdma.txt
 create mode 100644 drivers/dma/at_xdmac.c
Signature · 1 line
2.0.3