1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, NVIDIA Corporation. 4 */ 5 6 #include <linux/platform_device.h> 7 #include <linux/dma-mapping.h> 8 #include <linux/firmware.h> 9 #include <linux/pci_ids.h> 10 #include <linux/iopoll.h> 11 12 #include "falcon.h" 13 #include "drm.h" 14 15 enum falcon_memory { 16 FALCON_MEMORY_IMEM, 17 FALCON_MEMORY_DATA, 18 }; 19 20 static void falcon_writel(struct falcon *falcon, u32 value, u32 offset) 21 { 22 writel(value, falcon->regs + offset); 23 } 24 25 int falcon_wait_idle(struct falcon *falcon) 26 { 27 u32 value; 28 29 return readl_poll_timeout(falcon->regs + FALCON_IDLESTATE, value, 30 (value == 0), 10, 100000); 31 } 32 33 static int falcon_dma_wait_idle(struct falcon *falcon) 34 { 35 u32 value; 36 37 return readl_poll_timeout(falcon->regs + FALCON_DMATRFCMD, value, 38 (value & FALCON_DMATRFCMD_IDLE), 10, 100000); 39 } 40 41 static int falcon_copy_chunk(struct falcon *falcon, 42 phys_addr_t base, 43 unsigned long offset, 44 enum falcon_memory target) 45 { 46 u32 cmd = FALCON_DMATRFCMD_SIZE_256B; 47 48 if (target == FALCON_MEMORY_IMEM) 49 cmd |= FALCON_DMATRFCMD_IMEM; 50 51 falcon_writel(falcon, offset, FALCON_DMATRFMOFFS); 52 falcon_writel(falcon, base, FALCON_DMATRFFBOFFS); 53 falcon_writel(falcon, cmd, FALCON_DMATRFCMD); 54 55 return falcon_dma_wait_idle(falcon); 56 } 57 58 static void falcon_copy_firmware_image(struct falcon *falcon, 59 const struct firmware *firmware) 60 { 61 u32 *firmware_vaddr = falcon->firmware.vaddr; 62 dma_addr_t daddr; 63 size_t i; 64 int err; 65 66 /* copy the whole thing taking into account endianness */ 67 for (i = 0; i < firmware->size / sizeof(u32); i++) 68 firmware_vaddr[i] = le32_to_cpu(((u32 *)firmware->data)[i]); 69 70 /* ensure that caches are flushed and falcon can see the firmware */ 71 daddr = dma_map_single(falcon->dev, firmware_vaddr, 72 falcon->firmware.size, DMA_TO_DEVICE); 73 err = dma_mapping_error(falcon->dev, daddr); 74 if (err) { 75 dev_err(falcon->dev, "failed to map firmware: %d\n", err); 76 return; 77 } 78 dma_sync_single_for_device(falcon->dev, daddr, 79 falcon->firmware.size, DMA_TO_DEVICE); 80 dma_unmap_single(falcon->dev, daddr, falcon->firmware.size, 81 DMA_TO_DEVICE); 82 } 83 84 static int falcon_parse_firmware_image(struct falcon *falcon) 85 { 86 struct falcon_fw_bin_header_v1 *bin = (void *)falcon->firmware.vaddr; 87 struct falcon_fw_os_header_v1 *os; 88 89 /* endian problems would show up right here */ 90 if (bin->magic != PCI_VENDOR_ID_NVIDIA) { 91 dev_err(falcon->dev, "incorrect firmware magic\n"); 92 return -EINVAL; 93 } 94 95 /* currently only version 1 is supported */ 96 if (bin->version != 1) { 97 dev_err(falcon->dev, "unsupported firmware version\n"); 98 return -EINVAL; 99 } 100 101 /* check that the firmware size is consistent */ 102 if (bin->size > falcon->firmware.size) { 103 dev_err(falcon->dev, "firmware image size inconsistency\n"); 104 return -EINVAL; 105 } 106 107 os = falcon->firmware.vaddr + bin->os_header_offset; 108 109 falcon->firmware.bin_data.size = bin->os_size; 110 falcon->firmware.bin_data.offset = bin->os_data_offset; 111 falcon->firmware.code.offset = os->code_offset; 112 falcon->firmware.code.size = os->code_size; 113 falcon->firmware.data.offset = os->data_offset; 114 falcon->firmware.data.size = os->data_size; 115 116 return 0; 117 } 118 119 int falcon_read_firmware(struct falcon *falcon, const char *name) 120 { 121 int err; 122 123 /* request_firmware prints error if it fails */ 124 err = request_firmware(&falcon->firmware.firmware, name, falcon->dev); 125 if (err < 0) 126 return err; 127 128 return 0; 129 } 130 131 int falcon_load_firmware(struct falcon *falcon) 132 { 133 const struct firmware *firmware = falcon->firmware.firmware; 134 int err; 135 136 falcon->firmware.size = firmware->size; 137 138 /* allocate iova space for the firmware */ 139 falcon->firmware.vaddr = falcon->ops->alloc(falcon, firmware->size, 140 &falcon->firmware.paddr); 141 if (IS_ERR(falcon->firmware.vaddr)) { 142 dev_err(falcon->dev, "DMA memory mapping failed\n"); 143 return PTR_ERR(falcon->firmware.vaddr); 144 } 145 146 /* copy firmware image into local area. this also ensures endianness */ 147 falcon_copy_firmware_image(falcon, firmware); 148 149 /* parse the image data */ 150 err = falcon_parse_firmware_image(falcon); 151 if (err < 0) { 152 dev_err(falcon->dev, "failed to parse firmware image\n"); 153 goto err_setup_firmware_image; 154 } 155 156 release_firmware(firmware); 157 falcon->firmware.firmware = NULL; 158 159 return 0; 160 161 err_setup_firmware_image: 162 falcon->ops->free(falcon, falcon->firmware.size, 163 falcon->firmware.paddr, falcon->firmware.vaddr); 164 165 return err; 166 } 167 168 int falcon_init(struct falcon *falcon) 169 { 170 /* check mandatory ops */ 171 if (!falcon->ops || !falcon->ops->alloc || !falcon->ops->free) 172 return -EINVAL; 173 174 falcon->firmware.vaddr = NULL; 175 176 return 0; 177 } 178 179 void falcon_exit(struct falcon *falcon) 180 { 181 if (falcon->firmware.firmware) { 182 release_firmware(falcon->firmware.firmware); 183 falcon->firmware.firmware = NULL; 184 } 185 186 if (falcon->firmware.vaddr) { 187 falcon->ops->free(falcon, falcon->firmware.size, 188 falcon->firmware.paddr, 189 falcon->firmware.vaddr); 190 falcon->firmware.vaddr = NULL; 191 } 192 } 193 194 int falcon_boot(struct falcon *falcon) 195 { 196 unsigned long offset; 197 u32 value; 198 int err; 199 200 if (!falcon->firmware.vaddr) 201 return -EINVAL; 202 203 err = readl_poll_timeout(falcon->regs + FALCON_DMACTL, value, 204 (value & (FALCON_DMACTL_IMEM_SCRUBBING | 205 FALCON_DMACTL_DMEM_SCRUBBING)) == 0, 206 10, 10000); 207 if (err < 0) 208 return err; 209 210 falcon_writel(falcon, 0, FALCON_DMACTL); 211 212 /* setup the address of the binary data so Falcon can access it later */ 213 falcon_writel(falcon, (falcon->firmware.paddr + 214 falcon->firmware.bin_data.offset) >> 8, 215 FALCON_DMATRFBASE); 216 217 /* copy the data segment into Falcon internal memory */ 218 for (offset = 0; offset < falcon->firmware.data.size; offset += 256) 219 falcon_copy_chunk(falcon, 220 falcon->firmware.data.offset + offset, 221 offset, FALCON_MEMORY_DATA); 222 223 /* copy the first code segment into Falcon internal memory */ 224 falcon_copy_chunk(falcon, falcon->firmware.code.offset, 225 0, FALCON_MEMORY_IMEM); 226 227 /* setup falcon interrupts */ 228 falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) | 229 FALCON_IRQMSET_SWGEN1 | 230 FALCON_IRQMSET_SWGEN0 | 231 FALCON_IRQMSET_EXTERR | 232 FALCON_IRQMSET_HALT | 233 FALCON_IRQMSET_WDTMR, 234 FALCON_IRQMSET); 235 falcon_writel(falcon, FALCON_IRQDEST_EXT(0xff) | 236 FALCON_IRQDEST_SWGEN1 | 237 FALCON_IRQDEST_SWGEN0 | 238 FALCON_IRQDEST_EXTERR | 239 FALCON_IRQDEST_HALT, 240 FALCON_IRQDEST); 241 242 /* enable interface */ 243 falcon_writel(falcon, FALCON_ITFEN_MTHDEN | 244 FALCON_ITFEN_CTXEN, 245 FALCON_ITFEN); 246 247 /* boot falcon */ 248 falcon_writel(falcon, 0x00000000, FALCON_BOOTVEC); 249 falcon_writel(falcon, FALCON_CPUCTL_STARTCPU, FALCON_CPUCTL); 250 251 err = falcon_wait_idle(falcon); 252 if (err < 0) { 253 dev_err(falcon->dev, "Falcon boot failed due to timeout\n"); 254 return err; 255 } 256 257 return 0; 258 } 259 260 void falcon_execute_method(struct falcon *falcon, u32 method, u32 data) 261 { 262 falcon_writel(falcon, method >> 2, FALCON_UCLASS_METHOD_OFFSET); 263 falcon_writel(falcon, data, FALCON_UCLASS_METHOD_DATA); 264 } 265