Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/tegra: falcon: Support newer VIC firmware

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>

authored by

Mikko Perttunen and committed by
Thierry Reding
58ef3aeb 5c8fe583

+18 -12
+5 -4
drivers/gpu/drm/tegra/falcon.c
··· 72 72 struct falcon_fw_os_header_v1 *os; 73 73 74 74 /* endian problems would show up right here */ 75 - if (bin->magic != PCI_VENDOR_ID_NVIDIA) { 75 + if (bin->magic != PCI_VENDOR_ID_NVIDIA && bin->magic != 0x10fe) { 76 76 dev_err(falcon->dev, "incorrect firmware magic\n"); 77 77 return -EINVAL; 78 78 } ··· 178 178 falcon->firmware.data.offset + offset, 179 179 offset, FALCON_MEMORY_DATA); 180 180 181 - /* copy the first code segment into Falcon internal memory */ 182 - falcon_copy_chunk(falcon, falcon->firmware.code.offset, 183 - 0, FALCON_MEMORY_IMEM); 181 + /* copy the code segment into Falcon internal memory */ 182 + for (offset = 0; offset < falcon->firmware.code.size; offset += 256) 183 + falcon_copy_chunk(falcon, falcon->firmware.code.offset + offset, 184 + offset, FALCON_MEMORY_IMEM); 184 185 185 186 /* setup falcon interrupts */ 186 187 falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) |
+13 -8
drivers/gpu/drm/tegra/vic.c
··· 135 135 136 136 hdr = vic->falcon.firmware.virt; 137 137 fce_bin_data_offset = *(u32 *)(hdr + VIC_UCODE_FCE_DATA_OFFSET); 138 - hdr = vic->falcon.firmware.virt + 139 - *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET); 140 - fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET); 141 138 142 139 falcon_execute_method(&vic->falcon, VIC_SET_APPLICATION_ID, 1); 143 - falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE, 144 - fce_ucode_size); 145 - falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_OFFSET, 146 - (vic->falcon.firmware.iova + fce_bin_data_offset) 147 - >> 8); 140 + 141 + /* Old VIC firmware needs kernel help with setting up FCE microcode. */ 142 + if (fce_bin_data_offset != 0x0 && fce_bin_data_offset != 0xa5a5a5a5) { 143 + hdr = vic->falcon.firmware.virt + 144 + *(u32 *)(hdr + VIC_UCODE_FCE_HEADER_OFFSET); 145 + fce_ucode_size = *(u32 *)(hdr + FCE_UCODE_SIZE_OFFSET); 146 + 147 + falcon_execute_method(&vic->falcon, VIC_SET_FCE_UCODE_SIZE, 148 + fce_ucode_size); 149 + falcon_execute_method( 150 + &vic->falcon, VIC_SET_FCE_UCODE_OFFSET, 151 + (vic->falcon.firmware.iova + fce_bin_data_offset) >> 8); 152 + } 148 153 149 154 err = falcon_wait_idle(&vic->falcon); 150 155 if (err < 0) {