]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/tegra: falcon: Pipeline firmware copy
authorMikko Perttunen <mperttunen@nvidia.com>
Wed, 5 Feb 2025 06:10:27 +0000 (06:10 +0000)
committerThierry Reding <treding@nvidia.com>
Wed, 7 May 2025 15:47:36 +0000 (17:47 +0200)
The Falcon DMA engine allows queueing multiple operations for
improved performance. Do this to optimize firmware loading.
A performance improvement of 4x to 6x is observed.

Co-developed-by: Ivan Raul Guadarrama <iguadarrama@nvidia.com>
Signed-off-by: Ivan Raul Guadarrama <iguadarrama@nvidia.com>
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://lore.kernel.org/r/20250205061027.1205748-1-mperttunen@nvidia.com
drivers/gpu/drm/tegra/falcon.c
drivers/gpu/drm/tegra/falcon.h

index c0d85463eb1ac215d2920e14a02c32fad7c1c35b..17f616bbcb45bb1e46a0d415143395444650400f 100644 (file)
@@ -30,6 +30,14 @@ int falcon_wait_idle(struct falcon *falcon)
                                  (value == 0), 10, 100000);
 }
 
+static int falcon_dma_wait_not_full(struct falcon *falcon)
+{
+       u32 value;
+
+       return readl_poll_timeout(falcon->regs + FALCON_DMATRFCMD, value,
+                                 !(value & FALCON_DMATRFCMD_FULL), 10, 100000);
+}
+
 static int falcon_dma_wait_idle(struct falcon *falcon)
 {
        u32 value;
@@ -44,6 +52,7 @@ static int falcon_copy_chunk(struct falcon *falcon,
                             enum falcon_memory target)
 {
        u32 cmd = FALCON_DMATRFCMD_SIZE_256B;
+       int err;
 
        if (target == FALCON_MEMORY_IMEM)
                cmd |= FALCON_DMATRFCMD_IMEM;
@@ -56,11 +65,15 @@ static int falcon_copy_chunk(struct falcon *falcon,
         */
        cmd |= FALCON_DMATRFCMD_DMACTX(1);
 
+       err = falcon_dma_wait_not_full(falcon);
+       if (err < 0)
+               return err;
+
        falcon_writel(falcon, offset, FALCON_DMATRFMOFFS);
        falcon_writel(falcon, base, FALCON_DMATRFFBOFFS);
        falcon_writel(falcon, cmd, FALCON_DMATRFCMD);
 
-       return falcon_dma_wait_idle(falcon);
+       return 0;
 }
 
 static void falcon_copy_firmware_image(struct falcon *falcon,
@@ -191,6 +204,11 @@ int falcon_boot(struct falcon *falcon)
                falcon_copy_chunk(falcon, falcon->firmware.code.offset + offset,
                                  offset, FALCON_MEMORY_IMEM);
 
+       /* wait for DMA to complete */
+       err = falcon_dma_wait_idle(falcon);
+       if (err < 0)
+               return err;
+
        /* setup falcon interrupts */
        falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) |
                              FALCON_IRQMSET_SWGEN1 |
index 1955cf11a8a656788200709b9fd9a7648d3d966e..902bb7e4fd0fc5c61c2e404f78b936f2684158ed 100644 (file)
@@ -47,6 +47,7 @@
 #define FALCON_DMATRFMOFFS                     0x00001114
 
 #define FALCON_DMATRFCMD                       0x00001118
+#define FALCON_DMATRFCMD_FULL                  (1 << 0)
 #define FALCON_DMATRFCMD_IDLE                  (1 << 1)
 #define FALCON_DMATRFCMD_IMEM                  (1 << 4)
 #define FALCON_DMATRFCMD_SIZE_256B             (6 << 8)