drm/tegra: falcon: Support newer VIC firmware
authorMikko Perttunen <mperttunen@nvidia.com>
Tue, 12 Jan 2021 11:37:06 +0000 (13:37 +0200)
committerThierry Reding <treding@nvidia.com>
Fri, 15 Jan 2021 16:15:50 +0000 (17:15 +0100)
Support newer VIC firmware by accepting the new magic number 0x10fe,
loading the full code segment instead of just the first page at boot
time, and skipping FCE setup if the firmware header indicates that
FCE is handled internally by the firmware.

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/falcon.c
drivers/gpu/drm/tegra/vic.c

index 56edef06c48e7f6bc7dd864ce5c01cfd207339c7..223ab2ceb7e626a8fd69e88ddbb68784dd86d2ed 100644 (file)
@@ -72,7 +72,7 @@ static int falcon_parse_firmware_image(struct falcon *falcon)
        struct falcon_fw_os_header_v1 *os;
 
        /* endian problems would show up right here */
-       if (bin->magic != PCI_VENDOR_ID_NVIDIA) {
+       if (bin->magic != PCI_VENDOR_ID_NVIDIA && bin->magic != 0x10fe) {
                dev_err(falcon->dev, "incorrect firmware magic\n");
                return -EINVAL;
        }
@@ -178,9 +178,10 @@ int falcon_boot(struct falcon *falcon)
                                  falcon->firmware.data.offset + offset,
                                  offset, FALCON_MEMORY_DATA);
 
-       /* copy the first code segment into Falcon internal memory */
-       falcon_copy_chunk(falcon, falcon->firmware.code.offset,
-                         0, FALCON_MEMORY_IMEM);
+       /* copy the code segment into Falcon internal memory */
+       for (offset = 0; offset < falcon->firmware.code.size; offset += 256)
+               falcon_copy_chunk(falcon, falcon->firmware.code.offset + offset,
+                                 offset, FALCON_MEMORY_IMEM);
 
        /* setup falcon interrupts */
        falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) |
index ade56b860cf9de7155d390b1ef04dc5293590262..a3dbb8813fafed53eee019d99aa1d92aed5bdf6a 100644 (file)
@@ -135,16 +135,21 @@ static int vic_boot(struct vic *vic)
 
        hdr = vic->falcon.firmware.virt;
        fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET);
-       hdr = vic->falcon.firmware.virt +
-               *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET);
-       fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET);
 
        falcon_execute_method(&vic->falcon, VIC_SET_APPLICATION_ID, 1);
-       falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE,
-                             fce_ucode_size);
-       falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_OFFSET,
-                             (vic->falcon.firmware.iova + fce_bin_data_offset)
-                               >> 8);
+
+       /* Old VIC firmware needs kernel help with setting up FCE microcode. */
+       if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) {
+               hdr = vic->falcon.firmware.virt +
+                       *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET);
+               fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET);
+
+               falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE,
+                                     fce_ucode_size);
+               falcon_execute_method(
+                       &vic->falcon, VIC_SET_FCE_UCODE_OFFSET,
+                       (vic->falcon.firmware.iova + fce_bin_data_offset) >> 8);
+       }
 
        err = falcon_wait_idle(&vic->falcon);
        if (err < 0) {