Commit 17ce2522 authored by Lizhi Hou's avatar Lizhi Hou Committed by Vinod Koul
Browse files

dmaengine: xilinx: xdma: Add xilinx xdma driver

Add driver to enable PCIe board which uses XDMA (the DMA/Bridge Subsystem
for PCI Express). For example, Xilinx Alveo PCIe devices.
    https://www.xilinx.com/products/boards-and-kits/alveo.html

The XDMA engine support up to 4 Host to Card (H2C) and 4 Card to Host (C2H)
channels. Memory transfers are specified on a per-channel basis in
descriptor linked lists, which the DMA fetches from host memory and
processes. Events such as descriptor completion and errors are signaled
using interrupts. The hardware detail is provided by
    https://docs.xilinx.com/r/en-US/pg195-pcie-dma/Introduction



This driver implements dmaengine APIs.
    - probe the available DMA channels
    - use dma_slave_map for channel lookup
    - use virtual channel to manage dmaengine tx descriptors
    - implement device_prep_slave_sg callback to handle host scatter gather
      list
    - implement device_config to config device address for DMA transfer

Signed-off-by: default avatarLizhi Hou <lizhi.hou@amd.com>
Signed-off-by: default avatarSonal Santan <sonal.santan@amd.com>
Signed-off-by: default avatarMax Zhen <max.zhen@amd.com>
Signed-off-by: default avatarBrian Xu <brian.xu@amd.com>
Tested-by: default avatarMartin Tuma <tumic@gpxsee.org>
Link: https://lore.kernel.org/r/1674145926-29449-2-git-send-email-lizhi.hou@amd.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 4b23603a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -22889,6 +22889,16 @@ F: Documentation/devicetree/bindings/media/xilinx/
F:	drivers/media/platform/xilinx/
F:	include/uapi/linux/xilinx-v4l2-controls.h
XILINX XDMA DRIVER
M:	Lizhi Hou <lizhi.hou@amd.com>
M:	Brian Xu <brian.xu@amd.com>
M:	Raj Kumar Rampelli <raj.kumar.rampelli@amd.com>
L:	dmaengine@vger.kernel.org
S:	Supported
F:	drivers/dma/xilinx/xdma-regs.h
F:	drivers/dma/xilinx/xdma.c
F:	include/linux/platform_data/amd_xdma.h
XILINX ZYNQMP DPDMA DRIVER
M:	Hyun Kwon <hyun.kwon@xilinx.com>
M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+14 −0
Original line number Diff line number Diff line
@@ -728,6 +728,20 @@ config XILINX_DMA
	  the scatter gather interface with multiple channels independent
	  configuration support.

config XILINX_XDMA
	tristate "Xilinx DMA/Bridge Subsystem DMA Engine"
	depends on HAS_IOMEM
	select DMA_ENGINE
	select DMA_VIRTUAL_CHANNELS
	select REGMAP_MMIO
	help
	  Enable support for Xilinx DMA/Bridge Subsystem DMA engine. The DMA
	  provides high performance block data movement between Host memory
	  and the DMA subsystem. These direct memory transfers can be both in
	  the Host to Card (H2C) and Card to Host (C2H) transfers.
	  The core also provides up to 16 user interrupt wires that generate
	  interrupts to the host.

config XILINX_ZYNQMP_DMA
	tristate "Xilinx ZynqMP DMA Engine"
	depends on ARCH_ZYNQ || MICROBLAZE || ARM64 || COMPILE_TEST
+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o
obj-$(CONFIG_XILINX_XDMA) += xdma.o
obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
obj-$(CONFIG_XILINX_ZYNQMP_DPDMA) += xilinx_dpdma.o
+166 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved.
 * Copyright (C) 2022, Advanced Micro Devices, Inc.
 */

#ifndef __DMA_XDMA_REGS_H
#define __DMA_XDMA_REGS_H

/* The length of register space exposed to host */
#define XDMA_REG_SPACE_LEN	65536

/*
 * maximum number of DMA channels for each direction:
 * Host to Card (H2C) or Card to Host (C2H)
 */
#define XDMA_MAX_CHANNELS	4

