Skip to content

Commit 5cfe585

Browse files
docularxuvinodkoul
authored andcommitted
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: Guodong Xu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 35e40bf commit 5cfe585

File tree

2 files changed

+82
-1
lines changed

2 files changed

+82
-1
lines changed

drivers/dma/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ config MILBEAUT_XDMAC
450450

451451
config MMP_PDMA
452452
tristate "MMP PDMA support"
453-
depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
453+
depends on ARCH_MMP || ARCH_PXA || ARCH_SPACEMIT || COMPILE_TEST
454454
select DMA_ENGINE
455455
help
456456
Support the MMP PDMA engine for PXA and MMP platform.

drivers/dma/mmp_pdma.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#define DDADR(n) (0x0200 + ((n) << 4))
2929
#define DSADR(n) (0x0204 + ((n) << 4))
3030
#define DTADR(n) (0x0208 + ((n) << 4))
31+
#define DDADRH(n) (0x0300 + ((n) << 4))
32+
#define DSADRH(n) (0x0304 + ((n) << 4))
33+
#define DTADRH(n) (0x0308 + ((n) << 4))
3134
#define DCMD 0x020c
3235

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

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

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

239+
/* For 64-bit PDMA */
240+
static void write_next_addr_64(struct mmp_pdma_phy *phy, dma_addr_t addr)
241+
{
242+
writel(lower_32_bits(addr), phy->base + DDADR(phy->idx));
243+
writel(upper_32_bits(addr), phy->base + DDADRH(phy->idx));
244+
}
245+
246+
static u64 read_src_addr_64(struct mmp_pdma_phy *phy)
247+
{
248+
u32 low = readl(phy->base + DSADR(phy->idx));
249+
u32 high = readl(phy->base + DSADRH(phy->idx));
250+
251+
return ((u64)high << 32) | low;
252+
}
253+
254+
static u64 read_dst_addr_64(struct mmp_pdma_phy *phy)
255+
{
256+
u32 low = readl(phy->base + DTADR(phy->idx));
257+
u32 high = readl(phy->base + DTADRH(phy->idx));
258+
259+
return ((u64)high << 32) | low;
260+
}
261+
262+
static void set_desc_next_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
263+
{
264+
desc->ddadr = lower_32_bits(addr);
265+
desc->ddadrh = upper_32_bits(addr);
266+
}
267+
268+
static void set_desc_src_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
269+
{
270+
desc->dsadr = lower_32_bits(addr);
271+
desc->dsadrh = upper_32_bits(addr);
272+
}
273+
274+
static void set_desc_dst_addr_64(struct mmp_pdma_desc_hw *desc, dma_addr_t addr)
275+
{
276+
desc->dtadr = lower_32_bits(addr);
277+
desc->dtadrh = upper_32_bits(addr);
278+
}
279+
280+
static u64 get_desc_src_addr_64(const struct mmp_pdma_desc_hw *desc)
281+
{
282+
return ((u64)desc->dsadrh << 32) | desc->dsadr;
283+
}
284+
285+
static u64 get_desc_dst_addr_64(const struct mmp_pdma_desc_hw *desc)
286+
{
287+
return ((u64)desc->dtadrh << 32) | desc->dtadr;
288+
}
289+
225290
static int mmp_pdma_config_write(struct dma_chan *dchan,
226291
struct dma_slave_config *cfg,
227292
enum dma_transfer_direction direction);
@@ -1110,10 +1175,26 @@ static const struct mmp_pdma_ops marvell_pdma_v1_ops = {
11101175
.dma_mask = 0, /* let OF/platform set DMA mask */
11111176
};
11121177

1178+
static const struct mmp_pdma_ops spacemit_k1_pdma_ops = {
1179+
.write_next_addr = write_next_addr_64,
1180+
.read_src_addr = read_src_addr_64,
1181+
.read_dst_addr = read_dst_addr_64,
1182+
.set_desc_next_addr = set_desc_next_addr_64,
1183+
.set_desc_src_addr = set_desc_src_addr_64,
1184+
.set_desc_dst_addr = set_desc_dst_addr_64,
1185+
.get_desc_src_addr = get_desc_src_addr_64,
1186+
.get_desc_dst_addr = get_desc_dst_addr_64,
1187+
.run_bits = (DCSR_RUN | DCSR_LPAEEN),
1188+
.dma_mask = DMA_BIT_MASK(64), /* force 64-bit DMA addr capability */
1189+
};
1190+
11131191
static const struct of_device_id mmp_pdma_dt_ids[] = {
11141192
{
11151193
.compatible = "marvell,pdma-1.0",
11161194
.data = &marvell_pdma_v1_ops
1195+
}, {
1196+
.compatible = "spacemit,k1-pdma",
1197+
.data = &spacemit_k1_pdma_ops
11171198
}, {
11181199
/* sentinel */
11191200
}

0 commit comments

Comments
 (0)