Commit 5cfe585d authored by Guodong Xu's avatar Guodong Xu Committed by Vinod Koul
Browse files

dmaengine: mmp_pdma: Add SpacemiT K1 PDMA support with 64-bit addressing



Add support for SpacemiT K1 PDMA controller which features 64-bit
addressing capabilities.

The SpacemiT K1 PDMA extends the descriptor format with additional
32-bit words for high address bits, enabling access to memory beyond
4GB boundaries. The new spacemit_k1_pdma_ops provides necessary 64-bit
address handling functions and k1 specific controller configurations.

Key changes:
- Add ARCH_SPACEMIT dependency to Kconfig
- Define new high 32-bit address registers (DDADRH, DSADRH, DTADRH)
- Add DCSR_LPAEEN bit for Long Physical Address Extension Enable
- Implement 64-bit operations for SpacemiT K1 PDMA

Signed-off-by: default avatarGuodong Xu <guodong@riscstar.com>
Link: https://lore.kernel.org/r/20250822-working_dma_0701_v2-v5-5-f5c0eda734cc@riscstar.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 35e40bf7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -450,7 +450,7 @@ config MILBEAUT_XDMAC

config MMP_PDMA
	tristate "MMP PDMA support"
	depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
	depends on ARCH_MMP || ARCH_PXA || ARCH_SPACEMIT || COMPILE_TEST
	select DMA_ENGINE
	help
	  Support the MMP PDMA engine for PXA and MMP platform.
+81 −0
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@
#define DDADR(n)	(0x0200 + ((n) << 4))
#define DSADR(n)	(0x0204 + ((n) << 4))
#define DTADR(n)	(0x0208 + ((n) << 4))
#define DDADRH(n)	(0x0300 + ((n) << 4))
#define DSADRH(n)	(0x0304 + ((n) << 4))
#define DTADRH(n)	(0x0308 + ((n) << 4))
#define DCMD		0x020c

#define DCSR_RUN	BIT(31)	/* Run Bit (read / write) */
@@ -44,6 +47,7 @@
#define DCSR_EORSTOPEN	BIT(26)	/* STOP on an EOR */
#define DCSR_SETCMPST	BIT(25)	/* Set Descriptor Compare Status */
#define DCSR_CLRCMPST	BIT(24)	/* Clear Descriptor Compare Status */
#define DCSR_LPAEEN	BIT(21)	/* Long Physical Address Extension Enable */
#define DCSR_CMPST	BIT(10)	/* The Descriptor Compare Status */
#define DCSR_EORINTR	BIT(9)	/* The end of Receive */

@@ -76,6 +80,16 @@ struct mmp_pdma_desc_hw {
	u32 dsadr;	/* DSADR value for the current transfer */
	u32 dtadr;	/* DTADR value for the current transfer */
	u32 dcmd;	/* DCMD value for the current transfer */
	/*
	 * The following 32-bit words are only used in the 64-bit, ie.
	 * LPAE (Long Physical Address Extension) mode.
	 * They are used to specify the high 32 bits of the descriptor's
	 * addresses.
	 */
	u32 ddadrh;	/* High 32-bit of DDADR */
	u32 dsadrh;	/* High 32-bit of DSADR */
	u32 dtadrh;	/* High 32-bit of DTADR */
	u32 rsvd;	/* reserved */
} __aligned(32);

struct mmp_pdma_desc_sw {
@@ -222,6 +236,57 @@ static u64 get_desc_dst_addr_32(const struct mmp_pdma_desc_hw *desc)
	return desc->dtadr;
}

/* For 64-bit PDMA */
static void write_next_addr_64(struct mmp_pdma_phy *phy, dma_addr_t addr)
{
	writel(lower_32_bits(addr), phy->base + DDADR(phy->idx));
	writel(upper_32_bits(addr), phy->base + DDADRH(phy->idx));
}

static u64 read_src_addr_64(struct mmp_pdma_phy *phy)
{
	u32 low = readl(phy->base + DSADR(phy->idx));
	u32 high = readl(phy->base + DSADRH(phy->idx));

	return ((u64)high << 32) | low;
}

static u64 read_dst_addr_64(struct mmp_pdma_phy *phy)
{
	u32 low = readl(phy->base + DTADR(phy->idx));
	u32 high = readl(phy->base + DTADRH(phy->idx));

	return ((u64)high << 32) | low;
}

static void set_desc_next_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
{
	desc->ddadr = lower_32_bits(addr);
	desc->ddadrh = upper_32_bits(addr);
}

static void set_desc_src_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
{
	desc->dsadr = lower_32_bits(addr);
	desc->dsadrh = upper_32_bits(addr);
}

static void set_desc_dst_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
{
	desc->dtadr = lower_32_bits(addr);
	desc->dtadrh = upper_32_bits(addr);
}

static u64 get_desc_src_addr_64(const struct mmp_pdma_desc_hw *desc)
{
	return ((u64)desc->dsadrh << 32) | desc->dsadr;
}

static u64 get_desc_dst_addr_64(const struct mmp_pdma_desc_hw *desc)
{
	return ((u64)desc->dtadrh << 32) | desc->dtadr;
}

static int mmp_pdma_config_write(struct dma_chan *dchan,
				 struct dma_slave_config *cfg,
				 enum dma_transfer_direction direction);
@@ -1110,10 +1175,26 @@ static const struct mmp_pdma_ops marvell_pdma_v1_ops = {
	.dma_mask = 0,			/* let OF/platform set DMA mask */
};

static const struct mmp_pdma_ops spacemit_k1_pdma_ops = {
	.write_next_addr = write_next_addr_64,
	.read_src_addr = read_src_addr_64,
	.read_dst_addr = read_dst_addr_64,
	.set_desc_next_addr = set_desc_next_addr_64,
	.set_desc_src_addr = set_desc_src_addr_64,
	.set_desc_dst_addr = set_desc_dst_addr_64,
	.get_desc_src_addr = get_desc_src_addr_64,
	.get_desc_dst_addr = get_desc_dst_addr_64,
	.run_bits = (DCSR_RUN | DCSR_LPAEEN),
	.dma_mask = DMA_BIT_MASK(64),	/* force 64-bit DMA addr capability */
};

static const struct of_device_id mmp_pdma_dt_ids[] = {
	{
		.compatible = "marvell,pdma-1.0",
		.data = &marvell_pdma_v1_ops
	}, {
		.compatible = "spacemit,k1-pdma",
		.data = &spacemit_k1_pdma_ops
	}, {
		/* sentinel */
	}