/*
 * macros to define the number of descriptor blocks can be used in one
 * DMA transfer request.
 * the DMA engine uses a linked list of descriptor blocks that specify the
 * source, destination, and length of the DMA transfers.
 */
#define XDMA_DESC_BLOCK_NUM		BIT(7)
#define XDMA_DESC_BLOCK_MASK		(XDMA_DESC_BLOCK_NUM - 1)

/* descriptor definitions */
#define XDMA_DESC_ADJACENT		32
#define XDMA_DESC_ADJACENT_MASK		(XDMA_DESC_ADJACENT - 1)
#define XDMA_DESC_ADJACENT_BITS		GENMASK(13, 8)
#define XDMA_DESC_MAGIC			0xad4bUL
#define XDMA_DESC_MAGIC_BITS		GENMASK(31, 16)
#define XDMA_DESC_FLAGS_BITS		GENMASK(7, 0)
#define XDMA_DESC_STOPPED		BIT(0)
#define XDMA_DESC_COMPLETED		BIT(1)
#define XDMA_DESC_BLEN_BITS		28
#define XDMA_DESC_BLEN_MAX		(BIT(XDMA_DESC_BLEN_BITS) - PAGE_SIZE)

/* macros to construct the descriptor control word */
#define XDMA_DESC_CONTROL(adjacent, flag)				\
	(FIELD_PREP(XDMA_DESC_MAGIC_BITS, XDMA_DESC_MAGIC) |		\
	 FIELD_PREP(XDMA_DESC_ADJACENT_BITS, (adjacent) - 1) |		\
	 FIELD_PREP(XDMA_DESC_FLAGS_BITS, (flag)))
#define XDMA_DESC_CONTROL_LAST						\
	XDMA_DESC_CONTROL(1, XDMA_DESC_STOPPED | XDMA_DESC_COMPLETED)

/*
 * Descriptor for a single contiguous memory block transfer.
 *
 * Multiple descriptors are linked by means of the next pointer. An additional
 * extra adjacent number gives the amount of extra contiguous descriptors.
 *
 * The descriptors are in root complex memory, and the bytes in the 32-bit
 * words must be in little-endian byte ordering.
 */
struct xdma_hw_desc {
	__le32		control;
	__le32		bytes;
	__le64		src_addr;
	__le64		dst_addr;
	__le64		next_desc;
};

#define XDMA_DESC_SIZE		sizeof(struct xdma_hw_desc)
#define XDMA_DESC_BLOCK_SIZE	(XDMA_DESC_SIZE * XDMA_DESC_ADJACENT)
#define XDMA_DESC_BLOCK_ALIGN	4096

/*
 * Channel registers
 */
#define XDMA_CHAN_IDENTIFIER		0x0
#define XDMA_CHAN_CONTROL		0x4
#define XDMA_CHAN_CONTROL_W1S		0x8
#define XDMA_CHAN_CONTROL_W1C		0xc
#define XDMA_CHAN_STATUS		0x40
#define XDMA_CHAN_COMPLETED_DESC	0x48
#define XDMA_CHAN_ALIGNMENTS		0x4c
#define XDMA_CHAN_INTR_ENABLE		0x90
#define XDMA_CHAN_INTR_ENABLE_W1S	0x94
#define XDMA_CHAN_INTR_ENABLE_W1C	0x9c

#define XDMA_CHAN_STRIDE	0x100
#define XDMA_CHAN_H2C_OFFSET	0x0
#define XDMA_CHAN_C2H_OFFSET	0x1000
#define XDMA_CHAN_H2C_TARGET	0x0
#define XDMA_CHAN_C2H_TARGET	0x1

/* macro to check if channel is available */
#define XDMA_CHAN_MAGIC		0x1fc0
#define XDMA_CHAN_CHECK_TARGET(id, target)		\
	(((u32)(id) >> 16) == XDMA_CHAN_MAGIC + (target))

