Re: FDT DMA controller interface extension

Yuri Honegger <[email protected]> Sun, 25 Jan 2026 15:20:01 +0100
Newsgroups gmane.os.netbsd.ports.arm
Message-ID <[email protected]>
> Hi everyone,
> 
> Recently, I've been writing a DMA controller for the i.MX23. The i.MX23 DMA
> controller works by passing the hardware a pointer to a DMA command chain stored
> in memory. A DMA command looks roughly like this:
> 
> struct dma_command {
> void *next; /* you can chain commands */
> uint32_t control;
> void *buffer; /* memory buffer to transfer to/from */
> uint32_t pio_words[3];
> };
> 
> The i.MX23 DMA controller supports so-called "Programmable IO Words", short PIO.
> These PIO words get written to the hardware configuration register of the
> peripheral we are interacting over DMA before transferring data.
> 
> Due to some peculiarities of the i.MX23 hardware, you basically need to use PIO
> for the SD card driver if you don't want to write a polling driver.
> 
> The issue is that the FDT DMA controller interface (sys/dev/fdt/fdt_dma.h)
> doesn't provide a way to pass PIO data from a driver to the DMA controller.
> Therefore, I suggest to extend the fdtbus_dma_req struct with some optional
> parameters to specify PIO operations.
> 
> Here is my suggested diff. It solves the problem in the most straightforward way
> that works for the i.MX23.
> 
> Is it fine like this? I’m a bit afraid of ballooning the fdtbus_dma_req struct even more.
> Already right now most options are only supported by 1-2 controllers due to the wide
> variety in DMA controllers. 
> 
> Thanks,
> Yuri

Hi,
With the help of Nick and Jared, we’ve created an updated patch. It should be less 
i.MX23-specific by using a pointer+size approach.
Yuri
fdt_dma_v2.diff (application/octet-stream, 729 B)
diff --git a/sys/dev/fdt/fdt_dma.h b/sys/dev/fdt/fdt_dma.h
index a876bc62d67f..147aa187f0ac 100644
--- a/sys/dev/fdt/fdt_dma.h
+++ b/sys/dev/fdt/fdt_dma.h
@@ -41,7 +41,8 @@ struct fdtbus_dma {
 
 enum fdtbus_dma_dir {
 	FDT_DMA_READ,		/* device -> memory */
-	FDT_DMA_WRITE		/* memory -> device */
+	FDT_DMA_WRITE,		/* memory -> device */
+	FDT_DMA_NO_XFER		/* dma operation without data transfer */
 };
 
 struct fdtbus_dma_opt {
@@ -56,6 +57,9 @@ struct fdtbus_dma_req {
 	bus_dma_segment_t *dreq_segs;	/* Memory */
 	int dreq_nsegs;
 
+	void *dreq_data;		/* Controller-specific ancillary data */
+	int dreq_datalen;		/* Size of dreq_data */
+
 	bus_addr_t dreq_dev_phys;	/* Device */
 	int dreq_sel;			/* Device selector */