/* bits of the channel control register */
#define CHAN_CTRL_RUN_STOP			BIT(0)
#define CHAN_CTRL_IE_DESC_STOPPED		BIT(1)
#define CHAN_CTRL_IE_DESC_COMPLETED		BIT(2)
#define CHAN_CTRL_IE_DESC_ALIGN_MISMATCH	BIT(3)
#define CHAN_CTRL_IE_MAGIC_STOPPED		BIT(4)
#define CHAN_CTRL_IE_IDLE_STOPPED		BIT(6)
#define CHAN_CTRL_IE_READ_ERROR			GENMASK(13, 9)
#define CHAN_CTRL_IE_DESC_ERROR			GENMASK(23, 19)
#define CHAN_CTRL_NON_INCR_ADDR			BIT(25)
#define CHAN_CTRL_POLL_MODE_WB			BIT(26)

#define CHAN_CTRL_START	(CHAN_CTRL_RUN_STOP |				\
			 CHAN_CTRL_IE_DESC_STOPPED |			\
			 CHAN_CTRL_IE_DESC_COMPLETED |			\
			 CHAN_CTRL_IE_DESC_ALIGN_MISMATCH |		\
			 CHAN_CTRL_IE_MAGIC_STOPPED |			\
			 CHAN_CTRL_IE_READ_ERROR |			\
			 CHAN_CTRL_IE_DESC_ERROR)

/* bits of the channel interrupt enable mask */
#define CHAN_IM_DESC_ERROR			BIT(19)
#define CHAN_IM_READ_ERROR			BIT(9)
#define CHAN_IM_IDLE_STOPPED			BIT(6)
#define CHAN_IM_MAGIC_STOPPED			BIT(4)
#define CHAN_IM_DESC_COMPLETED			BIT(2)
#define CHAN_IM_DESC_STOPPED			BIT(1)

#define CHAN_IM_ALL	(CHAN_IM_DESC_ERROR | CHAN_IM_READ_ERROR |	\
			 CHAN_IM_IDLE_STOPPED | CHAN_IM_MAGIC_STOPPED | \
			 CHAN_IM_DESC_COMPLETED | CHAN_IM_DESC_STOPPED)

/*
 * Channel SGDMA registers
 */
#define XDMA_SGDMA_IDENTIFIER	0x4000
#define XDMA_SGDMA_DESC_LO	0x4080
#define XDMA_SGDMA_DESC_HI	0x4084
#define XDMA_SGDMA_DESC_ADJ	0x4088
#define XDMA_SGDMA_DESC_CREDIT	0x408c

/* bits of the SG DMA control register */
#define XDMA_CTRL_RUN_STOP			BIT(0)
#define XDMA_CTRL_IE_DESC_STOPPED		BIT(1)
#define XDMA_CTRL_IE_DESC_COMPLETED		BIT(2)
#define XDMA_CTRL_IE_DESC_ALIGN_MISMATCH	BIT(3)
#define XDMA_CTRL_IE_MAGIC_STOPPED		BIT(4)
#define XDMA_CTRL_IE_IDLE_STOPPED		BIT(6)
#define XDMA_CTRL_IE_READ_ERROR			GENMASK(13, 9)
#define XDMA_CTRL_IE_DESC_ERROR			GENMASK(23, 19)
#define XDMA_CTRL_NON_INCR_ADDR			BIT(25)
#define XDMA_CTRL_POLL_MODE_WB			BIT(26)

/*
 * interrupt registers
 */
#define XDMA_IRQ_IDENTIFIER		0x2000
#define XDMA_IRQ_USER_INT_EN		0x2004
#define XDMA_IRQ_USER_INT_EN_W1S	0x2008
#define XDMA_IRQ_USER_INT_EN_W1C	0x200c
#define XDMA_IRQ_CHAN_INT_EN		0x2010
#define XDMA_IRQ_CHAN_INT_EN_W1S	0x2014
#define XDMA_IRQ_CHAN_INT_EN_W1C	0x2018
#define XDMA_IRQ_USER_INT_REQ		0x2040
#define XDMA_IRQ_CHAN_INT_REQ		0x2044
#define XDMA_IRQ_USER_INT_PEND		0x2048
#define XDMA_IRQ_CHAN_INT_PEND		0x204c
#define XDMA_IRQ_USER_VEC_NUM		0x2080
#define XDMA_IRQ_CHAN_VEC_NUM		0x20a0

#define XDMA_IRQ_VEC_SHIFT		8

#endif /* __DMA_XDMA_REGS_H */
+893 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading